friendfeed 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.13
1
+ 0.1.14
data/bin/tw2ff CHANGED
@@ -106,6 +106,12 @@ class FriendFeed::Client
106
106
  }
107
107
  t.unlink
108
108
  end
109
+
110
+ def follow_twitter_user(twitter_name, display_name, picture_url = nil)
111
+ id = create_imaginary_friend(display_name)
112
+ add_twitter(id, twitter_name, 'includeatreplies' => 'on')
113
+ change_picture_to_url(id, picture_url) if picture_url
114
+ end
109
115
  end
110
116
 
111
117
  def friendfeed_client
@@ -131,10 +137,6 @@ class Twitter::Base
131
137
  }
132
138
  list
133
139
  end
134
-
135
- def get_profile(name)
136
- friends(:screen_name => name).first
137
- end
138
140
  end
139
141
 
140
142
  def twitter_client
@@ -175,13 +177,67 @@ EOF
175
177
  system ENV['VISUAL'] || ENV['EDITOR'] || 'vi', ConfigFile()
176
178
  end
177
179
  end
180
+
181
+ mode 'follow' do
182
+ description 'Import a Twitter user to FriendFeed as an "imaginary friend"'
183
+
184
+ option('name-format') {
185
+ description 'A printf format to generate an imaginary friend\'s name from a Twitter name'
186
+
187
+ argument_required
188
+ default '(%s)'
189
+ }
190
+
191
+ argument('names') {
192
+ description 'List of Twitter user names to follow'
193
+ arity -1
194
+ }
195
+
196
+ def run
197
+ name_format = params['name-format'].value
198
+
199
+ names = params['names'].values
200
+
201
+ exit if names.empty?
202
+
203
+ names.each { |name|
204
+ twuser =
205
+ begin
206
+ twitter_client().user(name)
207
+ rescue Twitter::NotFound
208
+ putinfo 'Twitter user not found: %s', name
209
+ next
210
+ rescue => e
211
+ putinfo 'Twitter user not accessible: %s: %s', name, e
212
+ next
213
+ end
214
+
215
+ if !twuser.status
216
+ putinfo 'Twitter user may not be followable: %s', name
217
+ end
218
+
219
+ putinfo 'Creating an imaginary friend for %s', name
220
+ friendfeed_client().follow_twitter_user(name, name_format % name,
221
+ twuser.profile_image_url)
222
+ }
223
+ end
224
+ end
178
225
 
179
226
  mode 'friends' do
180
227
  description 'Import Twitter-only friends to FriendFeed as "imaginary friends"'
181
228
 
229
+ option('name-format') {
230
+ description 'A printf format to generate an imaginary friend\'s name from a Twitter name'
231
+
232
+ argument_required
233
+ default '(%s)'
234
+ }
235
+
182
236
  def run
183
237
  require 'set'
184
238
 
239
+ name_format = params['name-format'].value
240
+
185
241
  ffcli = friendfeed_client()
186
242
 
187
243
  subscribed_real = Set[]
@@ -258,12 +314,8 @@ EOF
258
314
 
259
315
  to_subscribe.each { |name|
260
316
  putinfo 'Creating an imaginary friend for %s', name
261
- id = ffcli.create_imaginary_friend('(%s)' % name)
262
- ffcli.add_twitter(id, name)
263
- if url = picture_urls[name]
264
- putinfo 'Setting the picture of %s', name
265
- ffcli.change_picture_to_url(id, url)
266
- end
317
+ friendfeed_client().follow_twitter_user(name, name_format % name,
318
+ picture_urls[name])
267
319
  }
268
320
 
269
321
  printf <<-EOS, 'http://friendfeed.com/friends/twitter?username=' + URI.escape(twitter_me)
@@ -299,7 +351,7 @@ to see if someone is joining FriendFeed:
299
351
  if picture_urls.key?(name)
300
352
  url = picture_urls[name]
301
353
  else
302
- friend = twcli.get_profile(name) rescue
354
+ friend = twcli.user(name) rescue
303
355
  begin
304
356
  putinfo "Failed to get profile of %s", name
305
357
  next
@@ -315,6 +367,32 @@ to see if someone is joining FriendFeed:
315
367
  end
316
368
  end
317
369
 
370
+ mode 'includeatreplies' do
371
+ description 'Fix imaginary friends to include @replies'
372
+
373
+ def run
374
+ ffcli = friendfeed_client()
375
+
376
+ putinfo "Checking imaginary friends in FriendFeed..."
377
+ ffcli.get_imaginary_friends.each { |profile|
378
+ id = profile['id']
379
+ ffcli.get_services(id).each { |service|
380
+ url = service['profileUrl'] or next
381
+
382
+ if (name = TWITTER_URI.route_to(url).to_s).match(/\A[A-Za-z0-9_]+\z/)
383
+ name.downcase!
384
+ putinfo 'Trying to include @replies by %s', name
385
+ begin
386
+ ffcli.edit_service(id, service['serviceid'], 'includeatreplies' => 'on')
387
+ rescue => e
388
+ putinfo 'Failed, maybe due to the Twitter account removal or a network problem.'
389
+ end
390
+ end
391
+ }
392
+ }
393
+ end
394
+ end
395
+
318
396
  mode 'favorites' do
