ayadn 0.6.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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