diff --git a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts
index 0c74bfb50d..b3c4f77d1c 100644
--- a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts
+++ b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts
@@ -11,7 +11,7 @@ import type { Config } from '@/config.js';
import { getInstance } from './endpoints/meta.js';
import { MetaService } from '@/core/MetaService.js';
import multer from 'fastify-multer';
-import { apiAuthMastodon, apiAccountMastodon, apiFilterMastodon, apiNotifyMastodon, apiSearchMastodon } from './endpoints.js';
+import { apiAuthMastodon, apiAccountMastodon, apiFilterMastodon, apiNotifyMastodon, apiSearchMastodon, apiTimelineMastodon } from './endpoints.js';
const staticAssets = fileURLToPath(new URL('../../../../assets/', import.meta.url));
@@ -722,6 +722,31 @@ export class MastodonApiServerService {
reply.code(401).send(e.response.data);
}
});
+ //#endregion
+
+ //#region Timelines
+ const TLEndpoint = new apiTimelineMastodon(fastify);
+
+ // GET Endpoints
+ TLEndpoint.getTL();
+ TLEndpoint.getHomeTl();
+ TLEndpoint.getListTL();
+ TLEndpoint.getTagTl();
+ TLEndpoint.getConversations();
+ TLEndpoint.getList();
+ TLEndpoint.getLists();
+ TLEndpoint.getListAccounts();
+
+ // POST Endpoints
+ TLEndpoint.createList();
+ TLEndpoint.addListAccount();
+
+ // PUT Endpoint
+ TLEndpoint.updateList();
+
+ // DELETE Endpoints
+ TLEndpoint.deleteList();
+ TLEndpoint.rmListAccount();
//#endregion
done();
}
diff --git a/packages/backend/src/server/api/mastodon/endpoints.ts b/packages/backend/src/server/api/mastodon/endpoints.ts
index d5528ade51..111f9ef9c5 100644
--- a/packages/backend/src/server/api/mastodon/endpoints.ts
+++ b/packages/backend/src/server/api/mastodon/endpoints.ts
@@ -3,11 +3,13 @@ import { apiAccountMastodon } from './endpoints/account.js';
import { apiSearchMastodon } from './endpoints/search.js';
import { apiNotifyMastodon } from './endpoints/notifications.js';
import { apiFilterMastodon } from './endpoints/filter.js';
+import { apiTimelineMastodon } from './endpoints/timeline.js';
export {
apiAccountMastodon,
apiAuthMastodon,
apiSearchMastodon,
apiNotifyMastodon,
- apiFilterMastodon
+ apiFilterMastodon,
+ apiTimelineMastodon
}
diff --git a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts
index 1d2812c37c..ec7010ee70 100644
--- a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts
+++ b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts
@@ -1,5 +1,8 @@
import { convertId, IdConvertType as IdType, convertAccount, convertConversation, convertList, convertStatus } from '../converters.js';
import { ParsedUrlQuery } from 'querystring';
+import type { Entity, MegalodonInterface } from 'megalodon';
+import type { FastifyInstance } from 'fastify';
+import { getClient } from '../MastodonApiServerService.js';
export function limitToInt(q: ParsedUrlQuery) {
let object: any = q;
@@ -65,4 +68,250 @@ function nl2br(str: string) {
str = str.replace(/\r\n/g, '
');
str = str.replace(/(\n|\r)/g, '
');
return str;
+}
+
+export class apiTimelineMastodon {
+ private fastify: FastifyInstance;
+
+ constructor(fastify: FastifyInstance) {
+ this.fastify = fastify;
+ }
+
+ public async getTL() {
+ this.fastify.get('/v1/timelines/public', async (_request, reply) => {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ try {
+ const query: any = _request.query;
+ const data = query.local === 'true'
+ ? await client.getLocalTimeline(convertTimelinesArgsId(argsToBools(limitToInt(query))))
+ : await client.getPublicTimeline(convertTimelinesArgsId(argsToBools(limitToInt(query))));
+ reply.send(data.data.map((status: Entity.Status) => convertStatus(status)));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async getHomeTl() {
+ this.fastify.get('/v1/timelines/home', async (_request, reply) => {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ try {
+ const query: any = _request.query;
+ const data = await client.getHomeTimeline(convertTimelinesArgsId(limitToInt(query)));
+ reply.send(data.data.map((status: Entity.Status) => convertStatus(status)));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async getTagTl() {
+ this.fastify.get<{ Params: { hashtag: string } }>('/v1/timelines/tag/:hashtag', async (_request, reply) => {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ try {
+ const query: any = _request.query;
+ const params: any = _request.params;
+ const data = await client.getTagTimeline(params.hashtag, convertTimelinesArgsId(limitToInt(query)));
+ reply.send(data.data.map((status: Entity.Status) => convertStatus(status)));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async getListTL() {
+ this.fastify.get<{ Params: { id: string } }>('/v1/timelines/list/:id', async (_request, reply) => {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ try {
+ const query: any = _request.query;
+ const params: any = _request.params;
+ const data = await client.getListTimeline(convertId(params.id, IdType.SharkeyId), convertTimelinesArgsId(limitToInt(query)));
+ reply.send(data.data.map((status: Entity.Status) => convertStatus(status)));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async getConversations() {
+ this.fastify.get('/v1/conversations', async (_request, reply) => {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ try {
+ const query: any = _request.query;
+ const data = await client.getConversationTimeline(convertTimelinesArgsId(limitToInt(query)));
+ reply.send(data.data.map((conversation: Entity.Conversation) => convertConversation(conversation)));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async getList(){
+ this.fastify.get<{ Params: { id: string } }>('/v1/lists/:id', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const params: any = _request.params;
+ const data = await client.getList(convertId(params.id, IdType.SharkeyId));
+ reply.send(convertList(data.data));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async getLists() {
+ this.fastify.get('/v1/lists', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const account = await client.verifyAccountCredentials();
+ const data = await client.getLists(account.data.id);
+ reply.send(data.data.map((list: Entity.List) => convertList(list)));
+ } catch (e: any) {
+ console.error(e);
+ return e.response.data;
+ }
+ });
+ }
+
+ public async getListAccounts(){
+ this.fastify.get<{ Params: { id: string } }>('/v1/lists/:id/accounts', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const params: any = _request.params;
+ const query: any = _request.query;
+ const data = await client.getAccountsInList(
+ convertId(params.id, IdType.SharkeyId),
+ convertTimelinesArgsId(query)
+ );
+ reply.send(data.data.map((account: Entity.Account) => convertAccount(account)));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async addListAccount() {
+ this.fastify.post<{ Params: { id: string } }>('/v1/lists/:id/accounts', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const params: any = _request.params;
+ const query: any = _request.query;
+ const data = await client.addAccountsToList(
+ convertId(params.id, IdType.SharkeyId),
+ (query.accounts_id as string[]).map((id) => convertId(id, IdType.SharkeyId))
+ );
+ reply.send(data.data);
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async rmListAccount() {
+ this.fastify.delete<{ Params: { id: string } }>('/v1/lists/:id/accounts', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const params: any = _request.params;
+ const query: any = _request.query;
+ const data = await client.deleteAccountsFromList(
+ convertId(params.id, IdType.SharkeyId),
+ (query.accounts_id as string[]).map((id) => convertId(id, IdType.SharkeyId))
+ );
+ reply.send(data.data);
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async createList() {
+ this.fastify.post('/v1/lists', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const body: any = _request.body;
+ const data = await client.createList(body.title);
+ reply.send(convertList(data.data));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async updateList() {
+ this.fastify.put<{ Params: { id: string } }>('/v1/lists/:id', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const body: any = _request.body;
+ const params: any = _request.params;
+ const data = await client.updateList(convertId(params.id, IdType.SharkeyId), body.title);
+ reply.send(convertList(data.data));
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
+ public async deleteList() {
+ this.fastify.delete<{ Params: { id: string } }>('/v1/lists/:id', async (_request, reply) => {
+ try {
+ const BASE_URL = `${_request.protocol}://${_request.hostname}`;
+ const accessTokens = _request.headers.authorization;
+ const client = getClient(BASE_URL, accessTokens);
+ const params: any = _request.params;
+ const data = await client.deleteList(convertId(params.id, IdType.SharkeyId));
+ reply.send(data.data);
+ } catch (e: any) {
+ console.error(e);
+ console.error(e.response.data);
+ reply.code(401).send(e.response.data);
+ }
+ });
+ }
+
}
\ No newline at end of file