blackwinter-twitter2jabber 0.1.6 → 0.2.0
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/README +1 -1
- data/Rakefile +1 -1
- data/TODO +3 -1
- data/bin/twitter2jabber +61 -3
- data/lib/twitter2jabber.rb +39 -25
- data/lib/twitter2jabber/version.rb +2 -2
- metadata +12 -2
data/README
CHANGED
data/Rakefile
CHANGED
@@ -16,7 +16,7 @@ begin
|
|
16
16
|
:homepage => %q{http://twitter2jabber.rubyforge.org/},
|
17
17
|
:files => FileList['lib/**/*.rb', 'bin/*'].to_a,
|
18
18
|
:extra_files => FileList['[A-Z]*', 'sample/**/*'].to_a,
|
19
|
-
:dependencies => %w[twitter xmpp4r-simple highline shorturl longurl]
|
19
|
+
:dependencies => %w[twitter xmpp4r-simple highline shorturl longurl elif]
|
20
20
|
}
|
21
21
|
}}
|
22
22
|
rescue LoadError
|
data/TODO
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
- threading? (decouple Twitter and Jabber event loops)
|
1
2
|
- 'direct message' command
|
2
|
-
- persistent cache
|
3
|
+
- persistent cache? (friends_timeline: since/since_id?)
|
3
4
|
- OAuth (register: http://twitter.com/oauth_clients/new)
|
4
5
|
- better interrupt handling (in loop mode)
|
5
6
|
- daemonize after asking for credentials (in loop mode)
|
6
7
|
- additional commands?
|
8
|
+
- SPECS!!!
|
data/bin/twitter2jabber
CHANGED
@@ -26,6 +26,8 @@
|
|
26
26
|
###############################################################################
|
27
27
|
#++
|
28
28
|
|
29
|
+
$KCODE = 'u' unless RUBY_VERSION >= '1.9'
|
30
|
+
|
29
31
|
require 'optparse'
|
30
32
|
require 'yaml'
|
31
33
|
|
@@ -54,6 +56,9 @@ options = {
|
|
54
56
|
:template_dir => nil,
|
55
57
|
:loop => false,
|
56
58
|
:pause => nil,
|
59
|
+
:last => nil,
|
60
|
+
:wrap => nil,
|
61
|
+
:log => STDERR,
|
57
62
|
:verbose => false,
|
58
63
|
:debug => false
|
59
64
|
}
|
@@ -109,6 +114,19 @@ OptionParser.new { |opts|
|
|
109
114
|
options[:pause] = p
|
110
115
|
}
|
111
116
|
|
117
|
+
opts.separator ' '
|
118
|
+
|
119
|
+
opts.on('-S', '--since-id ID', 'Return tweets with status IDs greater than ID') { |i|
|
120
|
+
options[:last] = i
|
121
|
+
}
|
122
|
+
|
123
|
+
opts.separator ' '
|
124
|
+
|
125
|
+
opts.on('-L', '--loop-wrap [LOG]', "Convenience switch: implies '--loop', '--verbose', and", "'--since-id'; kills existing process and logs output to LOG") { |l|
|
126
|
+
options[:wrap] = true
|
127
|
+
options[:log] = l && File.open(l, 'a')
|
128
|
+
}
|
129
|
+
|
112
130
|
opts.separator ' '
|
113
131
|
opts.separator 'Generic options:'
|
114
132
|
|
@@ -152,17 +170,57 @@ config[:jabber][:pass] ||= ask("Password for Jabber ID #{config[:jabber][:user]}
|
|
152
170
|
recipients = options[:recipients] + (config.delete(:recipients) || [])
|
153
171
|
recipients.uniq!
|
154
172
|
|
155
|
-
[:formats, :template_dir, :verbose, :debug].each { |key|
|
173
|
+
[:formats, :template_dir, :log, :verbose, :debug].each { |key|
|
156
174
|
config[key] = options[key] if options[key]
|
157
175
|
}
|
158
176
|
|
159
177
|
begin
|
178
|
+
if options[:wrap]
|
179
|
+
options[:loop] = true
|
180
|
+
options[:verbose] = true
|
181
|
+
|
182
|
+
case log = config[:log]
|
183
|
+
when String
|
184
|
+
config[:log] = File.open(log, 'a')
|
185
|
+
when File
|
186
|
+
log = log.path
|
187
|
+
when IO
|
188
|
+
abort "Invalid log file: #{log.tty? ? "FILENO=#{log.fileno}" : log}"
|
189
|
+
else
|
190
|
+
abort 'Log file missing!'
|
191
|
+
end
|
192
|
+
|
193
|
+
if File.readable?(log)
|
194
|
+
require 'elif'
|
195
|
+
|
196
|
+
pid = nil
|
197
|
+
|
198
|
+
Elif.foreach(log) { |line|
|
199
|
+
case line
|
200
|
+
when /\A(\d+)\z/
|
201
|
+
pid ||= $1.to_i
|
202
|
+
break if options[:last]
|
203
|
+
when / TWITTER (\d+)\z/
|
204
|
+
options[:last] ||= $1.to_i
|
205
|
+
break if pid
|
206
|
+
end
|
207
|
+
}
|
208
|
+
|
209
|
+
begin
|
210
|
+
Process.kill(:INT, pid)
|
211
|
+
sleep 1
|
212
|
+
rescue Errno::ESRCH
|
213
|
+
end if pid
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
160
217
|
twitter2jabber = Twitter2Jabber.new(config)
|
161
218
|
|
162
219
|
if options[:loop]
|
163
|
-
twitter2jabber.
|
220
|
+
twitter2jabber.send(:log_, Process.pid)
|
221
|
+
twitter2jabber.loop(recipients, options[:pause] || config[:pause], options[:last])
|
164
222
|
else
|
165
|
-
twitter2jabber.run(recipients)
|
223
|
+
twitter2jabber.run(recipients, options[:last])
|
166
224
|
end
|
167
225
|
rescue RuntimeError => err
|
168
226
|
abort err
|
data/lib/twitter2jabber.rb
CHANGED
@@ -48,15 +48,15 @@ class Twitter2Jabber
|
|
48
48
|
JABBER_NS = 'http://jabber.org/protocol/xhtml-im'
|
49
49
|
XHTML_NS = 'http://www.w3.org/1999/xhtml'
|
50
50
|
|
51
|
-
def self.loop(options, recipients = [], pause = nil, &block)
|
52
|
-
new(options).loop(recipients, pause, &block)
|
51
|
+
def self.loop(options, recipients = [], pause = nil, last = nil, &block)
|
52
|
+
new(options).loop(recipients, pause, last, &block)
|
53
53
|
end
|
54
54
|
|
55
|
-
def self.run(options, recipients = [], &block)
|
56
|
-
new(options).run(recipients, &block)
|
55
|
+
def self.run(options, recipients = [], last = nil, &block)
|
56
|
+
new(options).run(recipients, last, &block)
|
57
57
|
end
|
58
58
|
|
59
|
-
attr_reader :id, :verbose, :debug, :twitter, :jabber, :filter, :formats, :templates, :_erb
|
59
|
+
attr_reader :id, :verbose, :debug, :log, :twitter, :jabber, :filter, :formats, :templates, :_erb
|
60
60
|
|
61
61
|
def initialize(options, &block)
|
62
62
|
[:twitter, :jabber].each { |client|
|
@@ -67,6 +67,9 @@ class Twitter2Jabber
|
|
67
67
|
|
68
68
|
@verbose = options[:verbose]
|
69
69
|
@debug = options[:debug]
|
70
|
+
@log = options[:log]
|
71
|
+
|
72
|
+
logm 'HAI!'
|
70
73
|
|
71
74
|
@twitter = twitter_connect(options[:twitter])
|
72
75
|
@jabber = jabber_connect(options[:jabber])
|
@@ -86,37 +89,39 @@ class Twitter2Jabber
|
|
86
89
|
}
|
87
90
|
end
|
88
91
|
|
89
|
-
def run(recipients = [],
|
90
|
-
deliver_tweets(recipients,
|
92
|
+
def run(recipients = [], last = nil, flag = true, &block)
|
93
|
+
last = deliver_tweets(recipients, last, &block) if flag
|
91
94
|
post_messages(recipients)
|
95
|
+
|
96
|
+
last
|
92
97
|
end
|
93
98
|
|
94
|
-
def loop(recipients = [], pause = nil, &block)
|
99
|
+
def loop(recipients = [], pause = nil, last = nil, &block)
|
95
100
|
pause ||= DEFAULT_PAUSE
|
96
101
|
|
97
|
-
i
|
102
|
+
i = 1
|
98
103
|
|
99
104
|
trap(:INT) {
|
100
|
-
|
105
|
+
logm 'SIGINT received, shutting down...'
|
101
106
|
i = -1
|
102
107
|
}
|
103
108
|
|
104
109
|
while i > 0
|
105
|
-
run(recipients,
|
110
|
+
last = run(recipients, last, i % pause == 1, &block)
|
106
111
|
|
107
112
|
sleep 1
|
108
113
|
|
109
114
|
i += 1
|
110
115
|
end
|
111
116
|
|
112
|
-
|
113
|
-
end
|
117
|
+
logm 'KTHXBYE!'
|
114
118
|
|
115
|
-
|
116
|
-
|
117
|
-
next if seen[tweet.id]
|
119
|
+
last
|
120
|
+
end
|
118
121
|
|
119
|
-
|
122
|
+
def deliver_tweets(recipients, last = nil, &block)
|
123
|
+
get_tweets(last).each { |tweet|
|
124
|
+
logt last = tweet.id
|
120
125
|
|
121
126
|
# apply filters
|
122
127
|
next if filter && !filter[tweet]
|
@@ -130,6 +135,8 @@ class Twitter2Jabber
|
|
130
135
|
|
131
136
|
sleep 1
|
132
137
|
}
|
138
|
+
|
139
|
+
last
|
133
140
|
end
|
134
141
|
|
135
142
|
def post_messages(recipients = [])
|
@@ -171,8 +178,11 @@ class Twitter2Jabber
|
|
171
178
|
raise "Can't connect to Jabber with JID '#{options[:user]}': #{err}"
|
172
179
|
end
|
173
180
|
|
174
|
-
def get_tweets
|
175
|
-
|
181
|
+
def get_tweets(last = nil)
|
182
|
+
options = {}
|
183
|
+
options[:since_id] = last if last
|
184
|
+
|
185
|
+
tweets = twitter.friends_timeline(options)
|
176
186
|
return [] unless tweets.is_a?(Array)
|
177
187
|
|
178
188
|
tweets.sort_by { |tweet|
|
@@ -222,8 +232,8 @@ class Twitter2Jabber
|
|
222
232
|
end
|
223
233
|
|
224
234
|
def process_html(text)
|
225
|
-
text.gsub(/(
|
226
|
-
gsub(/(
|
235
|
+
text.gsub(/(\A|\W)@(\w+)/, '\1@<a href="http://twitter.com/\2">\2</a>').
|
236
|
+
gsub(/(\A|\W)#(\w+)/, '\1<a href="http://search.twitter.com/search?q=%23\2">#\2</a>')
|
227
237
|
end
|
228
238
|
|
229
239
|
def process_text(text)
|
@@ -341,16 +351,20 @@ le[n[gth]] STATUS -- Determine length
|
|
341
351
|
twitter.update(msg, options)
|
342
352
|
end
|
343
353
|
|
344
|
-
def
|
345
|
-
|
354
|
+
def log_(msg, verbose = verbose)
|
355
|
+
log.puts msg if verbose
|
356
|
+
end
|
357
|
+
|
358
|
+
def logm(msg, verbose = verbose)
|
359
|
+
log_("#{Time.now} [#{id}] #{msg}", verbose)
|
346
360
|
end
|
347
361
|
|
348
362
|
def logt(msg, verbose = verbose)
|
349
|
-
|
363
|
+
logm("TWITTER #{msg}", verbose)
|
350
364
|
end
|
351
365
|
|
352
366
|
def logj(msg, verbose = verbose)
|
353
|
-
|
367
|
+
logm("JABBER #{msg}", verbose)
|
354
368
|
end
|
355
369
|
|
356
370
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blackwinter-twitter2jabber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jens Wille
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-13 00:00:00 -07:00
|
13
13
|
default_executable: twitter2jabber
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -62,6 +62,16 @@ dependencies:
|
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: "0"
|
64
64
|
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: elif
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
65
75
|
description: Twitter-to-Jabber gateway.
|
66
76
|
email: jens.wille@uni-koeln.de
|
67
77
|
executables:
|