ayadn 1.8.2 → 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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/CHANGELOG.md +73 -52
  4. data/README.md +17 -3
  5. data/ayadn.gemspec +3 -4
  6. data/doc/01-index.md +6 -5
  7. data/doc/02-install.md +23 -1
  8. data/doc/03-first-steps.md +22 -28
  9. data/doc/04-options.md +1 -1
  10. data/doc/05-streams.md +29 -9
  11. data/doc/06-post.md +13 -5
  12. data/doc/07-actions.md +63 -1
  13. data/doc/08-listings.md +112 -4
  14. data/doc/09-accounts.md +17 -3
  15. data/doc/10-nicerank.md +5 -5
  16. data/doc/11-blacklist.md +8 -14
  17. data/doc/12-alias.md +1 -13
  18. data/doc/14-set.md +8 -110
  19. data/doc/15-nowplaying.md +16 -4
  20. data/doc/18-contact.md +14 -13
  21. data/doc/19-examples.md +2 -0
  22. data/lib/ayadn/action.rb +322 -183
  23. data/lib/ayadn/alias.rb +17 -45
  24. data/lib/ayadn/annotations.rb +1 -1
  25. data/lib/ayadn/api.rb +7 -8
  26. data/lib/ayadn/app.rb +99 -12
  27. data/lib/ayadn/authorize.rb +92 -57
  28. data/lib/ayadn/blacklist.rb +52 -62
  29. data/lib/ayadn/check.rb +81 -74
  30. data/lib/ayadn/cnx.rb +77 -26
  31. data/lib/ayadn/databases.rb +890 -105
  32. data/lib/ayadn/debug.rb +30 -89
  33. data/lib/ayadn/descriptions.rb +876 -329
  34. data/lib/ayadn/endpoints.rb +2 -2
  35. data/lib/ayadn/errors.rb +9 -9
  36. data/lib/ayadn/extend.rb +8 -1
  37. data/lib/ayadn/fileops.rb +10 -8
  38. data/lib/ayadn/mark.rb +79 -56
  39. data/lib/ayadn/migration.rb +427 -0
  40. data/lib/ayadn/nicerank.rb +74 -72
  41. data/lib/ayadn/nowplaying.rb +123 -60
  42. data/lib/ayadn/nowwatching.rb +26 -10
  43. data/lib/ayadn/pinboard.rb +12 -7
  44. data/lib/ayadn/post.rb +40 -37
  45. data/lib/ayadn/profile.rb +5 -2
  46. data/lib/ayadn/scroll.rb +20 -5
  47. data/lib/ayadn/search.rb +30 -22
  48. data/lib/ayadn/set.rb +146 -50
  49. data/lib/ayadn/settings.rb +66 -67
  50. data/lib/ayadn/status.rb +459 -234
  51. data/lib/ayadn/stream.rb +80 -46
  52. data/lib/ayadn/switch.rb +51 -47
  53. data/lib/ayadn/tvshow.rb +47 -15
  54. data/lib/ayadn/version.rb +1 -1
  55. data/lib/ayadn/view.rb +119 -60
  56. data/lib/ayadn/workers.rb +144 -92
  57. data/lib/ayadn.rb +7 -8
  58. data/spec/mock/ayadn/accounts.sqlite +0 -0
  59. data/spec/mock/ayadn.sqlite +0 -0
  60. data/spec/unit/annotations_spec.rb +12 -13
  61. data/spec/unit/api_spec.rb +3 -4
  62. data/spec/unit/blacklistworkers_spec.rb +18 -23
  63. data/spec/unit/databases_spec.rb +51 -36
  64. data/spec/unit/endpoints_spec.rb +5 -2
  65. data/spec/unit/extend_spec.rb +24 -0
  66. data/spec/unit/nicerank_spec.rb +13 -13
  67. data/spec/unit/post_spec.rb +47 -36
  68. data/spec/unit/set_spec.rb +67 -96
  69. data/spec/unit/view_spec.rb +12 -6
  70. data/spec/unit/workers_spec.rb +38 -12
  71. data/tags +1285 -0
  72. metadata +29 -39
  73. data/spec/mock/aliases.db +0 -0
  74. data/spec/mock/blacklist.db +0 -0
  75. data/spec/mock/bookmarks.db +0 -0
  76. data/spec/mock/channels.db +0 -0
  77. data/spec/mock/index.db +0 -0
  78. data/spec/mock/nicerank.db +0 -0
  79. data/spec/mock/pagination.db +0 -0
  80. data/spec/mock/users.db +0 -0
  81. data/spec/unit/status_spec.rb +0 -9
