ayadn 3.0 → 4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -4
  3. data/CHANGELOG.md +12 -4
  4. data/README.md +2 -5
  5. data/ayadn.gemspec +0 -2
  6. data/doc/01-index.md +0 -3
  7. data/doc/02-install.md +0 -4
  8. data/doc/06-post.md +0 -16
  9. data/doc/{18-contact.md → 16-contact.md} +0 -0
  10. data/doc/{19-examples.md → 17-examples.md} +0 -0
  11. data/doc/18-develop.md +165 -0
  12. data/lib/ayadn/action.rb +206 -396
  13. data/lib/ayadn/alias.rb +1 -1
  14. data/lib/ayadn/annotations.rb +15 -27
  15. data/lib/ayadn/api.rb +39 -28
  16. data/lib/ayadn/app.rb +19 -29
  17. data/lib/ayadn/authorize.rb +22 -13
  18. data/lib/ayadn/blacklist.rb +6 -19
  19. data/lib/ayadn/channel_object.rb +75 -0
  20. data/lib/ayadn/check.rb +19 -11
  21. data/lib/ayadn/cnx.rb +9 -15
  22. data/lib/ayadn/databases.rb +15 -27
  23. data/lib/ayadn/debug.rb +9 -9
  24. data/lib/ayadn/descriptions.rb +1 -99
  25. data/lib/ayadn/diagnostics.rb +16 -15
  26. data/lib/ayadn/endpoints.rb +18 -22
  27. data/lib/ayadn/errors.rb +1 -1
  28. data/lib/ayadn/fileops.rb +12 -12
  29. data/lib/ayadn/filtered_post_object.rb +11 -0
  30. data/lib/ayadn/ids.rb +0 -3
  31. data/lib/ayadn/logs.rb +4 -4
  32. data/lib/ayadn/mark.rb +34 -30
  33. data/lib/ayadn/nicerank.rb +7 -7
  34. data/lib/ayadn/nowplaying.rb +8 -22
  35. data/lib/ayadn/pinboard.rb +8 -12
  36. data/lib/ayadn/post.rb +18 -18
  37. data/lib/ayadn/post_object.rb +118 -0
  38. data/lib/ayadn/preferences_object.rb +290 -0
  39. data/lib/ayadn/profile.rb +2 -2
  40. data/lib/ayadn/scroll.rb +58 -67
  41. data/lib/ayadn/search.rb +22 -15
  42. data/lib/ayadn/set.rb +93 -83
  43. data/lib/ayadn/settings.rb +25 -33
  44. data/lib/ayadn/status.rb +24 -26
  45. data/lib/ayadn/stream.rb +68 -66
  46. data/lib/ayadn/stream_object.rb +56 -0
  47. data/lib/ayadn/switch.rb +2 -2
  48. data/lib/ayadn/user_object.rb +116 -0
  49. data/lib/ayadn/version.rb +1 -1
  50. data/lib/ayadn/view.rb +255 -278
  51. data/lib/ayadn/workers.rb +172 -174
  52. data/spec/integration/action_spec.rb +55 -34
  53. data/spec/mock/ayadn.sqlite +0 -0
  54. data/spec/unit/annotations_spec.rb +54 -41
  55. data/spec/unit/api_spec.rb +78 -7
  56. data/spec/unit/blacklistworkers_spec.rb +92 -20
  57. data/spec/unit/databases_spec.rb +117 -36
  58. data/spec/unit/endpoints_spec.rb +82 -10
  59. data/spec/unit/nicerank_spec.rb +56 -27
  60. data/spec/unit/post_spec.rb +94 -21
  61. data/spec/unit/set_spec.rb +141 -210
  62. data/spec/unit/view_spec.rb +105 -32
  63. data/spec/unit/workers_spec.rb +143 -52
  64. metadata +12 -37
  65. data/doc/16-movie.md +0 -39
  66. data/doc/17-tvshow.md +0 -46
  67. data/lib/ayadn/nowwatching.rb +0 -118
  68. data/lib/ayadn/tvshow.rb +0 -162
data/lib/ayadn/status.rb CHANGED
@@ -2,8 +2,10 @@
2
2
  module Ayadn
