githabit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 149f2f360c3bfcd617482d297e650c7b59aee469
4
+ data.tar.gz: 3ce86ad065553872ba38cfcb1434eed0f0dab0e5
5
+ SHA512:
6
+ metadata.gz: 66273797e69c994fe943c0d0a0a89caefcd967c2bff31a4e00e56142c0396e04437b11bfd83718a8c17c9fe95093b53962b8b3c1c8649888f7472f0b4923d992
7
+ data.tar.gz: 078934caba66f89458bb0a0ad23b0328c18db112338d6f85b943aa1a05c8350517602f928c489490d9127761f99b4f30960df287fe9c2a6996d5e75311ce5ccf
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ syntax:glob
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.swp
12
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in githabit.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Morgan Kesler
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Githabit
2
+
3
+ Githabit is an application for monitoring your Github activities and rewarding you automatically onto your HabitRPG account for specific actions.
4
+
5
+ You will be rewarded for closing isues and making commits on the master branch of any of your repositories.
6
+
7
+ ## Installation
8
+
9
+ Install the gem using
10
+
11
+ $ gem install githabit
12
+
13
+ For the first time running you will need to initialize the cache, run
14
+
15
+ $ githabit --setup
16
+
17
+ After the initial run all you will need to run is
18
+
19
+ $ githabit
20
+
21
+ ## Configuration
22
+
23
+ Until I finish the setup function, you will need to create a config file in ~/.githabit.yml
24
+
25
+ You can find an example config [on my github](https://github.com/keslerm/githabit/blob/master/config-example.yml).
26
+
27
+ There are two main modes, interactive and autowatch mode. You can configure it in the config file by changing the autowatch paramter to true or false.
28
+
29
+ 1. Autowatch Mode: Runs continously checking your github for events every X minutes which is configured by setting the frequency in the config file
30
+ 2. Interative Mode: Runs once and exists, good if you just want to run it once at the end of the day.
31
+
32
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/bundler ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'bundler' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('bundler', 'bundler')
data/bin/githabit ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'githabit' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('githabit', 'githabit')
data/bin/nokogiri ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'nokogiri' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('nokogiri', 'nokogiri')
data/bin/rackup ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rackup' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rack', 'rackup')
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/bin/restclient ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'restclient' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rest-client', 'restclient')
@@ -0,0 +1,10 @@
1
+ habitrpg:
2
+ user: UUID
3
+ token: UUID
4
+
5
+ github:
6
+ user: USERNAME
7
+ password: PASSWORD
8
+ monitor_user: foobar
9
+ autowatch: false
10
+ frequency: 5
data/exe/githabit ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "githabit"
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
+
data/githabit.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'githabit/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "githabit"
8
+ spec.version = Githabit::VERSION
9
+ spec.authors = ["Morgan Kesler"]
10
+ spec.email = ["keslerm@dasbiersec.com"]
11
+
12
+ spec.summary = "Automatically awards for tasks in HabitRPG based on github events."
13
+ spec.description = "Gamify your github work on GithabitRPG. This gem will automatically award those tasks for these events."
14
+ spec.homepage = "https://github.com/keslerm/githabit"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.8"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rest-client", "~> 1.8"
25
+ spec.add_development_dependency "github_api", "~> 0.12.3"
26
+ end
@@ -0,0 +1,114 @@
1
+ require 'yaml'
2
+ require 'pp'
3
+ require 'githabit/github_api'
4
+ require 'githabit/habitrpg_api'
5
+ require 'githabit/cache'
6
+
7
+ module Githabit
8
+ class App
9
+
10
+ def initialize()
11
+ @log = Logger.new(STDOUT)
12
+
13
+ # Load config file
14
+ @settings = YAML::load_file(File.expand_path("~/.githabit.yml"))
15
+
16
+ # Init apis
17
+ @log.debug("Loading APIs")
18
+ @habit_api = HabitRPGAPI.new(@settings['habitrpg']['user'], @settings['habitrpg']['token'])
19
+ @github_api = GithubAPI.new(@settings['github']['user'], @settings['github']['password'])
20
+
21
+ # Initialize cache
22
+ @cache = Cache.new
23
+ end
24
+
25
+ def setup()
26
+ @log.info("Running setup - Caching all current events, no rewards will be generated for them")
27
+
28
+ # Initialize cache
29
+ @log.info("Checking github for new events")
30
+ events = @github_api.get_user_events(@settings['github']['monitor_user'])
31
+
32
+ events.select { |e| e['type'] == 'PushEvent'}.each do |event|
33
+ @log.debug("Caching event - #{event['id']}")
34
+ @cache.cache(event)
35
+ end
36
+
37
+ @log.info("Setup completed, starting main loop")
38
+ end
39
+
40
+ def start()
41
+ find_tasks()
42
+
43
+ if (@settings['github']['autowatch'] == true)
44
+ @log.info("Starting auto watch with delay of #{@settings['github']['frequency']} minutes")
45
+ while (true)
46
+ check_for_events()
47
+ sleep(60 * @settings['github']['frequency'].to_i)
48
+ end
49
+ else
50
+ check_for_events()
51
+ end
52
+ end
53
+
54
+ def find_tasks()
55
+ @log.info("Finding HabitRPG task ids")
56
+
57
+ @habit_api.list_tasks.each do |task|
58
+ if (task['text'] == 'Make a Github commit')
59
+ @log.info("Found github task id: " + task['id'])
60
+ @github_commit_task_id = task['id']
61
+ else
62
+ if (task['text'] == "Close Github issue")
63
+ @log.info("Found Close issue task: #{task['id']}")
64
+ @github_issue_task_id = task['id']
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+ def check_for_events()
72
+ new_events_found = 0
73
+
74
+ @log.info("Checking github for new events")
75
+ events = @github_api.get_user_events(@settings['github']['monitor_user'])
76
+
77
+ # For now only push events
78
+ events.select { |e| e['type'] == 'PushEvent'}.each do |event|
79
+ # We only want pushes to master branches
80
+ next if event['payload']['ref'] != "refs/heads/master"
81
+
82
+ # Find how many commits
83
+ event['payload']['commits'].each do |commit|
84
+
85
+ # If already in the cache - skip it, we've already rewarded it
86
+ next if @cache.cached? ("Commit:#{commit['sha']}")
87
+
88
+ @log.info("Rewarding commit: " + commit['sha'] + " to repo: " + event['repo']['name'] + " Message: " + commit['message'])
89
+ @habit_api.score_task(@github_commit_task_id, 'up', nil)
90
+
91
+ new_events_found += 1
92
+ end
93
+
94
+ @cache.cache(event)
95
+
96
+ end
97
+
98
+ events.select { |e| e['type'] == 'IssuesEvent'}.each do |event|
99
+ next if @cache.cached? ("Issue:#{event['id']}") or event['payload']['action'] != 'closed'
100
+
101
+ @log.info("Rewarding closed issue for id: #{event['id']} Issue: #{event['payload']['issue']['title']}")
102
+
103
+ @habit_api.score_task(@github_issue_task_id, 'up', nil)
104
+ new_events_found += 1
105
+
106
+ @cache.cache(event)
107
+
108
+ end
109
+
110
+ @log.info("Found " + new_events_found.to_s + " new events this run")
111
+ end
112
+ end
113
+ end
114
+
@@ -0,0 +1,47 @@
1
+ # Cachefile will be
2
+ # eventype:id
3
+ # PushEvent:SHAHASH
4
+ # IssueEvent:ISSUEID
5
+
6
+ class Cache
7
+ def initialize()
8
+ @cache = []
9
+ @file_cache = open(File.expand_path("~/.githabit.cache"), "a+")
10
+
11
+ # Load cache
12
+ @file_cache.each do |line|
13
+ @cache.push(line.strip)
14
+ end
15
+ end
16
+
17
+ def cached? (cache_id)
18
+ @cache.include? cache_id
19
+ end
20
+
21
+ def cache (event)
22
+ if (event['type'] == 'PushEvent')
23
+ # Cache each of the commits
24
+ event['payload']['commits'].each do |commit|
25
+ if (!cached? "Commit:#{commit['sha']}")
26
+ add("Commit:#{commit['sha']}")
27
+ end
28
+ end
29
+ elsif (event['type'] == "IssuesEvent")
30
+ if (!cached? "Issue:#{event['id']}")
31
+ add("Issue:#{event['id']}")
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ private
38
+ def add (cache_id)
39
+ @cache.push(cache_id)
40
+
41
+ # Write cache to file
42
+ @file_cache.write(cache_id)
43
+ @file_cache.write("\n")
44
+ end
45
+
46
+
47
+ end
@@ -0,0 +1,14 @@
1
+ require 'github_api'
2
+ require 'pp'
3
+
4
+ class GithubAPI
5
+ def initialize(username, password)
6
+ @github = Github.new(
7
+ :basic_auth => "#{username}:#{password}"
8
+ )
9
+ end
10
+
11
+ def get_user_events(username)
12
+ @github.activity.events.performed(username).body
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+ require 'pp'
4
+
5
+ class HabitRPGAPI
6
+
7
+ def initialize(api_user, api_token)
8
+ @api_user = api_user
9
+ @api_token = api_token
10
+ end
11
+
12
+ def score_task(task_id, direction, task)
13
+ post("user/tasks/#{task_id}/#{direction}", task)
14
+ end
15
+
16
+ def list_tasks()
17
+ get("user/tasks")
18
+ end
19
+
20
+ def get_task(task_id)
21
+ get("user/tasks/#{task_id}")
22
+ end
23
+
24
+ def create_task(task)
25
+ post("user/tasks", task)
26
+ end
27
+
28
+ private
29
+ def delete(url, params = nil)
30
+ JSON.parse(RestClient.delete("https://habitrpg.com/api/v2/#{url}", { 'x-api-key' => @api_token, 'x-api-user' => @api_user }))
31
+ end
32
+
33
+ private
34
+ def post(url, params = nil)
35
+ JSON.parse(RestClient.put("https://habitrpg.com/api/v2/#{url}", params, { 'x-api-key' => @api_token, 'x-api-user' => @api_user }))
36
+ end
37
+
38
+ private
39
+ def post(url, params = nil)
40
+ JSON.parse(RestClient.post("https://habitrpg.com/api/v2/#{url}", params, { 'x-api-key' => @api_token, 'x-api-user' => @api_user }))
41
+ end
42
+
43
+ private
44
+ def get(url, params = nil)
45
+ JSON.parse(RestClient.get("https://habitrpg.com/api/v2/#{url}", { 'x-api-key' => @api_token, 'x-api-user' => @api_user }))
46
+ end
47
+ end
48
+
@@ -0,0 +1,3 @@
1
+ module Githabit
2
+ VERSION = "0.1.0"
3
+ end
data/lib/githabit.rb ADDED
@@ -0,0 +1,15 @@
1
+ require "githabit/version"
2
+ require "githabit/app"
3
+
4
+ if (!File.exist? File.expand_path("~/.githabit.cache") and ARGV[0] != "--setup")
5
+ puts "No cache found please run with --setup argument to intialize cache."
6
+ exit
7
+ end
8
+
9
+ app = Githabit::App.new()
10
+
11
+ if (ARGV[0] == "--setup")
12
+ app.setup()
13
+ end
14
+
15
+ app.start()
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: githabit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Morgan Kesler
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-04-20 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.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
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: rest-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: github_api
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.12.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.12.3
69
+ description: Gamify your github work on GithabitRPG. This gem will automatically award
70
+ those tasks for these events.
71
+ email:
72
+ - keslerm@dasbiersec.com
73
+ executables:
74
+ - githabit
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/bundler
84
+ - bin/githabit
85
+ - bin/nokogiri
86
+ - bin/rackup
87
+ - bin/rake
88
+ - bin/restclient
89
+ - config-example.yml
90
+ - exe/githabit
91
+ - githabit.gemspec
92
+ - lib/githabit.rb
93
+ - lib/githabit/app.rb
94
+ - lib/githabit/cache.rb
95
+ - lib/githabit/github_api.rb
96
+ - lib/githabit/habitrpg_api.rb
97
+ - lib/githabit/version.rb
98
+ homepage: https://github.com/keslerm/githabit
99
+ licenses:
100
+ - MIT
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.4.6
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Automatically awards for tasks in HabitRPG based on github events.
122
+ test_files: []