zombie_fans 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c9492ee42f9a335779037517faa678e1ceb34078
4
+ data.tar.gz: 5f27421ad585d25057d3785ac4622aeb4ccafe91
5
+ SHA512:
6
+ metadata.gz: e3474ce1c5a3db0f1a749f2fdddb9f63264160248df557500e8a2d4a21aa4dfb6bf879fcf25d0afecf04e228cff367e07fcc453f48c6f16f111b28efb7c69efd
7
+ data.tar.gz: a3f749329984eb3047ad30d9a1ec018699d5d3c2f4550adfa06d8aa4dd987c1db4ee66a875982de24c3f3904235d1e26ce7cc54450c44c0737ba8d375e3803e1
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /db/
7
+ /doc/
8
+ /examples/log/*.log
9
+ /examples/.env
10
+ /examples/daily_check.rb
11
+ /log/
12
+ /pkg/
13
+ /spec/reports/
14
+ /tmp/
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at bbtfrr@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'dotenv'
4
+ gem 'whenever'
5
+ gem 'eventmachine'
6
+ gem 'mail'
7
+
8
+ # Specify your gem's dependencies in zombie_fans.gemspec
9
+ gemspec
@@ -0,0 +1,52 @@
1
+ # ZombieFans
2
+
3
+ Create github zombie fans to follow you / star your repo.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'zombie_fans'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install zombie_fans
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+
25
+ robot = ZombieFans::Robot.new # create a robot
26
+
27
+ robot.sign_up # sign up with random login, email & password, these will be saved in db/zombie_fans.yml
28
+ robot.upload_avatar # upload random avatar
29
+ robot.update_profile # fill profile form with random company name & city name
30
+
31
+ # or you can use an existed account in db/zombie_fans.yml
32
+ robot = ZombieFans::Robot.find('username') # find user by username
33
+ robot = ZombieFans::Robot.sample # random pick an existed account
34
+
35
+ robot.sign_in # sign in
36
+
37
+ robot.star_repo 'bbtfr/zombie-fans' # star a repo
38
+ robot.follow_user 'bbtfr' # follow an user
39
+ ```
40
+
41
+ You can find more examples [here](https://github.com/bbtfr/zombie-fans/tree/master/examples).
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+
49
+ ## Contributing
50
+
51
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bbtfr/zombie_fans. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
52
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "zombie_fans"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,26 @@
1
+ # Use this file to easily define all of your cron jobs.
2
+ #
3
+ # It's helpful, but not entirely necessary to understand cron before proceeding.
4
+ # http://en.wikipedia.org/wiki/Cron
5
+
6
+ # Example:
7
+ #
8
+ # set :output, "/path/to/my/cron_log.log"
9
+ #
10
+ # every 2.hours do
11
+ # command "/usr/bin/some_great_command"
12
+ # runner "MyModel.some_method"
13
+ # rake "some:great:rake:task"
14
+ # end
15
+ #
16
+ # every 4.days do
17
+ # runner "AnotherModel.prune_old_records"
18
+ # end
19
+
20
+ # Learn more: http://github.com/javan/whenever
21
+
22
+ set :output, "log/crontab.log"
23
+ job_type :bundle_exec, "cd :path && bundle exec :task :output"
24
+ every 1.hours do
25
+ bundle_exec "ruby star_my_repo.rb"
26
+ end
File without changes
@@ -0,0 +1,4 @@
1
+ require 'zombie_fans'
2
+ require 'zombie_fans/smtp'
3
+
4
+ EventMachine.run { SMTP.start }
@@ -0,0 +1,14 @@
1
+ require 'zombie_fans'
2
+
3
+ repos = %w(bbtfr/tailog bbtfr/tailog bbtfr/evil-proxy bbtfr/zombie-fans)
4
+
5
+ puts nil, "=== #{Time.now} ===".colorize(:blue)
6
+ robot = ZombieFans::Robot.new
7
+ robot.sign_up
8
+ robot.upload_avatar
9
+ robot.update_profile
10
+ robot.add_confirmable_email
11
+ robot.set_email_private
12
+
13
+ robot.star_repo repos.sample
14
+ robot.follow_user 'bbtfr'
@@ -0,0 +1,6 @@
1
+ require "zombie_fans/version"
2
+ require "zombie_fans/robot"
3
+
4
+ module ZombieFans
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,52 @@
1
+ require 'faker'
2
+
3
+ module ZombieFans::Actions
4
+ module Auth
5
+ def sign_up
6
+ agent.get('https://github.com/join') do |page|
7
+ retry_register = true
8
+ while retry_register
9
+ page = fill_signup_page page
10
+ error_messages = page.search('.form-group.errored .error').map(&:text)
11
+ retry_register = error_messages.any?
12
+ log_error error_messages.join(', ').downcase if retry_register
13
+ end
14
+ save
15
+ end
16
+ end
17
+
18
+ def sign_in
19
+ agent.get('https://github.com/settings/profile') do |page|
20
+ log_action 'SignIn', "with login: #{login}, email: #{email}, password: #{password}."
21
+
22
+ page.form_with(action: '/session') do |form|
23
+ form['login'] = @login
24
+ form['password'] = @password
25
+ end.submit
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def sample_login
32
+ names = name.split(' ')
33
+ [names.join('-').downcase, names.join('-').downcase, names.join.downcase, names.first.downcase, names.last.downcase, (name[0] + names.last).downcase, (name[0..1] + '-' + names.last).downcase, names.join, names.join, names.first, names.last, Faker::Internet.user_name, Faker::Internet.user_name].sample
34
+ end
35
+
36
+ def fill_signup_page page
37
+ page.form_with(action: '/join') do |form|
38
+ @name = Faker::Name.name
39
+ @login = sample_login
40
+ @email = Faker::Internet.free_email sample_login
41
+ @password = Faker::Internet.password(7, 20, true)
42
+
43
+ log_action 'SignUp', "with login: #{login}, password: #{password}."
44
+
45
+ form['user[login]'] = @login
46
+ form['user[email]'] = @email
47
+ form['user[password]'] = @password
48
+ end.submit
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,50 @@
1
+ module ZombieFans::Actions
2
+ module Avatar
3
+ def upload_avatar
4
+ page = agent.get('http://randomavatar.com')
5
+ avatar_url = page.at('.RAFade').attr('src')
6
+
7
+ log_action 'UploadAvatar', "with #{avatar_url}."
8
+
9
+ page = agent.get('https://github.com/settings/profile')
10
+ form = page.at('form.js-upload-avatar-image')
11
+ owner_id = form.attr('data-alambic-owner-id')
12
+ owner_type = form.attr('data-alambic-owner-type')
13
+ upload_policy_url = form.attr('data-upload-policy-url')
14
+ authenticity_token = form.at('input[name=authenticity_token]').attr('value')
15
+ avatar_filename = "#{login}.jpg"
16
+ avatar = open(avatar_url)
17
+
18
+ query = {
19
+ name: avatar_filename,
20
+ size: avatar.size,
21
+ content_type: 'image/jpeg',
22
+ authenticity_token: authenticity_token,
23
+ owner_type: owner_type,
24
+ owner_id: owner_id
25
+ }
26
+
27
+ page = agent.post(upload_policy_url, query)
28
+ response = JSON.parse page.body
29
+
30
+ File.open avatar.path do |avatar_file|
31
+ query = response['asset'].merge({
32
+ authenticity_token: authenticity_token,
33
+ owner_type: owner_type,
34
+ owner_id: owner_id,
35
+ size: avatar.size,
36
+ content_type: 'image/jpeg',
37
+ file: avatar_file
38
+ })
39
+
40
+ # agent.agent.allowed_error_codes = [500]
41
+ page = agent.post(response['upload_url'], query, response['header'])
42
+ response = JSON.parse page.body
43
+ end
44
+
45
+ agent.get("https://github.com/settings/avatars/#{response['id']}") do |page|
46
+ page = page.form_with(action: "/settings/avatars/#{response['id']}").submit
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ module ZombieFans::Actions
2
+ module Confirm
3
+ CONFIRMABLE_EMAIL = "%s@theoli.gq"
4
+
5
+ def follow_confirm_link confirm_link
6
+ agent.get(confirm_link) do |page|
7
+ log_action 'FollowConfirmLink', "with login: #{login}, link: #{confirm_link}."
8
+ end
9
+ end
10
+
11
+ def add_confirmable_email
12
+ agent.get('https://github.com/settings/emails') do |page|
13
+ confirmable_email = CONFIRMABLE_EMAIL % login
14
+ log_action 'AddConfirmableEmail', "with login: #{login}, email: #{confirmable_email}"
15
+
16
+ page = page.form_with(action: "/users/#{login}/emails") do |form|
17
+ form['user_email[email]'] = confirmable_email
18
+ end.submit
19
+
20
+ if error = page.at('.flash.flash-error:not(.ajax-error-message)')
21
+ log_error error.text.strip
22
+ end
23
+ end
24
+ end
25
+
26
+ def set_email_private
27
+ agent.get('https://github.com/settings/emails') do |page|
28
+ log_action 'ToggleEmailVisibility', "with login: #{login}, visibility: #{false}"
29
+
30
+ page = page.form_with(action: "/users/#{login}/emails/toggle_visibility") do |form|
31
+ form['toggle_visibility'] = 'false'
32
+ end.submit
33
+
34
+ if error = page.at('.flash.flash-error:not(.ajax-error-message)')
35
+ log_error error.text.strip
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ require 'colorize'
2
+
3
+ module ZombieFans::Actions
4
+ module Logger
5
+ def log_action action, message
6
+ puts "#{action.colorize(:green)} #{message}"
7
+ end
8
+
9
+ def log_error message
10
+ puts "#{"Error occurred:".colorize(:red)} #{message}"
11
+ end
12
+
13
+ def debug_page page
14
+ File.write("debug.html", page.body)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,50 @@
1
+ require 'fileutils'
2
+ require 'json'
3
+ require 'yaml'
4
+
5
+ module ZombieFans::Actions
6
+ module Persist
7
+ ATTRIBUTES = %w(name login email password repos)
8
+
9
+ def save
10
+ record = {}
11
+ ATTRIBUTES.each do |key|
12
+ attribute = instance_variable_get(:"@#{key}")
13
+ record[key] = attribute if attribute
14
+ end
15
+
16
+ yaml = Persist.load
17
+ yaml << record
18
+ Persist.dump yaml
19
+ end
20
+
21
+ class << self
22
+ attr_accessor :path
23
+
24
+ def path
25
+ @path ||= File.expand_path '../../../../db/zombie_fans.yml', __FILE__
26
+ end
27
+
28
+ def load
29
+ return [] unless File.exist? path
30
+ YAML.load(File.read(path)) || []
31
+ end
32
+
33
+ def dump yaml
34
+ FileUtils.mkdir_p(File.dirname(path))
35
+ File.write(path, YAML.dump(yaml))
36
+ end
37
+ end
38
+
39
+ module ClassMethods
40
+ def init_attributes
41
+ attr_accessor *ATTRIBUTES
42
+ end
43
+
44
+ def sample
45
+ yaml = Persist.load
46
+ new yaml.sample
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,10 @@
1
+ module ZombieFans::Actions
2
+ module Query
3
+ module ClassMethods
4
+ def find query, key = 'login'
5
+ yaml = Persist.load
6
+ new yaml.find { |record| record[key] == query }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,64 @@
1
+ module ZombieFans::Actions
2
+ module Repo
3
+ def create_repo
4
+ agent.get('https://github.com/new') do |page|
5
+ page.form_with(action: '/repositories') do |form|
6
+ name = Faker::Internet.domain_word
7
+ description = Faker::Hacker.say_something_smart
8
+ @repos ||= []
9
+ @repos << name
10
+
11
+ log_action 'CreateRepo', "with name: #{name}, description: #{description}."
12
+
13
+ form['repository[name]'] = name
14
+ form['repository[description]'] = description
15
+ end.submit
16
+
17
+ save
18
+ end
19
+ end
20
+
21
+ def star_repo repo
22
+ page = agent.get("https://github.com/#{repo}")
23
+ form = page.at('.starring-container:not(.on) form.unstarred')
24
+ return unless form
25
+
26
+ log_action 'StarRepo', "#{repo}."
27
+
28
+ authenticity_token = form.at('input[name=authenticity_token]').attr('value')
29
+ star_repo_url = form.attr('action')
30
+
31
+ query = {
32
+ authenticity_token: authenticity_token
33
+ }
34
+
35
+ header = {
36
+ 'X-Requested-With' => 'XMLHttpRequest'
37
+ }
38
+
39
+ # agent.agent.allowed_error_codes = [400]
40
+ page = agent.post(star_repo_url, query, header)
41
+ response = JSON.parse page.body
42
+ end
43
+
44
+ def make_repo_private repo
45
+ toggle_permission repo, "private"
46
+ end
47
+
48
+ def make_repo_public repo
49
+ toggle_permission repo, "public"
50
+ end
51
+
52
+ def toggle_permission repo, permission
53
+ page = agent.get("https://github.com/#{repo}/settings")
54
+ button = page.at('a[href="#visibility_confirm"]')
55
+ return unless button && button.text == "Make #{permission}"
56
+
57
+ log_action 'TogglePermission', "#{repo} #{permission}."
58
+
59
+ page = page.form_with(action: "/#{repo}/settings/toggle_permission") do |form|
60
+ form['verify'] = repo
61
+ end.submit
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,55 @@
1
+ module ZombieFans::Actions
2
+ module User
3
+ def update_profile
4
+ agent.get('https://github.com/settings/profile') do |page|
5
+ page.form_with(action: "/users/#{login}") do |form|
6
+ name = sample_display_name
7
+ blog = sample_result Faker::Internet.url, 2
8
+ company = sample_result Faker::Company.name, 1, 2
9
+ location = sample_result Faker::Address.city, 1, 2
10
+
11
+ log_action 'UpdateProfile', "with name: #{name}, blog: #{blog || 'nil'}, company: #{company || 'nil'}, location: #{location || 'nil'}."
12
+
13
+ form['user[profile_name]'] = name
14
+ form['user[profile_blog]'] = blog
15
+ form['user[profile_company]'] = company
16
+ form['user[profile_location]'] = location
17
+ end.submit
18
+ end
19
+ end
20
+
21
+ def follow_user user
22
+ page = agent.get("https://github.com/#{user}")
23
+ form = page.at('.user-following-container:not(.on) .follow form')
24
+ return unless form
25
+
26
+ log_action 'FollowUser', "#{user}."
27
+
28
+ authenticity_token = form.at('input[name=authenticity_token]').attr('value')
29
+ follow_user_url = form.attr('action')
30
+
31
+ query = {
32
+ authenticity_token: authenticity_token
33
+ }
34
+
35
+ header = {
36
+ 'X-Requested-With' => 'XMLHttpRequest'
37
+ }
38
+
39
+ # agent.agent.allowed_error_codes = [400]
40
+ page = agent.post(follow_user_url, query, header)
41
+ response = JSON.parse page.body
42
+ end
43
+
44
+ private
45
+
46
+ def sample_display_name
47
+ names = name.split(' ')
48
+ names = [names.join('-').downcase, names.first.downcase, names.last.downcase, name, name, name, name, name, names.first, names.last].sample
49
+ end
50
+
51
+ def sample_result result, weight1 = 1, weight2 = 1
52
+ ([nil] * weight1 + [result] * weight2).sample
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,57 @@
1
+ require 'open-uri'
2
+ # Don't allow downloaded files to be created as StringIO. Force a tempfile to be created.
3
+ OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax')
4
+ OpenURI::Buffer.const_set 'StringMax', 0
5
+
6
+ require 'mechanize'
7
+
8
+ glob = File.expand_path("../actions/*.rb", __FILE__)
9
+ Dir[glob].each do |file|
10
+ require file
11
+ end
12
+
13
+ class Mechanize::Page
14
+ def preview
15
+ file = Tempfile.new(['mechanize', '.html'])
16
+ file.write(self.content)
17
+ file.close
18
+ system("open #{file.path}")
19
+ sleep 3
20
+ file.unlink
21
+ end
22
+ end
23
+
24
+ module ZombieFans
25
+ class Robot
26
+ include Actions::Logger
27
+ include Actions::Auth
28
+ include Actions::Confirm
29
+ include Actions::Avatar
30
+ include Actions::Repo
31
+ include Actions::User
32
+
33
+ include Actions::Persist
34
+ extend Actions::Persist::ClassMethods
35
+ init_attributes
36
+
37
+ extend Actions::Query::ClassMethods
38
+
39
+ attr_reader :agent
40
+
41
+ AGENT_ALIASES = [
42
+ 'Linux Firefox', 'Linux Konqueror', 'Linux Mozilla', 'Mac Firefox', 'Mac Mozilla', 'Mac Safari 4', 'Mac Safari', 'Windows Chrome', 'Windows IE 6', 'Windows IE 7', 'Windows IE 8', 'Windows IE 9', 'Windows IE 10', 'Windows IE 11', 'Windows Edge', 'Windows Mozilla', 'Windows Firefox'
43
+ ]
44
+
45
+ def initialize attributes = {}
46
+ # assign attributes
47
+ attributes.each do |key, value|
48
+ instance_variable_set(:"@#{key}", value)
49
+ end
50
+
51
+ @agent = Mechanize.new do |agent|
52
+ agent.user_agent_alias = AGENT_ALIASES.sample
53
+ agent.agent.allowed_error_codes = [500]
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,77 @@
1
+ require 'eventmachine'
2
+ require 'ostruct'
3
+ require 'mail'
4
+
5
+ class SMTP < EventMachine::Protocols::SmtpServer
6
+ def receive_sender(sender)
7
+ current.sender = sender
8
+ true
9
+ end
10
+
11
+ def receive_recipient(recipient)
12
+ current.recipient = recipient
13
+ true
14
+ end
15
+
16
+ def receive_message
17
+ current.received = true
18
+ current.completed_at = Time.now
19
+
20
+ puts "==> SMTP: Received message from '#{current.sender}' (#{current.data.length} bytes)"
21
+
22
+ if current.sender =~ /noreply@github.com/
23
+ mail = Mail.new current.data
24
+ plain_text = mail.body.parts.first.body.decoded
25
+ if plain_text =~ /https:\/\/github.com\/users\/(.*?)\/emails.*?(?=\n)/
26
+ confirm_link = $&
27
+ login = $1
28
+
29
+ robot = ZombieFans::Robot.find login
30
+ robot.sign_in
31
+ robot.follow_confirm_link confirm_link
32
+ end
33
+ end
34
+
35
+ true
36
+ rescue => error
37
+ puts "*** Error receiving message: #{current.inspect}"
38
+ puts " Exception: #{error}"
39
+ puts " Backtrace:"
40
+ $!.backtrace.each do |line|
41
+ puts " #{line}"
42
+ end
43
+ false
44
+ ensure
45
+ @current = nil
46
+ end
47
+
48
+ def receive_data_command
49
+ current.data = ""
50
+ true
51
+ end
52
+
53
+ def receive_data_chunk(data)
54
+ current.data << data.join("\n")
55
+ true
56
+ end
57
+
58
+ def current
59
+ @current ||= OpenStruct.new
60
+ end
61
+
62
+ def self.start(host = '0.0.0.0', port = 25)
63
+ @server = EventMachine.start_server host, port, self
64
+ puts "Starting MailCatcher on smtp://#{host}:#{port}"
65
+ end
66
+
67
+ def self.stop
68
+ if @server
69
+ EventMachine.stop_server @server
70
+ @server = nil
71
+ end
72
+ end
73
+
74
+ def self.running?
75
+ !!@server
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module ZombieFans
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'zombie_fans/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "zombie_fans"
8
+ spec.version = ZombieFans::VERSION
9
+ spec.authors = ["Theo Li"]
10
+ spec.email = ["bbtfrr@gmail.com"]
11
+
12
+ spec.summary = %q{Github Zombie Fans}
13
+ spec.description = %q{Github Zombie Fans to follow, star and many more.}
14
+ spec.homepage = "https://github.com/bbtfr/zombie-fans"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.12"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+
32
+ spec.add_dependency "mechanize", "~> 2.7.0"
33
+ spec.add_dependency "colorize", "~> 0.7.7"
34
+ spec.add_dependency "faker", "~> 1.6.3"
35
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zombie_fans
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Theo Li
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mechanize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.7.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.7.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.7.7
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.7.7
69
+ - !ruby/object:Gem::Dependency
70
+ name: faker
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.6.3
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.6.3
83
+ description: Github Zombie Fans to follow, star and many more.
84
+ email:
85
+ - bbtfrr@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - CODE_OF_CONDUCT.md
92
+ - Gemfile
93
+ - README.md
94
+ - Rakefile
95
+ - bin/console
96
+ - bin/setup
97
+ - examples/config/schedule.rb
98
+ - examples/log/.keep
99
+ - examples/smtp_server.rb
100
+ - examples/star_my_repo.rb
101
+ - lib/zombie_fans.rb
102
+ - lib/zombie_fans/actions/auth.rb
103
+ - lib/zombie_fans/actions/avatar.rb
104
+ - lib/zombie_fans/actions/confirm.rb
105
+ - lib/zombie_fans/actions/logger.rb
106
+ - lib/zombie_fans/actions/persist.rb
107
+ - lib/zombie_fans/actions/query.rb
108
+ - lib/zombie_fans/actions/repo.rb
109
+ - lib/zombie_fans/actions/user.rb
110
+ - lib/zombie_fans/robot.rb
111
+ - lib/zombie_fans/smtp.rb
112
+ - lib/zombie_fans/version.rb
113
+ - zombie_fans.gemspec
114
+ homepage: https://github.com/bbtfr/zombie-fans
115
+ licenses: []
116
+ metadata:
117
+ allowed_push_host: https://rubygems.org
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.5.1
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Github Zombie Fans
138
+ test_files: []