Merge branch 'develop'

This commit is contained in:
syuilo 2019-04-18 01:12:21 +09:00
commit c3ad1c62d1
20 changed files with 209 additions and 134 deletions

View File

@ -5,6 +5,14 @@ If you encounter any problems with updating, please try the following:
1. `npm run clean` or `npm run cleanall` 1. `npm run clean` or `npm run cleanall`
2. Retry update (Don't forget `npm i`) 2. Retry update (Don't forget `npm i`)
11.1.6 (2019/04/18)
-------------------
### Fixes
* 未認知ユーザーからActivityが飛んできた場合に処理できない問題を修正
* その投稿を見たのにも関わらずメンションインジケーターが点灯し続ける問題を修正
* ハッシュタグの判定を改善
* サーバーのエラーハンドリングを改善
11.1.5 (2019/04/17) 11.1.5 (2019/04/17)
------------------- -------------------
### Fixes ### Fixes

View File

@ -21,12 +21,11 @@ RUN apk add --no-cache \
pkgconfig \ pkgconfig \
python \ python \
zlib-dev zlib-dev
RUN npm i -g yarn
COPY package.json ./ COPY package.json ./
RUN yarn install RUN npm i
COPY . ./ COPY . ./
RUN yarn build RUN npm run build
FROM base AS runner FROM base AS runner

View File

@ -70,8 +70,14 @@ common:
followers: "Sledující" followers: "Sledující"
favorites: "Oblíbené" favorites: "Oblíbené"
permissions: permissions:
'read:drive': "Prohlížet Disk" "read:account": "Zobrazit informace o účtu"
'write:drive': "Pracovat s Diskem" "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: empty-timeline-info:
follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose" follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose"
explore: "Najít uživatele" explore: "Najít uživatele"
@ -1114,7 +1120,7 @@ mobile/views/components/post-form.vue:
reply: "Odpovědět" reply: "Odpovědět"
renote: "Renotovat" renote: "Renotovat"
reply-placeholder: "Odpovědět na tento příspěvěk" 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" error: "Chyba"
username-prompt: "Zadejte uživatelské jméno" username-prompt: "Zadejte uživatelské jméno"
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:
@ -1185,4 +1191,3 @@ deck/deck.user-column.vue:
activity: "Aktivita" activity: "Aktivita"
dev/views/new-app.vue: dev/views/new-app.vue:
app-name-desc: "Jméno vaší aplikace" app-name-desc: "Jméno vaší aplikace"
app-desc: "Stručný popis nebo představení vaší aplikace."

View File

@ -62,10 +62,14 @@ common:
followers: "Folgende" followers: "Folgende"
favorites: "Diesen Beitrag favorisieren" favorites: "Diesen Beitrag favorisieren"
permissions: permissions:
'read:account': "Accountinformationen anzeigen." "read:account": "Accountinformationen anzeigen."
'write:account': "Accountinformationen bearbeiten." "write:account": "Accountinformationen bearbeiten."
'read:drive': "Dateien anzeigen" "read:drive": "Dateien anzeigen"
'write:drive': "Dateien bearbeiten" "write:drive": "Dateien bearbeiten"
"read:favorites": "Favoriten anzeigen"
"read:messaging": "Unterhaltung anzeigen"
"write:messaging": "Unterhaltung bearbeiten"
"write:votes": "Abstimmen"
empty-timeline-info: empty-timeline-info:
follow-users-to-make-your-timeline: "Beiträge von Benutzern, denen du folgst, werden in der Zeitleiste angezeigt." follow-users-to-make-your-timeline: "Beiträge von Benutzern, denen du folgst, werden in der Zeitleiste angezeigt."
explore: "Benutzer finden" explore: "Benutzer finden"
@ -739,10 +743,7 @@ dev/views/new-app.vue:
create-app: "Erstelle Anwendung" create-app: "Erstelle Anwendung"
app-name: "Name der Anwendung" app-name: "Name der Anwendung"
app-name-desc: "Der 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-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: "Callback-URL (optional)"
callback-url-desc: "Die URL, auf die nach erfolgreicher Authentifizierung umgeleitet werden soll." callback-url-desc: "Die URL, auf die nach erfolgreicher Authentifizierung umgeleitet werden soll."
authority: "Berechtigungen" authority: "Berechtigungen"