@@ -0,0 +1,427 @@
1
+ # encoding: utf-8
2
+ module Ayadn
3
+ class Migration
4
+
5
+ begin
6
+ require 'daybreak'
7
+ rescue LoadError => e
8
+ puts "\nAYADN: Error while loading Gems\n\n"
9
+ puts "RUBY: #{e}\n\n"
10
+ exit
11
+ end
12
+
13
+ def initialize
14
+ @still = false
15
+ @thor = Thor::Shell::Color.new
16
+ accounts_old = Dir.home + "/ayadn/accounts.db"
17
+ unless File.exist?(accounts_old)
18
+ puts "\n"
19
+ @thor.say_status :error, "can't find the Ayadn 1.x accounts database", :red
20
+ @thor.say_status :canceled, "migration canceled", :red
21
+ puts "\n"
22
+ exit
23
+ end
24
+ begin
25
+ @accounts = Daybreak::DB.new(accounts_old)
26
+ # just in case of a previous canceled migration
27
+ # which could have left the accounts.db in place
28
+ if @accounts.size == 1 || @accounts.size == 0
29
+ @accounts.close
30
+ File.delete(Dir.home + "/ayadn/accounts.db")
31
+ @thor.say_status :delete, Dir.home + "/ayadn/accounts.db", :yellow
32
+ @thor.say_status :stopped, "no more accounts to migrate", :green
33
+ exit
34
+ end
35
+ @active_old = @accounts['ACTIVE']
36
+ @home = @accounts[@active_old][:path]
37
+ bookmarks_old = "#{@home}/db/bookmarks.db"
38
+ aliases_old = "#{@home}/db/aliases.db"
39
+ blacklist_old = "#{@home}/db/blacklist.db"
40
+ users_old = "#{@home}/db/users.db"
41
+ @pagination_old = "#{@home}/pagination/pagination.db"
42
+ @index_old = "#{@home}/pagination/index.db"
43
+
44
+ @config_path_old = "#{@home}/config/config.yml"
45
+
46
+ @bookmarks = Daybreak::DB.new(bookmarks_old) if File.exist?(bookmarks_old)
47
+ @aliases = Daybreak::DB.new(aliases_old) if File.exist?(aliases_old)
48
+ @blacklist = Daybreak::DB.new(blacklist_old) if File.exist?(blacklist_old)
49
+ @users = Daybreak::DB.new(users_old) if File.exist?(users_old)
50
+ @pagination = Daybreak::DB.new(@pagination_old) if File.exist?(@pagination_old)
51
+ @index = Daybreak::DB.new(@index_old) if File.exist?(@index_old)
52
+
53
+ @sqlfile = "#{@home}/db/ayadn.sqlite"
54
+ @sql = Amalgalite::Database.new(@sqlfile)
55
+ rescue Exception => e
56
+ puts "\n"
57
+ @thor.say_status :error, "#{e}", :red
58
+ @thor.say_status :stack, "#{caller}", :red
59
+ @thor.say_status :canceled, "migration canceled", :red
60
+ puts "\n"
61
+ exit
62
+ end
63
+ end
64
+
65
+ def all
66
+ # DON'T MODIFY THE ORDER!
67
+ puts banner()
68
+ puts "\n"
69
+ @thor.say_status :start, "migration", :yellow
70
+ old_backup = "#{@home}/backup"
71
+ if Dir.exist?(old_backup)
72
+ if Dir.entries(old_backup).size > 2
73
+ FileUtils.mv(Dir.glob("#{old_backup}/*"), "#{@home}/downloads")
74
+ @thor.say_status :move, "files from 'backup' to 'downloads'", :green
75
+ end
76
+ Dir.rmdir(old_backup)
77
+ @thor.say_status :delete, old_backup, :green
78
+ end
79
+ old_channels = "#{@home}/db/channels.db"
80
+ if File.exist?(old_channels)
81
+ @thor.say_status :delete, old_channels, :green
82
+ File.delete(old_channels)
83
+ end
84
+ if File.exist?("#{@home}/db/ayadn_pinboard.db")
85
+ @thor.say_status :move, "pinboard credentials", :green
86
+ FileUtils.mv("#{@home}/db/ayadn_pinboard.db", "#{@home}/auth/pinboard.data")
87
+ end
88
+ bookmarks()
89
+ aliases()
90
+ blacklist()
91
+ niceranks()
92
+ users()
93
+ pagination()
94
+ index()
95
+ accounts()
96
+ config()
97
+ @thor.say_status :done, "migration", :yellow
98
+ puts "\n"
99
+ if @still != false
100
+ @thor.say_status :WARNING, "another user, @#{@still}, is still in the old database", :red
101
+ @thor.say_status :PLEASE, "you should run `ayadn migrate` again right now", :yellow
102
+ puts "\n"
103
+ else
104
+ @thor.say_status :ok, "ready to go!", :green
105
+ @thor.say_status :thanks, "you can use Ayadn now", :cyan
106
+ puts "\n"
107
+ end
108
+ end
109
+
110
+ def bookmarks
111
+ @sql.execute_batch <<-SQL
112
+ CREATE TABLE Bookmarks (
113
+ post_id INTEGER,
114
+ bookmark TEXT
115
+ );
116
+ SQL
117
+ @sql.reload_schema!
118
+ if File.exist?("#{@home}/db/bookmarks.db")
119
+ @thor.say_status :import, "Bookmarks database", :cyan
120
+ @sql.transaction do |db_in_transaction|
121
+ @bookmarks.each do |k,v|
122
+ insert_data = {}
123
+ insert_data[":k"] = k.to_i
124
+ insert_data[":v"] = v.to_json.to_s
125
+ db_in_transaction.prepare("INSERT INTO Bookmarks(post_id, bookmark) VALUES(:k, :v);") do |insert|
126
+ insert.execute(insert_data)
127
+ end
128
+ end
129
+ end
130
+ @thor.say_status :done, "#{@bookmarks.size} objects", :green
131
+ @bookmarks.close
132
+ File.delete("#{@home}/db/bookmarks.db")
133
+ @thor.say_status :delete, "#{@home}/db/bookmarks.db", :green
134
+ end
135
+ end
136
+
137
+ def aliases
138
+ @sql.execute_batch <<-SQL
139
+ CREATE TABLE Aliases (
140
+ channel_id INTEGER,
141
+ alias VARCHAR(255)
142
+ );
143
+ SQL
144
+ @sql.reload_schema!
145
+ if File.exist?("#{@home}/db/aliases.db")
146
+ @thor.say_status :import, "Aliases database", :cyan
147
+ @sql.transaction do |db_in_transaction|
148
+ @aliases.each do |k,v|
149
+ insert_data = {}
150
+ insert_data[":k"] = v.to_i
151
+ insert_data[":v"] = k
152
+ db_in_transaction.prepare("INSERT INTO Aliases(channel_id, alias) VALUES(:k, :v);") do |insert|
153
+ insert.execute(insert_data)
154
+ end
155
+ end
156
+ end
157
+ @thor.say_status :done, "#{@aliases.size} objects", :green
158
+ @aliases.close
159
+ File.delete("#{@home}/db/aliases.db")
160
+ @thor.say_status :delete, "#{@home}/db/aliases.db", :green
161
+ end
162
+ end
163
+
164
+ def blacklist
165
+ @sql.execute_batch <<-SQL
166
+ CREATE TABLE Blacklist (
167
+ type VARCHAR(255),
168
+ content TEXT
169
+ );
170
+ SQL
171
+ @sql.reload_schema!
172
+ if File.exist?("#{@home}/db/blacklist.db")
173
+ @thor.say_status :import, "Blacklist database", :cyan
174
+ @sql.transaction do |db_in_transaction|
175
+ @blacklist.each do |k,v|
176
+ insert_data = {}
177
+ ks = k.dup.to_s
178
+ ks[0] = "" if ks[0] == "-"
179
+ ks[0] = "" if ks[0] == "@"
180
+ insert_data[":k"] = v.to_s
181
+ insert_data[":v"] = ks
182
+ db_in_transaction.prepare("INSERT INTO Blacklist(type, content) VALUES(:k, :v);") do |insert|
183
+ insert.execute(insert_data)
184
+ end
185
+ end
186
+ end
187
+ @thor.say_status :done, "#{@blacklist.size} objects", :green
188
+ @blacklist.close
189
+ File.delete("#{@home}/db/blacklist.db")
190
+ @thor.say_status :delete, "#{@home}/db/blacklist.db", :green
191
+ end
192
+ end
193
+
194
+ def niceranks
195
+ if File.exist?("#{@home}/db/nicerank.db")
196
+ File.delete("#{@home}/db/nicerank.db")
197
+ @thor.say_status :delete, "#{@home}/db/nicerank.db", :green
198
+ end
199
+ end
200
+
201
+ def users
202
+ @sql.execute_batch <<-SQL
203
+ CREATE TABLE Users (
204
+ user_id INTEGER,
205
+ username VARCHAR(20),
206
+ name TEXT
207
+ );
208
+ SQL
209
+ @sql.reload_schema!
210
+ if File.exist?("#{@home}/db/users.db")
211
+ @thor.say_status :import, "Users database", :cyan
212
+ @sql.transaction do |db_in_transaction|
213
+ @users.each do |k,v|
214
+ insert_data = {}
215
+ insert_data[":id"] = k.to_i
216
+ insert_data[":username"] = v.keys[0]
217
+ insert_data[":name"] = v.values[0]
218
+ db_in_transaction.prepare("INSERT INTO Users(user_id, username, name) VALUES(:id, :username, :name);") do |insert|
219
+ insert.execute(insert_data)
220
+ end
221
+ end
222
+ end
223
+ @thor.say_status :done, "#{@users.size} objects", :green
224
+ @users.close
225
+ File.delete("#{@home}/db/users.db")
226
+ @thor.say_status :delete, "#{@home}/db/users.db", :green
227
+ end
228
+ end
229
+
230
+ def pagination
231
+ @sql.execute_batch <<-SQL
232
+ CREATE TABLE Pagination (
233
+ name TEXT,
234
+ post_id INTEGER
235
+ );
236
+ SQL
237
+ @sql.reload_schema!
238
+ if File.exist?(@pagination_old)
239
+ @thor.say_status :import, "Pagination database", :cyan
240
+ @sql.transaction do |db_in_transaction|
241
+ @pagination.each do |k,v|
242
+ insert_data = {}
243
+ insert_data[":post_id"] = v.to_i
244
+ insert_data[":name"] = k.to_s
245
+ db_in_transaction.prepare("INSERT INTO Pagination(name, post_id) VALUES(:name, :post_id);") do |insert|
246
+ insert.execute(insert_data)
247
+ end
248
+ end
249
+ end
250
+ @thor.say_status :done, "#{@pagination.size} objects", :green
251
+ @pagination.close
252
+ File.delete(@pagination_old)
253
+ @thor.say_status :delete, @pagination_old, :green
254
+ end
255
+ end
256
+
257
+ def index
258
+ @sql.execute_batch <<-SQL
259
+ CREATE TABLE TLIndex (
260
+ count INTEGER,
261
+ post_id INTEGER,
262
+ content TEXT
263
+ );
264
+ SQL
265
+ @sql.reload_schema!
266
+ if File.exist?(@index_old)
267
+ @thor.say_status :import, "Index database", :cyan
268
+ @sql.transaction do |db_in_transaction|
269
+ @index.each do |k,v|
270
+ insert_data = {}
271
+ insert_data[":post_id"] = v[:id]
272
+ insert_data[":count"] = v[:count]
273
+ insert_data[":content"] = v.to_json.to_s
274
+ db_in_transaction.prepare("INSERT INTO TLIndex(count, post_id, content) VALUES(:count, :post_id, :content);") do |insert|
275
+ insert.execute(insert_data)
276
+ end
277
+ end
278
+ end
279
+ @thor.say_status :done, "#{@index.size} objects", :green
280
+ @index.close
281
+ File.delete(@index_old)
282
+ @thor.say_status :delete, @index_old, :green
283
+ Dir.rmdir("#{@home}/pagination")
284
+ @thor.say_status :delete, "#{@home}/pagination", :green
285
+ end
286
+ end
287
+
288
+ def accounts
289
+ @thor.say_status :create, Dir.home + "/ayadn/accounts.sqlite", :blue
290
+ sql = Amalgalite::Database.new(Dir.home + "/ayadn/accounts.sqlite")
291
+ @thor.say_status :import, "account informations", :cyan
292
+ if sql.schema.tables.empty?
293
+ sql.execute_batch <<-SQL
294
+ CREATE TABLE Accounts (
295
+ username VARCHAR(20),
296
+ user_id INTEGER,
297
+ handle VARCHAR(21),
298
+ account_path TEXT,
299
+ active INTEGER,
300
+ token TEXT
301
+ );
302
+ SQL
303
+ sql.reload_schema!
304
+ end
305
+ active, active_account = ""
306
+ @accounts.each do |k,v|
307
+ if k == "ACTIVE"
308
+ active_account = v
309
+ next
310
+ end
311
+ end
312
+ actives = sql.execute("SELECT user_id FROM Accounts WHERE active=1")
313
+ sql.execute("UPDATE Accounts SET active=0") unless actives.empty?
314
+ sql.transaction do |db_in_transaction|
315
+ active = [@accounts[active_account]]
316
+ @thor.say_status :delete, "old @#{active_account} account", :green
317
+ @accounts.delete(active_account)
318
+ if @accounts.size == 1 # only the 'ACTIVE' label, so it's like 0
319
+ @accounts.close
320
+ File.delete(Dir.home + "/ayadn/accounts.db")
321
+ @thor.say_status :delete, Dir.home + "/ayadn/accounts.db", :green
322
+ else
323
+ @accounts.each do |k,v|
324
+ next if k == "ACTIVE"
325
+ @accounts['ACTIVE'] = v[:username]
326
+ @still = v[:username]
327
+ break
328
+ end
329
+ @accounts.close
330
+ end
331
+ active.each do |obj|
332
+ insert_data = {}
333
+ insert_data[":username"] = obj[:username]
334
+ insert_data[":user_id"] = obj[:id].to_i
335
+ insert_data[":handle"] = obj[:handle]
336
+ insert_data[":account_path"] = obj[:path]
337
+ insert_data[":active"] = 1
338
+ template = Dir.home + "/ayadn/#{obj[:username]}/auth/token"
339
+ insert_data[":token"] = File.read(template)
340
+ db_in_transaction.prepare("INSERT INTO Accounts(username, user_id, handle, account_path, active, token) VALUES(:username, :user_id, :handle, :account_path, :active, :token);") do |insert|
341
+ insert.execute(insert_data)
342
+ end
343
+ end
344
+ end
345
+ @thor.say_status :imported, "@#{active_account} account", :green
346
+ end
347
+
348
+ def config
349
+ @thor.say_status :load, "config file", :blue
350
+ old_conf = YAML.load(File.read(@config_path_old))
351
+ conf = Settings.defaults
352
+ @thor.say_status :convert, "settings", :cyan
353
+ conf[:timeline][:source] = old_conf[:timeline][:show_source] || true
354
+ conf[:timeline][:symbols] = old_conf[:timeline][:show_symbols] || true
355
+ conf[:timeline][:name] = old_conf[:timeline][:show_real_name] || true
356
+ conf[:timeline][:date] = old_conf[:timeline][:show_date] || true
357
+ conf[:timeline][:debug] = old_conf[:timeline][:show_debug] || false
358
+ conf[:timeline][:compact] = old_conf[:timeline][:compact] || false
359
+ if old_conf[:timeline][:directed] == 1 || old_conf[:timeline][:directed] == true
360
+ conf[:timeline][:directed] = true
361
+ else
362
+ conf[:timeline][:directed] = false
363
+ end
364
+ conf[:marker][:messages] = old_conf[:marker][:update_messages] || true
365
+ conf[:backup][:posts] = old_conf[:backup][:auto_save_sent_posts] || false
366
+ conf[:backup][:messages] = old_conf[:backup][:auto_save_sent_messages] || false
367
+ conf[:backup][:lists] = old_conf[:backup][:auto_save_lists] || false
368
+ conf[:colors][:id] = old_conf[:colors][:id] || :blue
369
+ conf[:colors][:index] = old_conf[:colors][:index] || :red
370
+ conf[:colors][:username] = old_conf[:colors][:username] || :green
371
+ conf[:colors][:name] = old_conf[:colors][:name] || :magenta
372
+ conf[:colors][:debug] = old_conf[:colors][:debug] || :red
373
+ conf[:colors][:date] = old_conf[:colors][:date] || :cyan
374
+ conf[:colors][:link] = old_conf[:colors][:link] || :yellow
375
+ conf[:colors][:dots] = old_conf[:colors][:dots] || :blue
376
+ conf[:colors][:hashtags] = old_conf[:colors][:hashtags] || :cyan
377
+ conf[:colors][:debug] = old_conf[:colors][:debug] || :red
378
+ conf[:colors][:mentions] = old_conf[:colors][:mentions] || :red
379
+ conf[:colors][:source] = old_conf[:colors][:source] || :cyan
380
+ conf[:colors][:symbols] = old_conf[:colors][:symbols] || :green
381
+ conf[:colors][:unread] = old_conf[:colors][:unread] || :cyan
382
+ conf[:formats][:list] = old_conf[:formats][:list] || {}
383
+ conf[:formats][:list][:reverse] = old_conf[:formats][:list][:reverse] || true
384
+ conf[:formats][:table] = old_conf[:formats][:table] || {}
385
+ conf[:formats][:table][:width] = old_conf[:formats][:table][:width] || 75
386
+ conf[:formats][:table][:borders] = old_conf[:formats][:table][:borders] || true
387
+ conf[:scroll][:spinner] = old_conf[:timeline][:show_spinner] || true
388
+ conf[:scroll][:timer] = old_conf[:scroll][:timer] || 3
389
+ conf[:movie][:hashtag] = old_conf[:movie][:hashtag] || 'nowwatching'
390
+ conf[:tvshow][:hashtag] = old_conf[:tvshow][:hashtag] || 'nowwatching'
391
+ conf[:channels][:links] = old_conf[:timeline][:show_channel_oembed] || true
392
+ conf[:nicerank][:threshold] = old_conf[:nicerank][:threshold] || 2.1
393
+ conf[:nicerank][:filter] = old_conf[:nicerank][:filter] || true
394
+ conf[:counts][:defaults] = old_conf[:counts][:defaults] || 50
395
+ conf[:counts][:unified] = old_conf[:counts][:unified] || 50
396
+ conf[:counts][:global] = old_conf[:counts][:global] || 50
397
+ conf[:counts][:checkins] = old_conf[:counts][:checkins] || 50
398
+ conf[:counts][:conversations] = old_conf[:counts][:conversations] || 50
399
+ conf[:counts][:photos] = old_conf[:counts][:photos] || 50
400
+ conf[:counts][:trending] = old_conf[:counts][:trending] || 50
401
+ conf[:counts][:mentions] = old_conf[:counts][:mentions] || 50
402
+ conf[:counts][:convo] = old_conf[:counts][:convo] || 50
403
+ conf[:counts][:posts] = old_conf[:counts][:posts] || 50
404
+ conf[:counts][:messages] = old_conf[:counts][:messages] || 50
405
+ conf[:counts][:search] = old_conf[:counts][:search] || 200
406
+ conf[:counts][:whoreposted] = old_conf[:counts][:whoreposted] || 20
407
+ conf[:counts][:whostarred] = old_conf[:counts][:whostarred] || 20
408
+ conf[:counts][:whatstarred] = old_conf[:counts][:whatstarred] || 100
409
+ conf[:counts][:files] = old_conf[:counts][:files] || 50
410
+ @thor.say_status :save, "config file", :green
411
+ File.write(@config_path_old, conf.to_yaml)
412
+ end
413
+
414
+ def banner
415
+ <<-BANNER
416
+
417
+ \t\t _____ __ __ _____ ____ _____
418
+ \t\t | _ | | | _ | \\| | |
419
+ \t\t | |_ _| | | | | | |
420
+ \t\t |__|__| |_| |__|__|____/|_|___|
421
+
422
+
423
+ BANNER
424
+ end
425
+
426
+ end
427
+ end
@@ -2,10 +2,81 @@
2
2
  module Ayadn
