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/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