View File

@ -70,10 +70,21 @@ common:
followers: "Followers" followers: "Followers"
favorites: "Favorites" favorites: "Favorites"
permissions: permissions:
'read:account': "View account information" "read:account": "View account information"
'write:account': "Update your account information" "write:account": "Update your account information"
'read:drive': "Browse the Drive" "read:blocks": "View Blocks"
'write:drive': "Work with the Drive" "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: empty-timeline-info:
follow-users-to-make-your-timeline: "Following users will show their posts in your timeline." follow-users-to-make-your-timeline: "Following users will show their posts in your timeline."
explore: "Find users" explore: "Find users"
@ -281,6 +292,7 @@ common:
nav: "Navigation" nav: "Navigation"
tips: "Tips" tips: "Tips"
hashtags: "Hashtags" hashtags: "Hashtags"
queue: "Queue"
dev: "Failed to create the application. Please try again." dev: "Failed to create the application. Please try again."
ai-chan-kawaii: "Ai-chan kawaii!" ai-chan-kawaii: "Ai-chan kawaii!"
you: "You" you: "You"
@ -1462,7 +1474,7 @@ mobile/views/components/post-form.vue:
quote-placeholder: "Quote this post... (optional)" quote-placeholder: "Quote this post... (optional)"
reply-placeholder: "Reply to this note..." reply-placeholder: "Reply to this note..."
cw-placeholder: "Comments for the post (optional)" 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" error: "Error"
username-prompt: "Enter user name" username-prompt: "Enter user name"
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:
@ -1615,10 +1627,7 @@ dev/views/new-app.vue:
create-app: "Creating application" create-app: "Creating application"
app-name: "Application name" app-name: "Application name"
app-name-desc: "The name of your app" app-name-desc: "The name of your app"
app-name-ex: "ex) Misskey for iOS"
app-overview: "Application summary" 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: "The callback URL (optional)"
callback-url-desc: "The URL to redirect to after the user is authenticated via the authentication form." callback-url-desc: "The URL to redirect to after the user is authenticated via the authentication form."
authority: "Permissions" authority: "Permissions"

View File

@ -20,8 +20,15 @@ common:
application-authorization: "Autorizaciones de la aplicación." application-authorization: "Autorizaciones de la aplicación."
close: "Cerrar" close: "Cerrar"
do-not-copy-paste: "Por favor no copies código aquí. Tu cuenta puede resultar comprometida." 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" enter-password: "Escribe una contraseña"
2fa: "Autenticación de dos factores" 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!" got-it: "¡Listo!"
customization-tips: customization-tips:
title: "Consejos de personalización" title: "Consejos de personalización"
@ -50,8 +57,22 @@ common:
drive: "Drive" drive: "Drive"
messaging: "Conversación" messaging: "Conversación"
home: "Inicio" home: "Inicio"
deck: "Deck"
timeline: "Timeline"
explore: "Explorar"
following: "Siguiendo" following: "Siguiendo"
followers: "Seguidores"
favorites: "Me gusta esta nota" 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: weekday-short:
sunday: "domingo" sunday: "domingo"
monday: "lunes" monday: "lunes"
@ -97,12 +118,24 @@ common:
d: "¿Quieres decir algo?" d: "¿Quieres decir algo?"
e: "¡Escribe aquí!" e: "¡Escribe aquí!"
f: "Esperando a que escribas algo..." f: "Esperando a que escribas algo..."
settings: "Configuración"
_settings: _settings:
profile: "Tu perfil" profile: "Tu perfil"
notification: "Notificaciones" notification: "Notificaciones"
apps: "Aplicaciones"
tags: "Etiquetas" tags: "Etiquetas"
mute-and-block: "Silenciar/Bloquear"
blocking: "Bloquear" blocking: "Bloquear"
security: "Seguridad"
password: "Contraseña" 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" use-os-default-emojis: "Usar los emoticonos estándar del sistema operativo"
line-width: "Grosor de línea" line-width: "Grosor de línea"
line-width-thick: "Grosor" line-width-thick: "Grosor"
@ -128,6 +161,19 @@ common:
contrasted-acct: "Añadir contraste al nombre de usuario" contrasted-acct: "Añadir contraste al nombre de usuario"
wallpaper: "Fondo de pantalla" wallpaper: "Fondo de pantalla"
choose-wallpaper: "Escoge un 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" navbar-position-left: "Izquierda"
search: "Buscar" search: "Buscar"
delete: "eliminar" delete: "eliminar"
@ -869,6 +915,7 @@ mobile/views/components/post-form.vue:
reply: "Responder" reply: "Responder"
renote: "Republicar" renote: "Republicar"
reply-placeholder: "Responder a esta nota..." reply-placeholder: "Responder a esta nota..."
geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización."
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:
private: "Esta publicación es privada" private: "Esta publicación es privada"
deleted: "Esta publicación ha sido removida" deleted: "Esta publicación ha sido removida"

