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/switch.rb CHANGED
@@ -2,8 +2,8 @@
2
2
  module Ayadn
3
3
  class Switch
4
4
 
5
- def initialize
6
- @status = Status.new
5
+ def initialize status = Status.new
6
+ @status = status
7
7
  begin
8
8
  @acc_db = Amalgalite::Database.new(Dir.home + "/ayadn/accounts.sqlite")
9
9
  rescue Amalgalite::SQLite3::Error => e
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+ module Ayadn
3
+
4
+ class UserMetaObject
5
+
6
+ attr_reader :input, :code
7
+
8
+ def initialize hash, username = nil
9
+ @input = hash["meta"].nil? ? {} : hash["meta"]
10
+ @code = @input["code"]
11
+ if code == 404
12
+ Status.new.user_404(username)
13
+ Errors.info("User #{username} doesn't exist")
14
+ exit
15
+ end
16
+ end
17
+ end
18
+
19
+ class UserCountsObject
20
+
21
+ attr_reader :input, :following, :posts, :followers, :stars
22
+
23
+ def initialize hash
24
+ @input = hash["counts"]
25
+ @following = @input["following"]
26
+ @posts = @input["posts"]
27
+ @followers = @input["followers"]
28
+ @stars = @input["stars"]
29
+ end
30
+ end
31
+
32
+ class UserAnnotationObject
33
+
34
+ attr_reader :input, :type, :value
35
+
36
+ def initialize hash
37
+ @input = hash
38
+ @type = @input["type"]
39
+ @value = @input["value"]
40
+ end
41
+ end
42
+
43
+ class AvatarImageObject
44
+
45
+ attr_reader :input, :url, :width, :is_default, :height
46
+
47
+ def initialize hash
48
+ @input = hash["avatar_image"]
49
+ @url = @input["url"]
50
+ @width = @input["width"]
51
+ @is_default = @input["is_default"]
52
+ @height = @input["height"]
53
+ end
54
+ end
55
+
56
+ class CoverImageObject
57
+
58
+ attr_reader :input, :url, :width, :is_default, :height
59
+
60
+ def initialize hash
61
+ @input = hash["cover_image"]
62
+ @url = @input["url"]
63
+ @width = @input["width"]
64
+ @is_default = @input["is_default"]
65
+ @height = @input["height"]
66
+ end
67
+ end
68
+
69
+ class UserDescriptionObject
70
+
71
+ attr_reader :input, :text, :entities
72
+
73
+ def initialize hash
74
+ @input = hash["description"].nil? ? {} : hash["description"]
75
+ @text = @input["text"].nil? ? "" : @input["text"]
76
+ @entities = EntitiesObject.new(@input)
77
+ end
78
+ end
79
+
80
+ class UserObject
81
+
82
+ attr_accessor :input, :you_muted, :you_can_subscribe, :is_following, :is_follower, :timezone, :you_follow, :counts, :canonical_url, :id, :locale, :type, :annotations, :username, :avatar_image, :description, :is_muted, :follows_you, :you_can_follow, :name, :created_at, :you_blocked, :cover_image, :verified_domain, :meta
83
+
84
+ def initialize hash, username = nil
85
+ @input = hash['data'].nil? ? hash : hash['data']
86
+ @meta = UserMetaObject.new(hash, username)
87
+ @you_muted = @input["you_muted"]
88
+ @you_can_subscribe = @input["you_can_subscribe"]
89
+ @is_follower = @input["is_follower"]
90
+ @is_following = @input["is_following"]
91
+ @timezone = @input["timezone"]
92
+ @you_follow = @input["you_follow"]
93
+ @counts = UserCountsObject.new(@input) unless @input.empty?
94
+ @canonical_url = @input["canonical_url"]
95
+ @id = @input["id"]
96
+ @locale = @input["locale"]
97
+ @type = @input["type"]
98
+ if !@input["annotations"].nil?
99
+ @annotations = @input["annotations"].map { |hash| UserAnnotationObject.new(hash) }
100
+ else
101
+ @annotations = []
102
+ end
103
+ @username = @input["username"]
104
+ @avatar_image = AvatarImageObject.new(@input) unless @input.empty?
105
+ @description = UserDescriptionObject.new(@input) unless @input.empty?
106
+ @is_muted = @input["is_muted"]
107
+ @follows_you = @input["follows_you"]
108
+ @you_can_follow = @input["you_can_follow"]
109
+ @name = @input["name"].to_s.force_encoding("UTF-8")
110
+ @created_at = @input["created_at"]
111
+ @you_blocked = @input["you_blocked"]
112
+ @cover_image = CoverImageObject.new(@input) unless @input.empty?
113
+ @verified_domain = @input["verified_domain"]
114
+ end
115
+ end
116
+ end
data/lib/ayadn/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Ayadn
3
- VERSION = "3.0"
3
+ VERSION = "4.0"
4
4
  end
data/lib/ayadn/view.rb CHANGED
@@ -2,9 +2,9 @@
2
2
  module Ayadn
3
3
  class View
4
4
 
5
- def initialize
6
- @workers = Workers.new
7
- @status = Status.new
5
+ def initialize status = Status.new, workers = nil
6
+ @status = status
7
+ @workers = workers.nil? ? Workers.new(status) : workers
8
8
  end
9
9
 