3
3
  class Status
4
4
 
5
- def initialize
6
- @thor = Thor::Shell::Color.new
5
+ attr_reader :thor
6
+
7
+ def initialize thor = Thor::Shell::Color.new
8
+ @thor = thor
7
9
  end
8
10
 
9
11
  def done
@@ -18,11 +20,11 @@ module Ayadn
18
20
  end
19
21
 
20
22
  def downloaded(name)
21
- info("downloaded", "#{Settings.config[:paths][:downloads]}/#{name}", "green")
23
+ info("downloaded", "#{Settings.config.paths.downloads}/#{name}", "green")
22
24
  end
23
25
 
24
26
  def links_saved(name)
25
- info("done", "links exported to file #{Settings.config[:paths][:lists]}/#{name}", "green")
27
+ info("done", "links exported to file #{Settings.config.paths.lists}/#{name}", "green")
26
28
  end
27
29
 
28
30
  def downloading
@@ -81,6 +83,18 @@ module Ayadn
81
83
  say_yellow :starring, "post #{post_id}"
82
84
  end
83
85
 
86
+ def all_hashtag_links hashtag
87
+ info("info", "links from posts containing hashtag '##{hashtag}':", "cyan")
88
+ end
89
+
90
+ def all_search_links words
91
+ info("info", "links from posts containing word(s) '#{words}':", "cyan")
92
+ end
93
+
94
+ def all_stars_links
95
+ info("info", "links from your starred posts:", "cyan")
96
+ end
97
+
84
98
  def not_deleted(post_id)
85
99
  info("error", "could not delete post #{post_id} (post isn't yours, or is already deleted)", "red")
86
100
  end
@@ -185,10 +199,6 @@ module Ayadn
185
199
  info("blocked", username, "green")
186
200
  end
187
201
 
188
- def error_missing_title
189
- info("error", "please specify (part of) a movie title", "red")
190
- end
191
-
192
202
  def error_missing_username
193
203
  info("error", "please specify a username", "red")
194
204
  end
@@ -218,7 +228,7 @@ module Ayadn
218
228
 
219
229
  def writing
220
230
  puts "\n"
221
- say_cyan :author, "#{Settings.config[:identity][:handle]}"
231
+ say_cyan :author, "#{Settings.config.identity.handle}"
222
232
  puts "\n"
223
233
  end
224
234
 
@@ -233,7 +243,7 @@ module Ayadn
233
243
 
234
244
  def message_from(username)
235
245
  puts "\n"
236
- say_yellow :from, "#{Settings.config[:identity][:handle]}"
246
+ say_yellow :from, "#{Settings.config.identity.handle}"
237
247
  say_yellow :to, "#{username[0]}"
238
248
  end
239
249
 
@@ -251,15 +261,15 @@ module Ayadn
251
261
  end
252
262
 
253
263
  def reply
254
- say_cyan :max, "#{Settings.config[:post_max_length]} characters"
264
+ say_cyan :max, "#{Settings.config.post_max_length} characters"
255
265
  end
256
266
 
257
267
  def post
258
- say_cyan :max, "#{Settings.config[:post_max_length]} characters"
268
+ say_cyan :max, "#{Settings.config.post_max_length} characters"
259
269
  end
260
270
 
261
271
  def message
262
- say_cyan :max, "#{Settings.config[:message_max_length]} characters"
272
+ say_cyan :max, "#{Settings.config.message_max_length} characters"
263
273
  end
264
274
 
265
275
  def valid_colors(colors_list)
@@ -420,18 +430,6 @@ module Ayadn
420
430
  info("connexion", "fetching informations from #{source}", "green")
421
431
  end
422
432
 
423
- def no_movie
424
- info("error", "sorry, can't find this movie", "red")
425
- end
426
-
427
- def no_show
428
- info("error", "sorry, can't find this show", "red")
429
- end
430
-
431
- def no_show_infos
432
- info("error", "sorry, can't find informations about this show", "red")
433
- end
434
-
435
433
  def no_force(target)
436
434
  say do
437
435
  say_error "'#{target}' can't be displayed (could be muted, blocked, in the Blacklist, etc)"
