moostodon 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/mastodon.rb +8 -0
- data/lib/mastodon/account.rb +62 -0
- data/lib/mastodon/app.rb +19 -0
- data/lib/mastodon/base.rb +52 -0
- data/lib/mastodon/card.rb +43 -0
- data/lib/mastodon/client.rb +32 -0
- data/lib/mastodon/collection.rb +30 -0
- data/lib/mastodon/emoji.rb +14 -0
- data/lib/mastodon/entities/app.rb +15 -0
- data/lib/mastodon/entities/hashtag.rb +15 -0
- data/lib/mastodon/entities/media.rb +31 -0
- data/lib/mastodon/entities/mention.rb +17 -0
- data/lib/mastodon/error.rb +37 -0
- data/lib/mastodon/headers.rb +20 -0
- data/lib/mastodon/instance.rb +25 -0
- data/lib/mastodon/list.rb +17 -0
- data/lib/mastodon/media.rb +37 -0
- data/lib/mastodon/notification.rb +32 -0
- data/lib/mastodon/relationship.rb +38 -0
- data/lib/mastodon/rest/accounts.rb +71 -0
- data/lib/mastodon/rest/api.rb +29 -0
- data/lib/mastodon/rest/apps.rb +28 -0
- data/lib/mastodon/rest/client.rb +13 -0
- data/lib/mastodon/rest/instances.rb +19 -0
- data/lib/mastodon/rest/media.rb +42 -0
- data/lib/mastodon/rest/notifications.rb +19 -0
- data/lib/mastodon/rest/relationships.rb +77 -0
- data/lib/mastodon/rest/request.rb +54 -0
- data/lib/mastodon/rest/search.rb +28 -0
- data/lib/mastodon/rest/statuses.rb +130 -0
- data/lib/mastodon/rest/suggestions.rb +19 -0
- data/lib/mastodon/rest/timelines.rb +47 -0
- data/lib/mastodon/rest/utils.rb +42 -0
- data/lib/mastodon/results.rb +19 -0
- data/lib/mastodon/status.rb +94 -0
- data/lib/mastodon/streaming/client.rb +103 -0
- data/lib/mastodon/streaming/connection.rb +47 -0
- data/lib/mastodon/streaming/deleted_status.rb +17 -0
- data/lib/mastodon/streaming/message_parser.rb +21 -0
- data/lib/mastodon/streaming/response.rb +45 -0
- data/lib/mastodon/version.rb +32 -0
- data/moostodon.gemspec +25 -0
- 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,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
|