october 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +35 -0
- data/README.md +14 -0
- data/Rakefile +38 -0
- data/bin/october +8 -0
- data/boot.rb +5 -0
- data/config/database.yml.example +3 -0
- data/config/irc.yml.example +9 -0
- data/config/plugins.yml.example +2 -0
- data/config/redis.yml.example +7 -0
- data/lib/october.rb +16 -0
- data/lib/october/base.rb +28 -0
- data/lib/october/config.rb +23 -0
- data/lib/october/debugger.rb +51 -0
- data/lib/october/environment.rb +24 -0
- data/lib/october/plugin.rb +26 -0
- data/lib/october/plugin/help.rb +20 -0
- data/lib/october/plugins.rb +94 -0
- data/lib/october/redis.rb +20 -0
- data/lib/october/version.rb +3 -0
- data/lib/october/watchdog.rb +36 -0
- data/october.gemspec +25 -0
- data/plugins/.gitkeep +0 -0
- data/plugins/autossh.rb +23 -0
- data/plugins/fortune.rb +13 -0
- data/plugins/help.rb +11 -0
- data/plugins/hudson.rb +73 -0
- data/plugins/hudson/config.rb +41 -0
- data/plugins/hudson/fetcher.rb +40 -0
- data/plugins/hudson/reporter.rb +104 -0
- data/plugins/hudson/test_run.rb +88 -0
- data/plugins/issues.rb +161 -0
- data/plugins/joke.rb +32 -0
- data/plugins/links.rb +42 -0
- data/plugins/links/link.rb +68 -0
- data/plugins/service.rb +11 -0
- data/plugins/update.rb +79 -0
- data/plugins/whisper.rb +70 -0
- data/spec/fixtures/hudson/console.log +37 -0
- data/spec/helpers/bot_context.rb +5 -0
- data/spec/october/environment_spec.rb +28 -0
- data/spec/plugins/hudson/reporter_spec.rb +27 -0
- data/spec/plugins/hudson/test_run_spec.rb +17 -0
- data/spec/plugins/hudson_spec.rb +44 -0
- data/spec/plugins/issues_spec.rb +26 -0
- data/spec/plugins/links_spec.rb +16 -0
- data/spec/plugins/whisper_spec.rb +6 -0
- data/spec/spec_helper.rb +13 -0
- metadata +185 -0
data/Gemfile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
gem 'cinch'
|
4
|
+
|
5
|
+
gem 'rake', :require => false
|
6
|
+
gem 'activesupport', :require => 'active_support/core_ext'
|
7
|
+
gem 'i18n'
|
8
|
+
|
9
|
+
# debugging
|
10
|
+
group :development do
|
11
|
+
gem 'pry'
|
12
|
+
gem 'pry-nav'
|
13
|
+
gem 'awesome_print'
|
14
|
+
end
|
15
|
+
|
16
|
+
# Redis stuff
|
17
|
+
gem 'redis'
|
18
|
+
gem 'hiredis'
|
19
|
+
gem 'redis-namespace'
|
20
|
+
gem 'redis-objects', :require => 'redis/objects'
|
21
|
+
|
22
|
+
# http stuff
|
23
|
+
gem 'typhoeus'
|
24
|
+
|
25
|
+
# issues stuff - https://github.com/peter-murach/github/
|
26
|
+
gem 'github_api'
|
27
|
+
|
28
|
+
gem 'json'
|
29
|
+
gem 'nokogiri'
|
30
|
+
gem 'curb'
|
31
|
+
|
32
|
+
group :test do
|
33
|
+
gem 'rspec'
|
34
|
+
gem 'fakefs', :require => 'fakefs/safe'
|
35
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# October
|
2
|
+
[![Build Status](https://secure.travis-ci.org/mikz/october.png)](http://travis-ci.org/#!/mikz/october)
|
3
|
+
|
4
|
+
IRC bot build on [Cinch framework](https://github.com/cinchrb/cinch) with some additional stuff like persistence layer od configuration in yml.
|
5
|
+
|
6
|
+
## Plugins
|
7
|
+
|
8
|
+
October provides some sugar for regular Cinch plugins such as redis persistence and help command.
|
9
|
+
|
10
|
+
|
11
|
+
## TODO
|
12
|
+
|
13
|
+
* Spec
|
14
|
+
* Moar features!
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
namespace :gem do
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
end
|
4
|
+
|
5
|
+
task :integrate do |task|
|
6
|
+
ENV['OCTOBER_ENV'] ||= 'test'
|
7
|
+
exec 'rspec spec'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :environment, :env do |task, args|
|
11
|
+
ENV['OCTOBER_ENV'] ||= args[:env]
|
12
|
+
|
13
|
+
$:.unshift File.dirname(__FILE__)
|
14
|
+
|
15
|
+
require 'boot'
|
16
|
+
require 'october'
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
task :boot, [:env, :console] => :environment do |task, args|
|
21
|
+
@bot = October::Base.new
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Starts IRC server'
|
25
|
+
task :start, [:env, :console] => :boot do |task, args|
|
26
|
+
if args[:console]
|
27
|
+
Cinch::IRC.send :include, October::Debugger
|
28
|
+
end
|
29
|
+
|
30
|
+
@bot.start
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Creates interactive console with Pry'
|
34
|
+
task :console, [:env] => :boot do |task, args|
|
35
|
+
@bot.pry
|
36
|
+
end
|
37
|
+
|
38
|
+
#task :default => :start
|
data/bin/october
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
root = File.expand_path("..", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
# this could be just 'october/daemon' when october will be rubygem
|
6
|
+
require File.expand_path(File.join('lib', 'october', 'watchdog'), root)
|
7
|
+
|
8
|
+
October::Watchdog.new(root, ARGV.shift).loop!
|
data/boot.rb
ADDED
data/lib/october.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
module October
|
4
|
+
autoload :Config, 'october/config'
|
5
|
+
autoload :Base, 'october/base'
|
6
|
+
autoload :Environment, 'october/environment'
|
7
|
+
autoload :Redis, 'october/redis'
|
8
|
+
autoload :Debugger, 'october/debugger'
|
9
|
+
autoload :Plugins, 'october/plugins'
|
10
|
+
autoload :Plugin, 'october/plugin'
|
11
|
+
|
12
|
+
def self.root
|
13
|
+
Pathname.new('.').expand_path
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
data/lib/october/base.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cinch'
|
2
|
+
|
3
|
+
module October
|
4
|
+
class Base < Cinch::Bot
|
5
|
+
|
6
|
+
def self.start
|
7
|
+
new.start
|
8
|
+
end
|
9
|
+
|
10
|
+
include Config
|
11
|
+
include Redis
|
12
|
+
include Plugins.initialize
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super do
|
16
|
+
load_config!
|
17
|
+
|
18
|
+
on :message, "hello" do |m|
|
19
|
+
m.reply "Hello, #{m.user.nick}"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module October
|
2
|
+
module Config
|
3
|
+
extend Environment
|
4
|
+
def load_config!
|
5
|
+
env = Config.configuration('irc.yml')
|
6
|
+
return unless env.present?
|
7
|
+
|
8
|
+
env.each_pair do |key, value|
|
9
|
+
# FIXME: make DRY
|
10
|
+
# FIXME: only one level - bad, only to support SSL nested values for now
|
11
|
+
if value.is_a? Hash
|
12
|
+
subconfig = config.send key.dup
|
13
|
+
value.each_pair do |key, value|
|
14
|
+
subconfig.send key.dup << '=', value
|
15
|
+
end
|
16
|
+
else
|
17
|
+
config.send key.dup << '=', value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
gem 'pry'
|
2
|
+
|
3
|
+
module October
|
4
|
+
module Debugger
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
##
|
7
|
+
# Extends capabilities of Cinch::IRC to
|
8
|
+
# launch debugger after connecting and creating all threads
|
9
|
+
#
|
10
|
+
|
11
|
+
included do
|
12
|
+
|
13
|
+
self.class_eval do
|
14
|
+
if method_defined? :start
|
15
|
+
alias_pry(:start)
|
16
|
+
elsif method_defined? :connect
|
17
|
+
alias_pry(:connect)
|
18
|
+
else
|
19
|
+
raise 'Unsupported version of Cinch'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
module InstanceMethods
|
26
|
+
def init_pry
|
27
|
+
Thread.new do
|
28
|
+
binding.pry
|
29
|
+
Thread.pass
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
def alias_pry(before)
|
37
|
+
class_eval %{
|
38
|
+
|
39
|
+
def #{before}_with_pry
|
40
|
+
init_pry
|
41
|
+
#{before}_without_pry
|
42
|
+
end
|
43
|
+
|
44
|
+
alias_method_chain :#{before}, :pry
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module October
|
2
|
+
module Environment
|
3
|
+
class NoSuchEnvironment < StandardError; end
|
4
|
+
|
5
|
+
def load_configuration(file)
|
6
|
+
config = File.join('config', file)
|
7
|
+
return {} unless File.exists?(config)
|
8
|
+
YAML.load_file( config ).with_indifferent_access
|
9
|
+
end
|
10
|
+
|
11
|
+
def environment
|
12
|
+
ENV['OCTOBER_ENV'].presence || 'default'
|
13
|
+
end
|
14
|
+
|
15
|
+
def configuration(file, env = environment)
|
16
|
+
load_configuration(file)[env.to_sym]
|
17
|
+
end
|
18
|
+
|
19
|
+
def configuration!(file, env = environment)
|
20
|
+
configuration(file, env) or raise NoSuchEnvironment.new("No environment #{env} in file #{file}")
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'cinch'
|
3
|
+
|
4
|
+
module October
|
5
|
+
module Plugin
|
6
|
+
autoload :Help, 'october/plugin/help'
|
7
|
+
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
include Cinch::Plugin
|
12
|
+
extend Help
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def name
|
17
|
+
to_s.underscore
|
18
|
+
end
|
19
|
+
|
20
|
+
def config
|
21
|
+
October::Plugins.config(name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module October
|
2
|
+
module Plugin
|
3
|
+
module Help
|
4
|
+
@@help = {}
|
5
|
+
|
6
|
+
def self.extended(base)
|
7
|
+
end
|
8
|
+
|
9
|
+
def register_help command, description = nil
|
10
|
+
@@help[command] = description
|
11
|
+
end
|
12
|
+
|
13
|
+
def list_help
|
14
|
+
@@help.map do |command, description|
|
15
|
+
[" !", [command, description].compact.join(' - ')].join
|
16
|
+
end.join("\n")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module October
|
2
|
+
class Plugins < Array
|
3
|
+
extend Environment
|
4
|
+
|
5
|
+
attr_reader :loaded
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@loaded = []
|
9
|
+
import Plugins.configuration('plugins.yml')
|
10
|
+
end
|
11
|
+
|
12
|
+
delegate :registered, :configure, :to => :'self.class'
|
13
|
+
|
14
|
+
def import plugins
|
15
|
+
return unless plugins.present?
|
16
|
+
|
17
|
+
plugins = Hash[ plugins.map {|plugin|
|
18
|
+
plugin.respond_to?(:to_a) ? plugin.to_a.flatten(1) : [plugin, {}]
|
19
|
+
}].with_indifferent_access
|
20
|
+
|
21
|
+
names = plugins.keys.map {|name| name.camelize }
|
22
|
+
|
23
|
+
diff = registered.keys & (names - self)
|
24
|
+
push *diff
|
25
|
+
load diff
|
26
|
+
|
27
|
+
self.class.configure(plugins)
|
28
|
+
end
|
29
|
+
|
30
|
+
def imported
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def load new
|
36
|
+
@loaded.push *new.map{ |plugin|
|
37
|
+
require registered[plugin]
|
38
|
+
plugin.constantize
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
module PluginMethods
|
43
|
+
extend ActiveSupport::Concern
|
44
|
+
|
45
|
+
included do
|
46
|
+
attr_reader :plugin_module
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
plugins = Plugins.new
|
51
|
+
super
|
52
|
+
# stupid, really, why so long?
|
53
|
+
self.config.plugins.plugins.push *plugins.loaded
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
class << self
|
59
|
+
|
60
|
+
@@plugins = {}
|
61
|
+
@@configs = {}.with_indifferent_access
|
62
|
+
|
63
|
+
def initialize
|
64
|
+
October.root.join('plugins').
|
65
|
+
each_child(false).
|
66
|
+
each do |file|
|
67
|
+
next unless file.to_s =~ /\.rb$/
|
68
|
+
name = file.basename('.rb').to_s.camelize
|
69
|
+
register name => file
|
70
|
+
end
|
71
|
+
|
72
|
+
PluginMethods
|
73
|
+
end
|
74
|
+
|
75
|
+
def register plugin
|
76
|
+
@@plugins.merge! plugin
|
77
|
+
end
|
78
|
+
|
79
|
+
def config(plugin)
|
80
|
+
@@configs.fetch(plugin, {})
|
81
|
+
end
|
82
|
+
|
83
|
+
def configure(plugin)
|
84
|
+
@@configs.merge! plugin
|
85
|
+
end
|
86
|
+
|
87
|
+
def registered
|
88
|
+
@@plugins
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'hiredis'
|
3
|
+
require 'active_support/core_ext/hash/keys'
|
4
|
+
|
5
|
+
module October
|
6
|
+
module Redis
|
7
|
+
extend Environment
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
return unless config = Redis.configuration('redis.yml')
|
11
|
+
# FIXME: parhaps more options, fetch from redis directly, or pass them all and let redis to handle it?
|
12
|
+
redis = ::Redis.new config.slice :host, :port, :path
|
13
|
+
if config.has_key? :namespace
|
14
|
+
redis = ::Redis::Namespace.new config[:namespace], :redis => redis
|
15
|
+
end
|
16
|
+
redis.incr 'launches'
|
17
|
+
$redis = redis
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|