@@ -528,7 +526,7 @@ module Ayadn
528
526
  end
529
527
 
530
528
  def server_error(bool)
531
- if bool == true
529
+ if bool
532
530
  say do
533
531
  say_error "Ayadn couldn't get the JSON reponse"
534
532
  say_yellow :next, "trying again in 10 seconds"
data/lib/ayadn/stream.rb CHANGED
@@ -5,31 +5,30 @@ module Ayadn
5
5
 
6
6
  require_relative("scroll")
7
7
 
8
- def initialize api, view, workers
8
+ def initialize api, view, workers, check, status
9
9
  @api = api
10
10
  @view = view
11
11
  @workers = workers
12
- @check = Check.new
13
- @status = Status.new
12
+ @check = check
13
+ @status = status
14
14
  end
15
15
 
16
16
  def global settings
17
- Settings.global[:force] = true if settings[:force]
18
17
  options = settings.dup
19
18
  options[:filter] = nicerank_true()
20
19
  @view.downloading(options)
21
20
  unless options[:scroll]
22
- stream = @api.get_global(options)
23
- Settings.global[:force] == true ? niceranks = {} : niceranks = NiceRank.new.get_ranks(stream)
24
- @check.no_new_posts(stream, options, 'global')
25
- Databases.save_max_id(stream, 'global') unless stream['meta']['max_id'].nil?
26
- @view.render(stream, options, niceranks)
21
+ stream_object = StreamObject.new(@api.get_global(options))
22
+ Settings.global.force ? niceranks = {} : niceranks = NiceRank.new.get_ranks(stream_object)
23
+ @check.no_new_posts(stream_object, options, 'global')
24
+ Databases.save_max_id(stream_object, 'global') unless stream_object.meta.max_id.nil?
25
+ @view.render(stream_object, options, niceranks)
27
26
  end
28
27
  if options[:scroll]
29
28
  @view.clear_screen()
30
29
  Scroll.new(@api, @view).global(options)
31
30
  end
32
- puts "\n" if Settings.options[:timeline][:compact] && options[:raw].nil?
31
+ puts "\n" if Settings.options.timeline.compact && options[:raw].nil?
33
32
  end
34
33
 
35
34
 
@@ -47,97 +46,98 @@ module Ayadn
47
46
  end
48
47
 
49
48
  def stream meth, options, target
50
- Settings.global[:force] = true if options[:force]
51
49
  @view.downloading(options)
52
50
  unless options[:scroll]
53
51
  stream = @api.send("get_#{meth}".to_sym, options)
54
- @check.no_new_posts(stream, options, target)
55
- Databases.save_max_id(stream)
56
- @view.render(stream, options)
52
+ stream_object = StreamObject.new(stream)
53
+ @check.no_new_posts(stream_object, options, target)
54
+ Databases.save_max_id(stream_object)
55
+ @view.render(stream_object, options)
57
56
  end
58
57
  if options[:scroll]
59
58
  @view.clear_screen()
60
59
  Scroll.new(@api, @view).send(meth, options)
61
60
  end
62
- puts "\n" if Settings.options[:timeline][:compact] && options[:raw].nil?
61
+ puts "\n" if Settings.options.timeline.compact && options[:raw].nil?
63
62
  end
64
63
 
65
64
 
66
65
  def mentions username, options
67
- Settings.global[:force] = true if options[:force]
68
66
  @check.no_username(username)
69
67
  username = @workers.add_arobase(username)
70
68
  @view.downloading(options)
71
69
  unless options[:scroll]
72
70
  stream = @api.get_mentions(username, options)
73
- @check.no_user(stream, username)
74
- Databases.save_max_id(stream)
75
- @check.no_data(stream, 'mentions')
71
+ stream_object = StreamObject.new(stream)
72
+ @check.no_user(stream_object, username)
73
+ Databases.save_max_id(stream_object)
74
+ @check.no_data(stream_object, 'mentions')
76
75
  options = options.dup
77
76
  options[:in_mentions] = true
78
- @view.render(stream, options)
77
+ @view.render(stream_object, options)
79
78
  end