10
10
  def show_cursor
@@ -16,13 +16,18 @@ module Ayadn
16
16
  end
17
17
 
18
18
  def show_posts_with_index(data, options = {}, niceranks = {})
19
- posts, view = build_stream_with_index(data, options, niceranks)
19
+ posts, view = build_stream_with_index(data.posts, options, niceranks)
20
20
  puts view unless view == ""
21
21
  Databases.save_indexed_posts(posts)
22
22
  end
23
23
 
24
24
  def show_posts(data, options = {}, niceranks = {})
25
- resp = build_stream_without_index(data, options, niceranks)
25
+ resp = build_stream_without_index(data.posts, options, niceranks)
26
+ puts resp unless resp == ""
27
+ end
28
+
29
+ def show_messages messages
30
+ resp = build_stream_without_index(messages, {}, {})
26
31
  puts resp unless resp == ""
27
32
  end
28
33
 
@@ -34,7 +39,14 @@ module Ayadn
34
39
  end
35
40
 
36
41
  def show_raw(stream, options = {})
37
- #puts stream.to_json
42
+ if stream.is_a? Hash
43
+ show_direct_raw stream
44
+ else
45
+ jj stream.input
46
+ end
47
+ end
48
+
49
+ def show_direct_raw(stream, options = {})
38
50
  jj stream
39
51
  end
40
52
 
@@ -43,7 +55,7 @@ module Ayadn
43
55
  end
44
56
 
45
57
  def show_posted(resp)
46
- show_simple_post([resp['data']], {})
58
+ show_simple_post([PostObject.new(resp['data'])], {})
47
59
  puts "\n" if timeline_is_compact
48
60
  end
49
61
 
@@ -61,57 +73,7 @@ module Ayadn
61
73
 
62
74
  def show_list_followings(list, target, options = {})
63
75
  if options["lastpost"]
64
- clear_screen()
65
- bucket = []
66
- list.each do |k,v|
67
- bucket << [k, v[0], v[1], v[2], v[3], v[4], v[5]]
68
- end
69
- count = bucket.size
70
- if options[:username]
71
- bucket.sort_by! { |obj| obj[1] }
72
- elsif options[:name]
73
- bucket.sort_by! { |obj| obj[2] }
74
- elsif options[:posts]
75
- bucket.sort_by! { |obj| [obj[5], obj[1]] }.reverse!
76
- elsif options[:date]
77
- bucket.keep_if { |obj| !obj[6].nil? }
78
- bucket.sort_by! { |obj| obj[6]["created_at"] }.reverse!
79
- end
80
- title = if target == "me"
81
- "Last post of users you're following".color(:cyan)
82
- else
83
- "Last post of users ".color(:cyan) + "#{target}".color(:red) + " is following ".color(:cyan)
84
- end
85
- puts "\t#{title}\n\n"
86
- bucket.each.with_index(1) do |obj,index|
87
- username = "@#{obj[1]}"
88
- colored_username = username.color(color_username)
89
- if obj[6].nil?
90
- @workers.thor.say_status :warning, "user #{colored_username} has no posts, ignored", :red
91
- newline()
92
- next
93
- end
94
- date = @workers.parsed_time(obj[6]["created_at"])
95
- mentions = @workers.extract_mentions(obj[6])
96
- hashtags = @workers.extract_hashtags(obj[6])
97
- text = @workers.colorize_text(obj[6]["text"], mentions, hashtags)
98
- total = "(#{obj[5]} posts)"
99
- name = obj[2] == "" ? "(no name)" : obj[2]
100
- colored_total = total.color(color_link)
101
- colored_name = name.color(color_name)
102
- colored_date = date.color(color_date)
103
- puts "#{colored_username} #{colored_name} #{colored_date} #{colored_total}\n"
104
- newline()
105
- puts text
106
- unless index == count
107
- newline()
108
- puts "----------\n"
109
- newline()
110
- else
111
- puts "\n"
112
- newline()
113
- end
114
- end
76
+ show_list_with_lastpost(list, target, options)
115
77
  else
116
78
  puts @workers.build_followings_list(list, target, options)
117
79
  puts "\n"
@@ -143,44 +105,13 @@ module Ayadn
143
105
  end
144
106
 
145
107
  def show_settings
146
- table = Terminal::Table.new do |t|
147
- if Settings.options[:formats][:table][:borders] == true
148
- t.style = { :width => Settings.options[:formats][:table][:width], border_x: '—', border_i: '+', border_y: '|' }
149
- else
150
- t.style = { :width => Settings.options[:formats][:table][:width], border_x: ' ', border_i: ' ', border_y: ' ' }
151
- end
152
- t.title = "Current Ayadn settings".color(:cyan)
153
- t.headings = [ "Category".color(:red), "Parameter".color(:red), "Value(s)".color(:red) ]
154
- @iter = 0
155
- opts = Settings.options.dup
156
- opts.each do |k,v|
157
- v.each do |x,y|
158
- t << :separator if @iter >= 1 && timeline_is_compact == false
159
- unless y.is_a?(Hash)
160
- t << [ k.to_s.color(:cyan), x.to_s.color(:yellow), y.to_s.color(:green) ]
161
- else
162
- y.each do |c|
163
- yk = c[0]
164
- tempv = c[1].to_s
165
- if tempv.size > 10
166
- yv = "#{tempv[0..7]}..."
167
- else
168
- yv = tempv
169
- end
170
- t << [ k.to_s.color(:cyan), x.to_s.color(:yellow), "#{yk} = #{yv}".color(:green) ]
171
- end
172
- end
173
- @iter += 1
174
- end
175
- end
176
- end
177
108
  clear_screen()
