blackwinter-twitter2jabber 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  == VERSION
4
4
 
5
- This documentation refers to twitter2jabber version 0.1.6
5
+ This documentation refers to twitter2jabber version 0.2.0
6
6
 
7
7
 
8
8
  == DESCRIPTION
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! (friends_timeline: since/since_id?)
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.loop(recipients, options[:pause] || config[:pause])
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
@@ -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 = [], seen = {}, flag = true, &block)
90
- deliver_tweets(recipients, seen, &block) if flag
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, seen = 1, Hash.new { |h, k| h[k] = true; false }
102
+ i = 1
98
103
 
99
104
  trap(:INT) {
100
- log 'SIGINT received, shutting down...'
105
+ logm 'SIGINT received, shutting down...'
101
106
  i = -1
102
107
  }
103
108
 
104
109
  while i > 0
105
- run(recipients, seen, i % pause == 1, &block)
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
- log 'KTHXBYE!'
113
- end
117
+ logm 'KTHXBYE!'
114
118
 
115
- def deliver_tweets(recipients, seen = {}, &block)
116
- get_tweets.each { |tweet|
117
- next if seen[tweet.id]
119
+ last
120
+ end
118
121
 
119
- logt tweet.id
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
- tweets = twitter.friends_timeline
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(/(?=\A|\W)@(\w+)/, '@<a href="http://twitter.com/\1">\1</a>').
226
- gsub(/(?=\A|\W)#(\w+)/, '<a href="http://search.twitter.com/search?q=%23\1">#\1</a>')
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 log(msg, verbose = verbose)
345
- warn "#{Time.now} [#{id}] #{msg}" if verbose
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
- log("TWITTER #{msg}", verbose)
363
+ logm("TWITTER #{msg}", verbose)
350
364
  end
351
365
 
352
366
  def logj(msg, verbose = verbose)
353
- log("JABBER #{msg}", verbose)
367
+ logm("JABBER #{msg}", verbose)
354
368
  end
355
369
 
356
370
  end
@@ -3,8 +3,8 @@ class Twitter2Jabber
3
3
  module Version
4
4
 
5
5
  MAJOR = 0
6
- MINOR = 1
7
- TINY = 6
6
+ MINOR = 2
7
+ TINY = 0
8
8
 
9
9
  class << self
10
10
 
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.1.6
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-11 00:00:00 -07:00
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: