-
Notifications
You must be signed in to change notification settings - Fork 2
/
collecta_bot.rb
150 lines (128 loc) · 4.4 KB
/
collecta_bot.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
require 'collecta'
require 'xmpp4r-simple'
require 'eventmachine'
#Jabber::debug = true
class Jabber::Simple
def subscribed_to?(x); true; end
def ask_for_auth(x); contacts(x).ask_for_authorization!; end
end
module Collecta
class Task
include EM::Deferrable
def do_subscribe(settings)
begin
if !settings["query"] and !settings["notify"]
raise "need at least one query or notify"
end
Bot.service.subscribe(settings["query"], settings["notify"])
set_deferred_status(:succeeded)
rescue Exception => e
puts e.to_s if settings["debug"]
set_deferred_status(:failed)
end
end
def do_unsubscribe(settings)
begin
Bot.service.unsubscribe
set_deferred_status(:succeeded)
rescue Exception => e
puts e.to_s if settings["debug"]
set_deferred_status(:failed)
end
end
end # class
class Bot
def self.announce(subscribers, messages)
return unless Bot.client
Array(subscribers).each do |to|
Array(messages).each do |body|
Bot.client.deliver(to, body)
end
end
end
def self.client
@@socket
end
def self.service
@@search
end
# redefine this function in your bots
def self.format_result(msg, debug = true)
begin
return msg unless payload = Collecta::Payload.new(msg)
return msg if payload.type == :unknown
return "[#{payload.meta}] #{payload.category}: #{payload.title}"
rescue Exception => e
puts "[E] #{e.to_s}" if debug
end
end
def self.run(config_fname)
settings = YAML.load(File.read(config_fname))
@@socket = Jabber::Simple.new(settings["bot.jid"], settings["bot.password"])
@@socket.accept_subscriptions = true
@@search = Collecta::Client.new(settings["collecta.apikey"])
@@search.anonymous_connect
puts "Connected: #{@@search.jid.to_s}" if settings["debug"]
Bot.service.add_message_callback do |msg|
puts "M: #{msg.inspect}" if settings["debug"]
Bot.client.deliver(settings["bot.console"], self.format_result(msg, settings["debug"]))
end
at_exit do
Bot.service.unsubscribe
Bot.client.disconnect
end
EM.epoll
EM.run do
EM::PeriodicTimer.new(0.05) do
Bot.client.received_messages do |msg|
from = msg.from.strip.to_s
next unless (msg.type == :chat and not msg.body.empty?)
cmdline = msg.body.split
case cmdline[0]
when "HELP", "H", "help", "H", "h", "?":
# TODO better help
help = "HELP (H), PING (P)"
help += ", S, N, UN" if from == settings["bot.console"]
Bot.client.deliver(from, help)
when "PING", "ping", "Ping", "P", "p":
Bot.client.ask_for_auth(msg.from)
Bot.client.deliver(from, "PONG ;)")
# Subscribe to query or notify
when "S", "s", "N", "n"
next unless (from == settings["bot.console"] and cmdline[1])
EM.spawn do
# TODO validate the query
type = (cmdline[0].downcase == "s") ? "query" : "notify"
settings[type] = msg.body.slice(2, msg.body.length)
task = Task.new
task.callback {
puts "Subscribed to #{type}: #{settings[type]}" if settings["debug"]
Bot.client.deliver(from, "Subscribed to #{type}: #{settings[type]}")
}
task.errback { Bot.client.deliver(from, "Subscription failed") }
task.do_subscribe(settings)
end.notify
# UnSubscribe
when "UN", "un", "U", "u"
next unless from == settings["bot.console"]
EM.spawn do
task = Task.new
task.callback { Bot.client.deliver(from, "Unsubscribed from all searches") }
task.errback { Bot.client.deliver(from, "Unsubscribe failed") }
task.do_unsubscribe(settings)
end.notify
end # case
end
end # EM::Timer
end # EM.run
end # Bot::run
end # Bot
end # module
if __FILE__ == $0
# register a handler for SIGINTs
trap(:INT) do
EM.stop
exit
end
Collecta::Bot.run("config.yml")
end