80
79
  if options[:scroll]
81
80
  @view.clear_screen()
82
81
  Scroll.new(@api, @view).mentions(username, options)
83
82
  end
84
- puts "\n" if Settings.options[:timeline][:compact] && options[:raw].nil?
83
+ puts "\n" if Settings.options.timeline.compact && options[:raw].nil?
85
84
  end
86
85
 
87
86
  def posts username, options
88
- Settings.global[:force] = true if options[:force]
89
87
  @check.no_username(username)
90
88
  username = @workers.add_arobase(username)
91
89
  @view.downloading(options)
92
90
  stream = @api.get_posts(username, options)
93
- @check.no_user(stream, username)
94
- Databases.save_max_id(stream) unless stream['meta']['marker'].nil?
95
- @check.no_data(stream, 'mentions')
96
- unless options[:raw] || Settings.global[:force]
91
+ stream_object = StreamObject.new(stream)
92
+ @check.no_user(stream_object, username)
93
+ Databases.save_max_id(stream_object) unless stream_object.meta.marker.nil?
94
+ @check.no_data(stream_object, 'mentions')
95
+ unless options[:raw] || Settings.global.force
97
96
  # this is just to show a message rather than an empty screen
98
- if Settings.options[:blacklist][:active] == true
97
+ if Settings.options.blacklist.active
99
98
  if Databases.is_in_blacklist?('mention', username)
100
99
  @status.no_force("#{username.downcase}")
101
100
  exit
102
101
  end
103
102
  end
104
103
  end
105
- if stream['data'][0]['user']['you_muted'] || stream['data'][0]['user']['you_blocked']
106
- unless options[:raw] || Settings.global[:force]
104
+ if stream_object.posts[0].user.you_muted || stream_object.posts[0].user.you_blocked
105
+ unless options[:raw] || Settings.global.force
107
106
  @status.no_force("#{username.downcase}")
108
107
  exit
109
108
  end
110
109
  end
111
- @view.render(stream, options)
110
+ @view.render(stream_object, options)
112
111
  Scroll.new(@api, @view).posts(username, options) if options[:scroll]
113
- puts "\n" if Settings.options[:timeline][:compact] && options[:raw].nil?
112
+ puts "\n" if Settings.options.timeline.compact && options[:raw].nil?
114
113
  end
115
114
 
116
115
  def whatstarred(username, options)
117
116
  @check.no_username(username)
118
117
  username = @workers.add_arobase(username)
119
118
  @view.downloading(options) unless options["again"]
120
-
121
119
  if options["again"]
122
120
  stream = FileOps.cached_list("whatstarred")
121
+ stream_object = StreamObject.new(stream)
123
122
  Errors.no_data('cached whatstarred') if stream.nil?
124
123
  else
125
124
  stream = @api.get_whatstarred(username, options)
125
+ stream_object = StreamObject.new(stream)
126
126
  end
127
127
 
128
- @check.no_user(stream, username)
129
- @check.no_data(stream, 'whatstarred')
128
+ @check.no_user(stream_object, username)
129
+ @check.no_data(stream_object, 'whatstarred')
130
130
 
131
131
  if options["cache"] && options["again"].nil?
132
- FileOps.cache_list(stream, "whatstarred")
132
+ FileOps.cache_list(stream_object.input, "whatstarred")
133
133
  end
134
134
 
135
135
  if options[:extract]
136
- @view.all_stars_links(stream)
136
+ @view.all_stars_links(stream_object)
137
137
  else
138
- @view.render(stream, options)
138
+ @view.render(stream_object, options)
139
139
  end
140
- puts "\n" if Settings.options[:timeline][:compact] == true
140
+ puts "\n" if Settings.options.timeline.compact
141
141
  end
142
142
 
143
143
  def followings(username, options)
@@ -155,15 +155,15 @@ module Ayadn
155
155
  Errors.no_data('followings') if list.empty?
156
156
  if options["lastpost"] && options["again"].nil?
157
157
  count = list.size
158
- @workers.thor.say_status :downloading, "please wait, it may take a while...", :red
158
+ @status.thor.say_status :downloading, "please wait, it may take a while...", :red
159
159
  puts "\n"
