diff --git a/CHANGELOG.md b/CHANGELOG.md index f1c9ac460..0c45b02b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ If you encounter any problems with updating, please try the following: 1. `npm run clean` or `npm run cleanall` 2. Retry update (Don't forget `npm i`) +11.1.6 (2019/04/18) +------------------- +### Fixes +* 未認知ユーザーからActivityが飛んできた場合に処理できない問題を修正 +* その投稿を見たのにも関わらずメンションインジケーターが点灯し続ける問題を修正 +* ハッシュタグの判定を改善 +* サーバーのエラーハンドリングを改善 + 11.1.5 (2019/04/17) ------------------- ### Fixes diff --git a/Dockerfile b/Dockerfile index ec7d8a6a2..be2768033 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,12 +21,11 @@ RUN apk add --no-cache \ pkgconfig \ python \ zlib-dev -RUN npm i -g yarn COPY package.json ./ -RUN yarn install +RUN npm i COPY . ./ -RUN yarn build +RUN npm run build FROM base AS runner diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index 653b08069..e3d89ab50 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -70,8 +70,14 @@ common: followers: "Sledující" favorites: "Oblíbené" permissions: - 'read:drive': "Prohlížet Disk" - 'write:drive': "Pracovat s Diskem" + "read:account": "Zobrazit informace o účtu" + "read:drive": "Prohlížet Disk" + "write:drive": "Pracovat s Diskem" + "read:favorites": "Prohlížet oblíbené" + "read:messaging": "Prohlížet konverzaci" + "write:messaging": "Pracovat s konverzaci" + "read:mutes": "Prohlížet ztlumené" + "write:votes": "Hlasovat" empty-timeline-info: follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose" explore: "Najít uživatele" @@ -1114,7 +1120,7 @@ mobile/views/components/post-form.vue: reply: "Odpovědět" renote: "Renotovat" reply-placeholder: "Odpovědět na tento příspěvěk" - location-alert: "Vaše zařízení nepodporuje lokační službu" + geolocation-alert: "Vaše zařízení nepodporuje lokační službu" error: "Chyba" username-prompt: "Zadejte uživatelské jméno" mobile/views/components/sub-note-content.vue: @@ -1185,4 +1191,3 @@ deck/deck.user-column.vue: activity: "Aktivita" dev/views/new-app.vue: app-name-desc: "Jméno vaší aplikace" - app-desc: "Stručný popis nebo představení vaší aplikace." diff --git a/locales/de-DE.yml b/locales/de-DE.yml index ed565c4f2..d6075f73b 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -62,10 +62,14 @@ common: followers: "Folgende" favorites: "Diesen Beitrag favorisieren" permissions: - 'read:account': "Accountinformationen anzeigen." - 'write:account': "Accountinformationen bearbeiten." - 'read:drive': "Dateien anzeigen" - 'write:drive': "Dateien bearbeiten" + "read:account": "Accountinformationen anzeigen." + "write:account": "Accountinformationen bearbeiten." + "read:drive": "Dateien anzeigen" + "write:drive": "Dateien bearbeiten" + "read:favorites": "Favoriten anzeigen" + "read:messaging": "Unterhaltung anzeigen" + "write:messaging": "Unterhaltung bearbeiten" + "write:votes": "Abstimmen" empty-timeline-info: follow-users-to-make-your-timeline: "Beiträge von Benutzern, denen du folgst, werden in der Zeitleiste angezeigt." explore: "Benutzer finden" @@ -739,10 +743,7 @@ dev/views/new-app.vue: create-app: "Erstelle Anwendung" app-name: "Name der Anwendung" app-name-desc: "Der Name der Anwendung" - app-name-ex: "z.B. Misskey für iOS" app-overview: "Beschreibung der Anwendung" - app-desc: "Eine kurze Beschreibung oder Einführung der Anwendung." - app-desc-ex: "z.B. Ein iOS-Client für Misskey." callback-url: "Callback-URL (optional)" callback-url-desc: "Die URL, auf die nach erfolgreicher Authentifizierung umgeleitet werden soll." authority: "Berechtigungen" diff --git a/locales/en-US.yml b/locales/en-US.yml index 85bc71399..a9852d0c5 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -70,10 +70,21 @@ common: followers: "Followers" favorites: "Favorites" permissions: - 'read:account': "View account information" - 'write:account': "Update your account information" - 'read:drive': "Browse the Drive" - 'write:drive': "Work with the Drive" + "read:account": "View account information" + "write:account": "Update your account information" + "read:blocks": "View Blocks" + "write:blocks": "Work with Blocks" + "read:drive": "Browse the Drive" + "write:drive": "Work with the Drive" + "read:favorites": "View Favorites" + "write:favorites": "Work with Favorites" + "read:following": "View Follower info" + "write:following": "Work with Follow info" + "read:messaging": "View Messaging" + "write:messaging": "Work with Messaging" + "read:mutes": "View Muted" + "write:mutes": "Work with Muted" + "write:votes": "Vote" empty-timeline-info: follow-users-to-make-your-timeline: "Following users will show their posts in your timeline." explore: "Find users" @@ -281,6 +292,7 @@ common: nav: "Navigation" tips: "Tips" hashtags: "Hashtags" + queue: "Queue" dev: "Failed to create the application. Please try again." ai-chan-kawaii: "Ai-chan kawaii!" you: "You" @@ -1462,7 +1474,7 @@ mobile/views/components/post-form.vue: quote-placeholder: "Quote this post... (optional)" reply-placeholder: "Reply to this note..." cw-placeholder: "Comments for the post (optional)" - location-alert: "Your device does not provide location services" + geolocation-alert: "Your device does not provide location services." error: "Error" username-prompt: "Enter user name" mobile/views/components/sub-note-content.vue: @@ -1615,10 +1627,7 @@ dev/views/new-app.vue: create-app: "Creating application" app-name: "Application name" app-name-desc: "The name of your app" - app-name-ex: "ex) Misskey for iOS" app-overview: "Application summary" - app-desc: "A brief description or introduction of your app." - app-desc-ex: "ex) Misskey iOS client." callback-url: "The callback URL (optional)" callback-url-desc: "The URL to redirect to after the user is authenticated via the authentication form." authority: "Permissions" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 9ce261326..871f79c32 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -20,8 +20,15 @@ common: application-authorization: "Autorizaciones de la aplicación." close: "Cerrar" do-not-copy-paste: "Por favor no copies código aquí. Tu cuenta puede resultar comprometida." + load-more: "Leer más" enter-password: "Escribe una contraseña" 2fa: "Autenticación de dos factores" + customize-home: "Personaliza la página principal" + featured-notes: "Destacados" + dark-mode: "Modo oscuro" + signin: "Iniciar sesión" + signup: "¡Regístrate!" + signout: "Cerrar sesión" got-it: "¡Listo!" customization-tips: title: "Consejos de personalización" @@ -50,8 +57,22 @@ common: drive: "Drive" messaging: "Conversación" home: "Inicio" + deck: "Deck" + timeline: "Timeline" + explore: "Explorar" following: "Siguiendo" + followers: "Seguidores" favorites: "Me gusta esta nota" + permissions: + "read:account": "Ver información de la cuenta" + "write:account": "Editar información de la cuenta" + "read:blocks": "Ver bloques" + "write:blocks": "Editar bloques" + "read:favorites": "Ver favoritos" + "write:favorites": "Editar favoritos" + "read:messaging": "Ver conversación" + "read:notifications": "Ver notificaciones" + "write:votes": "Vota" weekday-short: sunday: "domingo" monday: "lunes" @@ -97,12 +118,24 @@ common: d: "¿Quieres decir algo?" e: "¡Escribe aquí!" f: "Esperando a que escribas algo..." + settings: "Configuración" _settings: profile: "Tu perfil" notification: "Notificaciones" + apps: "Aplicaciones" tags: "Etiquetas" + mute-and-block: "Silenciar/Bloquear" blocking: "Bloquear" + security: "Seguridad" password: "Contraseña" + other: "Otros" + appearance: "Diseño" + behavior: "Comportamiento" + fetch-on-scroll-desc: "Cuando te deslizas al final de la página nuevo contenido se carga automáticamente." + note-visibility: "Visibilidad de la publicación" + default-note-visibility: "Rango de publicación predeterminado" + web-search-engine: "Buscador web" + web-search-engine-desc: "Ejemplo: https://www.google.com/?#q={{query}}" use-os-default-emojis: "Usar los emoticonos estándar del sistema operativo" line-width: "Grosor de línea" line-width-thick: "Grosor" @@ -128,6 +161,19 @@ common: contrasted-acct: "Añadir contraste al nombre de usuario" wallpaper: "Fondo de pantalla" choose-wallpaper: "Escoge un fondo de pantalla" + delete-wallpaper: "Quitar fondo de pantalla" + show-clock-on-header: "Muestra el reloj en la parte superior derecha" + timeline: "Timeline" + sound: "Sonido" + enable-sounds: "Habilitar sonido" + volume: "Volúmen" + test: "Prueba" + version: "Versión" + no-updates: "No hay actualizaciones disponibles" + no-updates-desc: "Tu Misskey está actualizado" + update-available: "¡Una nueva versión está disponible!" + update-available-desc: "Las actualizaciones se aplicarán cuando la página se vuelva a cargar." + advanced-settings: "Configuraciones avanzadas" navbar-position-left: "Izquierda" search: "Buscar" delete: "eliminar" @@ -869,6 +915,7 @@ mobile/views/components/post-form.vue: reply: "Responder" renote: "Republicar" reply-placeholder: "Responder a esta nota..." + geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización." mobile/views/components/sub-note-content.vue: private: "Esta publicación es privada" deleted: "Esta publicación ha sido removida" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index ab7588b68..2d802c1b1 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -68,10 +68,11 @@ common: followers: "Abonné·e·s" favorites: "Mettre cette note en favoris" permissions: - 'read:account': "Afficher les informations du compte" - 'write:account': "Mettre à jour les informations de votre compte" - 'read:drive': "Parcourir le Drive" - 'write:drive': "Écrire sur le Drive" + "read:account": "Afficher les informations du compte" + "write:account": "Mettre à jour les informations de votre compte" + "read:drive": "Parcourir le Drive" + "write:drive": "Écrire sur le Drive" + "write:votes": "Vote" empty-timeline-info: follow-users-to-make-your-timeline: "Les utilisateurs suivants afficheront leurs publications sur votre fil." explore: "Trouver des utilisateurs" @@ -274,6 +275,7 @@ common: nav: "Navigation" tips: "Conseils" hashtags: "Hashtags" + queue: "File d'attente" dev: "Échec lors de la création de l’application. Veuillez réessayer." ai-chan-kawaii: "Ai-Chan est mignonne !" you: "Vous" @@ -1434,7 +1436,7 @@ mobile/views/components/post-form.vue: quote-placeholder: "Citer ce billet ... (Facultatif)" reply-placeholder: "Répondre à cette note" cw-placeholder: "Commenter le contenu (optionnel)" - location-alert: "Votre appareil ne prend pas en charge les services de localisation" + geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation" error: "Erreur" username-prompt: "Saisir un nom d'utilisateur" mobile/views/components/sub-note-content.vue: @@ -1586,10 +1588,7 @@ dev/views/new-app.vue: create-app: "Création d’une application" app-name: "Nom de l’application" app-name-desc: "Le nom de votre application" - app-name-ex: "p. ex. Misskey pour iOS" app-overview: "Description courte de l’application" - app-desc: "Brève description introductive à votre application." - app-desc-ex: "p. ex) Misskey pour iOS" callback-url: "L’Url de callback (facultatif)" callback-url-desc: "Vous pouvez définir l’URL de redirection lorsque l’utilisateur s’est authentifié via formulaire d’authentification." authority: "Autorisations " diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 9f8e581ef..935c83df3 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -60,6 +60,8 @@ common: following: "フォローしとる" followers: "フォロワー" favorites: "お気に入り" + permissions: + "write:votes": "投票するで" weekday-short: sunday: "日" monday: "月" @@ -1126,7 +1128,7 @@ mobile/views/components/post-form.vue: quote-placeholder: "この投稿を持ってくる(オプション)" reply-placeholder: "この投稿への返信..." cw-placeholder: "内容への注釈 (オプション)" - location-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。" + geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。" error: "エラー" username-prompt: "ユーザー名を入力してや" mobile/views/components/sub-note-content.vue: @@ -1272,10 +1274,7 @@ dev/views/new-app.vue: create-app: "アプリケーション作る" app-name: "アプリケーションの名前" app-name-desc: "あんたのアプリの名前。" - app-name-ex: "ex) 関西ミスキー保安協会" app-overview: "このアプリどんなん?" - app-desc: "あんたのアプリどんなんか教えて" - app-desc-ex: "ex) 関西人なら誰でも口ずさめるこのCMがついにMisskeyへ。" callback-url: "コールバックURL (無くてもええで)" callback-url-desc: "ユーザーが認証フォームで認証した後どこに連れてくかを設定できるで" authority: "権限" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 4e7a5d353..1bf86ad0d 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -70,10 +70,11 @@ common: followers: "팔로워" favorites: "즐겨찾기" permissions: - 'read:account': "계정 정보 보기" - 'write:account': "계정 정보 변경" - 'read:drive': "드라이브 보기" - 'write:drive': "드라이브 수정" + "read:account": "계정 정보 보기" + "write:account": "계정 정보 변경" + "read:drive": "드라이브 보기" + "write:drive": "드라이브 수정" + "write:votes": "투표하기" empty-timeline-info: follow-users-to-make-your-timeline: "사용자를 팔로우하면 글이 타임라인에 표시됩니다." explore: "사용자 탐색" @@ -281,6 +282,7 @@ common: nav: "내비게이션" tips: "팁" hashtags: "해시태그" + queue: "큐" dev: "앱을 만드는 데 실패했습니다. 다시 시도하시기 바랍니다." ai-chan-kawaii: "아이쨩 귀여워" you: "당신" @@ -1462,7 +1464,7 @@ mobile/views/components/post-form.vue: quote-placeholder: "이 글을 인용... (선택적)" reply-placeholder: "이 글에 답글..." cw-placeholder: "내용 주석 (선택적)" - location-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다" + geolocation-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다" error: "오류" username-prompt: "사용자명을 입력하여 주십시오" mobile/views/components/sub-note-content.vue: @@ -1615,10 +1617,7 @@ dev/views/new-app.vue: create-app: "어플리케이션 생성" app-name: "어플리케이션 이름" app-name-desc: "앱의 이름." - app-name-ex: "ex) Misskey for iOS" app-overview: "앱 개요" - app-desc: "어플리케이션에 대한 간단한 설명." - app-desc-ex: "ex) Misskey iOS 클라이언트." callback-url: "콜백 URL (옵션)" callback-url-desc: "사용자가 인증 폼에서 인증한 뒤 리다이렉트할 URL을 설정합니다." authority: "권한" diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index 772d41f93..e31be1856 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -23,6 +23,8 @@ common: timeline: "Tijdlijn" followers: "Volgers" favorites: "Deze notitie toevoegen aan favorieten" + permissions: + "write:votes": "Stemmen" weekday-short: sunday: "Z" monday: "M" diff --git a/locales/no-NO.yml b/locales/no-NO.yml index ca613a20d..4dce106f2 100644 --- a/locales/no-NO.yml +++ b/locales/no-NO.yml @@ -37,6 +37,8 @@ common: home: "Hjem" followers: "Følgere" favorites: "Merket som favoritt" + permissions: + "write:votes": "Stem" weekday-short: sunday: "S" monday: "M" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 61d7a10e1..91558517d 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -63,7 +63,8 @@ common: followers: "Śledzący" favorites: "Moje ulubione" permissions: - 'read:drive': "Wyświetl dysk" + "read:drive": "Wyświetl dysk" + "write:votes": "Zagłosuj" empty-timeline-info: explore: "Poznaj" weekday-short: @@ -1082,7 +1083,7 @@ mobile/views/components/post-form.vue: quote-placeholder: "Zacytuj ten wpis… (nieobowiązkowe)" reply-placeholder: "Odpowiedź na ten wpis…" cw-placeholder: "Treść ostrzeżenia (opcjonalnie)" - location-alert: "Twoje urządzenie nie pozwala na przekazywanie informacji o lokalizacji" + geolocation-alert: "Twoje urządzenie nie obsługuje geolokalizacji." error: "Błąd" username-prompt: "Wprowadź nazwę użytkownika" mobile/views/components/sub-note-content.vue: diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 195c6d5ef..56a4fb10e 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -70,10 +70,26 @@ common: followers: "关注者" favorites: "最爱" permissions: - 'read:account': "查看账户信息" - 'write:account': "更改我的帐户信息" - 'read:drive': "查看网盘" - 'write:drive': "管理网盘文件" + "read:account": "查看账户信息" + "write:account": "更改我的帐户信息" + "read:blocks": "查看黑名单" + "write:blocks": "编辑黑名单" + "read:drive": "查看网盘" + "write:drive": "管理网盘文件" + "read:favorites": "查看收藏夹" + "write:favorites": "编辑收藏夹" + "read:following": "查看关注信息" + "write:following": "关注/取消关注" + "read:messaging": "查看对话" + "write:messaging": "对话操作" + "read:mutes": "查看屏蔽列表" + "write:mutes": "编辑屏蔽列表" + "write:notes": "创建或删除帖子" + "read:notifications": "查看通知" + "write:notifications": "管理通知" + "read:reactions": "查看回应" + "write:reactions": "回应操作" + "write:votes": "投票" empty-timeline-info: follow-users-to-make-your-timeline: "关注其他用户时,帖子将显示在时间线中。" explore: "查找用户" @@ -129,7 +145,7 @@ common: apps: "应用程序" tags: "标签" mute-and-block: "屏蔽/拉黑" - blocking: "屏蔽" + blocking: "拉黑" security: "安全性" signin: "登录历史" password: "密码" @@ -281,6 +297,7 @@ common: nav: "导航" tips: "提示" hashtags: "标签" + queue: "队列" dev: "构建应用程序失败,请再试一次。" ai-chan-kawaii: "小蓝真可爱" you: "您" @@ -966,6 +983,7 @@ common/views/components/password-settings.vue: changed: "密码已更改" failed: "更改密码失败" common/views/components/post-form-attaches.vue: + attach-cancel: "删除附件" mark-as-sensitive: "标记为“敏感”" unmark-as-sensitive: "取消标记为“敏感”" desktop/views/components/sub-note-content.vue: @@ -1385,6 +1403,7 @@ desktop/views/widgets/polls.vue: desktop/views/widgets/post-form.vue: title: "帖子" note: "帖子" + something-happened: "由于某种原因无法发帖。" desktop/views/widgets/profile.vue: update-banner: "点击来剪辑背景" update-avatar: "点击来剪辑头像" @@ -1461,7 +1480,7 @@ mobile/views/components/post-form.vue: quote-placeholder: "引用这个帖子t... (可选)" reply-placeholder: "回复这个帖子" cw-placeholder: "评论帖子(可选)" - location-alert: "您的设备不提供定位服务" + geolocation-alert: "您的设备不提供位置服务" error: "错误" username-prompt: "请输入用户名" mobile/views/components/sub-note-content.vue: @@ -1611,14 +1630,17 @@ dev/views/apps.vue: create-app: "创建应用" app-missing: "没有应用" dev/views/new-app.vue: + new-app: "新应用" + new-app-info: "可以从 API 中创建应用。 (app/create)" create-app: "正在创建应用" app-name: "应用名称" + app-name-placeholder: "ex) iOS版Misskey" app-name-desc: "您应用的名称" - app-name-ex: "ex) iOS版本的Misskey" app-overview: "应用摘要" - app-desc: "您的应用的简要说明或介绍。" - app-desc-ex: "ex) iOS版Misskey客户端." + app-overview-placeholder: " ex) iOS版Misskey客户端." + app-overview-desc: "您的应用的简要说明或介绍。" callback-url: "回应URL (optional)" + callback-url-placeholder: "ex) https://your.app.example.com/callback.php" callback-url-desc: "通过身份验证表单对用户进行身份验证后重定向到的URL。" authority: "权限" authority-desc: "只能通过API访问此处请求的功能。" diff --git a/package.json b/package.json index 4135d3e58..db2d9d0ea 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "misskey", "author": "syuilo ", - "version": "11.1.5", + "version": "11.1.6", "codename": "daybreak", "repository": { "type": "git", diff --git a/src/mfm/language.ts b/src/mfm/language.ts index fc191d042..207400d6d 100644 --- a/src/mfm/language.ts +++ b/src/mfm/language.ts @@ -141,7 +141,7 @@ export const mfmLanguage = P.createLanguage({ }, hashtag: () => P((input, i) => { const text = input.substr(i); - const match = text.match(/^#([^\s\.,!\?'"#:\/\[\]]+)/i); + const match = text.match(/^#([^\s\.,!\?'"#:\/\[\]【】]+)/i); if (!match) return P.makeFailure(i, 'not a hashtag'); let hashtag = match[1]; hashtag = removeOrphanedBrackets(hashtag); diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index d684b47e4..1d2ce7a9c 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -182,6 +182,7 @@ export class NoteRepository extends Repository { files: DriveFiles.packMany(note.fileIds), replyId: note.replyId, renoteId: note.renoteId, + mentions: note.mentions.length > 0 ? note.mentions : undefined, uri: note.uri || undefined, ...(opts.detail ? { diff --git a/src/queue/processors/inbox.ts b/src/queue/processors/inbox.ts index 05fed0566..e65785950 100644 --- a/src/queue/processors/inbox.ts +++ b/src/queue/processors/inbox.ts @@ -1,6 +1,5 @@ import * as Bull from 'bull'; import * as httpSignature from 'http-signature'; -import parseAcct from '../../misc/acct/parse'; import { IRemoteUser } from '../../models/entities/user'; import perform from '../../remote/activitypub/perform'; import { resolvePerson, updatePerson } from '../../remote/activitypub/models/person'; @@ -12,7 +11,7 @@ import { Instances, Users, UserPublickeys } from '../../models'; import { instanceChart } from '../../services/chart'; import { UserPublickey } from '../../models/entities/user-publickey'; import fetchMeta from '../../misc/fetch-meta'; -import { toPuny, toPunyNullable } from '../../misc/convert-host'; +import { toPuny } from '../../misc/convert-host'; import { validActor } from '../../remote/activitypub/type'; import { ensure } from '../../prelude/ensure'; @@ -35,68 +34,49 @@ export default async (job: Bull.Job): Promise => { let key: UserPublickey; if (keyIdLower.startsWith('acct:')) { - const acct = parseAcct(keyIdLower.slice('acct:'.length)); - const host = toPunyNullable(acct.host); - const username = toPuny(acct.username); + logger.warn(`Old keyId is no longer supported. ${keyIdLower}`); + return; + } - if (host === null) { - logger.warn(`request was made by local user: @${username}`); - return; + // アクティビティ内のホストの検証 + const host = toPuny(new URL(signature.keyId).hostname); + try { + ValidateActivity(activity, host); + } catch (e) { + logger.warn(e.message); + return; + } + + // ブロックしてたら中断 + // TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく + const meta = await fetchMeta(); + if (meta.blockedHosts.includes(host)) { + logger.info(`Blocked request: ${host}`); + return; + } + + const _key = await UserPublickeys.findOne({ + keyId: signature.keyId + }); + + if (_key) { + // 登録済みユーザー + user = await Users.findOne(_key.userId) as IRemoteUser; + key = _key; + } else { + // 未登録ユーザーの場合はリモート解決 + user = await resolvePerson(activity.actor) as IRemoteUser; + if (user == null) { + throw new Error('failed to resolve user'); } - // アクティビティ内のホストの検証 - try { - ValidateActivity(activity, host); - } catch (e) { - logger.warn(e.message); - return; - } - - // ブロックしてたら中断 - // TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく - const meta = await fetchMeta(); - if (meta.blockedHosts.includes(host)) { - logger.info(`Blocked request: ${host}`); - return; - } - - user = await Users.findOne({ - usernameLower: username.toLowerCase(), - host: host - }) as IRemoteUser; - key = await UserPublickeys.findOne(user.id).then(ensure); - } else { - // アクティビティ内のホストの検証 - const host = toPuny(new URL(signature.keyId).hostname); - try { - ValidateActivity(activity, host); - } catch (e) { - logger.warn(e.message); - return; - } - - // ブロックしてたら中断 - // TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく - const meta = await fetchMeta(); - if (meta.blockedHosts.includes(host)) { - logger.info(`Blocked request: ${host}`); - return; - } - - key = await UserPublickeys.findOne({ - keyId: signature.keyId - }).then(ensure); - - user = await Users.findOne(key.userId) as IRemoteUser; } // Update Person activityの場合は、ここで署名検証/更新処理まで実施して終了 if (activity.type === 'Update') { if (activity.object && validActor.includes(activity.object.type)) { - if (user == null) { - logger.warn('Update activity received, but user not registed.'); - } else if (!httpSignature.verifySignature(signature, key.keyPem)) { + if (!httpSignature.verifySignature(signature, key.keyPem)) { logger.warn('Update activity received, but signature verification failed.'); } else { updatePerson(activity.actor, null, activity.object); @@ -105,15 +85,6 @@ export default async (job: Bull.Job): Promise => { } } - // アクティビティを送信してきたユーザーがまだMisskeyサーバーに登録されていなかったら登録する - if (user == null) { - user = await resolvePerson(activity.actor) as IRemoteUser; - } - - if (user == null) { - throw new Error('failed to resolve user'); - } - if (!httpSignature.verifySignature(signature, key.keyPem)) { logger.error('signature verification failed'); return; diff --git a/src/remote/activitypub/kernel/delete/index.ts b/src/remote/activitypub/kernel/delete/index.ts index fab5e7ab6..199a6a618 100644 --- a/src/remote/activitypub/kernel/delete/index.ts +++ b/src/remote/activitypub/kernel/delete/index.ts @@ -20,21 +20,21 @@ export default async (actor: IRemoteUser, activity: IDelete): Promise => { const uri = (object as any).id; switch (object.type) { - case 'Note': - case 'Question': - case 'Article': - deleteNote(actor, uri); - break; - - case 'Tombstone': - const note = await Notes.findOne({ uri }); - if (note != null) { + case 'Note': + case 'Question': + case 'Article': deleteNote(actor, uri); - } - break; + break; - default: - apLogger.warn(`Unknown type: ${object.type}`); - break; + case 'Tombstone': + const note = await Notes.findOne({ uri }); + if (note != null) { + deleteNote(actor, uri); + } + break; + + default: + apLogger.warn(`Unknown type: ${object.type}`); + break; } }; diff --git a/src/remote/activitypub/kernel/like.ts b/src/remote/activitypub/kernel/like.ts index a08b453a8..23b4aedd1 100644 --- a/src/remote/activitypub/kernel/like.ts +++ b/src/remote/activitypub/kernel/like.ts @@ -2,6 +2,7 @@ import { IRemoteUser } from '../../../models/entities/user'; import { ILike } from '../type'; import create from '../../../services/note/reaction/create'; import { Notes } from '../../../models'; +import { apLogger } from '../logger'; export default async (actor: IRemoteUser, activity: ILike) => { const id = typeof activity.object == 'string' ? activity.object : activity.object.id; @@ -14,7 +15,8 @@ export default async (actor: IRemoteUser, activity: ILike) => { const note = await Notes.findOne(noteId); if (note == null) { - throw new Error(); + apLogger.warn(`Like activity recivied, but no such note: ${id}`, { id }); + return; } await create(actor, note, activity._misskey_reaction); diff --git a/test/mfm.ts b/test/mfm.ts index 8098102e9..89b414eba 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -562,6 +562,14 @@ describe('MFM', () => { ]); }); + it('ignore 】', () => { + const tokens = parse('#foo】'); + assert.deepStrictEqual(tokens, [ + leaf('hashtag', { hashtag: 'foo' }), + text('】'), + ]); + }); + it('allow including number', () => { const tokens = parse('#foo123'); assert.deepStrictEqual(tokens, [