178
- puts table
109
+ puts Settings.options.to_table
179
110
  puts "\n"
180
111
  end
181
112
 
182
- def show_userinfos(content, token, show_ranks = false)
183
- if timeline_is_compact == true
113
+ def show_userinfos(user, token, show_ranks = false)
114
+ if timeline_is_compact
184
115
  padding = "\n"
185
116
  view = "\n"
186
117
  else
@@ -188,106 +119,92 @@ module Ayadn
188
119
  view = ""
189
120
  end
190
121
 
191
- if content['name']
192
- view << "Name\t\t\t".color(:cyan) + content['name'].color(color_name)
122
+ if !user.name.blank?
123
+ view << "Name\t\t\t".color(:cyan) + user.name.color(color_name)
193
124
  else
194
125
  view << "Name\t\t\t".color(:cyan) + "(no name)".color(:red)
195
126
  end
196
127
 
197
- view << "#{padding}Username\t\t".color(:cyan) + "@#{content['username']}".color(color_username)
128
+ view << "#{padding}Username\t\t".color(:cyan) + "@#{user.username}".color(color_username)
198
129
 
199
- view << "#{padding}ID\t\t\t".color(:cyan) + content['id'].color(color_id)
130
+ view << "#{padding}ID\t\t\t".color(:cyan) + user.id.color(color_id)
200
131
 
201
- view << "#{padding}URL\t\t\t".color(:cyan) + content['canonical_url'].color(color_link)
132
+ view << "#{padding}URL\t\t\t".color(:cyan) + user.canonical_url.color(color_link)
202
133
 
203
- unless content['verified_domain'].nil?
204
- if content['verified_domain'] =~ (/http/ || /https/)
205
- domain = content['verified_domain']
134
+ unless user.verified_domain.nil?
135
+ if user.verified_domain =~ (/http/ || /https/)
136
+ domain = user.verified_domain
206
137
  else
207
- domain = "http://#{content['verified_domain']}"
138
+ domain = "http://#{user.verified_domain}"
208
139
  end
209
140
  view << "\nVerified domain\t\t".color(:cyan) + domain.color(color_link)
210
141
  end
211
142
 
212
143
 
213
- view << "#{padding}Account creation\t".color(:cyan) + @workers.parsed_time(content['created_at']).color(color_excerpt)
214
- view << "#{padding}TimeZone\t\t".color(:cyan) + content['timezone'].color(color_excerpt)
215
- view << "\nLocale\t\t\t".color(:cyan) + content['locale'].color(color_excerpt)
216
-
217
- view << "#{padding}Posts\t\t\t".color(:cyan) + content['counts']['posts'].to_s.color(color_excerpt)
218
-
144
+ view << "#{padding}Account creation\t".color(:cyan) + @workers.parsed_time(user.created_at).color(color_excerpt)
145
+ view << "#{padding}TimeZone\t\t".color(:cyan) + user.timezone.color(color_excerpt)
146
+ view << "\nLocale\t\t\t".color(:cyan) + user.locale.color(color_excerpt)
219
147
 
220
- # unless show_ranks == false
221
- # # this is ok for one user, but do not call this in a loop
222
- # # do call them all at once instead if many
223
- # ranks = NiceRank.new.get_posts_day([content['id'].to_i])
224
- # unless ranks.empty?
225
- # view << "#{padding}Posts/day\t\t".color(:cyan) + ranks[0][:posts_day].to_s.color(color_excerpt)
226
- # end
227
- # end
148
+ view << "#{padding}Posts\t\t\t".color(:cyan) + user.counts.posts.to_s.color(color_excerpt)
228
149
 
229
- view << "#{padding}Following\t\t".color(:cyan) + content['counts']['following'].to_s.color(color_excerpt)
230
- view << "\nFollowers\t\t".color(:cyan) + content['counts']['followers'].to_s.color(color_excerpt)
150
+ view << "#{padding}Following\t\t".color(:cyan) + user.counts.following.to_s.color(color_excerpt)
151
+ view << "\nFollowers\t\t".color(:cyan) + user.counts.followers.to_s.color(color_excerpt)
231
152
 
232
- if content['username'] == Settings.config[:identity][:username] && !token.nil?
153
+ if user.username == Settings.config.identity.username && !token.nil?
233
154
  view << "#{padding}Storage used\t\t".color(:cyan) + "#{token['storage']['used'].to_filesize}".color(color_excerpt)
234
155
  view << "\nStorage available\t".color(:cyan) + "#{token['storage']['available'].to_filesize}".color(color_excerpt)
235
156
  end
236
157
 
237
- #view << "\nStars\t\t\t".color(:cyan) + content['counts']['stars'].to_s.color(:yellow)
238
-
239
- unless content['username'] == Settings.config[:identity][:username]
240
- if content['you_follow']
241
- view << "#{padding}You follow ".color(:cyan) + "@#{content['username']}".color(color_username)
158
+ unless user.username == Settings.config.identity.username
159
+ if user.you_follow
160
+ view << "#{padding}You follow ".color(:cyan) + "@#{user.username}".color(color_username)
242
161
  else
