summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/mastodon/MastodonClientService.ts
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2025-03-20 20:43:05 -0400
committerHazelnoot <acomputerdog@gmail.com>2025-03-27 19:51:42 -0400
commitf61d71ac8cda6455238faa976ef221525ab5ed34 (patch)
treeae61964b8c9d33e4396be1863d2bbda1f20cd78c /packages/backend/src/server/api/mastodon/MastodonClientService.ts
parentmerge: fix: bubble timeline not being selectable when logged out (!950) (diff)
downloadsharkey-f61d71ac8cda6455238faa976ef221525ab5ed34.tar.gz
sharkey-f61d71ac8cda6455238faa976ef221525ab5ed34.tar.bz2
sharkey-f61d71ac8cda6455238faa976ef221525ab5ed34.zip
refactor mastodon API and preserve remote user agent for requests
Diffstat (limited to 'packages/backend/src/server/api/mastodon/MastodonClientService.ts')
-rw-r--r--packages/backend/src/server/api/mastodon/MastodonClientService.ts69
1 files changed, 69 insertions, 0 deletions
diff --git a/packages/backend/src/server/api/mastodon/MastodonClientService.ts b/packages/backend/src/server/api/mastodon/MastodonClientService.ts
new file mode 100644
index 0000000000..82f9b7bfa9
--- /dev/null
+++ b/packages/backend/src/server/api/mastodon/MastodonClientService.ts
@@ -0,0 +1,69 @@
+/*
+ * SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { megalodon, MegalodonInterface } from 'megalodon';
+import { Injectable } from '@nestjs/common';
+import { MiLocalUser } from '@/models/User.js';
+import { AuthenticateService } from '@/server/api/AuthenticateService.js';
+import type { FastifyRequest } from 'fastify';
+
+@Injectable()
+export class MastodonClientService {
+ constructor(
+ private readonly authenticateService: AuthenticateService,
+ ) {}
+
+ /**
+ * Gets the authenticated user and API client for a request.
+ */
+ public async getAuthClient(request: FastifyRequest, accessToken?: string | null): Promise<{ client: MegalodonInterface, me: MiLocalUser | null }> {
+ const authorization = request.headers.authorization;
+ accessToken = accessToken !== undefined ? accessToken : getAccessToken(authorization);
+
+ const me = await this.getAuth(request, accessToken);
+ const client = this.getClient(request, accessToken);
+
+ return { client, me };
+ }
+
+ /**
+ * Gets the authenticated client user for a request.
+ */
+ public async getAuth(request: FastifyRequest, accessToken?: string | null): Promise<MiLocalUser | null> {
+ const authorization = request.headers.authorization;
+ accessToken = accessToken !== undefined ? accessToken : getAccessToken(authorization);
+ const [me] = await this.authenticateService.authenticate(accessToken);
+ return me;
+ }
+
+ /**
+ * Creates an authenticated API client for a request.
+ */
+ public getClient(request: FastifyRequest, accessToken?: string | null): MegalodonInterface {
+ const authorization = request.headers.authorization;
+ accessToken = accessToken !== undefined ? accessToken : getAccessToken(authorization);
+
+ // TODO pass agent?
+ const baseUrl = this.getBaseUrl(request);
+ const userAgent = request.headers['user-agent'];
+ return megalodon('misskey', baseUrl, accessToken, userAgent);
+ }
+
+ /**
+ * Gets the base URL (origin) of the incoming request
+ */
+ public getBaseUrl(request: FastifyRequest): string {
+ return `${request.protocol}://${request.host}`;
+ }
+}
+
+/**
+ * Extracts the first access token from an authorization header
+ * Returns null if none were found.
+ */
+function getAccessToken(authorization: string | undefined): string | null {
+ const accessTokenArr = authorization?.split(' ') ?? [null];
+ return accessTokenArr[accessTokenArr.length - 1];
+}