View File

@ -68,10 +68,11 @@ common:
followers: "Abonné·e·s" followers: "Abonné·e·s"
favorites: "Mettre cette note en favoris" favorites: "Mettre cette note en favoris"
permissions: permissions:
'read:account': "Afficher les informations du compte" "read:account": "Afficher les informations du compte"
'write:account': "Mettre à jour les informations de votre compte" "write:account": "Mettre à jour les informations de votre compte"
'read:drive': "Parcourir le Drive" "read:drive": "Parcourir le Drive"
'write:drive': "Écrire sur le Drive" "write:drive": "Écrire sur le Drive"
"write:votes": "Vote"
empty-timeline-info: empty-timeline-info:
follow-users-to-make-your-timeline: "Les utilisateurs suivants afficheront leurs publications sur votre fil." follow-users-to-make-your-timeline: "Les utilisateurs suivants afficheront leurs publications sur votre fil."
explore: "Trouver des utilisateurs" explore: "Trouver des utilisateurs"
@ -274,6 +275,7 @@ common:
nav: "Navigation" nav: "Navigation"
tips: "Conseils" tips: "Conseils"
hashtags: "Hashtags" hashtags: "Hashtags"
queue: "File d'attente"
dev: "Échec lors de la création de lapplication. Veuillez réessayer." dev: "Échec lors de la création de lapplication. Veuillez réessayer."
ai-chan-kawaii: "Ai-Chan est mignonne !" ai-chan-kawaii: "Ai-Chan est mignonne !"
you: "Vous" you: "Vous"
@ -1434,7 +1436,7 @@ mobile/views/components/post-form.vue:
quote-placeholder: "Citer ce billet ... (Facultatif)" quote-placeholder: "Citer ce billet ... (Facultatif)"
reply-placeholder: "Répondre à cette note" reply-placeholder: "Répondre à cette note"
cw-placeholder: "Commenter le contenu (optionnel)" 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" error: "Erreur"
username-prompt: "Saisir un nom d'utilisateur" username-prompt: "Saisir un nom d'utilisateur"
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:
@ -1586,10 +1588,7 @@ dev/views/new-app.vue:
create-app: "Création dune application" create-app: "Création dune application"
app-name: "Nom de lapplication" app-name: "Nom de lapplication"
app-name-desc: "Le nom de votre application" app-name-desc: "Le nom de votre application"
app-name-ex: "p. ex. Misskey pour iOS"
app-overview: "Description courte de lapplication" app-overview: "Description courte de lapplication"
app-desc: "Brève description introductive à votre application."
app-desc-ex: "p. ex) Misskey pour iOS"
callback-url: "LUrl de callback (facultatif)" callback-url: "LUrl de callback (facultatif)"
callback-url-desc: "Vous pouvez définir lURL de redirection lorsque lutilisateur sest authentifié via formulaire dauthentification." callback-url-desc: "Vous pouvez définir lURL de redirection lorsque lutilisateur sest authentifié via formulaire dauthentification."
authority: "Autorisations " authority: "Autorisations "

View File