243
- view << "#{padding}You don't follow ".color(:cyan) + "@#{content['username']}".color(color_username)
162
+ view << "#{padding}You don't follow ".color(:cyan) + "@#{user.username}".color(color_username)
244
163
  end
245
- if content['follows_you']
246
- view << "\n" + "@#{content['username']}".color(color_username) + " follows you".color(:cyan)
164
+ if user.follows_you
165
+ view << "\n" + "@#{user.username}".color(color_username) + " follows you".color(:cyan)
247
166
  else
248
- view << "\n" + "@#{content['username']}".color(color_username) + " doesn't follow you".color(:cyan)
167
+ view << "\n" + "@#{user.username}".color(color_username) + " doesn't follow you".color(:cyan)
249
168
  end
250
- if content['you_muted']
251
- view << "\nYou muted " + "@#{content['username']}".color(color_username)
169
+ if user.you_muted
170
+ view << "\nYou muted " + "@#{user.username}".color(color_username)
252
171
  end
253
- if content['you_blocked']
254
- view << "\nYou blocked " + "@#{content['username']}".color(color_username)
172
+ if user.you_blocked
173
+ view << "\nYou blocked " + "@#{user.username}".color(color_username)
255
174
  end
256
175
  end
257
176
 
258
- unless content['annotations'].empty?
259
- view << "\n" unless timeline_is_compact == true
177
+ unless user.annotations.empty?
178
+ view << "\n" unless timeline_is_compact
260
179
  end
261
- content['annotations'].each do |anno|
262
- case anno['type']
180
+ user.annotations.each do |anno|
181
+ case anno.type
263
182
  when "net.app.core.directory.blog"
264
- view << "\nBlog\t\t\t".color(:cyan) + "#{anno['value']['url']}".color(color_link)
183
+ view << "\nBlog\t\t\t".color(:cyan) + "#{anno.value['url']}".color(color_link)
265
184
  when "net.app.core.directory.twitter"
266
- view << "\nTwitter\t\t\t".color(:cyan) + "#{anno['value']['username']}".color(:green)
185
+ view << "\nTwitter\t\t\t".color(:cyan) + "#{anno.value['username']}".color(:green)
267
186
  when "com.appnetizens.userinput.birthday"
268
- view << "\nBirthday\t\t".color(:cyan) + "#{anno['value']['birthday']}".color(:green)
187
+ view << "\nBirthday\t\t".color(:cyan) + "#{anno.value['birthday']}".color(:green)
269
188
  end
270
189
  end
271
190
 
272
-
273
- #view << "#{padding}Avatar URL\t\t".color(:cyan) + content['avatar_image']['url']
274
-
275
- if content['description']
276
- mentions = content['description']['entities']['mentions'].map {|m| "@#{m['name']}"}
277
- hashtags = content['description']['entities']['hashtags'].map {|m| m['name']}
278
- view << "#{padding}#{@workers.colorize_text(content['description']['text'], mentions, hashtags)}\n"
279
- view << "\n" unless timeline_is_compact == true
191
+ if !user.description.blank?
192
+ mentions = user.description.entities.mentions.map {|m| "@#{m.name}"}
193
+ hashtags = user.description.entities.hashtags.map {|m| m.name}
194
+ view << "#{padding}#{@workers.colorize_text(user.description.text, mentions, hashtags)}\n"
195
+ view << "\n" unless timeline_is_compact
280
196
  end
281
197
 
282
- view << "\n" if timeline_is_compact == true
198
+ view << "\n" if timeline_is_compact
283
199
 
284
200
  puts view
285
201
 
286
202
  end
287
203
 
288
- def show_channels(resp, options = {})
204
+ def show_channels(stream, options = {})
289
205
  view = ""
290
- bucket = @workers.build_channels(resp['data'], options)
206
+ bucket = @workers.build_channels(stream, options)
207
+
291
208
  bucket.reverse.each do |ch|
292
209
  if options[:broadcasts]
293
210
  next if ch.type != "net.app.core.broadcast"
@@ -331,8 +248,7 @@ module Ayadn
331
248
  view << "\n"
332
249
  if ch.owner
333
250
  view << "Owner: ".color(:cyan)
334
- view << "@#{ch.owner['username']}".color(color_username)
335
- # + (#{ch.owner['name']}) if ch.owner['name']
251
+ view << "@#{ch.owner.username}".color(color_username)
336
252
  view << "\n"
337
253
  end
338
254
  unless options[:channels] # unless the request comes from Search
@@ -344,42 +260,42 @@ module Ayadn
344
260
  view << "#{ch.type}".color(color_index)
345
261
  view << "\n"
346
262
  if ch.type == "net.patter-app.room"
347
- ann = ch.annotations.select {|a| a['type'] == "net.patter-app.settings"}
263
+ ann = ch.annotations.select {|a| a.type == "net.patter-app.settings"}
348
264
  view << "Name: ".color(:cyan)
349
- view << "#{ann[0]['value']['name']}".color(color_link)
265
+ view << "#{ann[0].value['name']}".color(color_link)
350
266
  view << "\n"
351
267
  view << "Description: ".color(:cyan)