319
397
  description 'Synchronize Twitter favorites and FriendFeed likes as far as possible'
320
398
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{friendfeed}
8
- s.version = "0.1.13"
8
+ s.version = "0.1.14"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Akinori MUSHA"]
12
- s.date = %q{2010-02-18}
12
+ s.date = %q{2010-06-01}
13
13
  s.default_executable = %q{tw2ff}
14
14
  s.description = %q{This is a Ruby library to provide access to FriendFeed API's.
15
15
 
@@ -42,7 +42,7 @@ manipulating friends, groups and services for your personal purposes.
42
42
  s.rdoc_options = ["--charset=UTF-8"]
43
43
  s.require_paths = ["lib"]
44
44
  s.rubyforge_project = %q{friendfeed}
45
- s.rubygems_version = %q{1.3.5}
45
+ s.rubygems_version = %q{1.3.7}
46
46
  s.summary = %q{A Ruby library to provide access to FriendFeed API's}
47
47
  s.test_files = [
48
48
  "test/friendfeed_test.rb",
@@ -53,7 +53,7 @@ manipulating friends, groups and services for your personal purposes.
53
53
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
54
  s.specification_version = 3
55
55
 
56
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
56
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
57
  s.add_runtime_dependency(%q<json>, [">= 0"])
58
58
  s.add_runtime_dependency(%q<mechanize>, [">= 1.0.0"])
59
59
  else
@@ -145,11 +145,11 @@ module FriendFeed
145
145
  hash = { 'stream' => id }
146
146
  form.xpath(".//input").each { |input|
147
147
  case input['type'].downcase
148
- when 'text'
148
+ when 'text', 'hidden'
149
149
  hash[input['name']] = input['value']
150
150
  when 'radio', 'checkbox'
151
151
  if input['checked']
152
- value = input['value']
152
+ value = input['value'] || 'on'
153
153
  if value && !value.empty?
154
154
  hash[input['name']] = value
155
155
  end
@@ -166,10 +166,36 @@ module FriendFeed
166
166
  # Supported fields are 'nickname', 'name', 'description', 'access'
167
167
  # ('private', 'semipublic' or 'public'), and 'anyoneinvite' (none
168
168
  # or '1'). [unofficial]
169
- def edit_group(id, hash)
170
- param_hash = get_group(id)
171
- param_hash.update(hash)
172
- post(EDIT_GROUP_URI, param_hash)
169
+ def edit_group(id, options)
170
+ params = get_group(id)
171
+ params.update(options)
172
+ post(EDIT_GROUP_URI, params)
173
+ end
174
+
175
+ # Gets information of a service specified by a unique
176
+ # ID. [unofficial]
177
+ def get_service(id, serviceid)
178
+ parser = post(ROOT_URI + '/a/servicedialog',
179
+ 'serviceid' => serviceid, 'stream' => id)['html_parser']
180
+ form = parser.at("//form[1]")
181
+ hash = { 'stream' => id }
182
+ form.xpath(".//input").each { |input|
183
+ case input['type'].downcase
184
+ when 'text', 'hidden'
185
+ hash[input['name']] = input['value']
186
+ when 'radio', 'checkbox'
187
+ if input['checked']
188
+ value = input['value'] || 'on'
189
+ if value && !value.empty?
190
+ hash[input['name']] = value
191
+ end
192
+ end
193
+ end
194
+ }
195
+ form.xpath(".//textarea").each { |input|
196
+ hash[input['name']] = input.text
197
+ }
198
+ hash
173
199
  end
174
200
 
175
201
  # Adds a feed to the authenticated user, a group or an imaginary
@@ -187,12 +213,8 @@ module FriendFeed
187
213
 
188
214
  # Edits a service of the authenticated user, a group or an
189
215
  # imaginary friend specified by a unique ID. [unofficial]
190
- def edit_service(id, serviceid, service, options = nil)
191
- params = {
192
- 'stream' => id,
193
- 'service' => service,
194
- 'serviceid' => serviceid,
195
- }
216
+ def edit_service(id, serviceid, options = nil)
217
+ params = get_service(id, serviceid)
196
218
  params.update(options) if options
197
219
  post(ROOT_URI + '/a/configureservice', params)
198
220
  end
@@ -244,65 +266,10 @@ module FriendFeed
244
266
 
245
267
  # Adds a Twitter service to the authenticated user, a group or an
246
268
  # imaginary friend specified by a unique ID. [unofficial]
247
- def add_twitter(id, twitter_name)
248
- add_service(id, 'twitter', 'username' => twitter_name)
249
- end
250
-
251
- # Edits a feed of the authenticated user, a group or an imaginary
252
- # friend specified by a unique ID. Specify 'isstatus' => 'on' to
253
- # display entries as messages (no link), and 'importcomment' =>
254
- # 'on' to include entry description as a comment. [unofficial]
255
- def edit_feed(id, serviceid, url, options = nil)
256
- params = { 'url' => url }
257
- params.update(options) if options
258
- edit_service(id, 'feed', options)
259
- end
260
-
261
- # Adds a blog feed to the authenticated user, a group or an
262
- # imaginary friend specified by a unique ID. Specify 'multiauth'
263
- # => 'on' when the blog has multiple authors, and 'author' =>
264
- # '(name)' to limit entries to those written by a specific
265
- # author. [unofficial]
266
- def edit_blog(id, url, options = nil)
267
- params = { 'url' => url }
268
- params.update(options) if options
269
- edit_service(id, 'blog', options)
270
- end
271
-
272
- # Edits a Twitter service of the authenticated user, a group or an
273
- # imaginary friend specified by a unique ID. Specify 'isstatus'
274
- # => 'on' to display entries as messages (no link), and
275
- # 'importcomment' => 'on' to include entry description as a
276
- # comment. [unofficial]
277
- def edit_twitter(id, serviceid, twitter_name)
278
- edit_service(id, serviceid, 'twitter', 'username' => twitter_name)
279
- end
280
-
281
- # Removes a feed from the authenticated user, a group or an
282
- # imaginary friend specified by a unique ID. Specify
283
- # 'deleteentries' => 'on' to delete entries also. [unofficial]
284
- def remove_feed(id, serviceid, url, options = nil)
285
- params = { 'url' => url }
286
- params.update(options) if options
287
- remove_service(id, serviceid, 'feed', options = nil)
288
- end
289
-
290
- # Removes a blog feed from the authenticated user, a group or an
291
- # imaginary friend specified by a unique ID. Specify
292
- # 'deleteentries' => 'on' to delete entries also. [unofficial]
293
- def remove_blog(id, serviceid, url, options = nil)
294
- params = { 'url' => url }
295
- params.update(options) if options
296
- remove_service(id, serviceid, 'blog', options = nil)
297
- end
298
-
299
- # Removes a Twitter service from the authenticated user, a group
300
- # or an imaginary friend specified by a unique ID. Specify
301
- # 'deleteentries' => 'on' to delete entries also. [unofficial]
302
- def remove_twitter(id, serviceid, twitter_name, options = nil)
269
+ def add_twitter(id, twitter_name, options = nil)
303
270
  params = { 'username' => twitter_name }
304
271
  params.update(options) if options
305
- remove_service(id, serviceid, 'twitter', options = nil)
272
+ add_service(id, 'twitter', params)
306
273
  end
307
274
 
308
275
  # Changes the picture of the authenticated user, a group or an
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: friendfeed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ hash: 7
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 14
10
+ version: 0.1.14
5
11
  platform: ruby
6
12
  authors:
7
13
  - Akinori MUSHA
@@ -9,29 +15,39 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-02-18 00:00:00 +09:00
18
+ date: 2010-06-01 00:00:00 +09:00
13
19
  default_executable: tw2ff
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: json
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
23
32
  version: "0"
24
- version:
33
+ type: :runtime
34
+ version_requirements: *id001
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: mechanize
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
30
40
  requirements:
31
41
  - - ">="
32
42
  - !ruby/object:Gem::Version
43
+ hash: 23
44
+ segments:
45
+ - 1
46
+ - 0
47
+ - 0
33
48
  version: 1.0.0
34
- version:
49
+ type: :runtime
50
+ version_requirements: *id002
35
51
  description: |
36
52
  This is a Ruby library to provide access to FriendFeed API's.
37
53
 
@@ -71,21 +87,27 @@ rdoc_options:
71
87
  require_paths:
72
88
  - lib
73
89
  required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
74
91
  requirements:
75
92
  - - ">="
76
93
  - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
77
97
  version: "0"
78
- version:
79
98
  required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
80
100
  requirements:
81
101
  - - ">="
82
102
  - !ruby/object:Gem::Version
103
+ hash: 3
104
+ segments:
105
+ - 0
83
106
  version: "0"
84
- version:
85
107
  requirements: []
86
108
 
87
109
  rubyforge_project: friendfeed
88
- rubygems_version: 1.3.5
110
+ rubygems_version: 1.3.7
89
111
  signing_key:
90
112
  specification_version: 3
91
113
  summary: A Ruby library to provide access to FriendFeed API's