@ -60,6 +60,8 @@ common:
following: "フォローしとる" following: "フォローしとる"
followers: "フォロワー" followers: "フォロワー"
favorites: "お気に入り" favorites: "お気に入り"
permissions:
"write:votes": "投票するで"
weekday-short: weekday-short:
sunday: "日" sunday: "日"
monday: "月" monday: "月"
@ -1126,7 +1128,7 @@ mobile/views/components/post-form.vue:
quote-placeholder: "この投稿を持ってくる(オプション)" quote-placeholder: "この投稿を持ってくる(オプション)"
reply-placeholder: "この投稿への返信..." reply-placeholder: "この投稿への返信..."
cw-placeholder: "内容への注釈 (オプション)" cw-placeholder: "内容への注釈 (オプション)"
location-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。" geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
error: "エラー" error: "エラー"
username-prompt: "ユーザー名を入力してや" username-prompt: "ユーザー名を入力してや"
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:
@ -1272,10 +1274,7 @@ dev/views/new-app.vue:
create-app: "アプリケーション作る" create-app: "アプリケーション作る"
app-name: "アプリケーションの名前" app-name: "アプリケーションの名前"
app-name-desc: "あんたのアプリの名前。" app-name-desc: "あんたのアプリの名前。"
app-name-ex: "ex) 関西ミスキー保安協会"
app-overview: "このアプリどんなん?" app-overview: "このアプリどんなん?"
app-desc: "あんたのアプリどんなんか教えて"
app-desc-ex: "ex) 関西人なら誰でも口ずさめるこのCMがついにMisskeyへ。"
callback-url: "コールバックURL (無くてもええで)" callback-url: "コールバックURL (無くてもええで)"
callback-url-desc: "ユーザーが認証フォームで認証した後どこに連れてくかを設定できるで" callback-url-desc: "ユーザーが認証フォームで認証した後どこに連れてくかを設定できるで"
authority: "権限" authority: "権限"

View File

@ -70,10 +70,11 @@ common:
followers: "팔로워" followers: "팔로워"
favorites: "즐겨찾기" favorites: "즐겨찾기"
permissions: permissions:
'read:account': "계정 정보 보기" "read:account": "계정 정보 보기"
'write:account': "계정 정보 변경" "write:account": "계정 정보 변경"
'read:drive': "드라이브 보기" "read:drive": "드라이브 보기"
'write:drive': "드라이브 수정" "write:drive": "드라이브 수정"
"write:votes": "투표하기"
empty-timeline-info: empty-timeline-info:
follow-users-to-make-your-timeline: "사용자를 팔로우하면 글이 타임라인에 표시됩니다." follow-users-to-make-your-timeline: "사용자를 팔로우하면 글이 타임라인에 표시됩니다."
explore: "사용자 탐색" explore: "사용자 탐색"
@ -281,6 +282,7 @@ common:
nav: "내비게이션" nav: "내비게이션"
tips: "팁" tips: "팁"
hashtags: "해시태그" hashtags: "해시태그"
queue: "큐"
dev: "앱을 만드는 데 실패했습니다. 다시 시도하시기 바랍니다." dev: "앱을 만드는 데 실패했습니다. 다시 시도하시기 바랍니다."
ai-chan-kawaii: "아이쨩 귀여워" ai-chan-kawaii: "아이쨩 귀여워"
you: "당신" you: "당신"
@ -1462,7 +1464,7 @@ mobile/views/components/post-form.vue:
quote-placeholder: "이 글을 인용... (선택적)" quote-placeholder: "이 글을 인용... (선택적)"
reply-placeholder: "이 글에 답글..." reply-placeholder: "이 글에 답글..."
cw-placeholder: "내용 주석 (선택적)" cw-placeholder: "내용 주석 (선택적)"
location-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다" geolocation-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다"
error: "오류" error: "오류"
username-prompt: "사용자명을 입력하여 주십시오" username-prompt: "사용자명을 입력하여 주십시오"
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:
@ -1615,10 +1617,7 @@ dev/views/new-app.vue:
create-app: "어플리케이션 생성" create-app: "어플리케이션 생성"
app-name: "어플리케이션 이름" app-name: "어플리케이션 이름"
app-name-desc: "앱의 이름." app-name-desc: "앱의 이름."
app-name-ex: "ex) Misskey for iOS"
app-overview: "앱 개요" app-overview: "앱 개요"
app-desc: "어플리케이션에 대한 간단한 설명."
app-desc-ex: "ex) Misskey iOS 클라이언트."
callback-url: "콜백 URL (옵션)" callback-url: "콜백 URL (옵션)"
callback-url-desc: "사용자가 인증 폼에서 인증한 뒤 리다이렉트할 URL을 설정합니다." callback-url-desc: "사용자가 인증 폼에서 인증한 뒤 리다이렉트할 URL을 설정합니다."
authority: "권한" authority: "권한"

