ayadn 0.6.4 → 1.0.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +20 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +17 -0
  5. data/Gemfile +14 -0
  6. data/Guardfile +26 -0
  7. data/LICENSE.txt +22 -0
  8. data/MANUAL.md +946 -0
  9. data/README.md +26 -411
  10. data/Rakefile +6 -0
  11. data/ayadn.gemspec +39 -0
  12. data/bin/ayadn +3 -3
  13. data/lib/ayadn.rb +12 -25
  14. data/lib/ayadn/action.rb +1121 -0
  15. data/lib/ayadn/alias.rb +106 -0
  16. data/lib/ayadn/api.rb +312 -301
  17. data/lib/ayadn/app.rb +429 -365
  18. data/lib/ayadn/authorize.rb +127 -28
  19. data/lib/ayadn/blacklist.rb +116 -0
  20. data/lib/ayadn/cnx.rb +105 -0
  21. data/lib/ayadn/databases.rb +110 -0
  22. data/lib/ayadn/descriptions.rb +1043 -0
  23. data/lib/ayadn/endpoints.rb +220 -153
  24. data/lib/ayadn/errors.rb +37 -0
  25. data/lib/ayadn/extend.rb +4 -10
  26. data/lib/ayadn/fileops.rb +48 -0
  27. data/lib/ayadn/logs.rb +32 -0
  28. data/lib/ayadn/pinboard.rb +46 -35
  29. data/lib/ayadn/post.rb +229 -212
  30. data/lib/ayadn/scroll.rb +251 -0
  31. data/lib/ayadn/set.rb +377 -0
  32. data/lib/ayadn/settings.rb +195 -0
  33. data/lib/ayadn/status.rb +226 -165
  34. data/lib/ayadn/switch.rb +72 -0
  35. data/lib/ayadn/version.rb +4 -0
  36. data/lib/ayadn/view.rb +506 -269
  37. data/lib/ayadn/workers.rb +362 -0
  38. data/spec/helpers.rb +19 -0
  39. data/spec/mock/@ericd.json +160 -0
  40. data/spec/mock/@m.json +45 -0
  41. data/spec/mock/checkins.json +1856 -0
  42. data/spec/mock/fwr_@ayadn.json +1077 -0
  43. data/spec/mock/posted.json +1 -0
  44. data/spec/mock/stream.json +1 -0
  45. data/spec/spec_helper.rb +14 -0
  46. data/spec/unit/api_spec.rb +61 -0
  47. data/spec/unit/databases_spec.rb +5 -0
  48. data/spec/unit/descriptions_spec.rb +9 -0
  49. data/spec/unit/endpoints_spec.rb +35 -0
  50. data/spec/unit/post_spec.rb +136 -0
  51. data/spec/unit/status_spec.rb +9 -0
  52. data/spec/unit/view_spec.rb +119 -0
  53. data/spec/unit/workers_spec.rb +147 -0
  54. metadata +216 -40
  55. data/CHANGELOG.md +0 -250
  56. data/CONTRIBUTORS.md +0 -5
  57. data/LICENSE.md +0 -14
  58. data/lib/ayadn/adn_files.rb +0 -84
  59. data/lib/ayadn/client-http.rb +0 -226
  60. data/lib/ayadn/colors.rb +0 -62
  61. data/lib/ayadn/config.yml +0 -35
  62. data/lib/ayadn/debug.rb +0 -36
  63. data/lib/ayadn/files.rb +0 -184
  64. data/lib/ayadn/get-api.rb +0 -43
  65. data/lib/ayadn/help.rb +0 -152
  66. data/lib/ayadn/list.rb +0 -89
  67. data/lib/ayadn/main.rb +0 -542
  68. data/lib/ayadn/requires.rb +0 -12
  69. data/lib/ayadn/skip.rb +0 -27
  70. data/lib/ayadn/tools.rb +0 -208
  71. data/lib/ayadn/user-stream.rb +0 -91
  72. data/lib/ayadn/view-channels.rb +0 -120
  73. data/lib/ayadn/view-interactions.rb +0 -57
  74. data/lib/ayadn/view-object.rb +0 -195
  75. data/lib/experiments.rb +0 -109
@@ -1,29 +1,128 @@
1
- #!/usr/bin/env ruby
2
1
  # encoding: utf-8
