moostodon 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/lib/mastodon.rb +8 -0
  3. data/lib/mastodon/account.rb +62 -0
  4. data/lib/mastodon/app.rb +19 -0
  5. data/lib/mastodon/base.rb +52 -0
  6. data/lib/mastodon/card.rb +43 -0
  7. data/lib/mastodon/client.rb +32 -0
  8. data/lib/mastodon/collection.rb +30 -0
  9. data/lib/mastodon/emoji.rb +14 -0
  10. data/lib/mastodon/entities/app.rb +15 -0
  11. data/lib/mastodon/entities/hashtag.rb +15 -0
  12. data/lib/mastodon/entities/media.rb +31 -0
  13. data/lib/mastodon/entities/mention.rb +17 -0
  14. data/lib/mastodon/error.rb +37 -0
  15. data/lib/mastodon/headers.rb +20 -0
  16. data/lib/mastodon/instance.rb +25 -0
  17. data/lib/mastodon/list.rb +17 -0
  18. data/lib/mastodon/media.rb +37 -0
  19. data/lib/mastodon/notification.rb +32 -0
  20. data/lib/mastodon/relationship.rb +38 -0
  21. data/lib/mastodon/rest/accounts.rb +71 -0
  22. data/lib/mastodon/rest/api.rb +29 -0
  23. data/lib/mastodon/rest/apps.rb +28 -0
  24. data/lib/mastodon/rest/client.rb +13 -0
  25. data/lib/mastodon/rest/instances.rb +19 -0
  26. data/lib/mastodon/rest/media.rb +42 -0
  27. data/lib/mastodon/rest/notifications.rb +19 -0
  28. data/lib/mastodon/rest/relationships.rb +77 -0
  29. data/lib/mastodon/rest/request.rb +54 -0
  30. data/lib/mastodon/rest/search.rb +28 -0
  31. data/lib/mastodon/rest/statuses.rb +130 -0
  32. data/lib/mastodon/rest/suggestions.rb +19 -0
  33. data/lib/mastodon/rest/timelines.rb +47 -0
  34. data/lib/mastodon/rest/utils.rb +42 -0
  35. data/lib/mastodon/results.rb +19 -0
  36. data/lib/mastodon/status.rb +94 -0
  37. data/lib/mastodon/streaming/client.rb +103 -0
  38. data/lib/mastodon/streaming/connection.rb +47 -0
  39. data/lib/mastodon/streaming/deleted_status.rb +17 -0
  40. data/lib/mastodon/streaming/message_parser.rb +21 -0
  41. data/lib/mastodon/streaming/response.rb +45 -0
  42. data/lib/mastodon/version.rb +32 -0
  43. data/moostodon.gemspec +25 -0
  44. metadata +156 -0
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mastodon
4
+ class List < Mastodon::Base
5
+ # @!attribute [r] id
6
+ # @return [String]
7
+ # @!attribute [r] title
8
+ # @return [String]
9
+
10
+ normal_attr_reader :id, :title
11
+
12
+ def initialize(attributes = {})
13
+ attributes.fetch('id')
14
+ super
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mastodon
4
+ class Media < Mastodon::Base
5
+ # @!attribute [r] id
6
+ # @return [String]
7
+ # @!attribute [r] type
8
+ # @return [String] Image or video
9
+ # @!attribute [r] url
10
+ # @return [String] Full file URL
11
+ # @!attribute [r] remote_url
12
+ # @return [String]
13
+ # @!attribute [r] preview_url
14
+ # @return [String] URL to preview image
15
+ # @!attribute [r] text_url
16
+ # @return [String] URL that can be put into status body and will
17
+ # redirect to the status/media
18
+ # @!attribute [r] meta
19
+ # @return [Hash]
20
+ # @!attribute [r] description
21
+ # @return [String]
22
+
23
+ normal_attr_reader :id,
24
+ :type,
25
+ :url,
26
+ :remote_url,
27
+ :preview_url,
28
+ :text_url,
29
+ :meta,
30
+ :description
31
+
32
+ def initialize(attributes = {})
33
+ attributes.fetch('id')
34
+ super
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mastodon
4
+ class Notification < Mastodon::Base
5
+ # @!attribute [r] id
6
+ # @return [String]
7
+ # @!attribute [r] type
8
+ # @return [String]
9
+ # @!attribute [r] created_at
10
+ # @return [String]
11
+ # @!attribute [r] account
12
+ # @return [Mastodon::Account]
13
+ # @!attribute [r] status
14
+ # @return [Mastodon::Status]
15
+
16
+ normal_attr_reader :id, :type, :created_at
17
+
18
+ object_attr_reader :account, Mastodon::Account
19
+ object_attr_reader :status, Mastodon::Status
20
+
21
+ def initialize(attributes = {})
22
+ attributes.fetch('id')
23
+ super
24
+ end
25
+
26
+ # Does this notification include a status?
27
+ # @return [Boolean] true if a status is included, false otherwise
28
+ def status?
29
+ attributes.key?('status')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mastodon
4
+ # Relationships. Purpose still to be found out (by Maxine Michalski)
5
+ class Relationship < Mastodon::Base
6
+ # @!attribute [r] id
7
+ # @return [String] Account ID
8
+ # @!attribute [r] following?
9
+ # @return [Boolean]
10
+ # @!attribute [r] followed_by?
11
+ # @return [Boolean]
12
+ # @!attribute [r] blocking?
13
+ # @return [Boolean]
14
+ # @!attribute [r] muting?
15
+ # @return [Boolean]
16
+ # @!attribute [r] muting_notifications?
17
+ # @return [Boolean]
18
+ # @!attribute [r] requested?
19
+ # @return [Boolean]
20
+ # @!attribute [r] domain_blocking?
21
+ # @return [Boolean]
22
+
23
+ normal_attr_reader :id
24
+
25
+ predicate_attr_reader :following,
26
+ :followed_by,
27
+ :blocking,
28
+ :muting,
29
+ :muting_notifications,
30
+ :requested,
31
+ :domain_blocking
32
+
33
+ def initialize(attributes = {})
34
+ attributes.fetch('id')
35
+ super
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/rest/utils'
4
+ require 'mastodon/account'
5
+
6
+ module Mastodon
7
+ module REST
8
+ module Accounts
9
+ include Mastodon::REST::Utils
10
+
11
+ # Retrieve account of authenticated user
12
+ # @return [Mastodon::Account]
13
+ def verify_credentials
14
+ perform_request_with_object(:get, '/api/v1/accounts/verify_credentials',
15
+ {}, Mastodon::Account)
16
+ end
17
+
18
+ # Update authenticated account attributes
19
+ # @param options [Hash]
20
+ # @option options display_name [String] The name to display in the
21
+ # user's profile
22
+ # @option options note [String] A new biography for the user
23
+ # @option options avatar [String] A base64 encoded image to display as
24
+ # the user's avatar
25
+ # @option options header [String] A base64 encoded image to display as
26
+ # the user's header image
27
+ # @return [Mastodon::Account]
28
+ def update_credentials(opts = {})
29
+ perform_request_with_object(:patch,
30
+ '/api/v1/accounts/update_credentials',
31
+ opts, Mastodon::Account)
32
+ end
33
+
34
+ # Retrieve account
35
+ # @param id [Integer]
36
+ # @return [Mastodon::Account]
37
+ def account(id)
38
+ perform_request_with_object(:get, "/api/v1/accounts/#{id}", {},
39
+ Mastodon::Account)
40
+ end
41
+
42
+ # Get a list of followers
43
+ # @param id [Integer]
44
+ # @return [Mastodon::Collection<Mastodon::Account>]
45
+ def followers(id)
46
+ perform_request_with_collection(:get,
47
+ "/api/v1/accounts/#{id}/followers",
48
+ {}, Mastodon::Account)
49
+ end
50
+
51
+ # Get a list of followed accounts
52
+ # @param id [Integer]
53
+ # @return [Mastodon::Collection<Mastodon::Account>]
54
+ def following(id)
55
+ perform_request_with_collection(:get,
56
+ "/api/v1/accounts/#{id}/following",
57
+ {}, Mastodon::Account)
58
+ end
59
+
60
+ # Follow a remote user
61
+ # @param uri [String] The URI of the remote user, in the format of
62
+ # username@domain
63
+ # @return [Mastodon::Account]
64
+ def follow_by_uri(uri)
65
+ perform_request_with_object(:post,
66
+ '/api/v1/follows', { uri: uri },
67
+ Mastodon::Account)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/rest/statuses'
4
+ require 'mastodon/rest/accounts'
5
+ require 'mastodon/rest/timelines'
6
+ require 'mastodon/rest/notifications'
7
+ require 'mastodon/rest/search'
8
+ require 'mastodon/rest/relationships'
9
+ require 'mastodon/rest/media'
10
+ require 'mastodon/rest/suggestions'
11
+ require 'mastodon/rest/apps'
12
+ require 'mastodon/rest/instances'
13
+
14
+ module Mastodon
15
+ module REST
16
+ module API
17
+ include Mastodon::REST::Statuses
18
+ include Mastodon::REST::Accounts
19
+ include Mastodon::REST::Timelines
20
+ include Mastodon::REST::Notifications
21
+ include Mastodon::REST::Search
22
+ include Mastodon::REST::Relationships
23
+ include Mastodon::REST::Media
24
+ include Mastodon::REST::Suggestions
25
+ include Mastodon::REST::Apps
26
+ include Mastodon::REST::Instances
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/rest/utils'
4
+ require 'mastodon/app'
5
+
6
+ module Mastodon
7
+ module REST
8
+ module Apps
9
+ include Mastodon::REST::Utils
10
+
11
+ # Register a new OAuth client app on the target instance
12
+ # @param name [String]
13
+ # @param redirect_uri [String]
14
+ # @param scopes [String]
15
+ # @param website [String]
16
+ # @return [Mastodon::App]
17
+ def create_app(name, redirect_uri, scopes = 'read', website = nil)
18
+ perform_request_with_object(:post, '/api/v1/apps',
19
+ {
20
+ client_name: name,
21
+ redirect_uris: redirect_uri,
22
+ scopes: scopes,
23
+ website: website
24
+ }, Mastodon::App)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/client'
4
+ require 'mastodon/rest/api'
5
+
6
+ module Mastodon
7
+ module REST
8
+ # Main interaction class for the REST API.
9
+ class Client < Mastodon::Client
10
+ include Mastodon::REST::API
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/rest/utils'
4
+ require 'mastodon/instance'
5
+
6
+ module Mastodon
7
+ module REST
8
+ module Instances
9
+ include Mastodon::REST::Utils
10
+
11
+ # Retrieve the current instance. Does not require authentication
12
+ # @return [Mastodon::Instance]
13
+ def instance
14
+ perform_request_with_object(:get, '/api/v1/instance', {},
15
+ Mastodon::Instance)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/rest/utils'
4
+ require 'mastodon/media'
5
+
6
+ module Mastodon
7
+ module REST
8
+ module Media
9
+ include Mastodon::REST::Utils
10
+
11
+ # Upload a media file
12
+ # @param file [File, StringIO, HTTP::FormData::File] file to
13
+ # upload. Will be converted to HTTP::FormData::File before upload
14
+ # @param description [String] A text description of the image, to be
15
+ # along with the image.
16
+ # @return [Mastodon::Media]
17
+ def upload_media(file, description = nil)
18
+ file = if file.is_a?(HTTP::FormData::File)
19
+ file
20
+ else
21
+ HTTP::FormData::File.new(file)
22
+ end
23
+ payload = { file: file }
24
+ payload[:description] = description unless description.nil?
25
+ perform_request_with_object(:post, '/api/v1/media', payload,
26
+ Mastodon::Media)
27
+ end
28
+
29
+ # Update a media description, can only be updated while it's not
30
+ # associated to a status
31
+ # @param media_id [Integer] Id of the media, returned by upload_media
32
+ # @param description [String] A text description of the image, to be
33
+ # along with the image.
34
+ # @return [Mastodon::Media]
35
+ def update_media_description(media_id, description)
36
+ perform_request_with_object(:put, "/api/v1/media/#{media_id}",
37
+ { description: description },
38
+ Mastodon::Media)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/rest/utils'
4
+ require 'mastodon/notification'
5
+
6
+ module Mastodon
7
+ module REST
8
+ module Notifications
9
+ include Mastodon::REST::Utils
10
+
11
+ # Get a list of notifications for the authenticated user
12
+ # @return [Mastodon::Collection<Mastodon::Notification>]
13
+ def notifications
14
+ perform_request_with_collection(:get, '/api/v1/notifications', {},
15
+ Mastodon::Notification)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mastodon/rest/utils'
4
+ require 'mastodon/relationship'
5
+
6
+ module Mastodon
7
+ module REST
8
+ module Relationships
9
+ include Mastodon::REST::Utils
10
+
11
+ # Get the relationships of authenticated user towards given other users
12
+ # @param ids [Integer]
13
+ # @return [Mastodon::Collection<Mastodon::Relationship>]
14
+ def relationships(*ids)
15
+ perform_request_with_collection(:get, '/api/v1/accounts/relationships',
16
+ array_param(:id, ids),
17
+ Mastodon::Relationship)
18
+ end
19
+
20
+ # Follow a user
21
+ # @param id [Integer]
22
+ # @return [Mastodon::Relationship]
23
+ def follow(id)
24
+ perform_request_with_object(:post, "/api/v1/accounts/#{id}/follow",
25
+ {}, Mastodon::Relationship)
26
+ end
27
+
28
+ # Follow a remote user
29
+ # @param uri [String] username@domain of the person you want to follow
30
+ # @return [Mastodon::Account]
31
+ def remote_follow(uri)
32
+ perform_request_with_object(:post, '/api/v1/follows', { uri: uri },
33
+ Mastodon::Account)
34
+ end
35
+
36
+ # Unfollow a user
37
+ # @param id [Integer]
38
+ # @return [Mastodon::Relationship]
39
+ def unfollow(id)
40
+ perform_request_with_object(:post, "/api/v1/accounts/#{id}/unfollow",
41
+ {}, Mastodon::Relationship)
42
+ end
43
+
44
+ # Block a user
45
+ # @param id [Integer]
46
+ # @return [Mastodon::Relationship]
47
+ def block(id)
48
+ perform_request_with_object(:post, "/api/v1/accounts/#{id}/block",
49
+ {}, Mastodon::Relationship)
50
+ end
51
+
52
+ # Unblock a user
53
+ # @param id [Integer]
54
+ # @return [Mastodon::Relationship]
55
+ def unblock(id)
56
+ perform_request_with_object(:post, "/api/v1/accounts/#{id}/unblock",
57
+ {}, Mastodon::Relationship)
58
+ end
59
+
60
+ # Mute a user
61
+ # @param id [Integer]
62
+ # @return [Mastodon::Relationship]
63
+ def mute(id)
64
+ perform_request_with_object(:post, "/api/v1/accounts/#{id}/mute",
65
+ {}, Mastodon::Relationship)
66
+ end
67
+
68
+ # Unmute a user
69
+ # @param id [Integer]
70
+ # @return [Mastodon::Relationship]
71
+ def unmute(id)
72
+ perform_request_with_object(:post, "/api/v1/accounts/#{id}/unmute",
73
+ {}, Mastodon::Relationship)
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'addressable/uri'
4
+ require 'http'
5
+ require 'oj'
6
+ require 'mastodon/error'
7
+ require 'mastodon/headers'
8
+
9
+ module Mastodon
10
+ module REST
11
+ class Request
12
+ def initialize(client, request_method, path, options = {})
13
+ @client = client
14
+ @request_method = request_method
15
+ @uri = Addressable::URI.parse(@client.base_url + path)
16
+ @headers = Mastodon::Headers.new(@client).request_headers
17
+ @path = @uri.path
18
+ @options = options
19
+ # rubocop:disable GuardClause
20
+ if @options.is_a?(Hash) && @options[:headers]
21
+ @headers = @options.delete(:headers).merge @headers
22
+ end
23
+ # rubocop:enable GuardClause
24
+ end
25
+
26
+ def perform
27
+ options_key = @request_method == :get ? :params : :form
28
+ response = http_client.headers(@headers)
29
+ .public_send(@request_method, @uri.to_s,
30
+ options_key => @options)
31
+
32
+ STDERR.puts response.body if ENV['DEBUG'] == 'true'
33
+
34
+ r_body = response.body.empty? ? '' : Oj.load(response.to_s, mode: :null)
35
+ fail_or_return(response.code, r_body)
36
+ end
37
+
38
+ private
39
+
40
+ def fail_or_return(code, body)
41
+ if Mastodon::Error::ERRORS.include?(code)
42
+ raise Mastodon::Error::ERRORS[code].from_response(body)
43
+ end
44
+ body
45
+ end
46
+
47
+ def http_client
48
+ HTTP.timeout(:per_operation, connect: @client.timeout[:connect],
49
+ read: @client.timeout[:read],
50
+ write: @client.timeout[:write])
51
+ end
52
+ end
53
+ end
54
+ end