View File

@ -23,6 +23,8 @@ common:
timeline: "Tijdlijn" timeline: "Tijdlijn"
followers: "Volgers" followers: "Volgers"
favorites: "Deze notitie toevoegen aan favorieten" favorites: "Deze notitie toevoegen aan favorieten"
permissions:
"write:votes": "Stemmen"
weekday-short: weekday-short:
sunday: "Z" sunday: "Z"
monday: "M" monday: "M"

View File

@ -37,6 +37,8 @@ common:
home: "Hjem" home: "Hjem"
followers: "Følgere" followers: "Følgere"
favorites: "Merket som favoritt" favorites: "Merket som favoritt"
permissions:
"write:votes": "Stem"
weekday-short: weekday-short:
sunday: "S" sunday: "S"
monday: "M" monday: "M"

View File

@ -63,7 +63,8 @@ common:
followers: "Śledzący" followers: "Śledzący"
favorites: "Moje ulubione" favorites: "Moje ulubione"
permissions: permissions:
'read:drive': "Wyświetl dysk" "read:drive": "Wyświetl dysk"
"write:votes": "Zagłosuj"
empty-timeline-info: empty-timeline-info:
explore: "Poznaj" explore: "Poznaj"
weekday-short: weekday-short:
@ -1082,7 +1083,7 @@ mobile/views/components/post-form.vue:
quote-placeholder: "Zacytuj ten wpis… (nieobowiązkowe)" quote-placeholder: "Zacytuj ten wpis… (nieobowiązkowe)"
reply-placeholder: "Odpowiedź na ten wpis…" reply-placeholder: "Odpowiedź na ten wpis…"
cw-placeholder: "Treść ostrzeżenia (opcjonalnie)" 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" error: "Błąd"
username-prompt: "Wprowadź nazwę użytkownika" username-prompt: "Wprowadź nazwę użytkownika"
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:

View File