352
- view << "#{ann[0]['value']['blurb']}".color(color_username)
268
+ view << "#{ann[0].value['blurb']}".color(color_username)
353
269
  view << "\n"
354
- ann = ch.annotations.select {|a| a['type'] == "net.app.core.fallback_url"}
270
+ ann = ch.annotations.select {|a| a.type == "net.app.core.fallback_url"}
355
271
  view << "URL: ".color(:cyan)
356
- view << "#{ann[0]['value']['url']}".color(color_link)
272
+ view << "#{ann[0].value['url']}".color(color_link)
357
273
  view << "\n"
358
274
  end
359
275
  if ch.type == "net.app.core.broadcast"
360
- ann = ch.annotations.select {|a| a['type'] == "net.app.core.broadcast.metadata"}
276
+ ann = ch.annotations.select {|a| a.type == "net.app.core.broadcast.metadata"}
361
277
  view << "Title: ".color(:cyan)
362
- view << "#{ann[0]['value']['title']}".color(color_link)
278
+ view << "#{ann[0].value['title']}".color(color_link)
363
279
  view << "\n"
364
280
  view << "Description: ".color(:cyan)
365
- view << "#{ann[0]['value']['description']}".color(color_username)
281
+ view << "#{ann[0].value['description']}".color(color_username)
366
282
  view << "\n"
367
- ann = ch.annotations.select {|a| a['type'] == "net.app.core.fallback_url"}
283
+ ann = ch.annotations.select {|a| a.type == "net.app.core.fallback_url"}
368
284
  view << "URL: ".color(:cyan)
369
- view << "#{ann[0]['value']['url']}".color(color_link)
285
+ view << "#{ann[0].value['url']}".color(color_link)
370
286
  view << "\n"
371
287
  end
372
288
  unless ch.recent_message.nil?
373
- unless ch.recent_message['text'].nil?
374
- view << "Most recent message (#{@workers.parsed_time(ch.recent_message['created_at'])}): ".color(:cyan)
289
+ unless ch.recent_message.text.nil?
290
+ view << "Most recent message (#{@workers.parsed_time(ch.recent_message.created_at)}): ".color(:cyan)
375
291
  view << "\n"
376
- view << "---\n#{ch.recent_message['text']}\n---"
292
+ view << "---\n#{ch.recent_message.text}\n---"
377
293
  end
378
294
  end
379
295
  if ch.type == "net.paste-app.clips"
380
- ann = ch.recent_message['annotations'].select {|a| a['type'] == "net.paste-app.clip"}
296
+ ann = ch.recent_message.annotations.select {|a| a.type == "net.paste-app.clip"}
381
297
  view << "\n\n"
382
- view << ann[0]['value']['content']
298
+ view << ann[0].value['content']
383
299
  view << "\n"
384
300
  end
385
301
  view << "\n\n"
@@ -393,18 +309,18 @@ module Ayadn
393
309
 
394
310
  def render(stream, options = {}, niceranks = {})
395
311
  unless options[:raw]
396
- get(stream['data'], options, niceranks)
312
+ get(stream, options, niceranks)
397
313
  else
398
314
  show_raw(stream)
399
315
  end
400
316
  end
401
317
 
402
- def get(stream, options = {}, niceranks = {})
318
+ def get(data, options = {}, niceranks = {})
403
319
  clear_screen()
404
320
  if options[:index]
405
- show_posts_with_index(stream, options, niceranks)
321
+ show_posts_with_index(data, options, niceranks)
406
322
  else
407
- show_posts(stream, options, niceranks)
323
+ show_posts(data, options, niceranks)
408
324
  end
409
325
  end
410
326
 
@@ -428,30 +344,15 @@ module Ayadn
428
344
  end
429
345
 
430
346
  def all_hashtag_links(stream, hashtag)
431
- clear_screen()
432
- @status.info("info", "links from posts containing hashtag '##{hashtag}':", "cyan")
433
- links = @workers.links_from_posts(stream)
434
- links.uniq!
435
- show_links(links)
436
- @workers.save_links(links, "hashtag", hashtag)
347
+ all_links(stream, "hashtag", hashtag)
437
348
  end
438
349
 
439
350
  def all_search_links(stream, words)
440
- clear_screen()
441
- @status.info("info", "links from posts containing word(s) '#{words}':", "cyan")
442
- links = @workers.links_from_posts(stream)
443
- links.uniq!
444
- show_links(links)
445
- @workers.save_links(links, "search", words)
351
+ all_links(stream, "search", hashtag)
446
352
  end
447
353
 
448
354
  def all_stars_links(stream)
449
- clear_screen()
450
- @status.info("info", "links from your starred posts:", "cyan")
451
- links = @workers.links_from_posts(stream)
452
- links.uniq!
453
- show_links(links)
454
- @workers.save_links(links, 'starred')
355
+ all_links(stream, "starred")
455
356
  end
456
357
 
457
358
  def infos(stream, token)
@@ -489,8 +390,83 @@ module Ayadn
489
390
 
490
391
  private
491
392
 