160
160
  idx = 0
161
- list.each do |str_id,obj|
161
+ list.each do |str_id, obj|
162
162
  idx += 1
163
163
  tmp_username = "@#{obj[0]}"
164
- colored_username = tmp_username.color(Settings.options[:colors][:username])
164
+ colored_username = tmp_username.color(Settings.options.colors.username)
165
165
  iter = "#{idx}/#{count}"
166
- @workers.thor.say_status iter.to_sym, "last post from #{colored_username}", :cyan
166
+ @status.thor.say_status iter.to_sym, "last post from #{colored_username}", :cyan
167
167
  resp = @api.get_posts(tmp_username, {count: 1})
168
168
  obj << resp["data"][0]
169
169
  end
@@ -244,7 +244,7 @@ module Ayadn
244
244
  @view.if_raw(stream, options)
245
245
  @view.clear_screen
246
246
  @view.show_interactions(stream['data'])
247
- puts "\n" if Settings.options[:timeline][:compact] == true
247
+ puts "\n" if Settings.options.timeline.compact
248
248
  end
249
249
 
250
250
  def whoreposted(post_id, options)
@@ -261,7 +261,7 @@ module Ayadn
261
261
  details = @api.get_details(post_id, options)
262
262
  end
263
263
 
264
- @check.no_post(details, post_id)
264
+ @check.no_details(details, post_id)
265
265
  id = @workers.get_original_id(post_id, details)
266
266
 
267
267
  if options["cache"] && options["again"].nil?
@@ -301,7 +301,7 @@ module Ayadn
301
301
  details = @api.get_details(post_id, options)
302
302
  end
303
303
 
304
- @check.no_post(details, post_id)
304
+ @check.no_details(details, post_id)
305
305
  id = @workers.get_original_id(post_id, details)
306
306
 
307
307
  if options["cache"] && options["again"].nil?
@@ -329,54 +329,54 @@ module Ayadn
329
329
 
330
330
  def convo(post_id, options)
331
331
  @check.bad_post_id(post_id)
332
- if options[:force]
333
- Settings.global[:force] = true
334
- else
332
+ unless options[:force]
335
333
  post_id = @workers.get_real_post_id(post_id)
336
334
  end
337
335
  @view.downloading(options)
338
336
  details = @api.get_details(post_id, options)
339
- @check.no_post(details, post_id)
337
+ @check.no_details(details, post_id)
340
338
  id = @workers.get_original_id(post_id, details)
341
339
  stream = @api.get_convo(id, options)
342
- @check.no_post(stream, id)
343
- Databases.pagination_insert("replies:#{id}", stream['meta']['max_id'])
340
+ stream_object = StreamObject.new(stream)
341
+ @check.no_post(stream_object, id)
342
+ Databases.pagination_insert("replies:#{id}", stream_object.meta.max_id)
344
343
  options = options.dup
345
344
  options[:reply_to] = details['data']['reply_to'].to_i unless details['data']['reply_to'].nil?
346
345
  options[:post_id] = post_id.to_i
347
- @view.render(stream, options)
346
+ @view.render(stream_object, options)
348
347
  Scroll.new(@api, @view).convo(id, options) if options[:scroll]
349
- puts "\n" if Settings.options[:timeline][:compact] && options[:raw].nil?
348
+ puts "\n" if Settings.options.timeline.compact && options[:raw].nil?
350
349
  end
351
350
 
352
351
  def messages(channel_id, options)
353
352
  if options[:silent]
354
- Settings.options[:marker][:messages] = false
353
+ Settings.options.marker.messages = false
355
354
  end
356
355
  channel_id = @workers.get_channel_id_from_alias(channel_id)
357
356
  @view.downloading(options)
358
357
  resp = @api.get_messages(channel_id, options)
358
+ stream_object = StreamObject.new(resp)
359
359
  name = "channel:#{channel_id}"