@ -70,10 +70,26 @@ common:
followers: "关注者" followers: "关注者"
favorites: "最爱" favorites: "最爱"
permissions: permissions:
'read:account': "查看账户信息" "read:account": "查看账户信息"
'write:account': "更改我的帐户信息" "write:account": "更改我的帐户信息"
'read:drive': "查看网盘" "read:blocks": "查看黑名单"
'write:drive': "管理网盘文件" "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: empty-timeline-info:
follow-users-to-make-your-timeline: "关注其他用户时,帖子将显示在时间线中。" follow-users-to-make-your-timeline: "关注其他用户时,帖子将显示在时间线中。"
explore: "查找用户" explore: "查找用户"
@ -129,7 +145,7 @@ common:
apps: "应用程序" apps: "应用程序"
tags: "标签" tags: "标签"
mute-and-block: "屏蔽/拉黑" mute-and-block: "屏蔽/拉黑"
blocking: "屏蔽" blocking: "拉黑"
security: "安全性" security: "安全性"
signin: "登录历史" signin: "登录历史"
password: "密码" password: "密码"
@ -281,6 +297,7 @@ common:
nav: "导航" nav: "导航"
tips: "提示" tips: "提示"
hashtags: "标签" hashtags: "标签"
queue: "队列"
dev: "构建应用程序失败,请再试一次。" dev: "构建应用程序失败,请再试一次。"
ai-chan-kawaii: "小蓝真可爱" ai-chan-kawaii: "小蓝真可爱"
you: "您" you: "您"
@ -966,6 +983,7 @@ common/views/components/password-settings.vue:
changed: "密码已更改" changed: "密码已更改"
failed: "更改密码失败" failed: "更改密码失败"
common/views/components/post-form-attaches.vue: common/views/components/post-form-attaches.vue:
attach-cancel: "删除附件"
mark-as-sensitive: "标记为“敏感”" mark-as-sensitive: "标记为“敏感”"
unmark-as-sensitive: "取消标记为“敏感”" unmark-as-sensitive: "取消标记为“敏感”"
desktop/views/components/sub-note-content.vue: desktop/views/components/sub-note-content.vue:
@ -1385,6 +1403,7 @@ desktop/views/widgets/polls.vue:
desktop/views/widgets/post-form.vue: desktop/views/widgets/post-form.vue:
title: "帖子" title: "帖子"
note: "帖子" note: "帖子"
something-happened: "由于某种原因无法发帖。"
desktop/views/widgets/profile.vue: desktop/views/widgets/profile.vue:
update-banner: "点击来剪辑背景" update-banner: "点击来剪辑背景"
update-avatar: "点击来剪辑头像" update-avatar: "点击来剪辑头像"
@ -1461,7 +1480,7 @@ mobile/views/components/post-form.vue:
quote-placeholder: "引用这个帖子t... (可选)" quote-placeholder: "引用这个帖子t... (可选)"
reply-placeholder: "回复这个帖子" reply-placeholder: "回复这个帖子"
cw-placeholder: "评论帖子(可选)" cw-placeholder: "评论帖子(可选)"
location-alert: "您的设备不提供位服务" geolocation-alert: "您的设备不提供服务"
error: "错误" error: "错误"
username-prompt: "请输入用户名" username-prompt: "请输入用户名"
mobile/views/components/sub-note-content.vue: mobile/views/components/sub-note-content.vue:
@ -1611,14 +1630,17 @@ dev/views/apps.vue:
create-app: "创建应用" create-app: "创建应用"
app-missing: "没有应用" app-missing: "没有应用"
dev/views/new-app.vue: dev/views/new-app.vue:
new-app: "新应用"
new-app-info: "可以从 API 中创建应用。 (app/create)"
create-app: "正在创建应用" create-app: "正在创建应用"
app-name: "应用名称" app-name: "应用名称"
app-name-placeholder: "ex) iOS版Misskey"
app-name-desc: "您应用的名称" app-name-desc: "您应用的名称"
app-name-ex: "ex) iOS版本的Misskey"
app-overview: "应用摘要" app-overview: "应用摘要"
app-desc: "您的应用的简要说明或介绍。" app-overview-placeholder: " ex) iOS版Misskey客户端."
app-desc-ex: "ex) iOS版Misskey客户端." app-overview-desc: "您的应用的简要说明或介绍。"
callback-url: "回应URL (optional)" callback-url: "回应URL (optional)"
callback-url-placeholder: "ex) https://your.app.example.com/callback.php"
callback-url-desc: "通过身份验证表单对用户进行身份验证后重定向到的URL。" callback-url-desc: "通过身份验证表单对用户进行身份验证后重定向到的URL。"
authority: "权限" authority: "权限"
authority-desc: "只能通过API访问此处请求的功能。" authority-desc: "只能通过API访问此处请求的功能。"