393
+ def all_links stream, type, arg = nil
394
+ clear_screen()
395
+ case type
396
+ when "hashtag"
397
+ @status.all_hashtag_links(arg)
398
+ when "search"
399
+ @status.all_search_links(arg)
400
+ when "starred"
401
+ @status.all_stars_links
402
+ end
403
+ links = @workers.links_from_posts(stream)
404
+ links.uniq!
405
+ show_links(links)
406
+ arg.nil? ? @workers.save_links(links, type) : @workers.save_links(links, type, arg)
407
+ end
408
+
409
+ ### list = id => [username, name, bool, bool, int, message]
410
+ def show_list_with_lastpost(list, target, options)
411
+ clear_screen()
412
+ bucket = []
413
+ list.each do |k,v|
414
+ if !v[5].nil?
415
+ bucket << [k, v[0], v[1], v[2], v[3], v[4], PostObject.new(v[5])]
416
+ else
417
+ bucket << [k, v[0], v[1], v[2], v[3], v[4], nil]
418
+ end
419
+ end
420
+ count = bucket.size
421
+ if options[:username]
422
+ bucket.sort_by! { |obj| obj[1] }
423
+ elsif options[:name]
424
+ bucket.sort_by! { |obj| obj[2] }
425
+ elsif options[:posts]
426
+ bucket.sort_by! { |obj| [obj[5], obj[1]] }.reverse!
427
+ elsif options[:date]
428
+ bucket.keep_if { |obj| !obj[6].nil? }
429
+ bucket.sort_by! { |obj| obj[6].created_at }.reverse!
430
+ end
431
+ title = if target == "me"
432
+ "Last post of users you're following".color(:cyan)
433
+ else
434
+ "Last post of users ".color(:cyan) + "#{target}".color(:red) + " is following ".color(:cyan)
435
+ end
436
+ puts "\t#{title}\n\n"
437
+ bucket.each.with_index(1) do |obj,index|
438
+ username = "@#{obj[1]}"
439
+ colored_username = username.color(color_username)
440
+ if obj[6].nil?
441
+ @status.thor.say_status :warning, "user #{colored_username} has no posts, ignored", :red
442
+ newline()
443
+ next
444
+ end
445
+ date = @workers.parsed_time(obj[6].created_at)
446
+ mentions = @workers.extract_mentions(obj[6])
447
+ hashtags = @workers.extract_hashtags(obj[6])
448
+ text = @workers.colorize_text(obj[6].text, mentions, hashtags)
449
+ total = "(#{obj[5]} posts)"
450
+ name = obj[2].blank? ? "(no name)" : obj[2]
451
+ colored_total = total.color(color_link)
452
+ colored_name = name.color(color_name)
453
+ colored_date = date.color(color_date)
454
+ puts "#{colored_username} #{colored_name} #{colored_date} #{colored_total}\n"
455
+ newline()
456
+ puts text
457
+ unless index == count
458
+ newline()
459
+ puts "----------\n"
460
+ newline()
461
+ else
462
+ puts "\n"
463
+ newline()
464
+ end
465
+ end
466
+ end
467
+
492
468
  def newline
493
- puts "\n" unless timeline_is_compact == true
469
+ puts "\n" unless timeline_is_compact
494
470
  end
495
471
 
496
472
  def get_broadcast_alias_from_id(event_id)
@@ -503,78 +479,78 @@ module Ayadn
503
479
  end
504
480
 
505
481
  def filter_nicerank posts, options
506
- if options[:filter] == true # if this option is true in Action (it's only for global, actually)
507
- if Settings.options[:nicerank][:filter] == true
508
- filtered = {}
509
- posts.each do |id,content|
510
- if Settings.options[:nicerank][:unranked] == true
511
- next if content[:nicerank] == false
482
+ if options[:filter] # if this option is true in Action (it's only for global, actually)
483
+ if Settings.options.nicerank.filter
484
+ bucket = []
485
+ posts.each do |post|
486
+ if Settings.options.nicerank.unranked
487
+ next if !post.nicerank # .nicerank is False or Fixnum (yeah...)
512
488
  end
513
- unless content[:nicerank] == false
514
- next if content[:nicerank] < Settings.options[:nicerank][:threshold]
515
- next if content[:is_human] == 0
489
+ unless !post.nicerank
490
+ next if post.nicerank < Settings.options.nicerank.threshold
491
+ next if post.is_human == 0
516
492
  end
517
- filtered[id] = content
493
+ bucket << post
518
494
  end
519
- return filtered
495
+ return bucket
520
496
  end
521
497
  end
522
498
  return posts
523
499
  end
524
500
 
525
- def build_stream_with_index(data, options, niceranks) #expects an array
501
+ def build_stream_with_index(posts, options, niceranks)
526
502
  @view = ""
527
- posts = filter_nicerank(@workers.build_posts(data.reverse, niceranks), options)
528
- posts.each do |id,content|
529
- format = "%03d" % content[:count]
530
- arrow = arrow_count(options, content)
503
+ posts = filter_nicerank(@workers.build_posts(posts.reverse, niceranks), options)
504
+ posts.each do |post|
505
+ format = "%03d" % post.count
506
+ arrow = arrow_count(options, post)
531
507
  count = "#{arrow}#{format}"
532
- if content[:username] == Settings.config[:identity][:username]
508
+ if post.username == Settings.config.identity.username
533
509
  @view << count.color(color_index).inverse
534
- elsif content[:mentions].include?(Settings.config[:identity][:username]) && options[:in_mentions].nil?
510
+ elsif post.mentions.include?(Settings.config.identity.username) && options[:in_mentions].nil?
535
511
  @view << count.color(color_mention).inverse