360
- @check.no_new_posts(resp, options, name)
361
- if Settings.options[:marker][:messages] == true
362
- unless resp['meta']['max_id'].nil?
363
- marked = @api.update_marker(name, resp['meta']['max_id'])
360
+ @check.no_new_posts(stream_object, options, name)
361
+ if Settings.options.marker.messages
362
+ unless stream_object.meta.max_id.nil?
363
+ marked = @api.update_marker(name, stream_object.meta.max_id)
364
364
  updated = JSON.parse(marked)
365
365
  if updated['meta']['code'] != 200
366
366
  raise "couldn't update channel #{channel_id} as read"
367
367
  end
368
368
  end
369
369
  end
370
- Databases.save_max_id(resp)
371
- @view.if_raw(resp, options)
372
- @check.no_data(resp, 'messages') unless options[:scroll]
373
- @view.render(resp, options)
370
+ Databases.save_max_id(stream_object)
371
+ @view.if_raw(stream_object, options)
372
+ @check.no_data(stream_object, 'messages') unless options[:scroll]
373
+ @view.render(stream_object, options)
374
374
  Scroll.new(@api, @view).messages(channel_id, options) if options[:scroll]
375
- puts "\n" if Settings.options[:timeline][:compact] && options[:raw].nil?
375
+ puts "\n" if Settings.options.timeline.compact && options[:raw].nil?
376
376
  end
377
377
 
378
378
  def random_posts(options)
379
- Settings.global[:force] = true
379
+ Settings.global.force = true
380
380
  #_, cols = @view.winsize
381
381
  #max_posts = cols / 16
382
382
  max_posts = 6
@@ -390,8 +390,10 @@ module Ayadn
390
390
  begin
391
391
  @random_post_id = rand(@max_id)
392
392
  @resp = @api.get_details(@random_post_id, {})
393
+ next if @resp.nil?
394
+ next if @resp['data'].nil? || @resp['data'].empty?
393
395
  next if @resp['data']['is_deleted']
394
- @view.show_simple_post([@resp['data']], {})
396
+ @view.show_simple_post([PostObject.new(@resp['data'])], {})
395
397
  counter += 1
396
398
  if counter == max_posts
397
399
  wait.downto(1) do |i|
@@ -430,7 +432,7 @@ module Ayadn
430
432
  end
431
433
 
432
434
  def nicerank_true
433
- return true if Settings.options[:nicerank][:filter] == true
435
+ return true if Settings.options.nicerank.filter
434
436
  end
435
437
 
436
438
  end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ module Ayadn
3
+
4
+ class StreamMarkerObject
5
+
6
+ attr_reader :input, :name, :updated_at, :version, :last_read_id, :percentage, :id
7
+
8
+ def initialize hash
9
+ @input = hash["marker"].nil? ? {} : hash["marker"]
10
+ @name = @input["name"]
11
+ @updated_at = @input["updated_at"]
12
+ @version = @input["version"]
13
+ @last_read_id = @input["last_read_id"]
14
+ @percentage = @input["percentage"]
15
+ @id = @input["id"]
16
+ end
17
+ end
18
+
19
+ class StreamMetaObject
20
+
21
+ attr_reader :input, :marker, :min_id, :code, :max_id, :more
22
+
23
+ def initialize hash
24
+ @input = hash["meta"].nil? ? {} : hash["meta"]
25
+ @marker = hash["meta"].nil? ? nil : StreamMarkerObject.new(@input)
26
+ @min_id = @input["min_id"]
27
+ @code = @input["code"]
28
+ @max_id = @input["max_id"]
29
+ @more = @input["more"]
30
+ end
31
+ end
32
+
33
+ class StreamDataObject
34
+
35
+ attr_reader :input, :posts
36
+
37
+ def initialize hash
38
+ @input = hash["data"]
39
+ @posts = @input.blank? ? [] : @input.map { |post| PostObject.new(post) }
40
+ end
41
+ end
42
+
43
+ class StreamObject
44
+
45
+ attr_reader :input, :meta, :data, :posts
46
+ attr_accessor :view
47
+
48
+ def initialize hash
49
+ @input = hash
50
+ @meta = StreamMetaObject.new(@input)
51
+ @data = StreamDataObject.new(@input)
52
+ @posts = @data.posts
53
+ end
54
+ end
55
+
56
+ end