moostodon 0.1.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 (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