536
512
  else
537
513
  @view << count.color(color_index)
538
514
  end
539
515
  @view << ": ".color(color_index)
540
- @view << build_content(content)
516
+ @view << build_content(post)
541
517
  end
542
518
  return posts, @view
543
519
  end
544
520
 
545
- def build_stream_without_index(data, options, niceranks) #expects an array
521
+ def build_stream_without_index(posts, options, niceranks)
546
522
  @view = ""
547
- posts = filter_nicerank(@workers.build_posts(data.reverse, niceranks), options)
548
- posts.each do |id,content|
549
- content[:id] = arrow_id(options, content)
550
- if content[:username] == Settings.config[:identity][:username]
551
- @view << content[:id].color(color_id).inverse + " "
552
- elsif content[:mentions].include?(Settings.config[:identity][:username]) && options[:in_mentions].nil?
553
- @view << content[:id].color(color_mention).inverse + " "
523
+ posts = filter_nicerank(@workers.build_posts(posts.reverse, niceranks), options)
524
+ posts.each do |post|
525
+ post.id = arrow_id(options, post)
526
+ if post.username == Settings.config.identity.username
527
+ @view << post.id.color(Settings.options.colors.id).inverse + " "
528
+ elsif post.mentions.include?(Settings.config.identity.username) && options[:in_mentions].nil?
529
+ @view << post.id.color(color_mention).inverse + " "
554
530
  else
555
- @view << content[:id].color(color_id) + " "
531
+ @view << post.id.color(Settings.options.colors.id) + " "
556
532
  end
557
- @view << build_content(content)
533
+ @view << build_content(post)
558
534
  end
559
535
  @view
560
536
  end
561
537
 
562
- def arrow_count options, content
538
+ def arrow_count options, post
563
539
  if options[:reply_to]
564
- return '⬇︎ ' if options[:reply_to] == content[:id]
565
- return '⬆︎ ' if options[:post_id] == content[:id]
540
+ return '⬇︎ ' if options[:reply_to] == post.id
541
+ return '⬆︎ ' if options[:post_id] == post.id
566
542
  return ''
567
543
  end
568
544
  ''
569
545
  end
570
546
 
571
- def arrow_id options, content
547
+ def arrow_id options, post
572
548
  if options[:reply_to]
573
- return content[:id].to_s.prepend('⬇︎ ') if options[:reply_to] == content[:id]
574
- return content[:id].to_s.prepend('⬆︎ ') if options[:post_id] == content[:id]
575
- return content[:id].to_s
549
+ return post.id.to_s.prepend('⬇︎ ') if options[:reply_to] == post.id
550
+ return post.id.to_s.prepend('⬆︎ ') if options[:post_id] == post.id
551
+ return post.id.to_s
576
552
  end
577
- content[:id].to_s
553
+ post.id.to_s
578
554
  end
579
555
 
580
556
  def build_interactions_stream(data)
@@ -620,7 +596,7 @@ module Ayadn
620
596
  inter << "welcomed ".color(:green)
621
597
  inter << "you!".color(:yellow)
622
598
  end
623
- if timeline_is_compact == true
599
+ if timeline_is_compact
624
600
  inter << "\n"
625
601
  else
626
602
  inter << "\n\n"
@@ -672,25 +648,25 @@ module Ayadn
672
648
  view
673
649
  end
674
650
 
675
- def build_content(content)
651
+ def build_content(post)
676
652
  view = ""
677
- view << build_header(content)
678
- view << "\n" unless timeline_is_compact == true
679
- view << content[:text]
680
- view << "\n" unless timeline_is_compact == true
681
- if content[:has_checkins]
682
- view << build_checkins(content)
683
- view << "\n" unless timeline_is_compact == true
684
- end
685
- unless content[:links].empty?
653
+ view << build_header(post)
654
+ view << "\n" unless timeline_is_compact
655
+ view << post.text
656
+ view << "\n" unless timeline_is_compact
657
+ if post.has_checkins
658
+ view << build_checkins(post)
659
+ view << "\n" unless timeline_is_compact
660
+ end
661
+ unless post.links.empty?
686
662
  view << "\n"
687
- content[:links].each do |link|
663
+ post.links.each do |link|
688
664
  view << link.color(color_link)
689
665
  view << "\n"
690
666
  end
691
667
  end
692
- if timeline_is_compact == true
693
- if content[:links].empty?
668
+ if timeline_is_compact
669
+ if post.links.empty?
694
670
  view << "\n"
695
671
  else
696
672
  view
@@ -700,75 +676,76 @@ module Ayadn
700
676
  end
701
677
  end
702
678
 
703
- def build_header(content)
679
+ def build_header(post)
704
680
  header = ""
705
- header << content[:handle].color(color_username)
706
- if Settings.options[:timeline][:name]
681
+ header << post.handle.color(color_username)
682
+ if Settings.options.timeline.name
707
683
  header << " "
708
- header << content[:name].color(color_name)
684
+ header << post.name.color(color_name)
709
685
  end
710
- if Settings.options[:timeline][:date]
686
+ if Settings.options.timeline.date
711
687
  header << " "