3
- class AyaDN
4
- def ayadnAuthorize(action)
5
- $files.makedir($tools.ayadn_configuration[:authorization_path])
6
- if action == "reset"
7
- $files.reset_credentials
8
- end
9
- auth_token = $files.auth_read
10
- if auth_token == nil
11
- url = @api.makeAuthorizeURL
12
- case $tools.ayadn_configuration[:platform]
13
- when $tools.winplatforms
14
- puts $status.launchAuthorization("win")
15
- when /linux/
16
- puts $status.launchAuthorization("linux")
17
- else
18
- puts $status.launchAuthorization("osx")
19
- $tools.startBrowser(url)
20
- end
21
- auth_token = STDIN.gets.chomp()
22
- $files.auth_write(auth_token)
23
- puts $status.authorized
24
- sleep 3
25
- puts $tools.helpScreen
26
- puts "Enjoy!\n".cyan
27
- end
28
- end
29
- end
2
+ module Ayadn
3
+ class Authorize
4
+
5
+ def authorize
6
+ puts "\e[H\e[2J"
7
+ try_remove_old_ayadn
8
+ show_link
9
+ token = get_token
10
+ check_token(token)
11
+ puts "\n\nThanks! Contacting App.net...\n".color(:green)
12
+ user = create_user_data(token, Dir.home + "/ayadn")
13
+ prepare(user)
14
+ puts "Creating configuration...\n".color(:green)
15
+ Settings.load_config
16
+ Logs.create_logger
17
+ install
18
+ puts Status.done
19
+ Errors.info "Done!"
20
+ puts "\nThank you for using Ayadn. Enjoy!\n\n".color(:yellow)
21
+ end
22
+
23
+ private
24
+
25
+ def prepare(user)
26
+ puts "Ok! Creating Ayadn folders...\n".color(:green)
27
+ create_config_folders(user)
28
+ puts "Saving user token...\n".color(:green)
29
+ create_token_file(user)
30
+ puts "Creating user account for #{user.handle}...\n".color(:green)
31
+ accounts_db = Daybreak::DB.new("#{user.home_path}/accounts.db")
32
+ create_account(user, accounts_db)
33
+ end
34
+
35
+ def install
36
+ puts "Creating api and config files...\n".color(:green)
37
+ Errors.info "Creating api, version and config files..."
38
+ Errors.info "Creating version file..."
39
+ Settings.init_config
40
+ end
41
+
42
+ def create_account(user, accounts_db)
43
+ accounts_db[user.username] = {username: user.username, id: user.id, handle: user.handle, path: user.user_path}
44
+ accounts_db['ACTIVE'] = user.username
45
+ accounts_db.flush
46
+ accounts_db.close
47
+ end
48
+
49
+ def create_token_file(user)
50
+ File.write("#{user.user_path}/auth/token", user.token)
51
+ end
52
+
53
+ def create_config_folders(user)
54
+ begin
55
+ FileUtils.mkdir_p(user.user_path)
56
+ %w{log db pagination config auth downloads backup posts messages lists}.each do |target|
57
+ Dir.mkdir("#{user.user_path}/#{target}")
58
+ end
59
+ rescue => e
60
+ puts "\nError creating Ayadn #{user.handle} account folders.\n\n"
61
+ puts "Error: #{e}"
62
+ exit
63
+ end
64
+ end
65
+
66
+ def show_link
67
+ puts "\nPlease click this URL, or open a browser then copy/paste it:\n".color(:cyan)
68
+ puts Endpoints.new.authorize_url
69
+ puts "\n"
70
+ puts "On this page, log in with your App.net account to authorize Ayadn.\n".color(:cyan)
71
+ puts "You will then be redirected to a page showing a 'user token' (your secret code).\n".color(:cyan)
72
+ puts "Copy it then paste it here:\n".color(:yellow)
73
+ print "> "
74
+ end
75
+
76
+ def get_user(token)
77
+ JSON.parse(RestClient.get("https://alpha-api.app.net/stream/0/users/me?access_token=#{token}", :verify_ssl => OpenSSL::SSL::VERIFY_NONE) {|response, request, result| response })
78
+ end
79
+
80
+ def get_token
81
+ begin
82
+ STDIN.gets.chomp()
83
+ rescue Interrupt
84
+ puts Status.canceled
85
+ exit
86
+ end
87
+ end
88
+
89
+ def check_token(token)
90
+ if token.empty? || token.nil?
91
+ puts "\n\nOops, something went wrong, I couldn't get the token. Please try again.\n\n".color(:red)
92
+ exit
93
+ end
94
+ end
95
+
96
+ def try_remove_old_ayadn
97
+ if FileOps.old_ayadn?
98
+ answer = ask_del_old_ayadn
99
+ unless answer.downcase == "y"
100
+ puts Status.canceled
101
+ exit
102
+ end
103
+ puts "\nDeleting old version...\n".color(:green)
104
+ begin
105
+ old_dir = Dir.home + "/ayadn"
106
+ FileUtils.remove_dir(old_dir)
107
+ rescue => e
108
+ puts "Unable to remove folder: #{old_dir}\n\n".color(:red)
109
+ raise e
110
+ end
111
+ end
112
+ end
113
+
114
+ def ask_del_old_ayadn
115
+ puts "\nAn obsolete version of Ayadn has been detected and will be deleted. Install and authorize the new version? [y/N]\n".color(:red)
116
+ print "> "
117
+ STDIN.getch
118
+ end
119
+
120
+ def create_user_data(token, home_path)
121
+ resp = get_user(token)
122
+ model = Struct.new(:resp, :username, :id, :handle, :home_path, :user_path, :token)
123
+ username = resp['data']['username']
124
+ model.new(resp, username, resp['data']['id'], "@" + username, home_path, home_path + "/#{username}", token)
125
+ end
126
+
127
+ end
128
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+ module Ayadn
3
+ class Blacklist < Thor
4
+ desc "blacklist add TYPE TARGET", "Adds a mention, hashtag or client to your blacklist"
5
+ long_desc Descriptions.blacklist_add
6
+ def add(*args)
7
+ if args.length != 2
8
+ puts Status.type_and_target_missing
9
+ end
10
+ blacklist = BlacklistWorkers.new
11
+ blacklist.add(args)
12
+ puts Status.done
13
+ end
14
+
15
+ desc "blacklist remove TYPE TARGET", "Removes a mention, hashtag or client from your blacklist"
16
+ long_desc Descriptions.blacklist_remove
17
+ def remove(*args)
18
+ if args.length != 2
19
+ puts Status.type_and_target_missing
20
+ end
21
+ blacklist = BlacklistWorkers.new
22
+ blacklist.remove(args)
23
+ puts Status.done
24
+ end
25
+
26
+ desc "blacklist list", "List the content of your blacklist"
27
+ long_desc Descriptions.blacklist_list
28
+ def list
29
+ blacklist = BlacklistWorkers.new
30
+ blacklist.list
31
+ end
32
+
33
+ desc "blacklist import DATABASE", "Imports a blacklist database from another Ayadn account"
34
+ long_desc Descriptions.blacklist_import
35
+ def import(database)
36
+ blacklist = BlacklistWorkers.new
37
+ blacklist.import(database)
38
+ puts Status.done
39
+ end
40
+ end
41
+
42
+ class BlacklistWorkers
43
+ def initialize
44
+ Settings.load_config
45
+ Settings.get_token
46
+ Settings.init_config
47
+ Logs.create_logger
48
+ Databases.open_databases
49
+ end
50
+ def import(database)
51
+ begin
52
+ new_db = File.realpath(database)
53
+ if File.exist?(new_db)
54
+ Databases.import_blacklist(new_db)
55
+ Logs.rec.info "Imported '#{new_db}' values in blacklist database."
56
+ else
57
+ puts "\nFile '#{new_db}' doesn't exist.\n\n".color(:red)
58
+ Logs.rec.warn "File '#{new_db}' doesn't exist."
59
+ end
60
+ ensure
61
+ Databases.close_all
62
+ end
63
+ end
64
+ def add(args)
65
+ begin
66
+ type, target = args[0], args[1]
67
+ case type
68
+ when 'mention', 'mentions'
69
+ target = Workers.add_arobase_if_missing([target])
70
+ Databases.add_mention_to_blacklist(target)
71
+ Logs.rec.info "Added '#{target}' to blacklist of mentions."
72
+ when 'client', 'source'
73
+ Databases.add_client_to_blacklist(target)
74
+ Logs.rec.info "Added '#{target}' to blacklist of clients."
75
+ when 'hashtag', 'tag'
76
+ Databases.add_hashtag_to_blacklist(target)
77
+ Logs.rec.info "Added '#{target}' to blacklist of hashtags."
78
+ else
79
+ puts Status.wrong_arguments
80
+ end
81
+ ensure
82
+ Databases.close_all
83
+ end
84
+ end
85
+ def remove(args)
86
+ begin
87
+ type, target = args[0], args[1]
88
+ case type
89
+ when 'mention', 'mentions'
90
+ target = Workers.add_arobase_if_missing([target])
91
+ Databases.remove_from_blacklist(target)
92
+ Logs.rec.info "Removed '#{target}' from blacklist of mentions."
93
+ when 'client', 'source', 'hashtag', 'tag'
94
+ Databases.remove_from_blacklist(target)
95
+ Logs.rec.info "Removed '#{type}:#{target}' from blacklist."
96
+ else
97
+ puts Status.wrong_arguments
98
+ end
99
+ ensure
100
+ Databases.close_all
101
+ end
102
+ end
103
+ def list
104
+ begin
105
+ list = Databases.blacklist
106
+ unless list.empty?
107
+ puts Workers.new.build_blacklist_list(list)
108
+ else
109
+ abort(Status.empty_list)
110
+ end
111
+ ensure
112
+ Databases.close_all
113
+ end
114
+ end
115
+ end
116
+ end
data/lib/ayadn/cnx.rb ADDED
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+ module Ayadn
3
+ class CNX
4
+
5
+ def self.get_response_from(url)
6
+ begin
7
+ RestClient.get(url) do |response, request, result| #, :verify_ssl => OpenSSL::SSL::VERIFY_NONE
8
+ check(response)
9
+ end
10
+ rescue SocketError => e
11
+ puts "\nConnection error.".color(:red)
12
+ Errors.global_error("cnx.rb/get", url, e)
13
+ rescue SystemCallError => e
14
+ puts "\nConnection error.".color(:red)
15
+ Errors.global_error("cnx.rb/get", url, e)
16
+ rescue => e
17
+ Errors.global_error("cnx.rb/get", url, e)
18
+ end
19
+ end
20
+
21
+ def self.check(response)
22
+ case response.code
23
+ when 200
24
+ response
25
+ when 204
26
+ puts "\n'No content'".color(:red)
27
+ Errors.global_error("cnx.rb", response.headers, "NO CONTENT")
28
+ when 400
29
+ puts "\n'Bad request'".color(:red)
30
+ Errors.global_error("cnx.rb", response.headers, "BAD REQUEST")
31
+ when 401
32
+ puts "\n'Unauthorized'".color(:red)
33
+ Errors.global_error("cnx.rb", response.headers, "UNAUTHORIZED")
34
+ when 403
35
+ puts "\n'Forbidden'".color(:red)
36
+ Errors.global_error("cnx.rb", response.headers, "FORBIDDEN")
37
+ when 405
38
+ puts "\n'Method not allowed'".color(:red)
39
+ Errors.global_error("cnx.rb", response.headers, "METHOD NOT ALLOWED")
40
+ when 429
41
+ puts "\n'Too many requests'".color(:red)
42
+ puts "\n\nAyadn made too many requests to the App.net API. You should wait at least ".color(:cyan) + "#{response.headers[:retry_after]} ".color(:red) + "seconds before trying again. Maybe you launched a lot of Ayadn instances at the same time? That's no problem, but in this case you should increase the value of the scroll timer (do `ayadn set scroll timer 2.5` for example).".color(:cyan)
43
+ Errors.global_error("cnx.rb", response.headers, "TOO MANY REQUESTS")
44
+ when 500
45
+ puts "\n'App.net server error'".color(:red)
46
+ Errors.global_error("cnx.rb", response.headers, "APP.NET SERVER ERROR")
47
+ when 507
48
+ puts "\n'Insufficient storage'".color(:red)
49
+ Errors.global_error("cnx.rb", response.headers, "INSUFFICIENT STORAGE")
50
+ else
51
+ response
52
+ end
53
+ end
54
+
55
+ def self.delete(url)
56
+ begin
57
+ #RestClient::Resource.new(url).delete
58
+ RestClient.delete(url) do |response, request, result|
59
+ check(response)
60
+ end
61
+ rescue SocketError => e
62
+ puts "\nConnection error.".color(:red)
63
+ Errors.global_error("cnx.rb/delete", url, e)
64
+ rescue SystemCallError => e
65
+ puts "\nConnection error.".color(:red)
66
+ Errors.global_error("cnx.rb/delete", url, e)
67
+ rescue => e
68
+ Errors.global_error("cnx.rb/delete", url, e)
69
+ end
70
+ end
71
+
72
+ def self.post(url, payload = nil)
73
+ begin
74
+ RestClient.post(url, payload.to_json, :content_type => :json, :accept => :json) do |response, request, result|
75
+ check(response)
76
+ end
77
+ rescue SocketError => e
78
+ puts "\nConnection error.".color(:red)
79
+ Errors.global_error("cnx.rb/post", url, e)
80
+ rescue SystemCallError => e
81
+ puts "\nConnection error.".color(:red)
82
+ Errors.global_error("cnx.rb/post", url, e)
83
+ rescue => e
84
+ Errors.global_error("cnx.rb/post", [url, payload], e)
85
+ end
86
+ end
87
+
88
+ def self.put(url, payload)
89
+ begin
90
+ RestClient.put(url, payload.to_json, :content_type => :json, :accept => :json) do |response, request, result|
91
+ check(response)
92
+ end
93
+ rescue SocketError => e
94
+ puts "\nConnection error.".color(:red)
95
+ Errors.global_error("cnx.rb/put", url, e)
96
+ rescue SystemCallError => e
97
+ puts "\nConnection error.".color(:red)
98
+ Errors.global_error("cnx.rb/put", url, e)
99
+ rescue => e
100
+ Errors.global_error("cnx.rb/put", [url, payload], e)
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,110 @@
1
+ # encoding: utf-8
2
+ module Ayadn
3
+
4
+ class Databases
5
+
6
+ class << self
7
+ attr_accessor :users, :index, :pagination, :aliases, :blacklist
8
+ end
9
+
10
+ def self.open_databases
11
+ @users = Daybreak::DB.new "#{Settings.config[:paths][:db]}/users.db"
12
+ @index = Daybreak::DB.new "#{Settings.config[:paths][:pagination]}/index.db"
13
+ @pagination = Daybreak::DB.new "#{Settings.config[:paths][:pagination]}/pagination.db"
14
+ @aliases = Daybreak::DB.new "#{Settings.config[:paths][:db]}/aliases.db"
15
+ @blacklist = Daybreak::DB.new "#{Settings.config[:paths][:db]}/blacklist.db"
16
+ end
17
+
18
+ def self.close_all
19
+ [@users, @index, @pagination, @aliases, @blacklist].each do |db|
20
+ db.flush
21
+ db.close
22
+ end
23
+ end
24
+
25
+ def self.add_mention_to_blacklist(target)
26
+ @blacklist[target] = :mention
27
+ end
28
+ def self.add_client_to_blacklist(target)
29
+ @blacklist[target] = :client
30
+ end
31
+ def self.add_hashtag_to_blacklist(target)
32
+ @blacklist[target] = :hashtag
33
+ end
34
+ def self.remove_from_blacklist(target)
35
+ @blacklist.delete(target)
36
+ end
37
+ def self.import_blacklist(blacklist)
38
+ new_list = Daybreak::DB.new blacklist
39
+ new_list.each {|name,type| @blacklist[name] = type}
40
+ new_list.close
41
+ end
42
+
43
+ def self.save_max_id(stream)
44
+ @pagination[stream['meta']['marker']['name']] = stream['meta']['max_id']
45
+ end
46
+
47
+ def self.create_alias(channel_id, channel_alias)
48
+ @aliases[channel_alias] = channel_id
49
+ end
50
+
51
+ def self.delete_alias(channel_alias)
52
+ @aliases.delete(channel_alias)
53
+ end
54
+
55
+ def self.get_channel_id(channel_alias)
56
+ @aliases[channel_alias]
57
+ end
58
+
59
+ def self.import_aliases(aliases)
60
+ new_aliases = Daybreak::DB.new aliases
61
+ new_aliases.each {|al,id| @aliases[al] = id}
62
+ new_aliases.close
63
+ end
64
+
65
+ def self.get_alias_from_id(channel_id)
66
+ @aliases.each do |al, id|
67
+ return al if id == channel_id
68
+ end
69
+ nil
70
+ end
71
+
72
+ def self.save_indexed_posts(posts)
73
+ @index.clear
74
+ posts.each do |id, hash|
75
+ @index[id] = hash
76
+ end
77
+ end
78
+
79
+ def self.get_index_length
80
+ @index.length
81
+ end
82
+
83
+ def self.get_post_from_index(number)
84
+ unless number > @index.length || number <= 0
85
+ @index.to_h.each do |id, values|
86
+ return values if values[:count] == number
87
+ end
88
+ else
89
+ puts "\nNumber must be in the range of the indexed posts.\n".color(:red)
90
+ Errors.global_error("databases/get_post_from_index", number, "out of range")
91
+ end
92
+ end
93
+
94
+ def self.add_to_users_db_from_list(list)
95
+ list.each do |id, content_array|
96
+ @users[id] = {content_array[0] => content_array[1]}
97
+ end
98
+ end
99
+
100
+ def self.add_to_users_db(id, username, name)
101
+ @users[id] = {username => name}
102
+ end
103
+
104
+ def self.has_new?(stream, title)
105
+ stream['meta']['max_id'].to_i > @pagination[title].to_i
106
+ end
107
+
108
+ end
109
+
110
+ end