3
3
  class NiceRank
4
4
 
5
+ attr_reader :store
6
+
5
7
  def initialize
6
8
  @url = 'http://api.nice.social/user/nicerank?ids='
9
+ @store = FastCache::Cache.new(5_000, 120*60) # 5000 items with 2 hours TTL each
10
+ @hits = 0
11
+ @ids = 0
12
+ @posts = 0
13
+ end
14
+
15
+ # Get posts
16
+ # Get unique posters
17
+ # Get NR response
18
+ # Fetch IDs from store
19
+ # if absent, decode + save to dic + cache in store
20
+ # if present, save to dic from store (and count hits for debug)
21
+ def get_ranks stream
22
+ user_ids, niceranks = [], {}
23
+ stream['data'].each do |post|
24
+ id = post['user']['id']
25
+ user_ids << id if @store[id].nil?
26
+ end
27
+ user_ids.uniq!
28
+ got = CNX.get "#{@url}#{user_ids.join(',')}&show_details=Y" unless user_ids.empty?
29
+ if got.nil? || got == ""
30
+ parsed = {'meta' => {'code' => 404}, 'data' => []}
31
+ else
32
+ parsed = JSON.parse(got)
33
+ end
34
+ parsed['data'].each do |obj|
35
+ res = @store[obj['user_id']]
36
+ if res.nil?
37
+ obj['account']['is_human'] == true ? is_human = 1 : is_human = 0
38
+ obj['account']['real_person'] == true ? real_person = 1 : real_person = 0
39
+ content = {
40
+ username: obj['user']['username'],
41
+ rank: obj['rank'],
42
+ is_human: is_human,
43
+ real_person: real_person
44
+ }
45
+ @store[obj['user_id']] = content
46
+ niceranks[obj['user_id']] = content
47
+ else
48
+ @hits += 1
49
+ niceranks[obj['user_id']] = res
50
+ end
51
+
52
+ end
53
+
54
+ @posts += stream['data'].size
55
+ @ids += user_ids.size
56
+
57
+ if Settings.options[:timeline][:debug] == true
58
+ deb = "\n"
59
+ deb << "+ NICERANK\n"
60
+ deb << "* t#{Time.now.to_i}\n"
61
+ deb << "Posts:\t\t#{stream['data'].size}\n"
62
+ deb << "Requested NR:\t#{user_ids.size}\n"
63
+ deb << "* TOTALS\n"
64
+ deb << "Posts:\t\t#{@posts}\n"
65
+ deb << "Fetched ranks:\t#{@ids}\n"
66
+ deb << "DB hits:\t#{@hits}\n"
67
+ deb << "Uniques:\t#{@store.count}\n"
68
+ deb << "\n"
69
+ puts deb.color(Settings.options[:colors][:debug])
70
+ Logs.rec.debug "NICERANK/POSTS: #{@posts}"
71
+ Logs.rec.debug "NICERANK/NR CALLS: #{@ids}"
72
+ Logs.rec.debug "NICERANK/CACHE HITS: #{@hits}"
73
+ Logs.rec.debug "NICERANK/CACHED IDS: #{@store.count}"
74
+ end
75
+
76
+ return niceranks
7
77
  end
