From d2e4769fa4d366c46cff7cee4881fdf478218a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Sun, 9 Jul 2023 18:22:53 +0200 Subject: [PATCH 01/11] Fix Mastodon compatibility string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- packages/backend/src/server/api/mastodon/endpoints/meta.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/meta.ts b/packages/backend/src/server/api/mastodon/endpoints/meta.ts index 2df4af82a5..042071f0e0 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/meta.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/meta.ts @@ -1,4 +1,5 @@ import { Entity } from "megalodon"; +import config from "@/config/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; import { Users, Notes } from "@/models/index.js"; import { IsNull, MoreThan } from "typeorm"; @@ -17,7 +18,7 @@ export async function getInstance(response: Entity.Instance) { response.description || "This is a vanilla Calckey Instance. It doesnt seem to have a description. BTW you are using the Mastodon api to access this server :)", email: response.email || "", - version: "3.0.0 compatible (3.5+ Calckey)", //I hope this version string is correct, we will need to test it. + version: `3.0.0 (compatible; Calckey ${config.version})`, urls: response.urls, stats: { user_count: await totalUsers, From d850381376e789aeb7e64a2d9c1361396ad78581 Mon Sep 17 00:00:00 2001 From: sinofp Date: Sun, 9 Jul 2023 18:54:12 +0100 Subject: [PATCH 02/11] Implement speak-as-cat for Chinese and Greek MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Chinese meow character is 喵, whose pinyin is miāo. 妙, 庙, 描, 渺, 瞄, 秒, 苗, and 藐 are all the miao characters from *3500 commonly used Chinese characters.xls* @naskya proposed to include 廟 and να. Download the spreadsheet from https://faculty.blcu.edu.cn/xinghb/zh_CN/article/167473/content/1045.htm See the discussion at https://codeberg.org/calckey/calckey/issues/9746#issuecomment-974699 --- packages/backend/src/misc/nyaize.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts index dd0c5bbdff..2b996c611e 100644 --- a/packages/backend/src/misc/nyaize.ts +++ b/packages/backend/src/misc/nyaize.ts @@ -20,5 +20,9 @@ export function nyaize(text: string): string { ) .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") + // Chinese + .replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵") + // Greek + .replaceAll("να", "νια") ); } From 46d97d49a2298c1b8c1537ef1ed3eff376b49285 Mon Sep 17 00:00:00 2001 From: freeplay Date: Sun, 9 Jul 2023 15:05:39 -0400 Subject: [PATCH 03/11] style: link underlines --- packages/client/src/components/MkUrlPreview.vue | 3 ++- packages/client/src/components/global/MkUrl.vue | 2 ++ packages/client/src/components/mfm.ts | 1 + packages/client/src/style.scss | 16 ++++++++++++---- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/client/src/components/MkUrlPreview.vue b/packages/client/src/components/MkUrlPreview.vue index 6452e135da..8fa8092b8a 100644 --- a/packages/client/src/components/MkUrlPreview.vue +++ b/packages/client/src/components/MkUrlPreview.vue @@ -196,6 +196,7 @@ onUnmounted(() => { > a { display: flex; transition: background 0.2s; + text-decoration: none; > div:first-child:not(:last-child) { position: relative; width: 90px; @@ -277,7 +278,7 @@ onUnmounted(() => { &:focus, &:focus-within { background: var(--panelHighlight); - h1 { + h3 { text-decoration: underline; } } diff --git a/packages/client/src/components/global/MkUrl.vue b/packages/client/src/components/global/MkUrl.vue index 98ba8d94e9..3453bf5ed6 100644 --- a/packages/client/src/components/global/MkUrl.vue +++ b/packages/client/src/components/global/MkUrl.vue @@ -80,6 +80,8 @@ const target = self ? null : "_blank"; display: inline-block; overflow: clip; text-overflow: ellipsis; + text-decoration: none !important; + line-height: 1.05; > .icon { padding-left: 2px; diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index cb0942a338..63465f38b5 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -409,6 +409,7 @@ export default defineComponent({ key: Math.random(), to: `/tags/${encodeURIComponent(token.props.hashtag)}`, style: "color:var(--hashtag);", + class: "_link", }, `#${token.props.hashtag}`, ), diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index a6ef73015b..be12f8b156 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -145,6 +145,9 @@ a { cursor: pointer; color: inherit; -webkit-tap-highlight-color: transparent; + &:hover { + text-decoration: underline; + } } // i { @@ -229,6 +232,7 @@ hr { font-size: 1em; font-family: inherit; line-height: inherit; + text-decoration: none; &, * { @@ -628,18 +632,22 @@ hr { ._link { position: relative; color: var(--link); + text-decoration: none !important; - &:after { + &::before, &::after { content: ""; position: absolute; bottom: 0; left: 0; width: 0%; - border-bottom: 2px solid var(--link); + border-bottom: 1px solid var(--link); transition: 0.3s ease-in-out; } - - &:hover:after { + &::before { + width: 100%; + opacity: .4; + } + &:hover:after, &:focus:after { width: 100%; } } From 3237a0c27c15ca01a03ad22aec5efd2bc653d770 Mon Sep 17 00:00:00 2001 From: naskya Date: Sun, 9 Jul 2023 21:19:09 +0000 Subject: [PATCH 04/11] Nya-ify capital Greek alphabets --- packages/backend/src/misc/nyaize.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts index 2b996c611e..2ae3ceccd4 100644 --- a/packages/backend/src/misc/nyaize.ts +++ b/packages/backend/src/misc/nyaize.ts @@ -20,9 +20,11 @@ export function nyaize(text: string): string { ) .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, "다냥") .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, "냥") - // Chinese + // zh-CN, zh-TW .replace(/(妙|庙|描|渺|瞄|秒|苗|藐|廟)/g, "喵") - // Greek + // el-GR .replaceAll("να", "νια") + .replaceAll("ΝΑ", "ΝΙΑ") + .replaceAll("Να", "Νια") ); } From d1c9c7cc3111fbaa5e09362688809635f27116f4 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sun, 9 Jul 2023 21:27:09 +0200 Subject: [PATCH 05/11] [mastodon-client] fix poll notifications --- packages/megalodon/src/misskey/api_client.ts | 13 +++++++++---- packages/megalodon/src/misskey/notification.ts | 2 +- packages/megalodon/src/notification.ts | 3 +-- packages/megalodon/test/integration/misskey.spec.ts | 4 ++-- .../megalodon/test/unit/misskey/api_client.spec.ts | 8 ++++---- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 34e11784e0..813ffe08a2 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -396,8 +396,8 @@ namespace MisskeyAPI { return MisskeyNotificationType.Reaction case NotificationType.Reblog: return MisskeyNotificationType.Renote - case NotificationType.PollVote: - return MisskeyNotificationType.PollVote + case NotificationType.Poll: + return MisskeyNotificationType.PollEnded case NotificationType.FollowRequest: return MisskeyNotificationType.ReceiveFollowRequest default: @@ -417,8 +417,8 @@ namespace MisskeyAPI { return NotificationType.Reblog case MisskeyNotificationType.Reaction: return NotificationType.EmojiReaction - case MisskeyNotificationType.PollVote: - return NotificationType.PollVote + case MisskeyNotificationType.PollEnded: + return NotificationType.Poll case MisskeyNotificationType.ReceiveFollowRequest: return NotificationType.FollowRequest case MisskeyNotificationType.FollowRequestAccepted: @@ -458,6 +458,11 @@ namespace MisskeyAPI { notification = Object.assign(notification, { status: this.note(n.note, host) }) + if (notification.type === NotificationType.Poll) { + notification = Object.assign(notification, { + account: this.note(n.note, host).account + }) + } } if (n.reaction) { notification = Object.assign(notification, { diff --git a/packages/megalodon/src/misskey/notification.ts b/packages/megalodon/src/misskey/notification.ts index 9cf3dc58a3..e44b6159c6 100644 --- a/packages/megalodon/src/misskey/notification.ts +++ b/packages/megalodon/src/misskey/notification.ts @@ -7,7 +7,7 @@ namespace MisskeyNotificationType { export const Renote: MisskeyEntity.NotificationType = 'renote' export const Quote: MisskeyEntity.NotificationType = 'quote' export const Reaction: MisskeyEntity.NotificationType = 'favourite' - export const PollVote: MisskeyEntity.NotificationType = 'pollVote' + export const PollEnded: MisskeyEntity.NotificationType = 'pollEnded' export const ReceiveFollowRequest: MisskeyEntity.NotificationType = 'receiveFollowRequest' export const FollowRequestAccepted: MisskeyEntity.NotificationType = 'followRequestAccepted' export const GroupInvited: MisskeyEntity.NotificationType = 'groupInvited' diff --git a/packages/megalodon/src/notification.ts b/packages/megalodon/src/notification.ts index 9ea3898c6e..8e8c135795 100644 --- a/packages/megalodon/src/notification.ts +++ b/packages/megalodon/src/notification.ts @@ -8,8 +8,7 @@ namespace NotificationType { export const EmojiReaction: Entity.NotificationType = 'emoji_reaction' export const FollowRequest: Entity.NotificationType = 'follow_request' export const Status: Entity.NotificationType = 'status' - export const PollVote: Entity.NotificationType = 'poll_vote' - export const PollExpired: Entity.NotificationType = 'poll_expired' + export const Poll: Entity.NotificationType = 'poll' } export default NotificationType diff --git a/packages/megalodon/test/integration/misskey.spec.ts b/packages/megalodon/test/integration/misskey.spec.ts index 754f6cc28e..49d39a097e 100644 --- a/packages/megalodon/test/integration/misskey.spec.ts +++ b/packages/megalodon/test/integration/misskey.spec.ts @@ -93,7 +93,7 @@ const pollVote: MisskeyEntity.Notification = { createdAt: '2021-02-01T01:49:29', userId: user.id, user: user, - type: MisskeyNotificationType.PollVote, + type: MisskeyNotificationType.PollEnded, note: note } @@ -168,7 +168,7 @@ describe('getNotifications', () => { }, { event: pollVote, - expected: MegalodonNotificationType.PollVote, + expected: MegalodonNotificationType.Poll, title: 'pollVote' }, { diff --git a/packages/megalodon/test/unit/misskey/api_client.spec.ts b/packages/megalodon/test/unit/misskey/api_client.spec.ts index acaac39ca1..b8e1df048c 100644 --- a/packages/megalodon/test/unit/misskey/api_client.spec.ts +++ b/packages/megalodon/test/unit/misskey/api_client.spec.ts @@ -42,8 +42,8 @@ describe('api_client', () => { dist: MisskeyNotificationType.Renote }, { - src: MegalodonNotificationType.PollVote, - dist: MisskeyNotificationType.PollVote + src: MegalodonNotificationType.Poll, + dist: MisskeyNotificationType.PollEnded }, { src: MegalodonNotificationType.FollowRequest, @@ -83,8 +83,8 @@ describe('api_client', () => { dist: MegalodonNotificationType.EmojiReaction }, { - src: MisskeyNotificationType.PollVote, - dist: MegalodonNotificationType.PollVote + src: MisskeyNotificationType.PollEnded, + dist: MegalodonNotificationType.Poll }, { src: MisskeyNotificationType.ReceiveFollowRequest, From 32ea8320ac0a6111016e5cbc0fd96714a476f98a Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sun, 9 Jul 2023 21:47:49 +0200 Subject: [PATCH 06/11] [mastodon-client] populate user details for notifications --- packages/megalodon/src/misskey.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index dbf3471c0f..1c15acf382 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1236,6 +1236,8 @@ export default class Misskey implements MegalodonInterface { const notification = this.converter.notification(n, host); if (n.note) notification.status = await this.noteWithDetails(n.note, host, cache); + if (notification.account) + notification.account = (await this.getAccount(notification.account.id)).data return notification; } From 76a10c0a5481d1d3ca2ca9ee93fdd9850a413d5a Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sun, 9 Jul 2023 22:59:04 +0200 Subject: [PATCH 07/11] [mastodon-client] fix posting polls --- .../server/api/mastodon/endpoints/status.ts | 19 +++++++++++++++++++ packages/megalodon/src/misskey.ts | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 76057ef0a2..1bff3aa4c7 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -67,6 +67,25 @@ export function apiStatusMastodon(router: Router): void { const { sensitive } = body; body.sensitive = typeof sensitive === "string" ? sensitive === "true" : sensitive; + + if (body.poll) { + if ( + body.poll.expires_in != null && + typeof body.poll.expires_in === "string" + ) + body.poll.expires_in = parseInt(body.poll.expires_in); + if ( + body.poll.multiple != null && + typeof body.poll.multiple === "string" + ) + body.poll.multiple = body.poll.multiple == "true"; + if ( + body.poll.hide_totals != null && + typeof body.poll.hide_totals === "string" + ) + body.poll.hide_totals = body.poll.hide_totals == "true"; + } + const data = await client.postStatus(text, body); ctx.body = convertStatus(data.data); } catch (e: any) { diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 1c15acf382..7ff802dc86 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1169,7 +1169,7 @@ export default class Misskey implements MegalodonInterface { let pollParam = { choices: options.poll.options, expiresAt: null, - expiredAfter: options.poll.expires_in + expiredAfter: options.poll.expires_in * 1000 } if (options.poll.multiple !== undefined) { pollParam = Object.assign(pollParam, { From 28992db8e463a472ee2e489257376de527586f48 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sun, 9 Jul 2023 23:35:07 +0200 Subject: [PATCH 08/11] [server/api/notes/show] return correct status code --- packages/backend/src/server/api/endpoints/notes/show.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts index 39d128134f..8c5f91c5c1 100644 --- a/packages/backend/src/server/api/endpoints/notes/show.ts +++ b/packages/backend/src/server/api/endpoints/notes/show.ts @@ -21,6 +21,7 @@ export const meta = { message: "No such note.", code: "NO_SUCH_NOTE", id: "24fcbfc6-2e37-42b6-8388-c29b3861a08d", + httpStatusCode: 404, }, }, } as const; From ec06d62d61dcfe2a17f033e50d8daa6078e98c15 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sun, 9 Jul 2023 23:39:48 +0200 Subject: [PATCH 09/11] [mastodon-client] return 404 instead of 401 on NO_SUCH_NOTE --- packages/backend/src/server/api/mastodon/endpoints/status.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 1bff3aa4c7..caa9d1d688 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -105,7 +105,7 @@ export function apiStatusMastodon(router: Router): void { ctx.body = convertStatus(data.data); } catch (e: any) { console.error(e); - ctx.status = 401; + ctx.status = ctx.status == 404 ? 404 : 401; ctx.body = e.response.data; } }); From c1e43407d5a23e324c1671c413fb300f59bafeb4 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sun, 9 Jul 2023 23:53:15 +0200 Subject: [PATCH 10/11] [mastodon-client] enforce limits for favorites and bookmarks --- packages/megalodon/src/misskey.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 7ff802dc86..fd765b3dcf 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -408,7 +408,7 @@ export default class Misskey implements MegalodonInterface { if (options) { if (options.limit) { params = Object.assign(params, { - limit: options.limit + limit: options.limit <= 100 ? options.limit : 100 }) } if (options.max_id) { @@ -738,7 +738,7 @@ export default class Misskey implements MegalodonInterface { if (options) { if (options.limit) { params = Object.assign(params, { - limit: options.limit + limit: options.limit <= 100 ? options.limit : 100 }) } else { From 02ddbe2363661cd12ab485559a4c5e6432d23683 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Mon, 10 Jul 2023 00:05:52 +0200 Subject: [PATCH 11/11] [mastodon-client] return actual status bookmark state --- packages/megalodon/src/misskey.ts | 8 ++++++++ packages/megalodon/src/misskey/api_client.ts | 3 ++- packages/megalodon/src/misskey/entities/state.ts | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 packages/megalodon/src/misskey/entities/state.ts diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index fd765b3dcf..026b8e9b7a 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1243,9 +1243,17 @@ export default class Misskey implements MegalodonInterface { public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache); + status.bookmarked = await this.isStatusBookmarked(n.id); return this.addMentionsToStatus(status, cache); } + public async isStatusBookmarked(id: string) : Promise { + return this.client + .post('/api/notes/state', { + noteId: id + }).then(p => p.data.isFavorited ?? false); + } + public async addUserDetailsToStatus(status: Entity.Status, cache: AccountCache) : Promise { if (status.account.followers_count === 0 && status.account.followers_count === 0 && status.account.statuses_count === 0) status.account = await this.getAccountCached(status.account.id, status.account.acct, cache) ?? status.account; diff --git a/packages/megalodon/src/misskey/api_client.ts b/packages/megalodon/src/misskey/api_client.ts index 813ffe08a2..f80d5a4421 100644 --- a/packages/megalodon/src/misskey/api_client.ts +++ b/packages/megalodon/src/misskey/api_client.ts @@ -40,7 +40,8 @@ namespace MisskeyAPI { export type GetAll = MisskeyEntity.GetAll export type UserKey = MisskeyEntity.UserKey export type Session = MisskeyEntity.Session - export type Stats = MisskeyEntity.Stats + export type Stats = MisskeyEntity.Stats + export type State = MisskeyEntity.State export type APIEmoji = { emojis: Emoji[] } } diff --git a/packages/megalodon/src/misskey/entities/state.ts b/packages/megalodon/src/misskey/entities/state.ts new file mode 100644 index 0000000000..4538fb4619 --- /dev/null +++ b/packages/megalodon/src/misskey/entities/state.ts @@ -0,0 +1,7 @@ +namespace MisskeyEntity { + export type State = { + isFavorited: boolean + isMutedThread: boolean + isWatching: boolean + } +}