This Ruby script is based on the code from
Build your own Twitter 'track' feature [dzone.com] but now the latest entry can be tracked for any RSS or Atom feed.
1
2
3
4
5 require 'rubygems'
6 require 'open-uri'
7 require 'xmpp4r-simple'
8 require 'rexml/document'
9 include REXML
10
11 URL_BASE = 'http://yourwebsite.com/sqlite3/'
12 messenger = Jabber::Simple.new('jeeves3@jamesrobertson.eu', "passwordsecret")
13 $file = ''
14
15 class String
16 def escape()
17 URI.escape(self).gsub(/\?/,'%3F')
18 end
19 end
20
21 def get_title(url)
22
23 title = ''
24 buffer = open(url, "UserAgent" => "Ruby-RSS2IMbot").read
25
26 doc = Document.new(buffer)
27
28 node_title = doc.root.elements['channel/title|title']
29 puts 'title : ' + node_title.to_s
30 unless node_title.nil?
31 title = node_title.text.to_s
32 end
33 title
34 end
35
36
37 def check_feed(messenger)
38 result = false
39 puts 'check feed'
40 buddy = 'james@jamesrobertson.eu'
41
42 url = URL_BASE + "select/rss2imbot.db/t1/column=*"
43 buffer = open(url, "UserAgent" => "Ruby-RSS2IMbot").read
44 doc = Document.new(buffer)
45 rows = doc.root.elements['rows']
46 puts 'rows : ' + rows.to_s
47 unless rows.nil?
48 result = rows.elements.each('row'){}.map do |node|
49
50
51 rss_title = node.elements["col[@name='title']"].text.to_s
52 old_item_title = node.elements["col[@name='item_title']"].text.to_s
53 id = node.elements["col[@name='t1key']"].text.to_s
54 rss_link = node.elements["col[@name='link']"].text.to_s
55
56
57 new_item_title, link = get_item_title(rss_link)
58
59 if new_item_title != old_item_title then
60
61
62 result = update_feed(id, new_item_title)
63 messenger.deliver(buddy, '"' + new_item_title + '" ' + link)
64 end
65
66 end
67 end
68 end
69
70
71 def update_feed(id, item_title)
72 result = false
73
74 url = URL_BASE + "update/rss2imbot.db/t1/set-column=item_title:#{item_title.escape}&t1key=#{id}"
75 buffer = open(url, "UserAgent" => "Ruby-RSS2IMbot").read
76 doc = Document.new(buffer)
77 node_result = doc.root.attribute('method')
78 result = true unless node_result.nil?
79 result
80 end
81
82 def get_item_title(url)
83
84 title = ''
85 buffer = open(url, "UserAgent" => "Ruby-RSS2IMbot").read
86
87 doc = Document.new(buffer)
88
89 node_title = doc.root.elements['channel/item/title|entry/title']
90 unless node_title.nil?
91 title = node_title.text.to_s
92 node_link = doc.root.elements['channel/item/link|entry/link']
93 unless node_link.nil?
94 unless node_link.text.to_s.empty? then
95 link = node_link.text.to_s
96 else
97 link = node_link.attribute('href').to_s
98 end
99 end
100 end
101 return title, link
102 end
103
104 def action_msg(messenger, buddy, message)
105
106 action = message[/^(\w+)(\s+)?(.*)?/,1]
107
108 case action
109 when 'add'
110 rss_feed = $3
111 if rss_feed.match(/^http:\/\/.*$/) then
112 title = get_title(rss_feed)
113 add_feed(title,rss_feed)
114 else
115 messenger.deliver(buddy, "That web feed isn't valid'")
116 end
117
118 when 'list'
119 url = URL_BASE + "select/rss2imbot.db/t1/column=*"
120 buffer = open(url,"UserAgent" => "Ruby-IMBot").read
121 doc = Document.new(buffer)
122 rows = doc.root.elements['rows']
123 unless rows.nil?
124 result = rows.elements.each('row'){}.map do |node|
125 node.attribute('id').to_s + '. ' + node.elements["col[@name='title']"].text.to_s
126 end
127 messenger.deliver(buddy, result.inspect)
128 end
129
130 when 'remove'
131 id = $3
132
133 url = URL_BASE + 'select/rss2imbot.db/t1/column=title&t1key=1'
134 buffer = open(url,"UserAgent" => "Ruby-IMBot").read
135 doc = Document.new(buffer)
136 node_col = doc.root.elements['rows/row/col']
137 unless node_col.nil?
138
139 title = node_col.text.to_s
140 messenger.deliver(buddy, 'remove \'' + title + '\' (y/n)')
141 elapsed = 0
142 start_time = Time.now
143 answered = false
144 response = ''
145
146 while (elapsed < 30 and not answered == true)
147 messenger.received_messages do |msg|
148 puts msg.body
149 if msg.body.match(/^(y|n)$/) then
150 response = msg.body
151 answered = true
152 end
153 end
154 elapsed = Time.now - start_time
155 end
156 messenger.deliver(buddy, 'you took too long to answer, I\'m *not* removing any feed now!') if elapsed >= 30
157 if response == 'y' then
158 messenger.deliver(buddy, ' will now remove ' + title)
159 url = URL_BASE + "delete/rss2imbot.db/t1/t1key=#{id}"
160 result_buffer = open(url,"UserAgent" => "Ruby-IMBot").read
161 doc_result = Document.new(result_buffer)
162 node_result = doc_result.root.attribute('method')
163 messenger.deliver(buddy, '\'' + title + '\' has been removed.') unless node_result.nil?
164 end
165 end
166
167 when 'help'
168 messenger.deliver(buddy, "Help: 'add' a feed, 'list' all feeds, or 'remove' a feed.")
169 else
170 puts 'sorry I don\'t know how to process that. Type \'help\' for a list of commands.'
171 end
172 end
173
174 def add_feed(title, link)
175 result = false
176
177 puts "insert/rss2imbot.db/t1/title=#{title.escape}&link=#{link.escape}"
178 url = URL_BASE + "insert/rss2imbot.db/t1/title=#{title.escape}&link=#{link.escape}"
179 buffer = open(url, "UserAgent" => "Ruby-RSS2IMbot").read
180 doc = Document.new(buffer)
181 node_result = doc.root.attribute('method')
182 result = true unless node_result.nil?
183 result
184 end
185
186
187 while true
188
189
190 check_feed(messenger) if Time.now.strftime("%S").to_i <= 3
191 messenger.received_messages do |msg|
192
193 message = URI.unescape(msg.body).gsub(/</,'<').gsub(/>/,'>').gsub(/'/,'\'').gsub(/"/,'"').gsub(/&/,'&')
194 buddy = msg.from
195
196 messenger.deliver(buddy, "you said ... " + message)
197 action_msg(messenger,buddy, message)
198
199 end
200 sleep 2
201 end
test:
[01:20:38] jeeves3 is now Available (Available)
[01:20:41] James: list
[01:20:42] jeeves3: you said ... list
[01:20:43] jeeves3: ["1. ruby - Twitter Search"]
[01:21:04] jeeves3: "babysitting Ruby while the missus gets some accupuncture.. now covered in vomit too - thanks Ruby!" http://twitter.com/gregdwyer/statuses/922733451
[01:21:39] James: add http://snippets.dzone.com/rss
[01:21:41] jeeves3: you said ... add http://snippets.dzone.com/rss
[01:22:16] jeeves3: "Test" http://feeds.dzone.com/~r/dzone/snippets/~3/393549326/6080
[01:22:20] James: list
[01:22:20] jeeves3: you said ... list
[01:22:21] jeeves3: ["1. ruby - Twitter Search", "2. DZone Snippets: Store, sort and share source code, with tag goodness"]
[01:22:49] James: remove 1
[01:22:49] jeeves3: you said ... remove 1
[01:22:51] jeeves3: remove 'ruby - Twitter Search' (y/n)
[01:22:53] James: y
[01:22:53] jeeves3: will now remove ruby - Twitter Search
[01:22:54] jeeves3: 'ruby - Twitter Search' has been removed.
[01:22:57] James: list
[01:22:58] jeeves3: you said ... list
[01:23:00] jeeves3: ["1. DZone Snippets: Store, sort and share source code, with tag goodness"]