8
78
 
79
+ # This is for user info, no scrolling: no need to cache
9
80
  def get_posts_day ids
10
81
  resp = JSON.parse(CNX.get("#{@url}#{ids.join(',')}&show_details=Y"))
11
82
  if resp.nil? || resp['meta']['code'] != 200
@@ -21,6 +92,9 @@ module Ayadn
21
92
  end
22
93
  end
23
94
 
95
+ # This is for user lists, no scrolling: no need to cache
96
+ # Even with a lot of requests, it's within the NR limits
97
+ # because of the slicing (upto 200 objects / call)
24
98
  def from_ids ids
25
99
  blocs, ranks = [], []
26
100
  blank = JSON.parse({'meta' => {'code' => 404}, 'data' => []}.to_json)
@@ -39,77 +113,5 @@ module Ayadn
39
113
  return ranks.flatten!
40
114
  end
41
115
 
42
- def get_ranks stream
43
- user_ids, get_these, table, niceranks = [], [], {}, {}
44
-
45
- stream['data'].each do |post|
46
- user_ids << post['user']['id'].to_i
47
- table[post['user']['id'].to_i] = post['user']['username']
48
- end
49
- user_ids.uniq!
50
-
51
- db_ranks = Databases.get_niceranks user_ids
52
- expire = Settings.options[:nicerank][:cache] * 3600 # Time.now needs seconds
53
-
54
- db_ranks.each do |id, ranks|
55
- if ranks.nil? || (Time.now - ranks[:cached]) > expire
56
- get_these << id
57
- else
58
- niceranks[id] = {
59
- username: ranks[:username],
60
- rank: ranks[:rank],
61
- is_human: ranks[:is_human],
62
- real_person: ranks[:real_person],
63
- cached: ranks[:cached]
64
- }
65
- end
66
- end
67
-
68
- Debug.how_many_ranks niceranks, get_these
69
-
70
- unless get_these.empty?
71
- got = CNX.get "#{@url}#{get_these.join(',')}&show_details=Y"
72
- blank = JSON.parse({'meta' => {'code' => 404}, 'data' => []}.to_json)
73
- if got.nil? || got == ""
74
- parsed = blank
75
- else
76
- parsed = JSON.parse(got)
77
- end
78
- if parsed['meta']['code'] != 200
79
- resp = blank
80
- else
81
- resp = parsed
82
- end
83
-
84
- if resp['meta']['code'] != 200
85
- Debug.niceranks_error resp
86
- Errors.nr "REQUESTED: #{get_these.join(' ')}"
87
- Errors.nr "RESPONSE: #{resp}"
88
- if niceranks
89
- Debug.ranks_pool niceranks
90
- return niceranks
91
- else
92
- return {}
93
- end
94
- end
95
-
96
- resp['data'].each do |obj|
97
- niceranks[obj['user_id']] = {
98
- username: table[obj['user_id']],
99
- rank: obj['rank'],
100
- is_human: obj['is_human'],
101
- real_person: obj['account']['real_person'],
102
- cached: Time.now
103
- }
104
- end
105
-
106
- Debug.total_ranks niceranks
107
- end
108
-
109
- Databases.add_niceranks niceranks
110
-
111
- niceranks
112
- end
113
-
114
116
  end
115
117
  end