712
- if Settings.global[:scrolling] == false
713
- header << content[:date].color(color_date)
688
+ if !Settings.global.scrolling
689
+ header << post.date.color(color_date)
714
690
  else
715
- if Settings.options[:scroll][:date] == false
716
- header << content[:date_short].color(color_date)
691
+ if !Settings.options.scroll.date
692
+ header << post.date_short.color(color_date)
717
693
  else
718
- header << content[:date].color(color_date)
694
+ header << post.date.color(color_date)
719
695
  end
720
696
  end
721
697
  end
722
- if Settings.options[:timeline][:source]
698
+ if Settings.options.timeline.source
723
699
  header << " "
724
- header << "[#{content[:source_name]}]".color(color_source)
700
+ header << "[#{post.source_name}]".color(color_source)
725
701
  end
726
- if Settings.options[:timeline][:symbols]
727
- header << " <".color(color_symbols) if content[:is_reply]
728
- header << " #{content[:num_stars]}*".color(color_symbols) if content[:is_starred]
729
- header << " #{content[:num_reposts]}x".color(color_symbols) if content[:num_reposts] > 0
730
- header << " >".color(color_symbols) if content[:num_replies] > 0
702
+ if Settings.options.timeline.symbols
703
+ header << " <".color(color_symbols) if post.is_reply
704
+ header << " #{post.num_stars}*".color(color_symbols) if post.is_starred
705
+ header << " #{post.num_reposts}x".color(color_symbols) if post.num_reposts > 0
706
+ header << " >".color(color_symbols) if post.num_replies > 0
731
707
  end
732
708
  header << "\n"
733
709
  end
734
710
 
735
- def build_checkins(content)
736
- unless content[:checkins][:name].nil?
737
- num_dots = content[:checkins][:name].length
711
+ def build_checkins(post)
712
+ unless post.checkins['name'].nil?
713
+ num_dots = post.checkins['name'].length
738
714
  else
739
715
  num_dots = 10
740
716
  end
741
- if timeline_is_compact == true
717
+ if timeline_is_compact
742
718
  hd = "\n"
743
719
  else
744
720
  hd = (".".color(color_dots)) * num_dots
745
721
  hd << "\n"
746
722
  end
747
723
  formatted = { header: hd }
748
- content[:checkins].each do |key, val|
724
+ post.checkins.each do |key, val|
749
725
  formatted[key] = val
750
726
  end
751
727
 
752
728
  formatted[:name] = "" if formatted[:name].nil?
753
729
  chk = formatted[:header]
730
+
754
731
  unless formatted[:name] == ""
755
732
  chk << formatted[:name].color(color_dots)
756
733
  chk << "\n"
757
734
  end
758
- unless formatted[:title].nil? || formatted[:title] == formatted[:name]
735
+ unless formatted[:title].blank? || formatted[:title] == formatted[:name]
759
736
  chk << formatted[:title]
760
737
  chk << "\n"
761
738
  end
762
- unless formatted[:address].nil?
739
+ unless formatted[:address].blank?
763
740
  chk << formatted[:address]
764
741
  chk << "\n"
765
742
  end
743
+
766
744
  unless formatted[:address_extended].nil?
767
745
  chk << formatted[:address_extended]
768
746
  chk << "\n"
769
747
  end
770
-
771
- unless formatted[:postcode].nil?
748
+ unless formatted[:postcode].blank?
772
749
  unless formatted[:locality].nil?
773
750
  chk << "#{formatted[:postcode]}, #{formatted[:locality]}"
774
751
  else
@@ -817,51 +794,51 @@ module Ayadn
817
794
  private
818
795
 
819
796
  def color_username
820
- Settings.options[:colors][:username]
797
+ Settings.options.colors.username
821
798
  end
822
799
 
823
800
  def color_name
824
- Settings.options[:colors][:name]
801
+ Settings.options.colors.name
825
802
  end
826
803
 
827
804
  def color_link
828
- Settings.options[:colors][:link]
805
+ Settings.options.colors.link
829
806
  end
830
807
 
831
808
  def color_date
832
- Settings.options[:colors][:date]
809
+ Settings.options.colors.date
833
810
  end
834
811
 
835
812
  def color_id
836
- Settings.options[:colors][:id]
813
+ Settings.options.colors.id
837
814
  end
838
815
 
839
816
  def color_excerpt
840
- Settings.options[:colors][:excerpt]
817
+ Settings.options.colors.excerpt
841
818
  end
842
819
 
843
820
  def color_symbols
844
- Settings.options[:colors][:symbols]
821
+ Settings.options.colors.symbols
845
822
  end
846
823
 
847
824
  def color_index
848
- Settings.options[:colors][:index]
825
+ Settings.options.colors.index
849
826
  end
850
827
 
851
828
  def color_mention
852
- Settings.options[:colors][:mentions]
829
+ Settings.options.colors.mentions
853
830
  end
854
831
 
855
832
  def color_source
856
- Settings.options[:colors][:source]
833
+ Settings.options.colors.source
857
834
  end
858
835
 
859
836
  def color_dots
860
- Settings.options[:colors][:dots]
837
+ Settings.options.colors.dots
861
838
  end
862
839
 
863
840
  def timeline_is_compact
864
- Settings.options[:timeline][:compact]
841
+ Settings.options.timeline.compact
865
842
  end
866
843
 
867
844
  end