View File

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "11.1.5", "version": "11.1.6",
"codename": "daybreak", "codename": "daybreak",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -141,7 +141,7 @@ export const mfmLanguage = P.createLanguage({
}, },
hashtag: () => P((input, i) => { hashtag: () => P((input, i) => {
const text = input.substr(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'); if (!match) return P.makeFailure(i, 'not a hashtag');
let hashtag = match[1]; let hashtag = match[1];
hashtag = removeOrphanedBrackets(hashtag); hashtag = removeOrphanedBrackets(hashtag);

View File

@ -182,6 +182,7 @@ export class NoteRepository extends Repository<Note> {
files: DriveFiles.packMany(note.fileIds), files: DriveFiles.packMany(note.fileIds),
replyId: note.replyId, replyId: note.replyId,
renoteId: note.renoteId, renoteId: note.renoteId,
mentions: note.mentions.length > 0 ? note.mentions : undefined,
uri: note.uri || undefined, uri: note.uri || undefined,
...(opts.detail ? { ...(opts.detail ? {

View File

@ -1,6 +1,5 @@
import * as Bull from 'bull'; import * as Bull from 'bull';
import * as httpSignature from 'http-signature'; import * as httpSignature from 'http-signature';
import parseAcct from '../../misc/acct/parse';
import { IRemoteUser } from '../../models/entities/user'; import { IRemoteUser } from '../../models/entities/user';
import perform from '../../remote/activitypub/perform'; import perform from '../../remote/activitypub/perform';
import { resolvePerson, updatePerson } from '../../remote/activitypub/models/person'; import { resolvePerson, updatePerson } from '../../remote/activitypub/models/person';
@ -12,7 +11,7 @@ import { Instances, Users, UserPublickeys } from '../../models';
import { instanceChart } from '../../services/chart'; import { instanceChart } from '../../services/chart';
import { UserPublickey } from '../../models/entities/user-publickey'; import { UserPublickey } from '../../models/entities/user-publickey';
import fetchMeta from '../../misc/fetch-meta'; 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 { validActor } from '../../remote/activitypub/type';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
@ -35,38 +34,10 @@ export default async (job: Bull.Job): Promise<void> => {
let key: UserPublickey; let key: UserPublickey;
if (keyIdLower.startsWith('acct:')) { if (keyIdLower.startsWith('acct:')) {
const acct = parseAcct(keyIdLower.slice('acct:'.length)); logger.warn(`Old keyId is no longer supported. ${keyIdLower}`);
const host = toPunyNullable(acct.host);
const username = toPuny(acct.username);
if (host === null) {
logger.warn(`request was made by local user: @${username}`);
return; return;
} }
// アクティビティ内のホストの検証
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); const host = toPuny(new URL(signature.keyId).hostname);
try { try {
@ -84,19 +55,28 @@ export default async (job: Bull.Job): Promise<void> => {
return; return;
} }
key = await UserPublickeys.findOne({ const _key = await UserPublickeys.findOne({
keyId: signature.keyId keyId: signature.keyId
}).then(ensure); });
user = await Users.findOne(key.userId) as IRemoteUser; 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');
}
key = await UserPublickeys.findOne(user.id).then(ensure);
} }
// Update Person activityの場合は、ここで署名検証/更新処理まで実施して終了 // Update Person activityの場合は、ここで署名検証/更新処理まで実施して終了
if (activity.type === 'Update') { if (activity.type === 'Update') {
if (activity.object && validActor.includes(activity.object.type)) { if (activity.object && validActor.includes(activity.object.type)) {
if (user == null) { if (!httpSignature.verifySignature(signature, key.keyPem)) {
logger.warn('Update activity received, but user not registed.');
} else if (!httpSignature.verifySignature(signature, key.keyPem)) {
logger.warn('Update activity received, but signature verification failed.'); logger.warn('Update activity received, but signature verification failed.');
} else { } else {
updatePerson(activity.actor, null, activity.object); updatePerson(activity.actor, null, activity.object);
@ -105,15 +85,6 @@ export default async (job: Bull.Job): Promise<void> => {
} }
} }
// アクティビティを送信してきたユーザーがまだ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)) { if (!httpSignature.verifySignature(signature, key.keyPem)) {
logger.error('signature verification failed'); logger.error('signature verification failed');
return; return;

View File

@ -2,6 +2,7 @@ import { IRemoteUser } from '../../../models/entities/user';
import { ILike } from '../type'; import { ILike } from '../type';
import create from '../../../services/note/reaction/create'; import create from '../../../services/note/reaction/create';
import { Notes } from '../../../models'; import { Notes } from '../../../models';
import { apLogger } from '../logger';
export default async (actor: IRemoteUser, activity: ILike) => { export default async (actor: IRemoteUser, activity: ILike) => {
const id = typeof activity.object == 'string' ? activity.object : activity.object.id; 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); const note = await Notes.findOne(noteId);
if (note == null) { 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); await create(actor, note, activity._misskey_reaction);

View File

@ -562,6 +562,14 @@ describe('MFM', () => {
]); ]);
}); });
it('ignore 】', () => {
const tokens = parse('#foo】');
assert.deepStrictEqual(tokens, [
leaf('hashtag', { hashtag: 'foo' }),
text('】'),
]);
});
it('allow including number', () => { it('allow including number', () => {
const tokens = parse('#foo123'); const tokens = parse('#foo123');
assert.deepStrictEqual(tokens, [ assert.deepStrictEqual(tokens, [