ayadn 3.0 → 4.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.
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