diff --git a/src/client/__mocks__/gateway.ts b/src/client/__mocks__/gateway.ts deleted file mode 100644 index 28dd0f032..000000000 --- a/src/client/__mocks__/gateway.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const getMock = jest.fn().mockResolvedValue({}); -export const postMock = jest.fn().mockResolvedValue({}); -export const deleteMock = jest.fn().mockResolvedValue({}); -export const patchMock = jest.fn().mockResolvedValue({}); -export const putMock = jest.fn().mockResolvedValue({}); -export const streamMock = jest.fn().mockResolvedValue({}); -export const paginateMock = jest.fn(); - -export const Gateway = jest.fn(() => ({ - uri: 'https://example.com', - streamingApiUrl: 'wss://example.com', - accessToken: 'token', - version: '99.99.9', - get: getMock, - post: postMock, - delete: deleteMock, - patch: patchMock, - put: putMock, - stream: streamMock, - paginate: paginateMock, -})); diff --git a/src/client/__tests__/__snapshots__/masto.spec.ts.snap b/src/client/__tests__/__snapshots__/masto.spec.ts.snap deleted file mode 100644 index 02e6b0d63..000000000 --- a/src/client/__tests__/__snapshots__/masto.spec.ts.snap +++ /dev/null @@ -1,2056 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Masto addAccountToList 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/lists/123123/accounts", - Object { - "account_ids": Array [ - "123", - "456", - "678", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto addPushSubscription 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/push/subscription", - Object { - "data": Object { - "alerts": Object { - "favourite": true, - "follow": true, - "mention": true, - "reblog": true, - }, - }, - "subscription": Object { - "endpoint": "https://example.com", - "keys": Object { - "auth": "yyyy", - "p256dh": "xxxx", - }, - }, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto authorizeFollowRequest 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/follow_requests/123123/authorize", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto blockAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/block", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto blockDomain 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/domain_blocks", - Object { - "domain": "example.com", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto clearNotifications 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/notifications/clear", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto createAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts", - Object { - "agreement": true, - "email": "example@example.com", - "password": "password", - "username": "username", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto createApp 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/apps", - Object { - "client_name": "My Client", - "redirect_uris": "https://example.com", - "scopes": "write read", - "website": "https://example.com", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto createFiler 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/filters", - Object { - "context": Array [ - "home", - "notifications", - "public", - "thread", - ], - "expires_in": 3600000, - "irreversible": true, - "phrase": "Twitter", - "whole_word": true, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto createList 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/lists", - Object { - "title": "My list", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto createStatus with Idempotency-Key 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses", - Object { - "status": "Too!", - }, - Object { - "headers": Object { - "Idempotency-Key": "59fe7e30-1a74-4050-8af7-5a8c7a224794", - }, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto createStatus with content 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses", - Object { - "in_reply_to_id": "123123", - "language": "en", - "poll": Object { - "expires_in": 60000, - "hide_totals": true, - "multiple": false, - "options": Array [ - "xxx", - "yyy", - "zzz", - ], - }, - "scheduled_at": "2019-03-28T04:39:31.121Z", - "sensitive": false, - "spoiler_text": "spoiler", - "status": "Toot!", - "visibility": "direct", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto createStatus with media ids 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses", - Object { - "media_ids": Array [ - "123", - "456", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto dissmissNotification 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/notifications/dismiss", - Object { - "id": "123123", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto favouriteStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/favourite", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchAccessToken with authorization code 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/oauth/token", - Object { - "client_id": "123123123", - "client_secret": "456456456", - "code": "789789789", - "grant_type": "authorization_code", - "redirect_uri": "https://example.com", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchAccessToken with password 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/oauth/token", - Object { - "grant_type": "password", - "password": "password", - "username": "username", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchAccountFollowers 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123123/followers", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchAccountFollowing 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123123/following", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchAccountIdentityProofs 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123123/identity_proofs", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchAccountLists 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/lists", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchAccountRelationships 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/relationship", - Object { - "id": Array [ - "123123", - "456456", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchAccountStatuses 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123123/statuses", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchBlocks 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/blocks", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchCommunityTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/timelines/public", - Object { - "limit": 10, - "local": true, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchConversations 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/conversations", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchCustomEmojis 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/custom_emojis", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchDirectTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/timelines/direct", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchDomainBlocks 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/domain_blocks", - undefined, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchEndorsements 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/endorsements", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchFavourites 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/favourites", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchFilter 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/filters/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchFilters 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/filters", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchFollowRequests 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/follow_requests", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchHomeTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/timelines/home", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchInstance 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/suggestions", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchInstanceActivity 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/instance/activity", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchInstancesPeers 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/instance/peers", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchList 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/lists/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchListAccounts 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/list/123123/accounts", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchListTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/timelines/list/123123", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchLists 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/lists", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchMutes 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/mutes", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchNotification 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/notifications/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchNotifications 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/notifications", - Object { - "exclude_types": Array [ - "favourite", - "follow", - "mention", - "poll", - "reblog", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchPoll 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/polls/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchPreferences 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/preferences", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchPublicTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/timelines/public", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchPushSubscription 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/push/subscription", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchScheduledStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/scheduled_statuses/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchScheduledStatuses 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/scheduled_statuses", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchStatusCard 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/card", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchStatusContext 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/context", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchStatusFavouritedBy 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/favourited_by", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchStatusRebloggedBy 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/reblogged_by", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto fetchSuggestions 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/suggestions", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto fetchTagTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/timelines/tag/DeleteTwitter", - Object { - "limit": 10, - "max_id": "5", - "min_id": "2", - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto followAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/follow", - Object { - "reblogs": false, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto followAccountByUsername 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/follows", - Object { - "uri": "user@example.com", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto muteAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/mute", - Object { - "notifications": false, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto muteStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/mute", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto pinAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/pin", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto pinStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/pin", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto reblogStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/reblog", - Object { - "visibility": "direct", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto rejectFollowRequest 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/follow_requests/123123/reject", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto removeAccountFromList 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/lists/123123/accounts", - Object { - "account_ids": Array [ - "123", - "456", - "678", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto removeFilter 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/filters/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto removeList 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/lists/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto removePushSubscription 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/push/subscription", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto removeScheduledStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/scheduled_statuses/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto removeStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto removeSuggestion 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/suggestions/123123", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto reportAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/reports", - Object { - "account_id": "123123", - "comment": "this is a report", - "forward": true, - "status_ids": Array [ - "456456", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto revokeAccessToken 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/oauth/revoke", - Object { - "client_id": "123123123", - "client_secret": "456456456", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto search (v1) 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/search", - Object { - "q": "query", - "resolve": true, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto search 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v2/search", - Object { - "account_id": "123", - "limit": 10, - "max_id": "5", - "min_id": "2", - "q": "query", - "resolve": true, - "since_id": "3", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], -} -`; - -exports[`Masto searchAccounts 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/search", - Object { - "following": false, - "limit": 123, - "q": "query", - "resolve": true, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto streamCommunityTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/streaming", - Object { - "stream": "public:local", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto streamDirectTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/streaming", - Object { - "stream": "direct", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto streamListTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/streaming", - Object { - "list": "123123", - "stream": "list", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto streamLocalTagTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/streaming", - Object { - "stream": "hashtag:local", - "tag": "deletetwitter", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto streamPublicTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/streaming", - Object { - "stream": "public", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto streamTagTimeline 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/streaming", - Object { - "stream": "hashtag", - "tag": "deletetwitter", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto streamUser 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/streaming", - Object { - "stream": "user", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unblockAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/unblock", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unblockDomain 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/domain_blocks", - Object { - "domain": "example.com", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unfavouriteStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/unfavourite", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unfollowAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/unfollow", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unmuteAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/unmute", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unmuteStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/unmute", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unpinAccount 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/123123/unpin", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unpinStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/unpin", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto unreblogStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/statuses/123123/unreblog", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto updateCredentials 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/update_credentials", - Object { - "avatar": "...", - "display_name": "Neetshin", - "fields_attributes": Array [ - Object { - "name": "GitHub", - "value": "https://github.com/neet", - }, - ], - "header": "...", - "locked": false, - "note": "web frontend engineer", - "source": Object { - "language": "ja", - "privacy": "direct", - "sensitive": false, - }, - }, - Object { - "headers": Object { - "Content-Type": "multipart/form-data", - }, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto updateFilter 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/filters/123123", - Object { - "context": Array [ - "home", - "notifications", - "public", - "thread", - ], - "expires_in": 3600000, - "irreversible": true, - "phrase": "Twitter", - "whole_word": true, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto updateList 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/lists/123123", - Object { - "title": "My list", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto updateMediaAttachment 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/media/123123", - Object { - "description": "Nice image", - "focus": "0, 0", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto updatePushSubscription 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/push/subscription", - Object { - "data": Object { - "alerts": Object { - "favourite": true, - "follow": true, - "mention": true, - "reblog": true, - }, - }, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto updateScheduledStatus 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/scheduled_statuses/123123", - Object { - "scheduled_at": "2019-03-28T04:39:31.121Z", - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto uploadMediaAttachment 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/media", - Object { - "description": "Nice image", - "file": "...", - }, - Object { - "headers": Object { - "Content-Type": "multipart/form-data", - }, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto verifyAppCredentials 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/apps/verify_credentials", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto verifyCredentials 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/accounts/verify_credentials", - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; - -exports[`Masto votePoll 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ - "/api/v1/polls/123123/votes", - Object { - "choices": Array [ - "xxx", - "yyy", - "zzz", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], -} -`; diff --git a/src/client/__tests__/masto.spec.ts b/src/client/__tests__/masto.spec.ts deleted file mode 100644 index 4dc34408f..000000000 --- a/src/client/__tests__/masto.spec.ts +++ /dev/null @@ -1,908 +0,0 @@ -// tslint:disable -// @ts-ignore -// prettier-ignore -import { getMock, postMock, deleteMock, patchMock, putMock, streamMock, paginateMock, Gateway } from '../gateway'; -import { Masto } from '../masto'; - -jest.mock('../gateway'); - -describe('Masto', () => { - let masto!: Masto; - - beforeEach(() => { - // @ts-ignore - masto = new Masto(new Gateway()); - - (getMock as jest.Mock).mockClear(); - (postMock as jest.Mock).mockClear(); - (deleteMock as jest.Mock).mockClear(); - (patchMock as jest.Mock).mockClear(); - (putMock as jest.Mock).mockClear(); - (streamMock as jest.Mock).mockClear(); - (paginateMock as jest.Mock).mockClear(); - }); - - test('login', async () => { - (getMock as jest.Mock).mockResolvedValueOnce({ - version: '2.8.0', - urls: { - streaming_api: 'wss://example.com/stream', - }, - }); - - const params = { - uri: 'https://example.com', - accessToken: 'tokentoken', - }; - const masto = await Masto.login(params); - - expect((Gateway as any) as jest.Mock).toBeCalledWith(params); - expect(getMock).toBeCalledWith(expect.stringContaining('/api/v1/instance')); - expect(masto.gateway.version).toBe('2.8.0'); - expect(masto.gateway.streamingApiUrl).toBe('wss://example.com/stream'); - }); - - test('streamUser', async () => { - await masto.streamUser(); - expect(streamMock).toBeCalledTimes(1); - expect(streamMock).toMatchSnapshot(); - }); - - test('streamPublicTimeline', async () => { - await masto.streamPublicTimeline(); - expect(streamMock).toBeCalledTimes(1); - expect(streamMock).toMatchSnapshot(); - }); - - test('streamCommunityTimeline', async () => { - await masto.streamCommunityTimeline(); - expect(streamMock).toBeCalledTimes(1); - expect(streamMock).toMatchSnapshot(); - }); - - test('streamTagTimeline', async () => { - await masto.streamTagTimeline('deletetwitter'); - expect(streamMock).toBeCalledTimes(1); - expect(streamMock).toMatchSnapshot(); - }); - - test('streamLocalTagTimeline', async () => { - await masto.streamLocalTagTimeline('deletetwitter'); - expect(streamMock).toBeCalledTimes(1); - expect(streamMock).toMatchSnapshot(); - }); - - test('streamListTimeline', async () => { - await masto.streamListTimeline('123123'); - expect(streamMock).toBeCalledTimes(1); - expect(streamMock).toMatchSnapshot(); - }); - - test('streamDirectTimeline', async () => { - await masto.streamDirectTimeline(); - expect(streamMock).toBeCalledTimes(1); - expect(streamMock).toMatchSnapshot(); - }); - - test('fetchAccessToken with authorization code', async () => { - await masto.fetchAccessToken({ - grant_type: 'authorization_code', - code: '789789789', - redirect_uri: 'https://example.com', - client_id: '123123123', - client_secret: '456456456', - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchAccessToken with password', async () => { - await masto.fetchAccessToken({ - grant_type: 'password', - username: 'username', - password: 'password', - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('revokeAccessToken', async () => { - await masto.revokeAccessToken({ - client_id: '123123123', - client_secret: '456456456', - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchAccount', async () => { - await masto.fetchAccount('123123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchAccountIdentityProofs', async () => { - await masto.fetchAccountIdentityProofs('123123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('createAccount', async () => { - await masto.createAccount({ - username: 'username', - password: 'password', - email: 'example@example.com', - agreement: true, - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('verifyCredentials', async () => { - await masto.verifyCredentials(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('updateCredentials', async () => { - await masto.updateCredentials({ - display_name: 'Neetshin', - avatar: '...', - header: '...', - note: 'web frontend engineer', - locked: false, - source: { - privacy: 'direct', - sensitive: false, - language: 'ja', - }, - fields_attributes: [ - { - name: 'GitHub', - value: 'https://github.com/neet', - }, - ], - }); - expect(patchMock).toBeCalledTimes(1); - expect(patchMock).toMatchSnapshot(); - }); - - test('fetchAccountFollowers', async () => { - await masto.fetchAccountFollowers('123123123', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchAccountFollowing', async () => { - await masto.fetchAccountFollowing('123123123', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchAccountStatuses', async () => { - await masto.fetchAccountStatuses('123123123', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('followAccount', async () => { - await masto.followAccount('123123', { - reblogs: false, - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unfollowAccount', async () => { - await masto.unfollowAccount('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchAccountRelationships', async () => { - await masto.fetchAccountRelationships(['123123', '456456']); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('searchAccounts', async () => { - await masto.searchAccounts({ - q: 'query', - resolve: true, - limit: 123, - following: false, - }); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('createApp', async () => { - await masto.createApp({ - client_name: 'My Client', - redirect_uris: 'https://example.com', - scopes: 'write read', - website: 'https://example.com', - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('verifyAppCredentials', async () => { - await masto.verifyAppCredentials(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchBlocks', async () => { - await masto.fetchBlocks({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('blockAccount', async () => { - await masto.blockAccount('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unblockAccount', async () => { - await masto.unblockAccount('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchCustomEmojis', async () => { - await masto.fetchCustomEmojis(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchDomainBlocks', async () => { - await masto.fetchDomainBlocks(); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('blockDomain', async () => { - await masto.blockDomain('example.com'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unblockDomain', async () => { - await masto.unblockDomain('example.com'); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('fetchEndorsements', async () => { - await masto.fetchEndorsements({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('pinAccount', async () => { - await masto.pinAccount('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unpinAccount', async () => { - await masto.unpinAccount('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchFavourites', async () => { - await masto.fetchFavourites({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('favouriteStatus', async () => { - await masto.favouriteStatus('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unfavouriteStatus', async () => { - await masto.unfavouriteStatus('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchFilters', async () => { - await masto.fetchFilters(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchFilter', async () => { - await masto.fetchFilter('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('createFiler', async () => { - await masto.createFiler({ - phrase: 'Twitter', - context: ['home', 'notifications', 'public', 'thread'], - irreversible: true, - whole_word: true, - expires_in: 1000 * 60 * 60, - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('updateFilter', async () => { - await masto.updateFilter('123123', { - phrase: 'Twitter', - context: ['home', 'notifications', 'public', 'thread'], - irreversible: true, - whole_word: true, - expires_in: 1000 * 60 * 60, - }); - expect(putMock).toBeCalledTimes(1); - expect(putMock).toMatchSnapshot(); - }); - - test('removeFilter', async () => { - await masto.removeFilter('123123'); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('fetchFollowRequests', async () => { - await masto.fetchFollowRequests({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('authorizeFollowRequest', async () => { - await masto.authorizeFollowRequest('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('rejectFollowRequest', async () => { - await masto.rejectFollowRequest('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchSuggestions', async () => { - await masto.fetchSuggestions(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('removeSuggestion', async () => { - await masto.removeSuggestion('123123'); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('fetchInstance', async () => { - await masto.fetchSuggestions(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchInstancesPeers', async () => { - await masto.fetchInstancesPeers(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchInstanceActivity', async () => { - await masto.fetchInstanceActivity(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchLists', async () => { - await masto.fetchLists(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchAccountLists', async () => { - await masto.fetchAccountLists('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchListAccounts', async () => { - await masto.fetchListAccounts('123123', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchList', async () => { - await masto.fetchList('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('createList', async () => { - await masto.createList({ - title: 'My list', - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('updateList', async () => { - await masto.updateList('123123', { - title: 'My list', - }); - expect(putMock).toBeCalledTimes(1); - expect(putMock).toMatchSnapshot(); - }); - - test('removeList', async () => { - await masto.removeList('123123'); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('addAccountToList', async () => { - await masto.addAccountToList('123123', { - account_ids: ['123', '456', '678'], - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('removeAccountFromList', async () => { - await masto.removeAccountFromList('123123', { - account_ids: ['123', '456', '678'], - }); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('uploadMediaAttachment', async () => { - await masto.uploadMediaAttachment({ - file: '...', - description: 'Nice image', - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('updateMediaAttachment', async () => { - await masto.updateMediaAttachment('123123', { - description: 'Nice image', - focus: '0, 0', - }); - expect(putMock).toBeCalledTimes(1); - expect(putMock).toMatchSnapshot(); - }); - - test('fetchMutes', async () => { - await masto.fetchMutes({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('muteAccount', async () => { - await masto.muteAccount('123123', { - notifications: false, - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unmuteAccount', async () => { - await masto.unmuteAccount('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('muteStatus', async () => { - await masto.muteStatus('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unmuteStatus', async () => { - await masto.unmuteStatus('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchNotifications', async () => { - await masto.fetchNotifications({ - exclude_types: ['favourite', 'follow', 'mention', 'poll', 'reblog'], - }); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchNotification', async () => { - await masto.fetchNotification('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('clearNotifications', async () => { - await masto.clearNotifications(); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('dissmissNotification', async () => { - await masto.dissmissNotification('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('addPushSubscription', async () => { - await masto.addPushSubscription({ - subscription: { - endpoint: 'https://example.com', - keys: { p256dh: 'xxxx', auth: 'yyyy' }, - }, - data: { - alerts: { - follow: true, - favourite: true, - reblog: true, - mention: true, - }, - }, - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchPushSubscription', async () => { - await masto.fetchPushSubscription(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('updatePushSubscription', async () => { - await masto.updatePushSubscription({ - data: { - alerts: { - follow: true, - favourite: true, - reblog: true, - mention: true, - }, - }, - }); - expect(putMock).toBeCalledTimes(1); - expect(putMock).toMatchSnapshot(); - }); - - test('removePushSubscription', async () => { - await masto.removePushSubscription(); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('fetchPoll', async () => { - await masto.fetchPoll('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('votePoll', async () => { - await masto.votePoll('123123', { - choices: ['xxx', 'yyy', 'zzz'], - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('reportAccount', async () => { - await masto.reportAccount({ - account_id: '123123', - status_ids: ['456456'], - comment: 'this is a report', - forward: true, - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchScheduledStatuses', async () => { - await masto.fetchScheduledStatuses(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchScheduledStatus', async () => { - await masto.fetchScheduledStatus('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('updateScheduledStatus', async () => { - await masto.updateScheduledStatus('123123', { - scheduled_at: '2019-03-28T04:39:31.121Z', - }); - expect(putMock).toBeCalledTimes(1); - expect(putMock).toMatchSnapshot(); - }); - - test('removeScheduledStatus', async () => { - await masto.removeScheduledStatus('123123'); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('search (v1)', async () => { - await masto.search( - { - q: 'query', - resolve: true, - }, - 'v1', - ); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('search', async () => { - await masto.search({ - q: 'query', - resolve: true, - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - account_id: '123', - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchStatus', async () => { - await masto.fetchStatus('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchStatusContext', async () => { - await masto.fetchStatusContext('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchStatusCard', async () => { - await masto.fetchStatusCard('123123'); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); - - test('fetchStatusRebloggedBy', async () => { - await masto.fetchStatusRebloggedBy('123123', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchStatusFavouritedBy', async () => { - await masto.fetchStatusFavouritedBy('123123', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('createStatus with content', async () => { - await masto.createStatus({ - status: 'Toot!', - in_reply_to_id: '123123', - poll: { - options: ['xxx', 'yyy', 'zzz'], - expires_in: 1000 * 60, - multiple: false, - hide_totals: true, - }, - sensitive: false, - spoiler_text: 'spoiler', - visibility: 'direct', - scheduled_at: '2019-03-28T04:39:31.121Z', - language: 'en', - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('createStatus with media ids', async () => { - await masto.createStatus({ - media_ids: ['123', '456'], - }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('createStatus with Idempotency-Key', async () => { - await masto.createStatus( - { - status: 'Too!', - }, - '59fe7e30-1a74-4050-8af7-5a8c7a224794', - ); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('removeStatus', async () => { - await masto.removeStatus('123123'); - expect(deleteMock).toBeCalledTimes(1); - expect(deleteMock).toMatchSnapshot(); - }); - - test('reblogStatus', async () => { - await masto.reblogStatus('123123', { visibility: 'direct' }); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unreblogStatus', async () => { - await masto.unreblogStatus('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('pinStatus', async () => { - await masto.pinStatus('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('unpinStatus', async () => { - await masto.unpinStatus('123123'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchHomeTimeline', async () => { - await masto.fetchHomeTimeline({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchCommunityTimeline', async () => { - await masto.fetchCommunityTimeline({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchPublicTimeline', async () => { - await masto.fetchPublicTimeline({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchTagTimeline', async () => { - await masto.fetchTagTimeline('DeleteTwitter', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchListTimeline', async () => { - await masto.fetchListTimeline('123123', { - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchDirectTimeline', async () => { - masto.gateway.version = '2.5.0'; - await masto.fetchDirectTimeline({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('fetchConversations', async () => { - await masto.fetchConversations({ - max_id: '5', - since_id: '3', - min_id: '2', - limit: 10, - }); - expect(paginateMock).toBeCalledTimes(1); - expect(paginateMock).toMatchSnapshot(); - }); - - test('followAccountByUsername', async () => { - await masto.followAccountByUsername('user@example.com'); - expect(postMock).toBeCalledTimes(1); - expect(postMock).toMatchSnapshot(); - }); - - test('fetchPreferences', async () => { - await masto.fetchPreferences(); - expect(getMock).toBeCalledTimes(1); - expect(getMock).toMatchSnapshot(); - }); -}); diff --git a/src/client/masto-events.ts b/src/client/masto-events.ts deleted file mode 100644 index 540f46d79..000000000 --- a/src/client/masto-events.ts +++ /dev/null @@ -1,93 +0,0 @@ -// tslint:disable no-unnecessary-override -import EventEmitter from 'eventemitter3'; -import WebSocket from 'isomorphic-ws'; -import { Conversation } from '../entities/conversation'; -import { Notification } from '../entities/notification'; -import { Status } from '../entities/status'; - -/** Callback argument of `ws` */ -export interface Message { - data: string; - type: string; - target: WebSocket; -} - -export interface EventTypesMap { - /** Status posted */ - update: Status; - /** Status deleted */ - delete: Status['id']; - /** User's notification */ - notification: Notification; - /** User's filter changed */ - filters_changed: undefined; - /** Status added to a conversation */ - conversation: Conversation; -} - -export type EventTypes = keyof EventTypesMap; - -/** - * Mastodon streaming api wrapper - */ -export class MastoEvents extends EventEmitter { - private ws?: WebSocket; - - /** - * Connect to the websocket endpoint - * @param url URL of the websocket endpoint - * @param protocols Subprotocol(s) for `Sec-Websocket-Protocol` - * @param params URL parameters - */ - public connect(url: string, protocols?: string | string[]) { - return new Promise((resolve, reject) => { - this.ws = new WebSocket(url, protocols); - - this.ws.addEventListener('message', this.handleMessage); - this.ws.addEventListener('error', reject); - this.ws.addEventListener('open', () => { - resolve(this); - }); - }); - } - - /** - * Disconnect from the websocket endpoint - */ - public disconnect() { - if (!this.ws) return; - this.ws.close(); - } - - /** - * Parse JSON data and emit it as an event - * @param message Websocket message - */ - public handleMessage = (message: Message) => { - const parsedMessage = JSON.parse(message.data); - let data: string | { [key: string]: any }; - - try { - data = JSON.parse(parsedMessage.payload); - } catch { - // If parsing failed, returns raw data - // Basically this is handling for `filters_changed` event - // Which doesn't contain payload in the data - data = parsedMessage.payload; - } - - this.emit(parsedMessage.event, data); - }; - - /** - * Add listener for the event - * @param event Type of the event. One of `update`, `delete`, `notification`, `filters_changed`, `conversation` - * @param callback Callback function - */ - public on( - event: T, - callback: (payload: EventTypesMap[T]) => void, - ) { - return super.on(event, callback); - } -} diff --git a/src/client/__tests__/decorators.spec.ts b/src/clients/__tests__/decorators.spec.ts similarity index 88% rename from src/client/__tests__/decorators.spec.ts rename to src/clients/__tests__/decorators.spec.ts index d22763acb..024fa731f 100644 --- a/src/client/__tests__/decorators.spec.ts +++ b/src/clients/__tests__/decorators.spec.ts @@ -4,9 +4,7 @@ import { available } from '../decorators'; describe('available', () => { test('throw an error when this.version and param.since is incompatible', () => { class Context { - gateway = { - version: '2.0.0', - }; + public version = '2.0.0'; // @ts-ignore @available({ since: '2.1.0' }) @@ -22,9 +20,7 @@ describe('available', () => { test('throw an error when this.version and param.until is incompatible', () => { class Context { - gateway = { - version: '2.0.0', - }; + public version = '2.0.0'; // @ts-ignore @available({ until: '1.9.0' }) @@ -40,9 +36,7 @@ describe('available', () => { test('not throw an error when this.version and params are compatible', () => { class Context { - gateway = { - version: '2.0.0', - }; + public version = '2.0.0'; // @ts-ignore @available({ sicne: '1.9.0', until: '2.1.0' }) diff --git a/src/client/decorators.ts b/src/clients/decorators.ts similarity index 88% rename from src/client/decorators.ts rename to src/clients/decorators.ts index 38987b22a..5e111b955 100644 --- a/src/client/decorators.ts +++ b/src/clients/decorators.ts @@ -1,9 +1,9 @@ import semver from 'semver'; import { MastoNotFoundError } from '../errors/masto-not-found-error'; -import { Masto } from './masto'; +import { Gateway } from '../gateway/gateway'; export type Decorator = ( - masto: Masto, + gateway: Gateway, name: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => any>, ) => void; @@ -29,8 +29,8 @@ export const available = (parameters: AvailabeParams): Decorator => ( const original = descriptor.value; const { since, until } = parameters; - descriptor.value = function(this: Masto, ...args: any[]) { - const version = semver.coerce(this.gateway.version); + descriptor.value = function(this: Gateway, ...args: any[]) { + const version = semver.coerce(this.version); if (since && version && semver.lt(version, since)) { throw new MastoNotFoundError( diff --git a/src/clients/masto-admin/__tests__/__snapshots__/masto-admin.spec.ts.snap b/src/clients/masto-admin/__tests__/__snapshots__/masto-admin.spec.ts.snap new file mode 100644 index 000000000..00dd13f6e --- /dev/null +++ b/src/clients/masto-admin/__tests__/__snapshots__/masto-admin.spec.ts.snap @@ -0,0 +1,369 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MastoAdmin actionAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"type\\":\\"disable\\",\\"report_id\\":\\"123123\\",\\"warning_preset_id\\":\\"123123\\",\\"text\\":\\"Your account have been disabled\\",\\"send_email_notification\\":false}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts/123/action", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin approveAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts/123/approve", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin assignReportToSelf 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/reports/123/assign_to_self", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin enableAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts/123/enable", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin fetchAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts/123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin fetchAccounts 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin fetchReport 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/reports/123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin fetchReports 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/reports", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin rejectAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts/123/reject", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin reopenReport 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/reports/123/reopen", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin resolveReport 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/reports/123/resolve", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin unassignReport 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/reports/123/unassign", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin unsilenceAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts/123/unsilence", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`MastoAdmin unsuspendAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/admin/accounts/123/unsuspend", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; diff --git a/src/clients/masto-admin/__tests__/masto-admin.spec.ts b/src/clients/masto-admin/__tests__/masto-admin.spec.ts new file mode 100644 index 000000000..95ecc7b3c --- /dev/null +++ b/src/clients/masto-admin/__tests__/masto-admin.spec.ts @@ -0,0 +1,117 @@ +// @ts-ignore +import axios from 'axios'; +import { MastoAdmin } from '../masto-admin'; + +jest.mock('axios'); + +describe('MastoAdmin', () => { + const masto = new MastoAdmin({ + uri: 'https://example.com', + version: '99.99.9', + streamingApiUrl: 'wss://example.com/stream', + }); + + beforeAll(async () => { + (axios.request as jest.Mock).mockResolvedValue({ + headers: { + link: '; rel="next"', + }, + data: {}, + }); + }); + + beforeEach(async () => { + masto.version = '99.99.9'; // avoid version error + (axios.request as jest.Mock).mockClear(); + }); + + test('fetchAccounts', async () => { + await masto.fetchAccounts(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccount', async () => { + await masto.fetchAccount('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('enableAccount', async () => { + await masto.enableAccount('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('approveAccount', async () => { + await masto.approveAccount('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('rejectAccount', async () => { + await masto.rejectAccount('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unsilenceAccount', async () => { + await masto.unsilenceAccount('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unsuspendAccount', async () => { + await masto.unsuspendAccount('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchReports', async () => { + await masto.fetchReports(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchReport', async () => { + await masto.fetchReport('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('assignReportToSelf', async () => { + await masto.assignReportToSelf('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unassignReport', async () => { + await masto.unassignReport('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('reopenReport', async () => { + await masto.reopenReport('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('resolveReport', async () => { + await masto.resolveReport('123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('actionAccount', async () => { + await masto.actionAccount('123', { + type: 'disable', + report_id: '123123', + warning_preset_id: '123123', + text: 'Your account have been disabled', + send_email_notification: false, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); +}); diff --git a/src/clients/masto-admin/masto-admin.ts b/src/clients/masto-admin/masto-admin.ts new file mode 100644 index 000000000..34cb92c62 --- /dev/null +++ b/src/clients/masto-admin/masto-admin.ts @@ -0,0 +1,158 @@ +import { AdminAccount } from '../../entities/admin-account'; +import { AdminReport } from '../../entities/admin-report'; +import { Gateway } from '../../gateway/gateway'; +import { available } from '../decorators'; +import { + AdminActionAccountParams, + AdminFetchAccountParams, + AdminFetchReportsParams, +} from './params'; + +/** + * Mastodon Moderation API client + */ +export class MastoAdmin extends Gateway { + /** + * Get accounts + * @param params parameters + * @retunr Accounts + */ + @available({ since: '2.9.1' }) + public fetchAccounts(params?: AdminFetchAccountParams) { + return this.get('/api/v1/admin/accounts', params); + } + + /** + * Get a specific account + * @param id ID of the account + * @return Account + */ + @available({ since: '2.9.1' }) + public fetchAccount(id: string) { + return this.get(`/api/v1/admin/accounts/${id}`); + } + + /** + * Re-enable account + * @param id ID of the account + * @return Account + */ + @available({ since: '2.9.1' }) + public enableAccount(id: string) { + return this.post(`/api/v1/admin/accounts/${id}/enable`); + } + + /** + * Approve pending account + * @param id ID of the account + * @return Account + */ + @available({ since: '2.9.1' }) + public approveAccount(id: string) { + return this.post(`/api/v1/admin/accounts/${id}/approve`); + } + + /** + * Reject pending account + * @param id ID of the account + * @return Account + */ + @available({ since: '2.9.1' }) + public rejectAccount(id: string) { + return this.post(`/api/v1/admin/accounts/${id}/reject`); + } + + /** + * Unsilence account + * @param id ID of the account + * @return Account + */ + @available({ since: '2.9.1' }) + public unsilenceAccount(id: string) { + return this.post(`/api/v1/admin/accounts/${id}/unsilence`); + } + + /** + * Unsuspend account + * @param id ID of the account + * @return Account + */ + @available({ since: '2.9.1' }) + public unsuspendAccount(id: string) { + return this.post(`/api/v1/admin/accounts/${id}/unsuspend`); + } + + /** + * Get reports + * @param params params + * @return Reports + */ + @available({ since: '2.9.1' }) + public fetchReports(params?: AdminFetchReportsParams) { + return this.get('/api/v1/admin/reports', params); + } + + /** + * Get a specific report + * @param id ID of the report + * @return Report + */ + @available({ since: '2.9.1' }) + public fetchReport(id: string) { + return this.get(`/api/v1/admin/reports/${id}`); + } + + /** + * Assign report to self + * @param id ID of the report + * @return Report + */ + @available({ since: '2.9.1' }) + public assignReportToSelf(id: string) { + return this.post(`/api/v1/admin/reports/${id}/assign_to_self`); + } + + /** + * Unassign report from self + * @param id ID of the report + * @return Report + */ + @available({ since: '2.9.1' }) + public unassignReport(id: string) { + return this.post(`/api/v1/admin/reports/${id}/unassign`); + } + + /** + * Re-open report + * @param id ID of the report + * @return Report + */ + @available({ since: '2.9.1' }) + public reopenReport(id: string) { + return this.post(`/api/v1/admin/reports/${id}/reopen`); + } + + /** + * Close report + * @param id ID of the report + * @return Report + */ + @available({ since: '2.9.1' }) + public resolveReport(id: string) { + return this.post(`/api/v1/admin/reports/${id}/resolve`); + } + + /** + * Perform a moderation action on an account + * @param id ID of the account + * @param params Params + * @return Acccount + */ + @available({ since: '2.9.1' }) + public actionAccount(id: string, params: AdminActionAccountParams) { + return this.post( + `/api/v1/admin/accounts/${id}/action`, + params, + ); + } +} diff --git a/src/clients/masto-admin/params.ts b/src/clients/masto-admin/params.ts new file mode 100644 index 000000000..506c73815 --- /dev/null +++ b/src/clients/masto-admin/params.ts @@ -0,0 +1,31 @@ +export interface AdminFetchAccountParams { + local?: boolean | null; + remote?: boolean | null; + by_domain?: string | null; + active?: boolean | null; + pending?: boolean | null; + disabled?: boolean | null; + silenced?: boolean | null; + suspended?: boolean | null; + usename?: string | null; + display_name?: string | null; + email?: string | null; + ip?: string | null; + staff?: boolean | null; +} + +export interface AdminFetchReportsParams { + resolved?: boolean | null; + account_id?: string | null; + target_account_id?: string | null; +} + +export type AccountActionType = 'none' | 'disable' | 'silence' | 'suspend'; + +export interface AdminActionAccountParams { + type: AccountActionType; + report_id: string; + warning_preset_id?: string | null; + text?: string | null; + send_email_notification?: boolean | null; +} diff --git a/src/clients/masto/__tests__/__snapshots__/masto.spec.ts.snap b/src/clients/masto/__tests__/__snapshots__/masto.spec.ts.snap new file mode 100644 index 000000000..c816c4dba --- /dev/null +++ b/src/clients/masto/__tests__/__snapshots__/masto.spec.ts.snap @@ -0,0 +1,2784 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Masto addAccountToList 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"account_ids\\":[\\"123\\",\\"456\\",\\"678\\"]}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/lists/123123/accounts", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto addPushSubscription 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"subscription\\":{\\"endpoint\\":\\"https://example.com\\",\\"keys\\":{\\"p256dh\\":\\"xxxx\\",\\"auth\\":\\"yyyy\\"}},\\"data\\":{\\"alerts\\":{\\"follow\\":true,\\"favourite\\":true,\\"reblog\\":true,\\"mention\\":true}}}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/push/subscription", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto authorizeFollowRequest 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/follow_requests/123123/authorize", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto blockAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/block", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto blockDomain 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"domain\\":\\"example.com\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/domain_blocks", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto clearNotifications 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/notifications/clear", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto createAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"username\\":\\"username\\",\\"password\\":\\"password\\",\\"email\\":\\"example@example.com\\",\\"agreement\\":true}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto createApp 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"client_name\\":\\"My Client\\",\\"redirect_uris\\":\\"https://example.com\\",\\"scopes\\":\\"write read\\",\\"website\\":\\"https://example.com\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/apps", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto createFiler 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"phrase\\":\\"Twitter\\",\\"context\\":[\\"home\\",\\"notifications\\",\\"public\\",\\"thread\\"],\\"irreversible\\":true,\\"whole_word\\":true,\\"expires_in\\":3600000}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/filters", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto createList 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"title\\":\\"My list\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/lists", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto createStatus with Idempotency-Key 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"status\\":\\"Too!\\"}", + "headers": Object { + "Content-Type": "application/json", + "Idempotency-Key": "59fe7e30-1a74-4050-8af7-5a8c7a224794", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto createStatus with content 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"status\\":\\"Toot!\\",\\"in_reply_to_id\\":\\"123123\\",\\"poll\\":{\\"options\\":[\\"xxx\\",\\"yyy\\",\\"zzz\\"],\\"expires_in\\":60000,\\"multiple\\":false,\\"hide_totals\\":true},\\"sensitive\\":false,\\"spoiler_text\\":\\"spoiler\\",\\"visibility\\":\\"direct\\",\\"scheduled_at\\":\\"2019-03-28T04:39:31.121Z\\",\\"language\\":\\"en\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto createStatus with media ids 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"media_ids\\":[\\"123\\",\\"456\\"]}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto dissmissNotification 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"id\\":\\"123123\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/notifications/dismiss", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto favouriteStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/favourite", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccessToken with authorization code 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"grant_type\\":\\"authorization_code\\",\\"code\\":\\"789789789\\",\\"redirect_uri\\":\\"https://example.com\\",\\"client_id\\":\\"123123123\\",\\"client_secret\\":\\"456456456\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/oauth/token", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccessToken with password 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"grant_type\\":\\"password\\",\\"username\\":\\"username\\",\\"password\\":\\"password\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/oauth/token", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccountFollowers 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123123/followers", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccountFollowing 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123123/following", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccountIdentityProofs 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123123/identity_proofs", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccountLists 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/lists", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccountRelationships 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "id": Array [ + "123123", + "456456", + ], + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/relationship", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchAccountStatuses 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123123/statuses", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchBlocks 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/blocks", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchCommunityTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "local": true, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/timelines/public", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchConversations 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/conversations", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchCustomEmojis 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/custom_emojis", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchDirectTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/timelines/direct", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchDomainBlocks 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": undefined, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/domain_blocks", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchEndorsements 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/endorsements", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchFavourites 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/favourites", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchFilter 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/filters/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchFilters 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/filters", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchFollowRequests 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/follow_requests", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchHomeTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/timelines/home", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchInstance 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/instance", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchInstanceActivity 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/instance/activity", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchInstancesPeers 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/instance/peers", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchList 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/lists/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchListAccounts 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/list/123123/accounts", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchListTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/timelines/list/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchLists 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/lists", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchMutes 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/mutes", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchNotification 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/notifications/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchNotifications 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "exclude_types": Array [ + "favourite", + "follow", + "mention", + "poll", + "reblog", + ], + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/notifications", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchPoll 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/polls/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchPreferences 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/preferences", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchPublicTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/timelines/public", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchPushSubscription 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/push/subscription", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchScheduledStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/scheduled_statuses/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchScheduledStatuses 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/scheduled_statuses", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchStatusCard 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/card", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchStatusContext 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/context", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchStatusFavouritedBy 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/favourited_by", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchStatusRebloggedBy 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/reblogged_by", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchSuggestions 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/suggestions", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto fetchTagTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "limit": 10, + "max_id": "5", + "min_id": "2", + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/timelines/tag/DeleteTwitter", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto followAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"reblogs\\":false}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/follow", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto followAccountByUsername 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"uri\\":\\"user@example.com\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/follows", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto muteAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"notifications\\":false}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/mute", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto muteStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/mute", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto pinAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/pin", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto pinStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/pin", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto reblogStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"visibility\\":\\"direct\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/reblog", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto rejectFollowRequest 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/follow_requests/123123/reject", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto removeAccountFromList 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"account_ids\\":[\\"123\\",\\"456\\",\\"678\\"]}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/lists/123123/accounts", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto removeFilter 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/filters/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto removeList 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/lists/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto removePushSubscription 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/push/subscription", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto removeScheduledStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/scheduled_statuses/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto removeStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto removeSuggestion 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/suggestions/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto reportAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"account_id\\":\\"123123\\",\\"status_ids\\":[\\"456456\\"],\\"comment\\":\\"this is a report\\",\\"forward\\":true}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/reports", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto revokeAccessToken 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"client_id\\":\\"123123123\\",\\"client_secret\\":\\"456456456\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/oauth/revoke", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto search (v1) 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "q": "query", + "resolve": true, + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/search", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto search 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "account_id": "123", + "limit": 10, + "max_id": "5", + "min_id": "2", + "q": "query", + "resolve": true, + "since_id": "3", + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v2/search", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto searchAccounts 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object { + "following": false, + "limit": 123, + "q": "query", + "resolve": true, + }, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/search", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto streamCommunityTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "wss://example.com/stream/api/v1/streaming?stream=public%3Alocal", + Array [], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Masto streamDirectTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "wss://example.com/stream/api/v1/streaming?stream=direct", + Array [], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Masto streamListTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "wss://example.com/stream/api/v1/streaming?stream=list&list=123123", + Array [], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Masto streamLocalTagTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "wss://example.com/stream/api/v1/streaming?stream=hashtag%3Alocal&tag=deletetwitter", + Array [], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Masto streamPublicTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "wss://example.com/stream/api/v1/streaming?stream=public", + Array [], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Masto streamTagTimeline 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "wss://example.com/stream/api/v1/streaming?stream=hashtag&tag=deletetwitter", + Array [], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Masto streamUser 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "wss://example.com/stream/api/v1/streaming?stream=user", + Array [], + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Masto unblockAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/unblock", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unblockDomain 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"domain\\":\\"example.com\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "DELETE", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/domain_blocks", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unfavouriteStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/unfavourite", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unfollowAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/unfollow", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unmuteAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/unmute", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unmuteStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/unmute", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unpinAccount 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/123123/unpin", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unpinStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/unpin", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto unreblogStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/statuses/123123/unreblog", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto updateFilter 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"phrase\\":\\"Twitter\\",\\"context\\":[\\"home\\",\\"notifications\\",\\"public\\",\\"thread\\"],\\"irreversible\\":true,\\"whole_word\\":true,\\"expires_in\\":3600000}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "PUT", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/filters/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto updateList 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"title\\":\\"My list\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "PUT", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/lists/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto updateMediaAttachment 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"description\\":\\"Nice image\\",\\"focus\\":\\"0, 0\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "PUT", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/media/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto updatePushSubscription 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"data\\":{\\"alerts\\":{\\"follow\\":true,\\"favourite\\":true,\\"reblog\\":true,\\"mention\\":true}}}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "PUT", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/push/subscription", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto updateScheduledStatus 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"scheduled_at\\":\\"2019-03-28T04:39:31.121Z\\"}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "PUT", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/scheduled_statuses/123123", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto verifyAppCredentials 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/apps/verify_credentials", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto verifyCredentials 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": undefined, + "headers": Object { + "Content-Type": "application/json", + }, + "method": "GET", + "params": Object {}, + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/accounts/verify_credentials", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; + +exports[`Masto votePoll 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + Object { + "data": "{\\"choices\\":[\\"xxx\\",\\"yyy\\",\\"zzz\\"]}", + "headers": Object { + "Content-Type": "application/json", + }, + "method": "POST", + "transformResponse": Array [ + [Function], + ], + "url": "https://example.com/api/v1/polls/123123/votes", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], +} +`; diff --git a/src/clients/masto/__tests__/masto.spec.ts b/src/clients/masto/__tests__/masto.spec.ts new file mode 100644 index 000000000..09f88ac10 --- /dev/null +++ b/src/clients/masto/__tests__/masto.spec.ts @@ -0,0 +1,925 @@ +// tslint:disable +// @ts-ignore +// prettier-ignore +import axios from 'axios'; +import { Masto } from '../masto'; +// @ts-ignore +import { WebSocketEvents, connectMock } from '../../../gateway/websocket'; + +jest.mock('axios'); +jest.mock('../../../gateway/websocket'); + +describe('Masto', () => { + const masto = new Masto({ + uri: 'https://example.com', + version: '99.99.9', + streamingApiUrl: 'wss://example.com/stream', + }); + + beforeAll(async () => { + (axios.request as jest.Mock).mockResolvedValue({ + headers: { + link: '; rel="next"', + }, + data: {}, + }); + }); + + beforeEach(async () => { + masto.version = '99.99.9'; // avoid version error + (connectMock as jest.Mock).mockClear(); + (axios.request as jest.Mock).mockClear(); + }); + + test('streamUser', async () => { + await masto.streamUser(); + expect(connectMock).toBeCalledTimes(1); + expect(connectMock).toMatchSnapshot(); + }); + + test('streamPublicTimeline', async () => { + await masto.streamPublicTimeline(); + expect(connectMock).toBeCalledTimes(1); + expect(connectMock).toMatchSnapshot(); + }); + + test('streamCommunityTimeline', async () => { + await masto.streamCommunityTimeline(); + expect(connectMock).toBeCalledTimes(1); + expect(connectMock).toMatchSnapshot(); + }); + + test('streamTagTimeline', async () => { + await masto.streamTagTimeline('deletetwitter'); + expect(connectMock).toBeCalledTimes(1); + expect(connectMock).toMatchSnapshot(); + }); + + test('streamLocalTagTimeline', async () => { + await masto.streamLocalTagTimeline('deletetwitter'); + expect(connectMock).toBeCalledTimes(1); + expect(connectMock).toMatchSnapshot(); + }); + + test('streamListTimeline', async () => { + await masto.streamListTimeline('123123'); + expect(connectMock).toBeCalledTimes(1); + expect(connectMock).toMatchSnapshot(); + }); + + test('streamDirectTimeline', async () => { + await masto.streamDirectTimeline(); + expect(connectMock).toBeCalledTimes(1); + expect(connectMock).toMatchSnapshot(); + }); + + test('fetchAccessToken with authorization code', async () => { + await masto.fetchAccessToken({ + grant_type: 'authorization_code', + code: '789789789', + redirect_uri: 'https://example.com', + client_id: '123123123', + client_secret: '456456456', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccessToken with password', async () => { + await masto.fetchAccessToken({ + grant_type: 'password', + username: 'username', + password: 'password', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('revokeAccessToken', async () => { + await masto.revokeAccessToken({ + client_id: '123123123', + client_secret: '456456456', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccount', async () => { + await masto.fetchAccount('123123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccountIdentityProofs', async () => { + await masto.fetchAccountIdentityProofs('123123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('createAccount', async () => { + await masto.createAccount({ + username: 'username', + password: 'password', + email: 'example@example.com', + agreement: true, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('verifyCredentials', async () => { + await masto.verifyCredentials(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('updateCredentials', async () => { + await masto.updateCredentials({ + display_name: 'Neetshin', + avatar: '...', + header: '...', + note: 'web frontend engineer', + locked: false, + // source: { + // privacy: 'direct', + // sensitive: false, + // language: 'ja', + // }, + // fields_attributes: [ + // { + // name: 'GitHub', + // value: 'https://github.com/neet', + // }, + // ], + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toBeCalledWith( + expect.objectContaining({ + data: expect.any(FormData), + }), + ); + }); + + test('fetchAccountFollowers', async () => { + const iterable = masto.fetchAccountFollowers('123123123', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccountFollowing', async () => { + const iterable = masto.fetchAccountFollowing('123123123', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccountStatuses', async () => { + const iterable = masto.fetchAccountStatuses('123123123', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('followAccount', async () => { + await masto.followAccount('123123', { + reblogs: false, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unfollowAccount', async () => { + await masto.unfollowAccount('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccountRelationships', async () => { + await masto.fetchAccountRelationships(['123123', '456456']); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('searchAccounts', async () => { + await masto.searchAccounts({ + q: 'query', + resolve: true, + limit: 123, + following: false, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('createApp', async () => { + await masto.createApp({ + client_name: 'My Client', + redirect_uris: 'https://example.com', + scopes: 'write read', + website: 'https://example.com', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('verifyAppCredentials', async () => { + await masto.verifyAppCredentials(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchBlocks', async () => { + const iterable = masto.fetchBlocks({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('blockAccount', async () => { + await masto.blockAccount('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unblockAccount', async () => { + await masto.unblockAccount('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchCustomEmojis', async () => { + await masto.fetchCustomEmojis(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchDomainBlocks', async () => { + const iterable = masto.fetchDomainBlocks(); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('blockDomain', async () => { + await masto.blockDomain('example.com'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unblockDomain', async () => { + await masto.unblockDomain('example.com'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchEndorsements', async () => { + const iterable = masto.fetchEndorsements({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('pinAccount', async () => { + await masto.pinAccount('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unpinAccount', async () => { + await masto.unpinAccount('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchFavourites', async () => { + const iterable = masto.fetchFavourites({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('favouriteStatus', async () => { + await masto.favouriteStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unfavouriteStatus', async () => { + await masto.unfavouriteStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchFilters', async () => { + await masto.fetchFilters(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchFilter', async () => { + await masto.fetchFilter('123123'); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('createFiler', async () => { + await masto.createFiler({ + phrase: 'Twitter', + context: ['home', 'notifications', 'public', 'thread'], + irreversible: true, + whole_word: true, + expires_in: 1000 * 60 * 60, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('updateFilter', async () => { + await masto.updateFilter('123123', { + phrase: 'Twitter', + context: ['home', 'notifications', 'public', 'thread'], + irreversible: true, + whole_word: true, + expires_in: 1000 * 60 * 60, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('removeFilter', async () => { + await masto.removeFilter('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchFollowRequests', async () => { + const iterable = masto.fetchFollowRequests({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('authorizeFollowRequest', async () => { + await masto.authorizeFollowRequest('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('rejectFollowRequest', async () => { + await masto.rejectFollowRequest('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchSuggestions', async () => { + await masto.fetchSuggestions(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('removeSuggestion', async () => { + await masto.removeSuggestion('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchInstance', async () => { + await masto.fetchInstance(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchInstancesPeers', async () => { + await masto.fetchInstancesPeers(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchInstanceActivity', async () => { + await masto.fetchInstanceActivity(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchLists', async () => { + await masto.fetchLists(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchAccountLists', async () => { + await masto.fetchAccountLists('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchListAccounts', async () => { + const iterable = masto.fetchListAccounts('123123', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchList', async () => { + await masto.fetchList('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('createList', async () => { + await masto.createList({ + title: 'My list', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('updateList', async () => { + await masto.updateList('123123', { + title: 'My list', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('removeList', async () => { + await masto.removeList('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('addAccountToList', async () => { + await masto.addAccountToList('123123', { + account_ids: ['123', '456', '678'], + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('removeAccountFromList', async () => { + await masto.removeAccountFromList('123123', { + account_ids: ['123', '456', '678'], + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('uploadMediaAttachment', async () => { + await masto.uploadMediaAttachment({ + file: '...', + description: 'Nice image', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toBeCalledWith( + expect.objectContaining({ + data: expect.any(FormData), + }), + ); + }); + + test('updateMediaAttachment', async () => { + await masto.updateMediaAttachment('123123', { + description: 'Nice image', + focus: '0, 0', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchMutes', async () => { + const iterable = masto.fetchMutes({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('muteAccount', async () => { + await masto.muteAccount('123123', { + notifications: false, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unmuteAccount', async () => { + await masto.unmuteAccount('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('muteStatus', async () => { + await masto.muteStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unmuteStatus', async () => { + await masto.unmuteStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchNotifications', async () => { + await masto.fetchNotifications({ + exclude_types: ['favourite', 'follow', 'mention', 'poll', 'reblog'], + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchNotification', async () => { + await masto.fetchNotification('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('clearNotifications', async () => { + await masto.clearNotifications(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('dissmissNotification', async () => { + await masto.dissmissNotification('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('addPushSubscription', async () => { + await masto.addPushSubscription({ + subscription: { + endpoint: 'https://example.com', + keys: { p256dh: 'xxxx', auth: 'yyyy' }, + }, + data: { + alerts: { + follow: true, + favourite: true, + reblog: true, + mention: true, + }, + }, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchPushSubscription', async () => { + await masto.fetchPushSubscription(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('updatePushSubscription', async () => { + await masto.updatePushSubscription({ + data: { + alerts: { + follow: true, + favourite: true, + reblog: true, + mention: true, + }, + }, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('removePushSubscription', async () => { + await masto.removePushSubscription(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchPoll', async () => { + await masto.fetchPoll('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('votePoll', async () => { + await masto.votePoll('123123', { + choices: ['xxx', 'yyy', 'zzz'], + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('reportAccount', async () => { + await masto.reportAccount({ + account_id: '123123', + status_ids: ['456456'], + comment: 'this is a report', + forward: true, + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchScheduledStatuses', async () => { + await masto.fetchScheduledStatuses(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchScheduledStatus', async () => { + await masto.fetchScheduledStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('updateScheduledStatus', async () => { + await masto.updateScheduledStatus('123123', { + scheduled_at: '2019-03-28T04:39:31.121Z', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('removeScheduledStatus', async () => { + await masto.removeScheduledStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('search (v1)', async () => { + const iterable = masto.search( + { + q: 'query', + resolve: true, + }, + 'v1', + ); + iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('search', async () => { + const iterable = masto.search({ + q: 'query', + resolve: true, + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + account_id: '123', + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchStatus', async () => { + await masto.fetchStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchStatusContext', async () => { + await masto.fetchStatusContext('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchStatusCard', async () => { + await masto.fetchStatusCard('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchStatusRebloggedBy', async () => { + const iterable = masto.fetchStatusRebloggedBy('123123', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchStatusFavouritedBy', async () => { + const iterable = masto.fetchStatusFavouritedBy('123123', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('createStatus with content', async () => { + await masto.createStatus({ + status: 'Toot!', + in_reply_to_id: '123123', + poll: { + options: ['xxx', 'yyy', 'zzz'], + expires_in: 1000 * 60, + multiple: false, + hide_totals: true, + }, + sensitive: false, + spoiler_text: 'spoiler', + visibility: 'direct', + scheduled_at: '2019-03-28T04:39:31.121Z', + language: 'en', + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('createStatus with media ids', async () => { + await masto.createStatus({ + media_ids: ['123', '456'], + }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('createStatus with Idempotency-Key', async () => { + await masto.createStatus( + { + status: 'Too!', + }, + '59fe7e30-1a74-4050-8af7-5a8c7a224794', + ); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('removeStatus', async () => { + await masto.removeStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('reblogStatus', async () => { + await masto.reblogStatus('123123', { visibility: 'direct' }); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unreblogStatus', async () => { + await masto.unreblogStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('pinStatus', async () => { + await masto.pinStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('unpinStatus', async () => { + await masto.unpinStatus('123123'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchHomeTimeline', async () => { + const iterable = masto.fetchHomeTimeline({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchCommunityTimeline', async () => { + const iterable = await masto.fetchCommunityTimeline({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchPublicTimeline', async () => { + const iterable = await masto.fetchPublicTimeline({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchTagTimeline', async () => { + const iterable = masto.fetchTagTimeline('DeleteTwitter', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchListTimeline', async () => { + const iterable = masto.fetchListTimeline('123123', { + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchDirectTimeline', async () => { + masto.version = '2.5.0'; + const iterable = masto.fetchDirectTimeline({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchConversations', async () => { + const iterable = masto.fetchConversations({ + max_id: '5', + since_id: '3', + min_id: '2', + limit: 10, + }); + await iterable.next(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('followAccountByUsername', async () => { + await masto.followAccountByUsername('user@example.com'); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); + + test('fetchPreferences', async () => { + await masto.fetchPreferences(); + expect(axios.request as jest.Mock).toBeCalledTimes(1); + expect(axios.request as jest.Mock).toMatchSnapshot(); + }); +}); diff --git a/src/client/masto.ts b/src/clients/masto/masto.ts similarity index 78% rename from src/client/masto.ts rename to src/clients/masto/masto.ts index d79d455bf..21f2e2c97 100644 --- a/src/client/masto.ts +++ b/src/clients/masto/masto.ts @@ -2,27 +2,27 @@ import { Account, AccountCredentials, AccountIdentityProof, -} from '../entities/account'; -import { Application } from '../entities/application'; -import { Attachment } from '../entities/attachment'; -import { Card } from '../entities/card'; -import { Context } from '../entities/context'; -import { Conversation } from '../entities/conversation'; -import { Emoji } from '../entities/emoji'; -import { Filter } from '../entities/filter'; -import { Instance, InstanceActivity } from '../entities/instance'; -import { List } from '../entities/list'; -import { Notification } from '../entities/notification'; -import { OAuthClient, OAuthToken } from '../entities/oauth'; -import { Poll } from '../entities/poll'; -import { Preference } from '../entities/preference'; -import { PushSubscription } from '../entities/push-subscription'; -import { Relationship } from '../entities/relationship'; -import { Results, ResultsV1 } from '../entities/results'; -import { ScheduledStatus } from '../entities/scheduled-status'; -import { Status } from '../entities/status'; -import { available } from './decorators'; -import { Gateway } from './gateway'; +} from '../../entities/account'; +import { Application } from '../../entities/application'; +import { Attachment } from '../../entities/attachment'; +import { Card } from '../../entities/card'; +import { Context } from '../../entities/context'; +import { Conversation } from '../../entities/conversation'; +import { Emoji } from '../../entities/emoji'; +import { Filter } from '../../entities/filter'; +import { Instance, InstanceActivity } from '../../entities/instance'; +import { List } from '../../entities/list'; +import { Notification } from '../../entities/notification'; +import { OAuthClient, OAuthToken } from '../../entities/oauth'; +import { Poll } from '../../entities/poll'; +import { Preference } from '../../entities/preference'; +import { PushSubscription } from '../../entities/push-subscription'; +import { Relationship } from '../../entities/relationship'; +import { Results, ResultsV1 } from '../../entities/results'; +import { ScheduledStatus } from '../../entities/scheduled-status'; +import { Status } from '../../entities/status'; +import { Gateway } from '../../gateway/gateway'; +import { available } from '../decorators'; import { AddPushSubscriptionParams, CreateAccountParams, @@ -33,7 +33,6 @@ import { FetchNotificationsParams, FetchTimelineParams, FollowAccountParams, - LoginParams, ModifyFilterParams, ModifyListAccountsParams, ModifyListParams, @@ -55,34 +54,7 @@ import { /** * Mastodon API client */ -export class Masto { - /** Instance of Gateway */ - public gateway: Gateway; - - /** - * Private constructor - * @param gateway Instance of Gateway - */ - private constructor(gateway: Gateway) { - this.gateway = gateway; - } - - /** - * Login to Mastodon - * @param params Paramters - * @return Instance of Mastodon class - */ - public static async login(params: LoginParams) { - const gateway = new Gateway(params); - const masto = new Masto(gateway); - const instance = await masto.fetchInstance(); - - gateway.version = instance.version; - gateway.streamingApiUrl = instance.urls.streaming_api; - - return masto; - } - +export class Masto extends Gateway { /** * Starting home timeline and notification streaming * @return Instance of EventEmitter @@ -90,7 +62,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public streamUser() { - return this.gateway.stream('/api/v1/streaming', { + return this.stream('/api/v1/streaming', { stream: 'user', }); } @@ -102,7 +74,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public streamPublicTimeline() { - return this.gateway.stream('/api/v1/streaming', { + return this.stream('/api/v1/streaming', { stream: 'public', }); } @@ -114,7 +86,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public streamCommunityTimeline() { - return this.gateway.stream('/api/v1/streaming', { + return this.stream('/api/v1/streaming', { stream: 'public:local', }); } @@ -127,7 +99,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public streamTagTimeline(id: string) { - return this.gateway.stream('/api/v1/streaming', { + return this.stream('/api/v1/streaming', { stream: 'hashtag', tag: id, }); @@ -141,7 +113,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public streamLocalTagTimeline(id: string) { - return this.gateway.stream('/api/v1/streaming', { + return this.stream('/api/v1/streaming', { stream: 'hashtag:local', tag: id, }); @@ -155,7 +127,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public streamListTimeline(id: string) { - return this.gateway.stream('/api/v1/streaming', { + return this.stream('/api/v1/streaming', { stream: 'list', list: id, }); @@ -168,7 +140,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public streamDirectTimeline() { - return this.gateway.stream('/api/v1/streaming', { + return this.stream('/api/v1/streaming', { stream: 'direct', }); } @@ -180,7 +152,7 @@ export class Masto { * @see https://docs.joinmastodon.org/api/authentication/#post-oauth-token */ public fetchAccessToken(params: FetchAccessTokenParams) { - return this.gateway.post('/oauth/token', params); + return this.post('/oauth/token', params); } /** @@ -189,7 +161,7 @@ export class Masto { * @see https://docs.joinmastodon.org/api/authentication/#post-oauth-revoke */ public revokeAccessToken(params: RevokeAccessTokenParams) { - return this.gateway.post('/oauth/revoke', params); + return this.post('/oauth/revoke', params); } /** @@ -200,7 +172,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchAccount(id: string) { - return this.gateway.get(`/api/v1/accounts/${id}`); + return this.get(`/api/v1/accounts/${id}`); } /** @@ -211,7 +183,7 @@ export class Masto { */ @available({ since: '2.8.0' }) public fetchAccountIdentityProofs(id: string) { - return this.gateway.get( + return this.get( `/api/v1/accounts/${id}/identity_proofs`, ); } @@ -223,7 +195,7 @@ export class Masto { */ @available({ since: '2.7.0' }) public createAccount(params: CreateAccountParams) { - return this.gateway.post('/api/v1/accounts', params); + return this.post('/api/v1/accounts', params); } /** @@ -233,9 +205,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public verifyCredentials() { - return this.gateway.get( - '/api/v1/accounts/verify_credentials', - ); + return this.get('/api/v1/accounts/verify_credentials'); } /** @@ -246,7 +216,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public updateCredentials(params?: UpdateCredentialsParams) { - return this.gateway.patch( + return this.patch( '/api/v1/accounts/update_credentials', params, { headers: { 'Content-Type': 'multipart/form-data' } }, @@ -262,10 +232,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchAccountFollowers(id: string, params?: PaginationParams) { - return this.gateway.paginate( - `/api/v1/accounts/${id}/followers`, - params, - ); + return this.paginate(`/api/v1/accounts/${id}/followers`, params); } /** @@ -277,10 +244,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchAccountFollowing(id: string, params?: PaginationParams) { - return this.gateway.paginate( - `/api/v1/accounts/${id}/following`, - params, - ); + return this.paginate(`/api/v1/accounts/${id}/following`, params); } /** @@ -292,10 +256,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchAccountStatuses(id: string, params?: FetchAccountStatusesParams) { - return this.gateway.paginate( - `/api/v1/accounts/${id}/statuses`, - params, - ); + return this.paginate(`/api/v1/accounts/${id}/statuses`, params); } /** @@ -307,10 +268,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public followAccount(id: string, params?: FollowAccountParams) { - return this.gateway.post( - `/api/v1/accounts/${id}/follow`, - params, - ); + return this.post(`/api/v1/accounts/${id}/follow`, params); } /** @@ -321,7 +279,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public unfollowAccount(id: string) { - return this.gateway.post(`/api/v1/accounts/${id}/unfollow`); + return this.post(`/api/v1/accounts/${id}/unfollow`); } /** @@ -332,7 +290,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchAccountRelationships(id: string[]) { - return this.gateway.get(`/api/v1/accounts/relationship`, { + return this.get(`/api/v1/accounts/relationship`, { id, }); } @@ -345,7 +303,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public searchAccounts(params?: SearchAccountsParams) { - return this.gateway.get(`/api/v1/accounts/search`, params); + return this.get(`/api/v1/accounts/search`, params); } /** @@ -356,7 +314,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public createApp(params: CreateAppParams) { - return this.gateway.post(`/api/v1/apps`, params); + return this.post(`/api/v1/apps`, params); } /** @@ -366,7 +324,7 @@ export class Masto { */ @available({ since: '2.0.0' }) public verifyAppCredentials() { - return this.gateway.get(`/api/v1/apps/verify_credentials`); + return this.get(`/api/v1/apps/verify_credentials`); } /** @@ -377,7 +335,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchBlocks(params?: PaginationParams) { - return this.gateway.paginate(`/api/v1/blocks`, params); + return this.paginate(`/api/v1/blocks`, params); } /** @@ -388,7 +346,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public blockAccount(id: string) { - return this.gateway.post(`/api/v1/accounts/${id}/block`); + return this.post(`/api/v1/accounts/${id}/block`); } /** @@ -399,7 +357,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public unblockAccount(id: string) { - return this.gateway.post(`/api/v1/accounts/${id}/unblock`); + return this.post(`/api/v1/accounts/${id}/unblock`); } /** @@ -409,7 +367,7 @@ export class Masto { */ @available({ since: '2.0.0' }) public fetchCustomEmojis() { - return this.gateway.get(`/api/v1/custom_emojis`); + return this.get(`/api/v1/custom_emojis`); } /** @@ -420,7 +378,7 @@ export class Masto { */ @available({ since: '1.4.0' }) public fetchDomainBlocks(params?: PaginationParams) { - return this.gateway.paginate(`/api/v1/domain_blocks`, params); + return this.paginate(`/api/v1/domain_blocks`, params); } /** @@ -431,7 +389,7 @@ export class Masto { */ @available({ since: '1.4.0' }) public blockDomain(domain: string) { - return this.gateway.post(`/api/v1/domain_blocks`, { + return this.post(`/api/v1/domain_blocks`, { domain, }); } @@ -444,7 +402,7 @@ export class Masto { */ @available({ since: '1.4.0' }) public unblockDomain(domain: string) { - return this.gateway.delete(`/api/v1/domain_blocks`, { + return this.delete(`/api/v1/domain_blocks`, { domain, }); } @@ -456,7 +414,7 @@ export class Masto { */ @available({ since: '2.5.0' }) public fetchEndorsements(params?: PaginationParams) { - return this.gateway.paginate(`/api/v1/endorsements`, params); + return this.paginate(`/api/v1/endorsements`, params); } /** @@ -467,7 +425,7 @@ export class Masto { */ @available({ since: '2.5.0' }) public pinAccount(id: string) { - return this.gateway.post(`/api/v1/accounts/${id}/pin`); + return this.post(`/api/v1/accounts/${id}/pin`); } /** @@ -478,7 +436,7 @@ export class Masto { */ @available({ since: '2.5.0' }) public unpinAccount(id: string) { - return this.gateway.post(`/api/v1/accounts/${id}/unpin`); + return this.post(`/api/v1/accounts/${id}/unpin`); } /** @@ -489,7 +447,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchFavourites(params?: PaginationParams) { - return this.gateway.paginate(`/api/v1/favourites`, params); + return this.paginate(`/api/v1/favourites`, params); } /** @@ -500,7 +458,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public favouriteStatus(id: string) { - return this.gateway.post(`/api/v1/statuses/${id}/favourite`); + return this.post(`/api/v1/statuses/${id}/favourite`); } /** @@ -511,7 +469,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public unfavouriteStatus(id: string) { - return this.gateway.post(`/api/v1/statuses/${id}/unfavourite`); + return this.post(`/api/v1/statuses/${id}/unfavourite`); } /** @@ -521,7 +479,7 @@ export class Masto { */ @available({ since: '2.4.3' }) public fetchFilters() { - return this.gateway.get(`/api/v1/filters`); + return this.get(`/api/v1/filters`); } /** @@ -532,7 +490,7 @@ export class Masto { */ @available({ since: '2.4.3' }) public fetchFilter(id: string) { - return this.gateway.get(`/api/v1/filters/${id}`); + return this.get(`/api/v1/filters/${id}`); } /** @@ -543,7 +501,7 @@ export class Masto { */ @available({ since: '2.4.3' }) public createFiler(params?: ModifyFilterParams) { - return this.gateway.post(`/api/v1/filters`, params); + return this.post(`/api/v1/filters`, params); } /** @@ -555,7 +513,7 @@ export class Masto { */ @available({ since: '2.4.3' }) public updateFilter(id: string, params?: ModifyFilterParams) { - return this.gateway.put(`/api/v1/filters/${id}`, params); + return this.put(`/api/v1/filters/${id}`, params); } /** @@ -566,7 +524,7 @@ export class Masto { */ @available({ since: '2.4.3' }) public removeFilter(id: string) { - return this.gateway.delete(`/api/v1/filters/${id}`); + return this.delete(`/api/v1/filters/${id}`); } /** @@ -577,7 +535,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchFollowRequests(params?: PaginationParams) { - return this.gateway.paginate(`/api/v1/follow_requests`, params); + return this.paginate(`/api/v1/follow_requests`, params); } /** @@ -588,7 +546,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public authorizeFollowRequest(id: string) { - return this.gateway.post(`/api/v1/follow_requests/${id}/authorize`); + return this.post(`/api/v1/follow_requests/${id}/authorize`); } /** @@ -599,7 +557,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public rejectFollowRequest(id: string) { - return this.gateway.post(`/api/v1/follow_requests/${id}/reject`); + return this.post(`/api/v1/follow_requests/${id}/reject`); } /** @@ -609,7 +567,7 @@ export class Masto { */ @available({ since: '2.4.3' }) public fetchSuggestions() { - return this.gateway.get('/api/v1/suggestions'); + return this.get('/api/v1/suggestions'); } /** @@ -620,7 +578,7 @@ export class Masto { */ @available({ since: '2.4.3' }) public removeSuggestion(id: string) { - return this.gateway.delete(`/api/v1/suggestions/${id}`); + return this.delete(`/api/v1/suggestions/${id}`); } /** @@ -630,7 +588,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchInstance() { - return this.gateway.get('/api/v1/instance'); + return this.get('/api/v1/instance'); } /** @@ -640,7 +598,7 @@ export class Masto { */ @available({ since: '2.1.2' }) public fetchInstancesPeers() { - return this.gateway.get('/api/v1/instance/peers'); + return this.get('/api/v1/instance/peers'); } /** @@ -650,7 +608,7 @@ export class Masto { */ @available({ since: '2.1.2' }) public fetchInstanceActivity() { - return this.gateway.get('/api/v1/instance/activity'); + return this.get('/api/v1/instance/activity'); } /** @@ -660,7 +618,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public fetchLists() { - return this.gateway.get('/api/v1/lists'); + return this.get('/api/v1/lists'); } /** @@ -671,7 +629,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public fetchAccountLists(id: string) { - return this.gateway.get(`/api/v1/accounts/${id}/lists`); + return this.get(`/api/v1/accounts/${id}/lists`); } /** @@ -683,10 +641,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public fetchListAccounts(id: string, params?: PaginationParams) { - return this.gateway.paginate( - `/api/v1/list/${id}/accounts`, - params, - ); + return this.paginate(`/api/v1/list/${id}/accounts`, params); } /** @@ -697,7 +652,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public fetchList(id: string) { - return this.gateway.get(`/api/v1/lists/${id}`); + return this.get(`/api/v1/lists/${id}`); } /** @@ -708,7 +663,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public createList(params: ModifyListParams) { - return this.gateway.post('/api/v1/lists', params); + return this.post('/api/v1/lists', params); } /** @@ -720,7 +675,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public updateList(id: string, params: ModifyListParams) { - return this.gateway.put(`/api/v1/lists/${id}`, params); + return this.put(`/api/v1/lists/${id}`, params); } /** @@ -731,7 +686,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public removeList(id: string) { - return this.gateway.delete(`/api/v1/lists/${id}`); + return this.delete(`/api/v1/lists/${id}`); } /** @@ -743,7 +698,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public addAccountToList(id: string, params: ModifyListAccountsParams) { - return this.gateway.post(`/api/v1/lists/${id}/accounts`, params); + return this.post(`/api/v1/lists/${id}/accounts`, params); } /** @@ -755,7 +710,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public removeAccountFromList(id: string, params: ModifyListAccountsParams) { - return this.gateway.delete(`/api/v1/lists/${id}/accounts`, params); + return this.delete(`/api/v1/lists/${id}/accounts`, params); } /** @@ -766,7 +721,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public uploadMediaAttachment(params: UploadMediaAttachmentParams) { - return this.gateway.post('/api/v1/media', params, { + return this.post('/api/v1/media', params, { headers: { 'Content-Type': 'multipart/form-data' }, }); } @@ -783,7 +738,7 @@ export class Masto { id: string, params: UpdateMediaAttachmentParams, ) { - return this.gateway.put(`/api/v1/media/${id}`, params); + return this.put(`/api/v1/media/${id}`, params); } /** @@ -794,7 +749,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchMutes(params?: PaginationParams) { - return this.gateway.paginate('/api/v1/mutes', params); + return this.paginate('/api/v1/mutes', params); } /** @@ -806,10 +761,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public muteAccount(id: string, params: MuteAccountParams) { - return this.gateway.post( - `/api/v1/accounts/${id}/mute`, - params, - ); + return this.post(`/api/v1/accounts/${id}/mute`, params); } /** @@ -820,7 +772,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public unmuteAccount(id: string) { - return this.gateway.post(`/api/v1/accounts/${id}/unmute`); + return this.post(`/api/v1/accounts/${id}/unmute`); } /** @@ -831,7 +783,7 @@ export class Masto { */ @available({ since: '1.4.2' }) public muteStatus(id: string) { - return this.gateway.post(`/api/v1/statuses/${id}/mute`); + return this.post(`/api/v1/statuses/${id}/mute`); } /** @@ -842,7 +794,7 @@ export class Masto { */ @available({ since: '1.4.2' }) public unmuteStatus(id: string) { - return this.gateway.post(`/api/v1/statuses/${id}/unmute`); + return this.post(`/api/v1/statuses/${id}/unmute`); } /** @@ -853,7 +805,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchNotifications(params?: FetchNotificationsParams) { - return this.gateway.get('/api/v1/notifications', params); + return this.get('/api/v1/notifications', params); } /** @@ -864,7 +816,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchNotification(id: string) { - return this.gateway.get(`/api/v1/notifications/${id}`); + return this.get(`/api/v1/notifications/${id}`); } /** @@ -874,7 +826,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public clearNotifications() { - return this.gateway.post('/api/v1/notifications/clear'); + return this.post('/api/v1/notifications/clear'); } /** @@ -885,7 +837,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public dissmissNotification(id: string) { - return this.gateway.post('/api/v1/notifications/dismiss', { + return this.post('/api/v1/notifications/dismiss', { id, }); } @@ -898,10 +850,7 @@ export class Masto { */ @available({ since: '2.4.0' }) public addPushSubscription(params: AddPushSubscriptionParams) { - return this.gateway.post( - '/api/v1/push/subscription', - params, - ); + return this.post('/api/v1/push/subscription', params); } /** @@ -911,7 +860,7 @@ export class Masto { */ @available({ since: '2.4.0' }) public fetchPushSubscription() { - return this.gateway.get('/api/v1/push/subscription'); + return this.get('/api/v1/push/subscription'); } /** @@ -922,10 +871,7 @@ export class Masto { */ @available({ since: '2.4.0' }) public updatePushSubscription(params: UpdatePushSubscriptionParams) { - return this.gateway.put( - '/api/v1/push/subscription', - params, - ); + return this.put('/api/v1/push/subscription', params); } /** @@ -935,7 +881,7 @@ export class Masto { */ @available({ since: '2.4.0' }) public removePushSubscription() { - return this.gateway.delete('/api/v1/push/subscription'); + return this.delete('/api/v1/push/subscription'); } /** @@ -946,7 +892,7 @@ export class Masto { */ @available({ since: '2.8.0' }) public fetchPoll(id: string) { - return this.gateway.get(`/api/v1/polls/${id}`); + return this.get(`/api/v1/polls/${id}`); } /** @@ -958,7 +904,7 @@ export class Masto { */ @available({ since: '2.8.0' }) public votePoll(id: string, params: VotePollParams) { - return this.gateway.post(`/api/v1/polls/${id}/votes`, params); + return this.post(`/api/v1/polls/${id}/votes`, params); } /** @@ -969,7 +915,7 @@ export class Masto { */ @available({ since: '1.1.0' }) public reportAccount(params: ReportAccountParams) { - return this.gateway.post('/api/v1/reports', params); + return this.post('/api/v1/reports', params); } /** @@ -979,7 +925,7 @@ export class Masto { */ @available({ since: '2.7.0' }) public fetchScheduledStatuses() { - return this.gateway.get('/api/v1/scheduled_statuses'); + return this.get('/api/v1/scheduled_statuses'); } /** @@ -990,9 +936,7 @@ export class Masto { */ @available({ since: '2.7.0' }) public fetchScheduledStatus(id: string) { - return this.gateway.get( - `/api/v1/scheduled_statuses/${id}`, - ); + return this.get(`/api/v1/scheduled_statuses/${id}`); } /** @@ -1007,7 +951,7 @@ export class Masto { id: string, params: UpdateScheduledStatusParams, ) { - return this.gateway.put( + return this.put( `/api/v1/scheduled_statuses/${id}`, params, ); @@ -1021,7 +965,7 @@ export class Masto { */ @available({ since: '2.7.0' }) public removeScheduledStatus(id: string) { - return this.gateway.delete(`/api/v1/scheduled_statuses/${id}`); + return this.delete(`/api/v1/scheduled_statuses/${id}`); } /** @@ -1036,7 +980,7 @@ export class Masto { params: SearchParams, version = 'v2' as V, ) { - return this.gateway.paginate( + return this.paginate( `/api/${version}/search`, params, ); @@ -1050,7 +994,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchStatus(id: string) { - return this.gateway.get(`/api/v1/statuses/${id}`); + return this.get(`/api/v1/statuses/${id}`); } /** @@ -1061,7 +1005,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchStatusContext(id: string) { - return this.gateway.get(`/api/v1/statuses/${id}/context`); + return this.get(`/api/v1/statuses/${id}/context`); } /** @@ -1071,7 +1015,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchStatusCard(id: string) { - return this.gateway.get(`/api/v1/statuses/${id}/card`); + return this.get(`/api/v1/statuses/${id}/card`); } /** @@ -1083,7 +1027,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchStatusRebloggedBy(id: string, params?: PaginationParams) { - return this.gateway.paginate( + return this.paginate( `/api/v1/statuses/${id}/reblogged_by`, params, ); @@ -1098,7 +1042,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchStatusFavouritedBy(id: string, params?: PaginationParams) { - return this.gateway.paginate( + return this.paginate( `/api/v1/statuses/${id}/favourited_by`, params, ); @@ -1114,12 +1058,12 @@ export class Masto { @available({ since: '0.0.0' }) public createStatus(params?: CreateStatusParams, idempotencyKey?: string) { if (idempotencyKey) { - return this.gateway.post('/api/v1/statuses', params, { + return this.post('/api/v1/statuses', params, { headers: { 'Idempotency-Key': idempotencyKey }, }); } - return this.gateway.post('/api/v1/statuses', params); + return this.post('/api/v1/statuses', params); } /** @@ -1130,7 +1074,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public removeStatus(id: string) { - return this.gateway.delete(`/api/v1/statuses/${id}`); + return this.delete(`/api/v1/statuses/${id}`); } /** @@ -1141,7 +1085,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public reblogStatus(id: string, params?: ReblogStatusParams) { - return this.gateway.post(`/api/v1/statuses/${id}/reblog`, params); + return this.post(`/api/v1/statuses/${id}/reblog`, params); } /** @@ -1152,7 +1096,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public unreblogStatus(id: string) { - return this.gateway.post(`/api/v1/statuses/${id}/unreblog`); + return this.post(`/api/v1/statuses/${id}/unreblog`); } /** @@ -1163,7 +1107,7 @@ export class Masto { */ @available({ since: '1.6.0' }) public pinStatus(id: string) { - return this.gateway.post(`/api/v1/statuses/${id}/pin`); + return this.post(`/api/v1/statuses/${id}/pin`); } /** @@ -1174,7 +1118,7 @@ export class Masto { */ @available({ since: '1.6.0' }) public unpinStatus(id: string) { - return this.gateway.post(`/api/v1/statuses/${id}/unpin`); + return this.post(`/api/v1/statuses/${id}/unpin`); } /** @@ -1185,7 +1129,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchHomeTimeline(params?: FetchTimelineParams) { - return this.gateway.paginate('/api/v1/timelines/home', params); + return this.paginate('/api/v1/timelines/home', params); } /** @@ -1196,7 +1140,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchCommunityTimeline(params?: FetchTimelineParams) { - return this.gateway.paginate('/api/v1/timelines/public', { + return this.paginate('/api/v1/timelines/public', { local: true, ...params, }); @@ -1210,7 +1154,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchPublicTimeline(params?: FetchTimelineParams) { - return this.gateway.paginate('/api/v1/timelines/public', params); + return this.paginate('/api/v1/timelines/public', params); } /** @@ -1222,10 +1166,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public fetchTagTimeline(id: string, params?: FetchTimelineParams) { - return this.gateway.paginate( - `/api/v1/timelines/tag/${id}`, - params, - ); + return this.paginate(`/api/v1/timelines/tag/${id}`, params); } /** @@ -1237,10 +1178,7 @@ export class Masto { */ @available({ since: '2.1.0' }) public fetchListTimeline(id: string, params?: FetchTimelineParams) { - return this.gateway.paginate( - `/api/v1/timelines/list/${id}`, - params, - ); + return this.paginate(`/api/v1/timelines/list/${id}`, params); } /** @@ -1249,7 +1187,7 @@ export class Masto { */ @available({ since: '0.0.0', until: '2.5.2' }) public fetchDirectTimeline(params?: FetchTimelineParams) { - return this.gateway.paginate('/api/v1/timelines/direct', params); + return this.paginate('/api/v1/timelines/direct', params); } /** @@ -1258,10 +1196,7 @@ export class Masto { */ @available({ since: '2.6.0' }) public fetchConversations(params?: PaginationParams) { - return this.gateway.paginate( - '/api/v1/conversations', - params, - ); + return this.paginate('/api/v1/conversations', params); } /** @@ -1272,7 +1207,7 @@ export class Masto { */ @available({ since: '0.0.0' }) public followAccountByUsername(uri: string) { - return this.gateway.post('/api/v1/follows', { uri }); + return this.post('/api/v1/follows', { uri }); } /** @@ -1282,6 +1217,6 @@ export class Masto { */ @available({ since: '2.8.0' }) public fetchPreferences() { - return this.gateway.get('/api/v1/preferences'); + return this.get('/api/v1/preferences'); } } diff --git a/src/client/params.ts b/src/clients/masto/params.ts similarity index 95% rename from src/client/params.ts rename to src/clients/masto/params.ts index 128f68bb7..381d4909d 100644 --- a/src/client/params.ts +++ b/src/clients/masto/params.ts @@ -1,16 +1,13 @@ import { ReadStream } from 'fs'; -import { AccountField, AccountSource } from '../entities/account'; -import { FilterContext } from '../entities/filter'; -import { NotificationType } from '../entities/notification'; -import { PushSubscriptionAlerts } from '../entities/push-subscription'; -import { StatusVisibility } from '../entities/status'; -import { GatewayConstructor } from './gateway'; +import { AccountField, AccountSource } from '../../entities/account'; +import { FilterContext } from '../../entities/filter'; +import { NotificationType } from '../../entities/notification'; +import { PushSubscriptionAlerts } from '../../entities/push-subscription'; +import { StatusVisibility } from '../../entities/status'; /** Union of acceptable values of form-data for browser and node */ export type IsomorphicFormDataValue = string | Blob | Buffer | ReadStream; -export type LoginParams = Pick; - export interface PaginationParams { /** Get a list of items with ID less than this value */ max_id?: string | null; diff --git a/src/entities/admin-account.ts b/src/entities/admin-account.ts new file mode 100644 index 000000000..a4aa080e9 --- /dev/null +++ b/src/entities/admin-account.ts @@ -0,0 +1,24 @@ +export type AdminAccountRole = 'moderator' | 'admin' | 'user'; + +/** + * Account entity from moderation apis + */ +export interface AdminAccount { + id: string; + username: string; + domain: string; + created_at: string; + email: string; + role: AdminAccountRole; + ip: string; + confirmed: boolean; + suspended: boolean; + silenced: boolean; + disabled: boolean; + approved: boolean; + account: Account; + locale?: string | null; + invite_request?: string | null; + created_by_application_id?: string | null; + invited_by_account_id?: string | null; +} diff --git a/src/entities/admin-report.ts b/src/entities/admin-report.ts new file mode 100644 index 000000000..8f73414e6 --- /dev/null +++ b/src/entities/admin-report.ts @@ -0,0 +1,14 @@ +import { Status } from './status'; + +export interface AdminReport { + id: string; + action_taken: boolean; + comment: string; + created_at: string; + updated_at: string; + account_id: string; + target_account_id: string; + assigned_account_id: string; + action_taken_by_account_id: string; + statuses: Status[]; +} diff --git a/src/client/__mocks__/masto-events.ts b/src/gateway/__mocks__/websocket.ts similarity index 58% rename from src/client/__mocks__/masto-events.ts rename to src/gateway/__mocks__/websocket.ts index 33729dea2..3595a6626 100644 --- a/src/client/__mocks__/masto-events.ts +++ b/src/gateway/__mocks__/websocket.ts @@ -1,5 +1,5 @@ export const connectMock = jest.fn(); -export const MastoEvents = jest.fn(() => ({ +export const WebSocketEvents = jest.fn(() => ({ connect: connectMock, })); diff --git a/src/client/__tests__/gateway.spec.ts b/src/gateway/__tests__/gateway.spec.ts similarity index 89% rename from src/client/__tests__/gateway.spec.ts rename to src/gateway/__tests__/gateway.spec.ts index e64a72418..9f7a3e2b6 100644 --- a/src/client/__tests__/gateway.spec.ts +++ b/src/gateway/__tests__/gateway.spec.ts @@ -1,21 +1,23 @@ // tslint:disable import axios from 'axios'; -import FormData from 'form-data'; -import { Gateway } from '../gateway'; // @ts-ignore -import { MastoEvents, connectMock } from '../masto-events'; +import { Gateway, getMock } from '../gateway'; +// @ts-ignore +import { WebSocketEvents, connectMock } from '../websocket'; import { MastoUnauthorizedError } from '../../errors/masto-unauthorized-error'; import { MastoNotFoundError } from '../../errors/masto-not-found-error'; import { MastoRateLimitError } from '../../errors/masto-rate-limit-error'; jest.mock('axios'); -jest.mock('../masto-events'); +jest.mock('../websocket'); describe('Gateway', () => { - let gateway!: Gateway; + class InheritedGateway extends Gateway {} + + let gateway!: InheritedGateway; beforeEach(() => { - gateway = new Gateway({ + gateway = new InheritedGateway({ uri: 'https://example.com', version: '99.9.9', streamingApiUrl: 'wss://example.com', @@ -27,8 +29,28 @@ describe('Gateway', () => { }); }); + test('login', async () => { + (axios.request as jest.Mock).mockResolvedValueOnce({ + data: { + version: '2.8.0', + urls: { + streaming_api: 'wss://example.com/stream', + }, + }, + }); + + const params = { + uri: 'https://example.com', + accessToken: 'tokentoken', + }; + const gateway = await InheritedGateway.login(params); + + expect(gateway.version).toBe('2.8.0'); + expect(gateway.streamingApiUrl).toBe('wss://example.com/stream'); + }); + test('streamingApiUrl has been set if construct with streamingApiUrl', () => { - gateway = new Gateway({ + gateway = new InheritedGateway({ uri: 'https://example.com', streamingApiUrl: 'wss://example.com', }); @@ -36,7 +58,7 @@ describe('Gateway', () => { }); test('version has been set if construct with version ', () => { - gateway = new Gateway({ + gateway = new InheritedGateway({ uri: 'https://example.com', version: '1.2.3', }); @@ -44,7 +66,7 @@ describe('Gateway', () => { }); test('accessToken has been set if construct with accessToken', () => { - gateway = new Gateway({ + gateway = new InheritedGateway({ uri: 'https://example.com', accessToken: 'token token', }); @@ -52,7 +74,7 @@ describe('Gateway', () => { }); test('this._uri accessor works', () => { - gateway = new Gateway({ + gateway = new InheritedGateway({ uri: 'https://example.com/aaa', }); gateway.uri = 'https://example.com/bbb'; @@ -60,7 +82,7 @@ describe('Gateway', () => { }); test('this._streamingApiUrl accessor works', () => { - gateway = new Gateway({ + gateway = new InheritedGateway({ uri: 'wss://example.com/aaa', }); gateway.uri = 'wss://example.com/bbb'; @@ -298,19 +320,19 @@ describe('Gateway', () => { ); }); - test('initialize MastoEvents and call connect with given params', async () => { + test('initialize WebSocketEvents and call connect with given params', async () => { const params = { a: 'a', b: 'b' }; await gateway.stream('/', params); expect(connectMock).toBeCalledWith('wss://example.com/?a=a&b=b', []); }); - test('initialize MastoEvents and call connect with access token', async () => { + test('initialize WebSocketEvents and call connect with access token', async () => { gateway.accessToken = 'tokentoken'; await gateway.stream('/'); expect(connectMock).toBeCalledWith('wss://example.com/', ['tokentoken']); }); - test('initialize MastoEvents and call connect with access token as a param for Mastodon < v2.8.4', async () => { + test('initialize WebSocketEvents and call connect with access token as a param for Mastodon < v2.8.4', async () => { gateway.version = '2.8.3'; gateway.accessToken = 'tokentoken'; await gateway.stream('/'); diff --git a/src/client/__tests__/utils.spec.ts b/src/gateway/__tests__/utils.spec.ts similarity index 100% rename from src/client/__tests__/utils.spec.ts rename to src/gateway/__tests__/utils.spec.ts diff --git a/src/client/__tests__/masto-events.spec.ts b/src/gateway/__tests__/websocket.spec.ts similarity index 64% rename from src/client/__tests__/masto-events.spec.ts rename to src/gateway/__tests__/websocket.spec.ts index 9f2ee56f4..64e74d76f 100644 --- a/src/client/__tests__/masto-events.spec.ts +++ b/src/gateway/__tests__/websocket.spec.ts @@ -1,11 +1,11 @@ // tslint:disable import WebSocket from 'isomorphic-ws'; -import { MastoEvents } from '../masto-events'; +import { WebSocketEvents } from '../websocket'; const onMock = jest.fn(); +const onMockWs = jest.fn(); const emitMock = jest.fn(); const closeMock = jest.fn(); -const addEventListenerMock = jest.fn(); jest.mock('eventemitter3', () => { return class { @@ -17,20 +17,27 @@ jest.mock('eventemitter3', () => { jest.mock('isomorphic-ws', () => { return jest.fn(() => ({ close: closeMock, - addEventListener: addEventListenerMock, + on: onMockWs, })); }); -describe('MastoEvents', () => { - let mastoEvents!: MastoEvents; +describe('WebSocketEvents', () => { + let mastoEvents!: WebSocketEvents; beforeAll(() => { - mastoEvents = new MastoEvents(); + mastoEvents = new WebSocketEvents(); + }); + + beforeEach(() => { + onMock.mockClear(); + onMockWs.mockClear(); + emitMock.mockClear(); + closeMock.mockClear(); }); test('connect to ws server', async () => { // Resolve open - addEventListenerMock.mockImplementation((e, fn) => { + onMockWs.mockImplementation((e, fn) => { if (e === 'open') { fn(); } @@ -43,20 +50,9 @@ describe('MastoEvents', () => { [], ); - expect(addEventListenerMock).toHaveBeenCalledWith( - 'message', - expect.any(Function), - ); - - expect(addEventListenerMock).toHaveBeenCalledWith( - 'error', - expect.any(Function), - ); - - expect(addEventListenerMock).toHaveBeenCalledWith( - 'open', - expect.any(Function), - ); + expect(onMockWs).toBeCalledWith('message', expect.any(Function)); + expect(onMockWs).toBeCalledWith('error', expect.any(Function)); + expect(onMockWs).toBeCalledWith('open', expect.any(Function)); }); test('disconnect from the server', async () => { @@ -68,35 +64,23 @@ describe('MastoEvents', () => { const originalPayload = { aaaa: 'foobar', }; - const originalData = { event: 'update', payload: JSON.stringify(originalPayload), }; - mastoEvents.handleMessage({ - type: 'utf8', - data: JSON.stringify(originalData), - target: {} as any, - }); - + mastoEvents.handleMessage(JSON.stringify(originalData)); expect(emitMock).toBeCalledWith('update', originalPayload); }); test('emit event with given props, with raw payload', () => { const originalPayload = 'foobar'; - const originalData = { event: 'update', payload: originalPayload, }; - mastoEvents.handleMessage({ - type: 'utf8', - data: JSON.stringify(originalData), - target: {} as any, - }); - + mastoEvents.handleMessage(JSON.stringify(originalData)); expect(emitMock).toBeCalledWith('update', originalPayload); }); diff --git a/src/client/gateway.ts b/src/gateway/gateway.ts similarity index 92% rename from src/client/gateway.ts rename to src/gateway/gateway.ts index f3a4f012b..bb8314152 100644 --- a/src/client/gateway.ts +++ b/src/gateway/gateway.ts @@ -3,16 +3,17 @@ import normalizeUrl from 'normalize-url'; import querystring from 'querystring'; import semver from 'semver'; import { oc } from 'ts-optchain'; +import { Instance } from '../entities/instance'; import { MastoNotFoundError } from '../errors/masto-not-found-error'; import { MastoRateLimitError } from '../errors/masto-rate-limit-error'; import { MastoUnauthorizedError } from '../errors/masto-unauthorized-error'; -import { MastoEvents } from './masto-events'; import { isAxiosError } from './utils'; +import { WebSocketEvents } from './websocket'; // tslint:disable-next-line no-import-side-effect import 'isomorphic-form-data'; -export interface GatewayConstructor { +export interface GatewayConstructorParams { /** URI of the instance */ uri: string; /** Streaming API URL */ @@ -23,6 +24,8 @@ export interface GatewayConstructor { accessToken?: string; } +export type LoginParams = Pick; + export type PaginateNextOptions = { /** Reset pagination */ reset?: boolean; @@ -49,7 +52,7 @@ export class Gateway { /** * @param params Parameters */ - public constructor(params: GatewayConstructor) { + constructor(params: GatewayConstructorParams) { this.uri = params.uri; if (params.streamingApiUrl) { @@ -81,6 +84,23 @@ export class Gateway { this._streamingApiUrl = normalizeUrl(streamingApiUrl); } + /** + * Login to Mastodon + * @param params Paramters + * @return Instance of Mastodon class + */ + public static async login( + this: T, + params: LoginParams, + ) { + const gateway = new this(params) as InstanceType; + const instance = await gateway.get('/api/v1/instance'); + gateway.version = instance.version; + gateway.streamingApiUrl = instance.urls.streaming_api; + + return gateway; + } + /** * Transform JSON to JS object * @param response Response object @@ -333,7 +353,7 @@ export class Gateway { path + (Object.keys(params).length ? `?${querystring.stringify(params)}` : ''); - return new MastoEvents().connect(url, protocols); + return new WebSocketEvents().connect(url, protocols); } /** @@ -372,7 +392,7 @@ export class Gateway { ); // Set next url from the link header - const link = oc(response.headers.link)(''); + const link = oc(response.headers).link(''); const match = link.match(/<(.+?)>; rel="next"/) as string[]; currentUrl = (match && match.length && match[1]) || ''; diff --git a/src/client/utils.ts b/src/gateway/utils.ts similarity index 100% rename from src/client/utils.ts rename to src/gateway/utils.ts diff --git a/src/gateway/websocket.ts b/src/gateway/websocket.ts new file mode 100644 index 000000000..9c3a32035 --- /dev/null +++ b/src/gateway/websocket.ts @@ -0,0 +1,147 @@ +// tslint:disable no-unnecessary-override +import EventEmitter from 'eventemitter3'; +import WebSocket from 'isomorphic-ws'; +import { Conversation } from '../entities/conversation'; +import { Notification } from '../entities/notification'; +import { Status } from '../entities/status'; + +/** Mastodon event */ +export interface Event { + event: EventType; + payload: string; +} + +export interface EventTypeMap { + /** Status posted */ + update: Status; + /** Status deleted */ + delete: Status['id']; + /** User's notification */ + notification: Notification; + /** User's filter changed */ + filters_changed: undefined; + /** Status added to a conversation */ + conversation: Conversation; +} + +export type EventType = keyof EventTypeMap; +export type EventListener = ( + payload: EventTypeMap[T], +) => void; + +/** + * Mastodon streaming api wrapper + */ +export class WebSocketEvents extends EventEmitter { + private ws?: WebSocket; + + /** + * Connect to the websocket endpoint + * @param url URL of the websocket endpoint + * @param protocols Subprotocol(s) for `Sec-Websocket-Protocol` + * @param params URL parameters + */ + public connect(url: string, protocols?: string | string[]) { + return new Promise((resolve, reject) => { + this.ws = new WebSocket(url, protocols); + + this.ws.on('message', this.handleMessage); + this.ws.on('error', reject); + this.ws.on('open', () => { + resolve(this); + }); + }); + } + + /** + * Disconnect from the websocket endpoint + */ + public disconnect() { + if (!this.ws) return; + this.ws.close(); + } + + /** + * Parse JSON data and emit it as an event + * @param message Websocket message + */ + public handleMessage = (message: string) => { + const event = JSON.parse(message) as Event; + let data: EventTypeMap[keyof EventTypeMap]; + + try { + data = JSON.parse(event.payload); + } catch { + // If parsing failed, returns raw data + // Basically this is handling for `filters_changed` event + // Which doesn't contain payload in the data + data = event.payload; + } + + this.emit(event.event, data); + }; + + /*------------------------------- + * + * ↓ Overwriting signatures + * + *------------------------------*/ + + public listeners(event: T) { + return super.listeners(event); + } + + public listenerCount(event: T) { + return super.listenerCount(event); + } + + public emit(event: T, ...args: any[]) { + return super.emit(event, ...args); + } + + public addListener( + event: T, + fn: EventListener, + context?: any, + ) { + return super.addListener(event, fn, context); + } + + public on( + event: T, + fn: EventListener, + context?: any, + ) { + return super.on(event, fn, context); + } + + public once( + event: T, + fn: EventListener, + context?: any, + ) { + return super.once(event, fn, context); + } + + public removeListener( + event: T, + fn?: EventListener, + context?: any, + once?: boolean, + ) { + return super.removeListener(event, fn, context, once); + } + + public off( + event: T, + fn?: EventListener, + context?: any, + once?: boolean, + ) { + return super.off(event, fn, context, once); + } + + public removeAllListeners(event?: T) { + return super.removeAllListeners(event); + } +} diff --git a/src/index.ts b/src/index.ts index 889e9c343..25a90fad9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,14 @@ -export * from './client/decorators'; -export * from './client/gateway'; -export * from './client/params'; -export * from './client/masto-events'; -export * from './client/utils'; +export * from './gateway/gateway'; +export * from './gateway/websocket'; +export * from './gateway/utils'; + +export * from './clients/decorators'; + +export * from './clients/masto/masto'; +export * from './clients/masto/params'; + +export * from './clients/masto-admin/masto-admin'; +export * from './clients/masto-admin/params'; export * from './entities/account'; export * from './entities/application'; @@ -30,5 +36,4 @@ export * from './errors/masto-not-found-error'; export * from './errors/masto-rate-limit-error'; export * from './errors/masto-unauthorized-error'; -export * from './client/masto'; -export { Masto as default } from './client/masto'; +export { Masto as default } from './clients/masto/masto';