diff --git a/.gitignore b/.gitignore index 0a1a09c90d..3c55ec0d78 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,9 @@ packages/backend/assets/LICENSE !/packages/backend/src/db !/packages/backend/src/server/api/endpoints/drive/files +packages/megalodon/lib +packages/megalodon/.idea + # blender backups *.blend1 *.blend2 diff --git a/Dockerfile b/Dockerfile index 2ad59950d2..dbd34d18d6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,7 @@ COPY packages/backend/package.json packages/backend/package.json COPY packages/client/package.json packages/client/package.json COPY packages/sw/package.json packages/sw/package.json COPY packages/firefish-js/package.json packages/firefish-js/package.json +COPY packages/megalodon/package.json packages/megalodon/package.json COPY packages/backend/native-utils/package.json packages/backend/native-utils/package.json COPY packages/backend/native-utils/npm/linux-x64-musl/package.json packages/backend/native-utils/npm/linux-x64-musl/package.json COPY packages/backend/native-utils/npm/linux-arm64-musl/package.json packages/backend/native-utils/npm/linux-arm64-musl/package.json @@ -57,6 +58,8 @@ RUN apt-get update && apt-get install -y libvips-dev zip unzip tini ffmpeg COPY . ./ +COPY --from=build /firefish/packages/megalodon /firefish/packages/megalodon + # Copy node modules COPY --from=build /firefish/node_modules /firefish/node_modules COPY --from=build /firefish/packages/backend/node_modules /firefish/packages/backend/node_modules diff --git a/package.json b/package.json index 9325611084..dde7b4f40b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://git.joinfirefish.org/firefish/firefish.git" }, - "packageManager": "pnpm@8.8.0", + "packageManager": "pnpm@8.9.2", "private": true, "scripts": { "rebuild": "pnpm run clean && pnpm run build", @@ -66,7 +66,7 @@ "gulp-replace": "1.1.4", "gulp-terser": "2.1.0", "install-peers": "^1.0.4", - "pnpm": "8.8.0", + "pnpm": "8.9.2", "start-server-and-test": "1.15.2", "typescript": "5.2.2" } diff --git a/packages/README.md b/packages/README.md index 75e38a4940..ea04817f06 100644 --- a/packages/README.md +++ b/packages/README.md @@ -7,3 +7,4 @@ This directory contains all of the packages Firefish uses. - `client`: Web interface written in Vue3 and TypeScript - `sw`: Web [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) written in TypeScript - `firefish-js`: TypeScript SDK for both backend and client, also published on [NPM](https://www.npmjs.com/package/firefish-js) for public use +- `megalodon`: TypeScript library used for partial Mastodon API compatibility diff --git a/packages/backend/package.json b/packages/backend/package.json index 689da8e59e..a28386c9b4 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -89,7 +89,7 @@ "koa-send": "5.0.1", "koa-slow": "2.1.0", "koa-views": "7.0.2", - "megalodon": "8.1.1", + "megalodon": "workspace:*", "meilisearch": "0.34.1", "mfm-js": "0.23.3", "mime-types": "2.1.35", diff --git a/packages/backend/src/server/api/mastodon/ApiMastodonCompatibleService.ts b/packages/backend/src/server/api/mastodon/ApiMastodonCompatibleService.ts index 3f6e671bd6..44485ac429 100644 --- a/packages/backend/src/server/api/mastodon/ApiMastodonCompatibleService.ts +++ b/packages/backend/src/server/api/mastodon/ApiMastodonCompatibleService.ts @@ -24,11 +24,7 @@ export function getClient( const accessTokenArr = authorization?.split(" ") ?? [null]; const accessToken = accessTokenArr[accessTokenArr.length - 1]; const generator = (megalodon as any).default; - const client = generator( - "firefish", - BASE_URL, - accessToken, - ) as MegalodonInterface; + const client = generator(BASE_URL, accessToken) as MegalodonInterface; return client; } diff --git a/packages/backend/src/server/api/mastodon/endpoints/auth.ts b/packages/backend/src/server/api/mastodon/endpoints/auth.ts index 3d6eb8c4d6..b55cb6388c 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/auth.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/auth.ts @@ -68,7 +68,7 @@ export function apiAuthMastodon(router: Router): void { website: body.website, redirect_uri: red, client_id: Buffer.from(appData.url || "").toString("base64"), - client_secret: appData.client_secret, + client_secret: appData.clientSecret, }; console.log(returns); ctx.body = returns; diff --git a/packages/backend/src/server/api/mastodon/endpoints/search.ts b/packages/backend/src/server/api/mastodon/endpoints/search.ts index 5bd24ca89b..8a48175579 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/search.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/search.ts @@ -1,7 +1,8 @@ +import megalodon, { MegalodonInterface } from "megalodon"; import Router from "@koa/router"; import { getClient } from "../ApiMastodonCompatibleService.js"; import axios from "axios"; -import Converter from "megalodon"; +import { Converter } from "megalodon"; import { convertTimelinesArgsId, limitToInt } from "./timeline.js"; import { convertAccount, convertStatus } from "../converters.js"; diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 2c35843dd3..bc95d77769 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -380,7 +380,7 @@ export function apiStatusMastodon(router: Router): void { const accessTokens = ctx.headers.authorization; const client = getClient(BASE_URL, accessTokens); try { - const data = await client.createEmojiReaction( + const data = await client.reactStatus( convertId(ctx.params.id, IdType.FirefishId), ctx.params.name, ); @@ -400,7 +400,7 @@ export function apiStatusMastodon(router: Router): void { const accessTokens = ctx.headers.authorization; const client = getClient(BASE_URL, accessTokens); try { - const data = await client.deleteEmojiReaction( + const data = await client.unreactStatus( convertId(ctx.params.id, IdType.FirefishId), ctx.params.name, ); diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index 5a47f2cba7..e483683151 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -25,7 +25,7 @@ import { readNotification } from "../common/read-notification.js"; import channels from "./channels/index.js"; import type Channel from "./channel.js"; import type { StreamEventEmitter, StreamMessages } from "./types.js"; -import Converter from "megalodon"; +import { Converter } from "megalodon"; import { getClient } from "../mastodon/ApiMastodonCompatibleService.js"; /** diff --git a/packages/backend/src/server/index.ts b/packages/backend/src/server/index.ts index a6f1c1fc06..208981edbd 100644 --- a/packages/backend/src/server/index.ts +++ b/packages/backend/src/server/index.ts @@ -179,10 +179,10 @@ mastoRouter.post("/oauth/token", async (ctx) => { ctx.body = ret; return; } - let client_id: Array | string | null = body.client_id; + let client_id: any = body.client_id; const BASE_URL = `${ctx.request.protocol}://${ctx.request.hostname}`; const generator = (megalodon as any).default; - const client = generator("firefish", BASE_URL, null) as MegalodonInterface; + const client = generator(BASE_URL, null) as MegalodonInterface; let token = null; if (body.code) { //m = body.code.match(/^([a-zA-Z0-9]{8})([a-zA-Z0-9]{4})([a-zA-Z0-9]{4})([a-zA-Z0-9]{4})([a-zA-Z0-9]{12})/); @@ -206,7 +206,7 @@ mastoRouter.post("/oauth/token", async (ctx) => { token ? token : "", ); const ret = { - access_token: atData.access_token, + access_token: atData.accessToken, token_type: "Bearer", scope: body.scope || "read write follow push", created_at: Math.floor(new Date().getTime() / 1000), diff --git a/packages/client/src/components/MkDialog.vue b/packages/client/src/components/MkDialog.vue index ce1bfc3871..216fb4500a 100644 --- a/packages/client/src/components/MkDialog.vue +++ b/packages/client/src/components/MkDialog.vue @@ -11,32 +11,27 @@
@@ -35,7 +35,7 @@ import { defineComponent } from "vue"; import { getUniqueId } from "@/os"; import { defaultStore } from "@/store"; -import icon from "@/scripts/icon"; +// import icon from "@/scripts/icon"; const localStoragePrefix = "ui:folder:"; diff --git a/packages/client/src/components/MkNote.vue b/packages/client/src/components/MkNote.vue index 7463d32f96..7a63f9012e 100644 --- a/packages/client/src/components/MkNote.vue +++ b/packages/client/src/components/MkNote.vue @@ -359,7 +359,7 @@ const isDeleted = ref(false); const muted = ref( getWordSoftMute( note.value, - $i.id, + $i?.id, defaultStore.state.mutedWords, defaultStore.state.mutedLangs, ), diff --git a/packages/client/src/components/MkNoteDetailed.vue b/packages/client/src/components/MkNoteDetailed.vue index 5e0770e151..a2e9c10db8 100644 --- a/packages/client/src/components/MkNoteDetailed.vue +++ b/packages/client/src/components/MkNoteDetailed.vue @@ -235,7 +235,7 @@ const isDeleted = ref(false); const muted = ref( getWordSoftMute( note.value, - $i.id, + $i?.id, defaultStore.state.mutedWords, defaultStore.state.mutedLangs, ), diff --git a/packages/client/src/components/MkNoteSub.vue b/packages/client/src/components/MkNoteSub.vue index 535320079d..1dd1351700 100644 --- a/packages/client/src/components/MkNoteSub.vue +++ b/packages/client/src/components/MkNoteSub.vue @@ -268,7 +268,7 @@ const isDeleted = ref(false); const muted = ref( getWordSoftMute( note.value, - $i.id, + $i?.id, defaultStore.state.mutedWords, defaultStore.state.mutedLangs, ), diff --git a/packages/client/src/components/MkRenoteButton.vue b/packages/client/src/components/MkRenoteButton.vue index 90ecb3217f..0c0790d86e 100644 --- a/packages/client/src/components/MkRenoteButton.vue +++ b/packages/client/src/components/MkRenoteButton.vue @@ -73,13 +73,16 @@ useTooltip(buttonRef, async (showing) => { }); const hasRenotedBefore = ref(false); -os.api("notes/renotes", { - noteId: props.note.id, - userId: $i.id, - limit: 1, -}).then((res) => { - hasRenotedBefore.value = res.length > 0; -}); + +if ($i != null) { + os.api("notes/renotes", { + noteId: props.note.id, + userId: $i.id, + limit: 1, + }).then((res) => { + hasRenotedBefore.value = res.length > 0; + }); +} const renote = (viaKeyboard = false, ev?: MouseEvent) => { pleaseLogin(); diff --git a/packages/client/src/components/MkWaitingDialog.vue b/packages/client/src/components/MkWaitingDialog.vue index 944ec29374..b5732c951d 100644 --- a/packages/client/src/components/MkWaitingDialog.vue +++ b/packages/client/src/components/MkWaitingDialog.vue @@ -14,8 +14,7 @@ > import { shallowRef, watch } from "vue"; import MkModal from "@/components/MkModal.vue"; +import iconClass from "@/scripts/icon" const modal = shallowRef>(); diff --git a/packages/client/src/components/form/folder.vue b/packages/client/src/components/form/folder.vue index 9446dabe6d..c289701d83 100644 --- a/packages/client/src/components/form/folder.vue +++ b/packages/client/src/components/form/folder.vue @@ -18,11 +18,14 @@