muzang-plugins 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/muzang-plugins.rb +2 -0
- data/lib/muzang-plugins/.muzang-rubygems.rb.swp +0 -0
- data/lib/muzang-plugins/muzang-eval.rb +46 -41
- data/lib/muzang-plugins/muzang-google.rb +24 -0
- data/lib/muzang-plugins/muzang-grep.rb +107 -0
- data/lib/muzang-plugins/muzang-grep/wrttn_in.rb +28 -0
- data/lib/muzang-plugins/muzang-livereload.rb +16 -12
- data/lib/muzang-plugins/muzang-meme.rb +95 -84
- data/lib/muzang-plugins/muzang-motd.rb +18 -14
- data/lib/muzang-plugins/muzang-nerdpursuit.rb +79 -75
- data/lib/muzang-plugins/muzang-plusone.rb +40 -36
- data/lib/muzang-plugins/muzang-reddit.rb +29 -25
- data/lib/muzang-plugins/muzang-rubygems.rb +73 -55
- data/lib/muzang-plugins/muzang-soupirc.rb +16 -12
- data/lib/muzang-plugins/version.rb +1 -1
- data/muzang-plugins.gemspec +7 -3
- data/spec/livereload_spec.rb +18 -16
- data/spec/meme_spec.rb +59 -31
- data/spec/motd_spec.rb +13 -12
- data/spec/muzang-eval_spec.rb +32 -30
- data/spec/nerdpursuit_spec.rb +56 -54
- data/spec/plusone_spec.rb +43 -41
- data/spec/reddit_spec.rb +34 -32
- data/spec/rubygems_spec.rb +90 -60
- data/spec/soupirc_spec.rb +16 -14
- metadata +125 -27
data/lib/muzang-plugins.rb
CHANGED
|
Binary file
|
|
@@ -1,51 +1,56 @@
|
|
|
1
|
-
module
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
unless args.first =~ /EM|EventMachine/
|
|
24
|
-
Safe::safe(*args, &block)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
1
|
+
module Muzang
|
|
2
|
+
module Plugins
|
|
3
|
+
module Safe; end
|
|
4
|
+
class << Safe
|
|
5
|
+
def safe(code, sandbox=nil)
|
|
6
|
+
error = nil
|
|
7
|
+
|
|
8
|
+
begin
|
|
9
|
+
$-w = nil
|
|
10
|
+
sandbox ||= Object.new.taint
|
|
11
|
+
yield(sandbox) if block_given?
|
|
12
|
+
|
|
13
|
+
$SAFE = 5
|
|
14
|
+
value = eval(code, sandbox.send(:binding))
|
|
15
|
+
result = Marshal.load(Marshal.dump(value))
|
|
16
|
+
rescue Exception => error
|
|
17
|
+
error = Marshal.load(Marshal.dump(error))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
return result, error
|
|
21
|
+
end
|
|
22
|
+
end
|
|
27
23
|
|
|
28
|
-
class Eval
|
|
29
|
-
|
|
24
|
+
class Eval
|
|
25
|
+
include Muzang::Plugins::Helpers
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
def initialize(bot)
|
|
28
|
+
@bot = bot
|
|
29
|
+
end
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
def call(connection, message)
|
|
32
|
+
on_channel(message) do
|
|
33
|
+
match(message, /^\% (.*)/) do |match|
|
|
34
|
+
operation = proc do
|
|
35
|
+
safe(match[1])
|
|
36
|
+
end
|
|
37
|
+
callback = proc do |tuple|
|
|
38
|
+
result, error = tuple
|
|
39
|
+
connection.msg(message.channel, "#{result}") if result
|
|
40
|
+
connection.msg(message.channel, "Error: #{error}") if error
|
|
41
|
+
end
|
|
42
|
+
EM.defer(operation, callback)
|
|
43
|
+
end
|
|
40
44
|
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def safe(*args, &block)
|
|
48
|
+
unless args.first =~ /EM|EventMachine/
|
|
49
|
+
Safe::safe(*args, &block)
|
|
45
50
|
end
|
|
46
|
-
EM.defer(operation, callback)
|
|
47
51
|
end
|
|
48
52
|
end
|
|
49
53
|
end
|
|
50
54
|
end
|
|
51
55
|
|
|
56
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Muzang
|
|
2
|
+
module Plugins
|
|
3
|
+
class Google
|
|
4
|
+
include Muzang::Plugins::Helpers
|
|
5
|
+
|
|
6
|
+
def initialize(bot)
|
|
7
|
+
@bot = bot
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(connection, message)
|
|
11
|
+
on_channel(message) do
|
|
12
|
+
message.message.match(/^(!|@)google (.*?)$/) do |m|
|
|
13
|
+
http = EventMachine::HttpRequest.new("http://ajax.googleapis.com/ajax/services/search/web").get :query => { :v => "1.0", :q => m[2] }
|
|
14
|
+
http.callback {
|
|
15
|
+
results = JSON.parse(http.response)
|
|
16
|
+
result = results["responseData"]["results"].first
|
|
17
|
+
connection.msg(message.channel, "#{result["url"]} | #{result["titleNoFormatting"]}")
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require 'sqlite3'
|
|
2
|
+
require 'active_record'
|
|
3
|
+
require 'muzang-plugins/muzang-grep/wrttn_in'
|
|
4
|
+
|
|
5
|
+
module Muzang
|
|
6
|
+
module Plugins
|
|
7
|
+
class Grep
|
|
8
|
+
include Muzang::Plugins::Helpers
|
|
9
|
+
|
|
10
|
+
DATABASE_FILE = 'irclog.sqlite3'
|
|
11
|
+
DATABASE_CONFIG = {
|
|
12
|
+
:database => 'irclog.sqlite3',
|
|
13
|
+
:encoding => 'utf8',
|
|
14
|
+
:adapter => 'sqlite3'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class Message < ActiveRecord::Base
|
|
18
|
+
def self.like(channel, term)
|
|
19
|
+
find(:all, :conditions => ['channel LIKE ? AND content MATCH ?' , channel, term], :order => 'created_at DESC', :limit => 20)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_text
|
|
23
|
+
["### #{user} @ #{created_at}:", "> #{content}", ''].join("\n")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Migration < ActiveRecord::Migration
|
|
27
|
+
def self.up
|
|
28
|
+
execute(%q{
|
|
29
|
+
CREATE VIRTUAL TABLE messages USING fts4(
|
|
30
|
+
channel VARCHAR(255) NOT NULL,
|
|
31
|
+
user VARCHAR(255) NOT NULL,
|
|
32
|
+
content VARCHAR(2048) NOT NULL,
|
|
33
|
+
created_at DATETIME NOT NULL);
|
|
34
|
+
})
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.down
|
|
38
|
+
drop_table :messages
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def initialize(bot)
|
|
44
|
+
@bot = bot
|
|
45
|
+
open_database
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def call(connection, message)
|
|
49
|
+
on_channel(message) do
|
|
50
|
+
match(message, /^[^~(Searched)]/) do
|
|
51
|
+
persist_message(message)
|
|
52
|
+
end
|
|
53
|
+
match(message, /^~ (.*)/) do |what|
|
|
54
|
+
search_for_term(connection, message, what[1])
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
rescue
|
|
58
|
+
puts $!
|
|
59
|
+
puts $!.backtrace
|
|
60
|
+
raise
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def persist_message(message)
|
|
64
|
+
Message.create!(:channel => message.channel,
|
|
65
|
+
:user => message.user,
|
|
66
|
+
:content => message.message)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def search_for_term(connection, message, term)
|
|
70
|
+
results = Message.like(message.channel, term)
|
|
71
|
+
if results.size > 0
|
|
72
|
+
link = save_results(term, results)
|
|
73
|
+
connection.msg(message.channel, "Searched for '#{term}', found #{results.size} matches: #{link}")
|
|
74
|
+
else
|
|
75
|
+
connection.msg(message.channel, "Searched for '#{term}', nothing found")
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
def open_database
|
|
81
|
+
initialize_database unless database_exists?
|
|
82
|
+
open_existing_database
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def database_exists?
|
|
86
|
+
File.exists?(DATABASE_FILE)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def initialize_database
|
|
90
|
+
ActiveRecord::Base.establish_connection(DATABASE_CONFIG)
|
|
91
|
+
Message::Migration.up
|
|
92
|
+
ActiveRecord::Base.connection.disconnect!
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def open_existing_database
|
|
96
|
+
ActiveRecord::Base.establish_connection(DATABASE_CONFIG)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def save_results(term, results)
|
|
100
|
+
content = ["Searched for '#{term}', found #{results.size} matches", '']
|
|
101
|
+
content += results.map(&:to_text)
|
|
102
|
+
content = content.join("\n")
|
|
103
|
+
WrttnIn.create(content).public_url
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
|
|
3
|
+
class WrttnIn
|
|
4
|
+
attr_reader :public_url, :content
|
|
5
|
+
|
|
6
|
+
def self.create(content, markup = :markdown)
|
|
7
|
+
post_data = {
|
|
8
|
+
:content => content,
|
|
9
|
+
:parser => markup
|
|
10
|
+
}
|
|
11
|
+
response = Net::HTTP.post_form(URI.parse('http://wrttn.in/create'), post_data)
|
|
12
|
+
if response.kind_of?(Net::HTTPRedirection)
|
|
13
|
+
response_body = Net::HTTP.get(URI.join('http://wrttn.in', response['Location']))
|
|
14
|
+
if id = response_body.match(/<a href="\/(.*)" class="lab" target="_blank">public url<\/a>/)[1]
|
|
15
|
+
self.new(id, content)
|
|
16
|
+
else
|
|
17
|
+
raise "Couldn't parse the response"
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
raise "Couldn't create a post"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def initialize(id, content)
|
|
25
|
+
@public_url = "http://wrttn.in/#{id}"
|
|
26
|
+
@content = content
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
module Muzang
|
|
2
|
+
module Plugins
|
|
3
|
+
class LiveReload
|
|
4
|
+
include Muzang::Plugins::Helpers
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
def initialize(bot)
|
|
7
|
+
@bot = bot
|
|
8
|
+
end
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
def call(connection, message)
|
|
11
|
+
on_channel(message) do
|
|
12
|
+
match(message, /^!reload$/) do
|
|
13
|
+
@bot.plugins.each do |plugin, instance|
|
|
14
|
+
Kernel.load("muzang-plugins/muzang-#{plugin.to_s.split("::").last.downcase}.rb")
|
|
15
|
+
instance = plugin.new(@bot)
|
|
16
|
+
connection.msg(message.channel, "Reloading: #{plugin}")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
15
19
|
end
|
|
16
20
|
end
|
|
17
21
|
end
|
|
@@ -3,99 +3,110 @@ require "json"
|
|
|
3
3
|
require "memetron"
|
|
4
4
|
require "soup-client"
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
module Muzang
|
|
7
|
+
module Plugins
|
|
8
|
+
class Meme
|
|
9
|
+
include Muzang::Plugins::Helpers
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
MEMES = {
|
|
12
|
+
dos_equis: { image_id: 2485, generator: 74 },
|
|
13
|
+
y_u_no?: { image_id: 166088, generator: 2 },
|
|
14
|
+
bear_grylls: { image_id: 89714, generator: 92 },
|
|
15
|
+
fry: { image_id: 84688, generator: 305 },
|
|
16
|
+
orly: { image_id: 117049, generator: 920 },
|
|
17
|
+
all: { image_id: 1121885, generator: 6013 },
|
|
18
|
+
obama: { image_id: 2154021, generator: 372781 }
|
|
19
|
+
}
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def call(connection, message)
|
|
26
|
-
message.message.match(/^meme$/) do
|
|
27
|
-
connection.msg("#{@bot.channels.first}", "Type 'meme [name of meme] \"Text0\" \"Text1\"'")
|
|
28
|
-
connection.msg("#{@bot.channels.first}", "Available memes: #{MEMES.keys.join(" ")}")
|
|
29
|
-
end
|
|
30
|
-
message.message.match(/^meme (.*?) "(.*?)"( "(.*?)")?$/) do |m|
|
|
31
|
-
if meme_ids = MEMES[m[1].to_sym]
|
|
32
|
-
@generator = meme_ids[:generator]
|
|
33
|
-
@image_id = meme_ids[:image_id]
|
|
34
|
-
else
|
|
35
|
-
return nil
|
|
21
|
+
def initialize(bot)
|
|
22
|
+
@bot = bot
|
|
23
|
+
@matcher = Memetron::Matcher.new
|
|
24
|
+
@soup = File.open(ENV["HOME"] + "/.muzang/" + "soup").read.split(":") rescue nil
|
|
36
25
|
end
|
|
37
26
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
on_channel(message) do
|
|
45
|
-
if meme = @matcher.match_and_parse(message.message)
|
|
46
|
-
@generator = MEMES[meme.first][:generator]
|
|
47
|
-
@image_id = MEMES[meme.first][:image_id]
|
|
48
|
-
|
|
49
|
-
case meme.first
|
|
50
|
-
when :dos_equis
|
|
51
|
-
@text0 = "I don't always #{meme[1][0]}"
|
|
52
|
-
@text1 = "but when I do #{meme[1][1]}"
|
|
53
|
-
when :y_u_no?
|
|
54
|
-
@text0 = meme[1][0] + " Y U NO"
|
|
55
|
-
@text1 = meme[1][1]
|
|
56
|
-
when :bear_grylls
|
|
57
|
-
@text0 = meme[1][0]
|
|
58
|
-
@text1 = "better drink my own piss"
|
|
59
|
-
when :fry
|
|
60
|
-
@text0 = "not sure if #{meme[1][1]}"
|
|
61
|
-
@text1 = "or #{meme[1][2]}"
|
|
62
|
-
when :orly
|
|
63
|
-
@text0 = meme[1][0]
|
|
64
|
-
@text1 = "ORLY?"
|
|
65
|
-
when :all
|
|
66
|
-
@text0 = meme[1][0]
|
|
67
|
-
@text1 = "all the things!"
|
|
68
|
-
when :obama
|
|
69
|
-
@text0 = meme[1][0]
|
|
70
|
-
@text1 = "not bad"
|
|
71
|
-
else
|
|
72
|
-
@text0 = meme[1][0]
|
|
73
|
-
@text1 = meme[1][1]
|
|
27
|
+
def call(connection, message)
|
|
28
|
+
message.message.match(/^meme$/) do
|
|
29
|
+
connection.msg("#{@bot.channels.first}", "Type 'meme [name of meme] \"Text0\" \"Text1\"'")
|
|
30
|
+
connection.msg("#{@bot.channels.first}", "Available memes: #{MEMES.keys.join(" ")}")
|
|
74
31
|
end
|
|
32
|
+
message.message.match(/^meme (.*?) "(.*?)"( "(.*?)")?$/) do |m|
|
|
33
|
+
if meme_ids = MEMES[m[1].to_sym]
|
|
34
|
+
@generator = meme_ids[:generator]
|
|
35
|
+
@image_id = meme_ids[:image_id]
|
|
36
|
+
else
|
|
37
|
+
return nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
@text0 = m[2]
|
|
41
|
+
@text1 = m[4]
|
|
42
|
+
|
|
75
43
|
create_instance(connection)
|
|
76
44
|
end
|
|
77
|
-
|
|
78
|
-
|
|
45
|
+
|
|
46
|
+
on_channel(message) do
|
|
47
|
+
if meme = @matcher.match_and_parse(message.message)
|
|
48
|
+
@generator = MEMES[meme.first][:generator]
|
|
49
|
+
@image_id = MEMES[meme.first][:image_id]
|
|
50
|
+
|
|
51
|
+
case meme.first
|
|
52
|
+
when :dos_equis
|
|
53
|
+
@text0 = "I don't always #{meme[1][0]}"
|
|
54
|
+
@text1 = "but when I do #{meme[1][1]}"
|
|
55
|
+
when :y_u_no?
|
|
56
|
+
@text0 = meme[1][0] + "Y U NO"
|
|
57
|
+
@text1 = meme[1][1]
|
|
58
|
+
when :bear_grylls
|
|
59
|
+
@text0 = meme[1][0]
|
|
60
|
+
@text1 = "better drink my own piss"
|
|
61
|
+
when :fry
|
|
62
|
+
@text0 = "not sure if #{meme[1][1]}"
|
|
63
|
+
@text1 = "or #{meme[1][2]}"
|
|
64
|
+
when :orly
|
|
65
|
+
@text0 = meme[1][0]
|
|
66
|
+
@text1 = "ORLY?"
|
|
67
|
+
when :all
|
|
68
|
+
@text0 = meme[1][0]
|
|
69
|
+
@text1 = "all the things!"
|
|
70
|
+
when :obama
|
|
71
|
+
@text0 = meme[1][0]
|
|
72
|
+
@text1 = "not bad"
|
|
73
|
+
else
|
|
74
|
+
@text0 = meme[1][0]
|
|
75
|
+
@text1 = meme[1][1]
|
|
76
|
+
end
|
|
77
|
+
create_instance(connection)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
79
81
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
def create_instance(connection)
|
|
83
|
+
http = EventMachine::HttpRequest.new('http://version1.api.memegenerator.net/Instance_Create')
|
|
84
|
+
.get(:query => {:username => 'drug-bot',
|
|
85
|
+
:password => 'drug-bot',
|
|
86
|
+
:languageCode => 'en',
|
|
87
|
+
:generatorID => @generator,
|
|
88
|
+
:imageID => @image_id,
|
|
89
|
+
:text0 => @text0,
|
|
90
|
+
:text1 => @text1})
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
http.callback {
|
|
93
|
+
meme = JSON.parse(http.response)
|
|
94
|
+
instance = meme['result']['instanceImageUrl']
|
|
95
|
+
|
|
96
|
+
if instance.include?("images")
|
|
97
|
+
url = instance
|
|
98
|
+
else
|
|
99
|
+
url = "http://iversion1.api.memegenerator.net#{instance}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
connection.msg("#{@bot.channels.first}", "Meme: #{url}")
|
|
103
|
+
if @soup
|
|
104
|
+
soup = Soup::Client.new(@soup.first, @soup.last.chomp)
|
|
105
|
+
soup.login
|
|
106
|
+
soup.new_image(url)
|
|
107
|
+
end
|
|
108
|
+
}
|
|
98
109
|
end
|
|
99
|
-
|
|
110
|
+
end
|
|
100
111
|
end
|
|
101
112
|
end
|