diff --git a/CHANGELOG.md b/CHANGELOG.md index 78caef3252..5247f5b05c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ You should also include the user name that made the change. ## 13.0.0 (unreleased) ### TL;DR -- New features (Play, new widgets, new charts, etc) +- New features (Play, new widgets, new charts, 🍪👈, etc) - Rewriten backend - Better performance (backend and frontend) - Various usability improvements @@ -30,6 +30,7 @@ You should also include the user name that made the change. #### For users - ノートのウォッチ機能が削除されました +- アンケートに投票された際に通知が作成されなくなりました - 新たに動的なPagesを作ることはできなくなりました - 代わりにAiScriptを用いてより柔軟に動的なコンテンツを作成できるMisskey Play機能が実装されています。 - AiScriptが0.12.2にアップデートされました @@ -39,6 +40,8 @@ You should also include the user name that made the change. - Firefox109以下はサポートされなくなりました #### For app developers +- API: metaのレスポンスに`emojis`プロパティが含まれなくなりました + - カスタム絵文字一覧情報を取得するには、`emojis`エンドポイントにリクエストします - API: カスタム絵文字エンティティに`url`プロパティが含まれなくなりました - 絵文字画像を表示するには、`/emoji/.webp`にリクエストすると画像が返ります。 - e.g. `https://p1.a9z.dev/emoji/misskey.webp` @@ -77,13 +80,17 @@ You should also include the user name that made the change. - Client: Improve RSS widget @tamaina - Client: show Unicode emoji tooltip with its name in MkReactionsViewer.reaction @saschanaz - Client: OpenSearch support @SoniEx2 @chaoticryptidz +- Client: Support remote objects in search @SoniEx2 +- Client: user activity page @syuilo - Client: add user list widget @syuilo - Client: add heatmap of daily active users to about page @syuilo - Client: introduce fluent emoji @syuilo +- Client: add new theme @syuilo - Client: show fireworks when visit user who today is birthday @syuilo - Client: show bot warning on screen when logged in as bot account @syuilo - Client: improve overall performance of client @syuilo - Client: ui tweaks @syuilo +- Client: clicker game @syuilo ### Bugfixes - Server: 引用内の文章がnyaizeされてしまう問題を修正 @kabo2468 @@ -94,6 +101,11 @@ You should also include the user name that made the change. - Server: アンテナの作成数上限を追加 @syuilo - Server: pages/likeのエラーIDが重複しているのを修正 @syuilo - Server: pages/updateのパラメータによってはsummaryの値が更新されないのを修正 @syuilo +- Server: Escape SQL LIKE @mei23 +- Server: 特定のPNG画像のアップロードに失敗する問題を修正 @usbharu +- Server: 非公開のクリップのURLでOGPレンダリングされる問題を修正 @syuilo +- Server: アンテナタイムライン(ストリーミング)が、フォローしていないユーザーの鍵投稿も拾ってしまう @syuilo +- Client: 日付形式の文字列などがカスタム絵文字として表示されるのを修正 @syuilo - Client: case insensitive emoji search @saschanaz - Client: InAppウィンドウが操作できなくなることがあるのを修正 @tamaina - Client: use proxied image for instance icon @syuilo diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 161a393bc2..773e239812 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -1294,7 +1294,6 @@ _notification: youGotReply: "ردّ عليك {name}" youGotQuote: "اقتبس منك {name}" youRenoted: "إعادت نشر من {name}" - youGotPoll: "شارك {name} في استطلاع الرأي" youGotMessagingMessageFromUser: "لقد تلقيت رسالة مِن {name}" youGotMessagingMessageFromGroup: "لقد أرسِلَت رسالة إلى الفريق {name}" youWereFollowed: "يتابعك" @@ -1311,7 +1310,6 @@ _notification: renote: "أعد النشر" quote: "الاقتباسات" reaction: "التفاعلات" - pollVote: "مصوِت شارك في الاستطلاع" receiveFollowRequest: "طلبات المتابعة المتلقاة" followRequestAccepted: "طلبات المتابعة المقبولة" groupInvited: "دعوات الفريق" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index 593cbb1b32..ac0a0e1a51 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -1386,7 +1386,6 @@ _notification: youGotReply: "{name} আপনাকে জবাব দিয়েছে" youGotQuote: "{name} আপনাকে উদ্ধৃত করেছে" youRenoted: "{name} এর Renote" - youGotPoll: "{name} আপনার পোলে ভোট দিয়েছে" youGotMessagingMessageFromUser: "{name} আপনাকে মেসেজ করেছে" youGotMessagingMessageFromGroup: "{name} গ্রুপে একটি নতুন মেসেজ আছে" youWereFollowed: "আপনাকে অনুসরণ করছে" @@ -1403,7 +1402,6 @@ _notification: renote: "রিনোট" quote: "উদ্ধৃতি" reaction: "প্রতিক্রিয়া" - pollVote: "পোলে ভোট আছে" pollEnded: "পোল শেষ" receiveFollowRequest: "প্রাপ্ত অনুসরণের অনুরোধসমূহ" followRequestAccepted: "গৃহীত অনুসরণের অনুরোধসমূহ" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index db6bd9ab05..70d0acc264 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -920,6 +920,10 @@ like: "Gefällt mir" unlike: "\"Gefällt mir\" entfernen" numberOfLikes: "\"Gefällt mir\"-Anzahl" show: "Anzeigen" +neverShow: "Nicht wieder anzeigen" +remindMeLater: "Vielleicht später" +didYouLikeMisskey: "Gefällt dir Misskey?" +pleaseDonate: "Misskey ist die kostenlose Software, die von {host} verwendet wird. Wir würden uns über Spenden freuen, damit dessen Entwicklung weitergeführt werden kann!" _sensitiveMediaDetection: description: "Ermöglicht eine Erleichterung der Servermoderation durch die automatische Erkennungen von NSFW-Medien unter Verwendung von Machine Learning. Hierdurch wird die Serverlast etwas erhöht." sensitivity: "Erkennungssensitivität" @@ -1324,6 +1328,7 @@ _widgets: userList: "Benutzerliste" _userList: chooseList: "Liste auswählen" + clicker: "Klickzähler" _cw: hide: "Inhalt verbergen" show: "Inhalt anzeigen" @@ -1499,7 +1504,6 @@ _notification: youGotReply: "{name} hat dir geantwortet" youGotQuote: "{name} hat dich zitiert" youRenoted: "Renote deiner Notiz von {name}" - youGotPoll: "{name} hat in deiner Umfrage abgestimmt" youGotMessagingMessageFromUser: "{name} hat dir eine Chatnachricht gesendet" youGotMessagingMessageFromGroup: "In die Gruppe {name} wurde eine Chatnachricht gesendet" youWereFollowed: "ist dir gefolgt" @@ -1517,7 +1521,6 @@ _notification: renote: "Renotes" quote: "Zitationen" reaction: "Reaktionen" - pollVote: "Antworten auf Umfragen" pollEnded: "Ende von Umfragen" receiveFollowRequest: "Erhaltene Follow-Anfragen" followRequestAccepted: "Akzeptierte Follow-Anfragen" diff --git a/locales/en-US.yml b/locales/en-US.yml index e2a7b32be8..ef42a8b97d 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -920,6 +920,10 @@ like: "Like" unlike: "Unlike" numberOfLikes: "Likes" show: "Show" +neverShow: "Don't show again" +remindMeLater: "Maybe later" +didYouLikeMisskey: "Have you taken a liking to Misskey?" +pleaseDonate: "{host} uses the free software, Misskey. We would highly appreciate your donations so development of Misskey can continue!" _sensitiveMediaDetection: description: "Reduces the effort of server moderation through automatically recognizing NSFW media via Machine Learning. This will slightly increase the load on the server." sensitivity: "Detection sensitivity" @@ -1324,6 +1328,7 @@ _widgets: userList: "User list" _userList: chooseList: "Select a list" + clicker: "Clicker" _cw: hide: "Hide" show: "Show content" @@ -1499,7 +1504,6 @@ _notification: youGotReply: "{name} replied to you" youGotQuote: "{name} quoted you" youRenoted: "Renote from {name}" - youGotPoll: "{name} voted on your poll" youGotMessagingMessageFromUser: "{name} sent you a chat message" youGotMessagingMessageFromGroup: "A chat message was sent to the {name} group" youWereFollowed: "followed you" @@ -1517,7 +1521,6 @@ _notification: renote: "Renotes" quote: "Quotes" reaction: "Reactions" - pollVote: "Votes on polls" pollEnded: "Polls ending" receiveFollowRequest: "Received follow requests" followRequestAccepted: "Accepted follow requests" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index c328737c4b..5e48fb6d31 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -1487,7 +1487,6 @@ _notification: youGotReply: "Respuesta de {name}" youGotQuote: "Citado por {name}" youRenoted: "Renotado por {name}" - youGotPoll: "Encuestado por {name}" youGotMessagingMessageFromUser: "{name} comenzó un chat contigo" youGotMessagingMessageFromGroup: "Tienes un chat de {name}" youWereFollowed: "te ha seguido" @@ -1505,7 +1504,6 @@ _notification: renote: "Renotar" quote: "Citar" reaction: "Reacción" - pollVote: "Votado en la encuesta" pollEnded: "La encuesta terminó" receiveFollowRequest: "Recibió una solicitud de seguimiento" followRequestAccepted: "El seguimiento fue aceptado" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 0d7399533d..8c777ab513 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -1478,7 +1478,6 @@ _notification: youGotReply: "Réponse de {name}" youGotQuote: "Cité·e par {name}" youRenoted: "{name} vous a Renoté" - youGotPoll: "{name} a participé à votre sondage" youGotMessagingMessageFromUser: "{name} vous envoyé un message" youGotMessagingMessageFromGroup: "Un message a été envoyé au groupe {name}" youWereFollowed: "Vous suit" @@ -1496,7 +1495,6 @@ _notification: renote: "Renotes" quote: "Citations" reaction: "Réactions" - pollVote: "Votes dans des sondages" pollEnded: "Sondages se cloturant" receiveFollowRequest: "Demande d'abonnement reçue" followRequestAccepted: "Demande d'abonnement acceptée" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index 3a2bf69a72..eee647d0f6 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -1402,7 +1402,6 @@ _notification: youGotReply: "{name} membalas kamu" youGotQuote: "{name} mengutip kamu" youRenoted: "{name} me-renote kamu" - youGotPoll: "{name} memilih di angket kamu" youGotMessagingMessageFromUser: "{name} mengirimi kamu pesan" youGotMessagingMessageFromGroup: "Sebuah pesan telah dikirim ke grup {name}" youWereFollowed: "Mengikuti kamu" @@ -1419,7 +1418,6 @@ _notification: renote: "Renote" quote: "Kutip" reaction: "Reaksi" - pollVote: "Memilih di angket" pollEnded: "Jajak pendapat berakhir" receiveFollowRequest: "Permintaan mengikuti diterima" followRequestAccepted: "Permintaan mengikuti disetujui" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 3fba19985e..013a1d2de4 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -28,7 +28,7 @@ timeline: "Timeline" noAccountDescription: "L'utente non ha ancora scritto niente nella biografia di profilo." login: "Accedi" loggingIn: "Accesso in corso..." -logout: "Esci" +logout: "Uscita" signup: "Iscriviti" uploading: "Caricamento..." save: "Salva" @@ -1487,7 +1487,6 @@ _notification: youGotReply: "{name} ti ha risposto" youGotQuote: "{name} ha citato il tuo Nota e ha detto" youRenoted: "{name} ha rinotato" - youGotPoll: "{name} ha votato" youGotMessagingMessageFromUser: "{name} ti ha mandato un messaggio" youGotMessagingMessageFromGroup: "{name} ti ha mandato un messaggio nella chat" youWereFollowed: "Ha iniziato a seguirti" @@ -1505,7 +1504,6 @@ _notification: renote: "Rinota" quote: "Cita" reaction: "Reazioni" - pollVote: "Voti ricevuti" pollEnded: "Sondaggio chiuso." receiveFollowRequest: "Richiesta di follow ricevuta" followRequestAccepted: "Richiesta di follow accettata" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index b49d872a0b..e42f9babe1 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1361,6 +1361,7 @@ _widgets: userList: "ユーザーリスト" _userList: chooseList: "リストを選択" + clicker: "クリッカー" _cw: hide: "隠す" @@ -1550,7 +1551,6 @@ _notification: youGotReply: "{name}からのリプライ" youGotQuote: "{name}による引用" youRenoted: "{name}がRenoteしました" - youGotPoll: "{name}が投票しました" youGotMessagingMessageFromUser: "{name}からのチャットがあります" youGotMessagingMessageFromGroup: "{name}のチャットがあります" youWereFollowed: "フォローされました" @@ -1569,7 +1569,6 @@ _notification: renote: "Renote" quote: "引用" reaction: "リアクション" - pollVote: "アンケートに投票された" pollEnded: "アンケートが終了" receiveFollowRequest: "フォロー申請を受け取った" followRequestAccepted: "フォローが受理された" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index f8c045db00..4eff3268d4 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -1485,7 +1485,6 @@ _notification: youGotReply: "{name}からのリプライ" youGotQuote: "{name}による引用" youRenoted: "{name}がRenoteしたみたいやで" - youGotPoll: "{name}が投票したみたいやで" youGotMessagingMessageFromUser: "{name}からのチャットがあるで" youGotMessagingMessageFromGroup: "{name}のチャットがあるで" youWereFollowed: "フォローされたで" @@ -1503,7 +1502,6 @@ _notification: renote: "Renote" quote: "引用" reaction: "リアクション" - pollVote: "アンケートに投票されたで" pollEnded: "アンケートが終了したで" receiveFollowRequest: "フォロー許可してほしいみたいやで" followRequestAccepted: "フォローが受理されたで" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index d3a4a40b49..f2ba0e6c7b 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -920,6 +920,10 @@ like: "좋아요!" unlike: "좋아요 취소" numberOfLikes: "좋아요 수" show: "표시" +neverShow: "다시 보지 않기" +remindMeLater: "나중에 알림" +didYouLikeMisskey: "Misskey가 마음에 드시나요?" +pleaseDonate: "{host}은(는) 무료 소프트웨어 Misskey를 사용합니다. 후원을 통해 저희의 개발이 이어질 수 있게 도와주세요!" _sensitiveMediaDetection: description: "기계학습을 통해 자동으로 민감한 미디어를 탐지하여, 모더레이션에 참고할 수 있도록 합니다. 서버의 부하를 약간 증가시킵니다." sensitivity: "탐지 민감도" @@ -1324,6 +1328,7 @@ _widgets: userList: "사용자 목록" _userList: chooseList: "리스트 선택" + clicker: "클리커" _cw: hide: "숨기기" show: "더 보기" @@ -1499,7 +1504,6 @@ _notification: youGotReply: "{name}님이 답글함" youGotQuote: "{name}님이 인용함" youRenoted: "{name}님이 Renote" - youGotPoll: "{name}님이 투표함" youGotMessagingMessageFromUser: "{name} 님이 보낸 채팅이 있어요" youGotMessagingMessageFromGroup: "{name}에서 보낸 채팅이 있어요" youWereFollowed: "새로운 팔로워가 있습니다" @@ -1517,7 +1521,6 @@ _notification: renote: "리노트" quote: "인용" reaction: "리액션" - pollVote: "투표 참여" pollEnded: "투표가 종료됨" receiveFollowRequest: "팔로우 요청을 받았을 때" followRequestAccepted: "팔로우 요청이 승인되었을 때" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 712c05bb78..9043d2ab94 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -1380,7 +1380,6 @@ _notification: youGotReply: "{name} odpowiedział(a) Tobie" youGotQuote: "{name} zacytował(a) Ciebie" youRenoted: "{name} udostępnił(a) Twój wpis" - youGotPoll: "{name} zagłosował(a) w Twojej ankiecie" youGotMessagingMessageFromUser: "{name} wysłał(a) Ci wiadomość" youGotMessagingMessageFromGroup: "Została wysłana wiadomość do grupy {name}" youWereFollowed: "Zaobserwował(a) Cię" @@ -1398,7 +1397,6 @@ _notification: renote: "Udostępnij" quote: "Cytuj" reaction: "Reakcja" - pollVote: "Głosy w ankietach" receiveFollowRequest: "Otrzymano prośbę o możliwość obserwacji" followRequestAccepted: "Przyjęto prośbę o możliwość obserwacji" groupInvited: "Zaproszono do grup" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index dd1c2954b7..ba4814c81b 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -524,7 +524,6 @@ _notification: youGotMention: "{name} te mencionou" youGotReply: "{name} te respondeu" youGotQuote: "{name} te citou" - youGotPoll: "{name} votou em sua enquete" youGotMessagingMessageFromUser: "{name} te mandou uma mensagem de bate-papo" youGotMessagingMessageFromGroup: "Uma mensagem foi mandada para o grupo {name}" youWereFollowed: "Você tem um novo seguidor" @@ -541,7 +540,6 @@ _notification: renote: "Repostar" quote: "Citar" reaction: "Reações" - pollVote: "Votações em enquetes" pollEnded: "Enquetes terminando" receiveFollowRequest: "Recebeu pedidos de seguimento" followRequestAccepted: "Aceitou pedidos de seguimento" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 553fa9e811..49cccc71ae 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -1399,7 +1399,6 @@ _notification: youGotReply: "{name} отвечает вам." youGotQuote: "{name} цитирует вас." youRenoted: "{name} передаёт вашу заметку." - youGotPoll: "{name} участвует в вашем опросе." youGotMessagingMessageFromUser: "{name} пишет вам." youGotMessagingMessageFromGroup: "Новое сообщение в группе «{name}»." youWereFollowed: "У вас новый подписчик." @@ -1414,7 +1413,6 @@ _notification: renote: "Репосты" quote: "Цитаты" reaction: "Реакции" - pollVote: "Голосования" receiveFollowRequest: "Получен запрос на подписку" followRequestAccepted: "Запрос на подписку одобрен" groupInvited: "Приглашение в группы" diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index 3abfd8609d..2627c70b67 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -913,6 +913,10 @@ tools: "Nástroje" cannotLoad: "Nedá sa načítať." like: "Páči sa mi" show: "Zobraziť" +neverShow: "Nabudúce nezobrazovať" +remindMeLater: "Pripomenúť neskôr" +didYouLikeMisskey: "Páči sa vám Misskey?" +pleaseDonate: "Misskey je bezplatný softvér, ktorý používa {host}. Prosím, prispejte, aby sme ho mohli ďalej rozvíjať!" _sensitiveMediaDetection: description: "Strojové učenie sa použije na automatickú detekciu citlivých médií na účely ich moderovania. Mierne sa zvýši zaťaženie servera." sensitivity: "Citlivosť detekcie" @@ -1480,7 +1484,6 @@ _notification: youGotReply: "{name} vám odpovedal/a" youGotQuote: "{name} vás citoval/a" youRenoted: "{name} preposlal/a vašu poznámku" - youGotPoll: "{name} hlasoval/a" youGotMessagingMessageFromUser: "{name} vám poslal/a správu" youGotMessagingMessageFromGroup: "Prišla správa do skupiny {name}" youWereFollowed: "Máte nového sledujúceho" @@ -1498,7 +1501,6 @@ _notification: renote: "Preposlať" quote: "Citovať" reaction: "Reakcie" - pollVote: "Hlasy v hlasovaniach" pollEnded: "Hlasovanie skončilo" receiveFollowRequest: "Doručené žiadosti o sledovanie" followRequestAccepted: "Schválené žiadosti o sledovanie" diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml index 8b87e36acd..4e2f942686 100644 --- a/locales/sv-SE.yml +++ b/locales/sv-SE.yml @@ -1,7 +1,7 @@ --- _lang_: "Svenska" headlineMisskey: "Ett nätverk kopplat av noter" -introMisskey: "Välkommen! Misskey är en öppen och decentraliserad mikrobloggningstjänst.\nSkapa en \"not\" och dela dina tankar med alla runtomkring dig. 📡\nMed \"reaktioner\" kan du snabbt uttrycka dina känslor kring andras noter.👍\nLåt oss utforska en nya värld!🚀" +introMisskey: "Välkommen! Misskey är en öppen och decentraliserad mikrobloggningstjänst.\nSkapa en \"not\" och dela dina tankar med alla runtomkring dig. 📡\nMed \"reaktioner\" kan du snabbt uttrycka dina känslor kring andras noter. 👍\nLåt oss utforska en ny värld! 🚀" poweredByMisskeyDescription: "{name} är en tjänst driven av den öppna källkodsplatformen Misskey (benämns \"Misskey instans\")." monthAndDay: "{day}/{month}" search: "Sök" @@ -17,7 +17,7 @@ noThankYou: "Nej tack" enterUsername: "Ange användarnamn" renotedBy: "Omnoterad av {user}" noNotes: "Inga noteringar" -noNotifications: "Inga aviseringar" +noNotifications: "Inga notifikationer" instance: "Instanser" settings: "Inställningar" basicSettings: "Basinställningar" @@ -30,13 +30,13 @@ login: "Logga in" loggingIn: "Loggar in" logout: "Logga ut" signup: "Registrera" -uploading: "Uppladdning sker..." +uploading: "Laddar upp..." save: "Spara" users: "Användare" addUser: "Lägg till användare" favorite: "Lägg till i favoriter" favorites: "Favoriter" -unfavorite: "Avfavorisera" +unfavorite: "Ta bort från favoriter" favorited: "Tillagd i favoriter." alreadyFavorited: "Redan tillagd i favoriter." cantFavorite: "Gick inte att lägga till i favoriter." @@ -146,7 +146,7 @@ flagAsBotDescription: "Aktivera det här alternativet om kontot är kontrollerat flagAsCat: "Markera konto som katt" flagAsCatDescription: "Aktivera denna inställning för att markera kontot som en katt." flagShowTimelineReplies: "Visa svar i tidslinje" -flagShowTimelineRepliesDescription: "Visar användarsvar till andra användares noter i tidslinjen om påslagen." +flagShowTimelineRepliesDescription: "Visar användarsvar till andra användares noter i tidslinjen om aktiverad." autoAcceptFollowed: "Godkänn följarförfrågningar från användare du följer automatiskt" addAccount: "Lägg till konto" loginFailed: "Inloggningen misslyckades" @@ -253,16 +253,111 @@ explore: "Utforska" messageRead: "Läs" noMoreHistory: "Det finns ingen mer historik" startMessaging: "Starta en chatt" +nUsersRead: "läst av {n}" +agreeTo: "Jag accepterar {0}" +tos: "Användarvillkor" +home: "Hem" +remoteUserCaution: "Då denna användaren kommer från en fjärrinstans, kan informationen visad vara ofullständig." +activity: "Aktivitet" +images: "Bilder" +birthday: "Födelsedag" +yearsOld: "{age} år gammal" +registeredDate: "Gick med" +location: "Plats" +theme: "Teman" +themeForLightMode: "Tema att använda i Ljust Läge" +themeForDarkMode: "Tema att använda i Mörkt Läge" +light: "Ljust" +dark: "Mörk" +lightThemes: "Ljusa teman" +darkThemes: "Mörka teman" +syncDeviceDarkMode: "Synka Mörkt Läge med din enhets inställningar" +drive: "Drive" +fileName: "Filnamn" +selectFile: "Välj en fil" +selectFiles: "Välj filer" +selectFolder: "Välj en mapp" +selectFolders: "Välj mappar" +renameFile: "Byt namn på filen" +folderName: "Mappnamn" +createFolder: "Skapa en mapp" +renameFolder: "Byt namn på mappen" +deleteFolder: "Ta bort mappen" +addFile: "Lägg till fil" +emptyDrive: "Din Drive är tom" +emptyFolder: "Denna mappen är tom" +unableToDelete: "Kunde inte ta bort" +inputNewFileName: "Ange nytt filnamn" +inputNewDescription: "Ange ny bildtext" +inputNewFolderName: "Ange nytt mappnamn" +circularReferenceFolder: "Destinationsmappen är en undermapp av mappen du vill flytta." +hasChildFilesOrFolders: "Då denna mappen inte är tom, kan den inte tas bort." +copyUrl: "Kopiera URL" +rename: "Byt namn" +avatar: "Profilbild" +banner: "Banner" nsfw: "Känsligt innehåll" +reload: "Ladda om" +doNothing: "Ignorera" +reloadConfirm: "Vill du ladda om tidslinjen?" +accept: "Tillåt" +reject: "Neka" +normal: "Normal" +instanceName: "Instansnamn" +instanceDescription: "Instansbeskrivning" +maintainerEmail: "Administratörens epost" +tosUrl: "URL till användarvillkår" +thisYear: "Detta året" +thisMonth: "Denna månaden" +today: "Idag" +dayX: "{day}" +monthX: "{month}" +yearX: "{year}" +pages: "Sidor" +integration: "Integrationer" +connectService: "Anslut" +disconnectService: "Koppla från" +enableLocalTimeline: "Aktivera lokal tidslinje" +enableGlobalTimeline: "Aktivera global tidslinje" +enableRegistration: "Aktivera registrering av nya användare" +inMb: "I megabyte" +iconUrl: "URL till profilbilden" +bannerUrl: "URL till banner-bilden" pinnedNotes: "Fästad not" +enableHcaptcha: "Aktivera hCaptcha" +enableRecaptcha: "Aktivera reCAPTCHA" +enableTurnstile: "Aktivera Turnstile" +enableServiceworker: "Aktivera pushnotiser i denna webbläsaren" +recentlyUpdatedUsers: "Nyligen aktiva användare" +recentlyRegisteredUsers: "Nyligen registrerade användare" userList: "Listor" +aboutMisskey: "Om Misskey" +administrator: "Administratör" +newPasswordIs: "Det nya lösenordet är \"{password}\"" +share: "Dela" +enable: "Aktivera" +serviceworkerInfo: "Måste vara aktiverad för pushnotiser." +enableInfiniteScroll: "Ladda mer automatiskt" +enablePlayer: "Öppna videospelare" +enableAll: "Aktivera alla" +enableEmail: "Aktivera epost-utskick" smtpHost: "Värd" smtpUser: "Användarnamn" smtpPass: "Lösenord" clearCache: "Rensa cache" +enabled: "Aktiverad" user: "Användare" +global: "Global" +squareAvatars: "Visa fyrkantiga profilbilder" searchByGoogle: "Sök" file: "Filer" +enableAutoSensitive: "Automatisk NSFW markering" +enableAutoSensitiveDescription: "Tillåter automatiskt detektering och marketing av NSFW media genom Maskininlärning när möjligt. Även om denna inställningen är avaktiverad, kan det vara aktiverat på hela instansen." +pushNotification: "Pushnotiser" +subscribePushNotification: "Aktivera pushnotiser" +unsubscribePushNotification: "Avaktivera pushnotiser" +pushNotificationAlreadySubscribed: "Pushnotiser är redan aktiverade" +pushNotificationNotSupported: "Din webbläsare eller instans har inte stöd för pushnotiser" _email: _follow: title: "följde dig" @@ -271,6 +366,9 @@ _mfm: quote: "Citat" emoji: "Anpassa emoji" search: "Sök" +_channel: + setBanner: "Välj banner" + removeBanner: "Ta bort banner" _theme: keys: mention: "Nämn" @@ -282,6 +380,7 @@ _sfx: _widgets: notifications: "Notifikationer" timeline: "Tidslinje" + activity: "Aktivitet" federation: "Federation" jobQueue: "Jobbkö" _userList: @@ -289,9 +388,12 @@ _widgets: _cw: show: "Ladda mer" _visibility: + home: "Hem" followers: "Följare" _profile: username: "Användarnamn" + changeAvatar: "Ändra profilbild" + changeBanner: "Ändra banner" _exportOrImport: followingList: "Följer" muteList: "Tysta" @@ -299,8 +401,15 @@ _exportOrImport: userLists: "Listor" _charts: federation: "Federation" +_timelines: + home: "Hem" + global: "Global" +_pages: + blocks: + image: "Bilder" _notification: youWereFollowed: "följde dig" + unreadAntennaNote: "Antenn {name}" _types: follow: "Följer" mention: "Nämn" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index 58deeff6f1..d86c3de0e9 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -8,7 +8,7 @@ search: "ค้นหา" notifications: "การเเจ้งเตือน" username: "ชื่อผู้ใช้" password: "รหัสผ่าน" -forgotPassword: "ลืมรหัสผ่าน?" +forgotPassword: "ลืมรหัสผ่านใช่ไหม" fetchingAsApObject: "กำลังดึงข้อมูล จาก เฟดิเวิร์ส..." ok: "โอเค" gotIt: "เข้าใจแล้ว !" @@ -917,7 +917,13 @@ tools: "เครื่องมือ" cannotLoad: "ไม่สามารถโหลดได้" numberOfProfileView: "มุมมองโปรไฟล์" like: "ชื่นชอบ" +unlike: "ไม่ชอบ" +numberOfLikes: "จำนวนไลค์" show: "แสดงผล" +neverShow: "ไม่ต้องแสดงข้อความนี้อีก" +remindMeLater: "ไว้ครั้งหน้าแล้วกัน" +didYouLikeMisskey: "คุณเคยชอบ Misskey ไหม?" +pleaseDonate: "{host} ใช้ซอฟต์แวร์ฟรี Misskey เราขอขอบคุณการบริจาคของคุณอย่างสูงเพื่อให้การพัฒนา Misskey สามารถดำเนินต่อไปได้นะ!" _sensitiveMediaDetection: description: "ลดความพยายามในการดูแลเซิร์ฟเวอร์ผ่านการจดจำสื่อ NSFW โดยอัตโนมัติผ่านการเรียนรู้ของเครื่อง การทำสิ่งนี้อาจจะเพิ่มภาระบนเซิร์ฟเวอร์เล็กน้อย" sensitivity: "การตรวจจับความไว" @@ -1317,10 +1323,12 @@ _widgets: jobQueue: "คิวงาน" serverMetric: "ตัวชี้วัดเซิร์ฟเวอร์" aiscript: "AiScript คอนโซล" + aiscriptApp: "AiScript แอพ" aichan: "เอไอ" userList: "รายชื่อผู้ใช้" _userList: chooseList: "เลือกรายการ" + clicker: "คลิกเกอร์" _cw: hide: "ซ่อน" show: "โหลดเพิ่มเติม" @@ -1423,7 +1431,16 @@ _timelines: social: "โซเชี่ยล" global: "ทั่วโลก" _play: + new: "สร้างการเล่น" + edit: "แก้ไขเล่น" + created: "สร้างการเล่นแล้ว" + updated: "แก้ไขการเล่นแล้ว" + deleted: "ลบการเล่นแล้ว" + pageSetting: "ตั้งค่าการเล่น" + editThisPage: "แก้ไข Play นี้" viewSource: "ดูต้นฉบับ" + my: "มาย เพลย์" + liked: "ไลค์ เพลย์" featured: "เป็นที่นิยม" title: "หัวข้อ" script: "สคริปต์" @@ -1487,7 +1504,6 @@ _notification: youGotReply: "{name} ตอบกลับถึงคุณ" youGotQuote: "{name} อ้างถึงคุณ" youRenoted: "รีโน้ตจาก {name}" - youGotPoll: "{name} โหวตบนแบบสำรวจความคิดเห็นของคุณ" youGotMessagingMessageFromUser: "{name} ได้ส่งข้อความแชทถึงคุณ" youGotMessagingMessageFromGroup: "ข้อความแชทถูกส่งไปยัง {name} กลุ่ม" youWereFollowed: "ได้ติดตามคุณ" @@ -1505,7 +1521,6 @@ _notification: renote: "รีโน้ต" quote: "อ้างคำพูด" reaction: "รีแอคชั่น" - pollVote: "จำนวนโหวตที่ได้รับ" pollEnded: "โพลนี้สิ้นสุดลงแล้ว" receiveFollowRequest: "ได้รับคำขอติดตาม\n" followRequestAccepted: "ยอมรับคำขอติดตาม" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 352fb354ee..c6afcde112 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -1415,7 +1415,6 @@ _notification: youGotReply: "{name} відповідає" youGotQuote: "{name} цитує вас" youRenoted: "{name} поширює" - youGotPoll: "{name} бере участь в опитуванні" youGotMessagingMessageFromUser: "Повідомлення від {name}" youGotMessagingMessageFromGroup: "Нове повідомлення в групі {name}" youWereFollowed: "Новий підписник" @@ -1430,7 +1429,6 @@ _notification: renote: "Поширення" quote: "Цитування" reaction: "Реакції" - pollVote: "Опитування" receiveFollowRequest: "Запити на підписку" followRequestAccepted: "Прийняті підписки" groupInvited: "Запрошення до груп" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index 0070af56f0..6824faaee1 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -1460,7 +1460,6 @@ _notification: youGotReply: "{name} trả lời bạn" youGotQuote: "{name} trích dẫn tút của bạn" youRenoted: "{name} đăng lại tút của bạn" - youGotPoll: "{name} bình chọn tút của bạn" youGotMessagingMessageFromUser: "{name} nhắn tin cho bạn" youGotMessagingMessageFromGroup: "Một tin nhắn trong nhóm {name}" youWereFollowed: "đã theo dõi bạn" @@ -1477,7 +1476,6 @@ _notification: renote: "Đăng lại" quote: "Trích dẫn" reaction: "Biểu cảm" - pollVote: "Lượt bình chọn" pollEnded: "Bình chọn kết thúc" receiveFollowRequest: "Yêu cầu theo dõi" followRequestAccepted: "Yêu cầu theo dõi được chấp nhận" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 7c3efec86c..8ebc3a1fb4 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -920,6 +920,9 @@ like: "点赞!" unlike: "取消赞" numberOfLikes: "点赞数" show: "显示" +neverShow: "不再显示" +remindMeLater: "稍后提醒我" +didYouLikeMisskey: "你在Misskey玩得还开心吗?" _sensitiveMediaDetection: description: "可以使用机器学习技术自动检测敏感媒体,以便进行审核。服务器负载将略微增加。" sensitivity: "检测敏感度" @@ -1499,7 +1502,6 @@ _notification: youGotReply: "来自{name}的回复" youGotQuote: "来自{name}的引用" youRenoted: "来自{name}的转发" - youGotPoll: "来自{name}的投票" youGotMessagingMessageFromUser: "来自{name}的聊天" youGotMessagingMessageFromGroup: "来自{name}的群聊" youWereFollowed: "关注了你。" @@ -1517,7 +1519,6 @@ _notification: renote: "转发" quote: "引用" reaction: "回应" - pollVote: "问卷调查被投票" pollEnded: "问卷调查结束" receiveFollowRequest: "收到关注请求" followRequestAccepted: "关注请求已通过" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 661325d506..8330be0388 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -252,7 +252,7 @@ uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。" explore: "探索" messageRead: "已讀" noMoreHistory: "沒有更多歷史紀錄" -startMessaging: "開始傳送訊息" +startMessaging: "開始聊天" nUsersRead: "{n}人已讀" agreeTo: "我同意{0}" tos: "使用條款" @@ -918,7 +918,12 @@ cannotLoad: "無法載入" numberOfProfileView: "個人檔案檢視次數" like: "讚" unlike: "收回讚" +numberOfLikes: "讚數" show: "檢視" +neverShow: "不再顯示" +remindMeLater: "以後再說" +didYouLikeMisskey: "您是否喜愛Misskey呢?" +pleaseDonate: "Misskey是由{host}使用的免費軟體。請贊助我們,讓開發能夠持續!" _sensitiveMediaDetection: description: "您可以使用機器學習自動檢測敏感媒體並將其用於審核。 伺服器的負荷會稍微增加。" sensitivity: "檢測敏感度" @@ -1187,7 +1192,7 @@ _sfx: note: "貼文" noteMy: "我的貼文" notification: "通知" - chat: "傳送訊息" + chat: "聊天" chatBg: "聊天背景" antenna: "天線接收" channel: "頻道通知" @@ -1318,10 +1323,12 @@ _widgets: jobQueue: "佇列" serverMetric: "服務器指標 " aiscript: "AiScript控制台" + aiscriptApp: "AiScript App" aichan: "小藍" userList: "使用者列表" _userList: chooseList: "選擇清單" + clicker: "點擊器" _cw: hide: "隱藏" show: "瀏覽更多" @@ -1424,7 +1431,16 @@ _timelines: social: "社群" global: "公開" _play: + new: "新增Play" + edit: "編輯Play" + created: "已新增Play" + updated: "已更新Play" + deleted: "已刪除Play" + pageSetting: "Play設定" + editThisPage: "編輯這個Play" viewSource: "檢視原始碼" + my: "自己的Play" + liked: "按了讚的Play" featured: "人氣" title: "標題" script: "腳本" @@ -1488,7 +1504,6 @@ _notification: youGotReply: "{name}回覆了您" youGotQuote: "{name}引用了您" youRenoted: "{name} 轉發了你的貼文" - youGotPoll: "{name}已投票" youGotMessagingMessageFromUser: "{name}發送給您的訊息" youGotMessagingMessageFromGroup: "{name}發送給您的訊息" youWereFollowed: "您有新的追隨者" @@ -1506,7 +1521,6 @@ _notification: renote: "轉發貼文" quote: "引用" reaction: "反應" - pollVote: "統計已投票數" pollEnded: "問卷調查結束" receiveFollowRequest: "已收到追隨請求" followRequestAccepted: "追隨請求已接受" diff --git a/package.json b/package.json index e3d429ec63..5d99966a18 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "13.0.0-beta.27", + "version": "13.0.0-beta.36", "codename": "indigo", "repository": { "type": "git", diff --git a/packages/backend/assets/notification-badges/LICENSE b/packages/backend/assets/notification-badges/LICENSE deleted file mode 100644 index 841c4c682b..0000000000 --- a/packages/backend/assets/notification-badges/LICENSE +++ /dev/null @@ -1,5 +0,0 @@ -Font Awesome Icons -------------------------- - -Ⓒ Font Awesome -CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/) diff --git a/packages/backend/assets/notification-badges/at.png b/packages/backend/assets/notification-badges/at.png deleted file mode 100644 index d1492856de..0000000000 Binary files a/packages/backend/assets/notification-badges/at.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/check.png b/packages/backend/assets/notification-badges/check.png deleted file mode 100644 index baeb76babf..0000000000 Binary files a/packages/backend/assets/notification-badges/check.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/clipboard-check-solid.png b/packages/backend/assets/notification-badges/clipboard-check-solid.png deleted file mode 100644 index d8cdfa9da4..0000000000 Binary files a/packages/backend/assets/notification-badges/clipboard-check-solid.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/clock.png b/packages/backend/assets/notification-badges/clock.png deleted file mode 100644 index 9323f8f307..0000000000 Binary files a/packages/backend/assets/notification-badges/clock.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/comments.png b/packages/backend/assets/notification-badges/comments.png deleted file mode 100644 index bc8a1c35b4..0000000000 Binary files a/packages/backend/assets/notification-badges/comments.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/id-card-alt.png b/packages/backend/assets/notification-badges/id-card-alt.png deleted file mode 100644 index 67e1410e34..0000000000 Binary files a/packages/backend/assets/notification-badges/id-card-alt.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/plus.png b/packages/backend/assets/notification-badges/plus.png deleted file mode 100644 index 05362c122b..0000000000 Binary files a/packages/backend/assets/notification-badges/plus.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/poll-h.png b/packages/backend/assets/notification-badges/poll-h.png deleted file mode 100644 index 3b7ded6659..0000000000 Binary files a/packages/backend/assets/notification-badges/poll-h.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/quote-right.png b/packages/backend/assets/notification-badges/quote-right.png deleted file mode 100644 index 0fa4837654..0000000000 Binary files a/packages/backend/assets/notification-badges/quote-right.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/reply.png b/packages/backend/assets/notification-badges/reply.png deleted file mode 100644 index 77021f71a7..0000000000 Binary files a/packages/backend/assets/notification-badges/reply.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/retweet.png b/packages/backend/assets/notification-badges/retweet.png deleted file mode 100644 index dc61060481..0000000000 Binary files a/packages/backend/assets/notification-badges/retweet.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/satellite.png b/packages/backend/assets/notification-badges/satellite.png deleted file mode 100644 index 0e1831e8a0..0000000000 Binary files a/packages/backend/assets/notification-badges/satellite.png and /dev/null differ diff --git a/packages/backend/assets/notification-badges/user-plus.png b/packages/backend/assets/notification-badges/user-plus.png deleted file mode 100644 index 9d376d04d6..0000000000 Binary files a/packages/backend/assets/notification-badges/user-plus.png and /dev/null differ diff --git a/packages/backend/assets/tabler-badges/LICENSE b/packages/backend/assets/tabler-badges/LICENSE new file mode 100644 index 0000000000..cab2551f67 --- /dev/null +++ b/packages/backend/assets/tabler-badges/LICENSE @@ -0,0 +1,24 @@ +Tabler Icons +https://github.com/tabler/tabler-icons/blob/master/LICENSE +==== +MIT License + +Copyright (c) 2020-2022 Paweł Kuna + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/backend/assets/tabler-badges/antenna.png b/packages/backend/assets/tabler-badges/antenna.png new file mode 100644 index 0000000000..013c7f4e61 Binary files /dev/null and b/packages/backend/assets/tabler-badges/antenna.png differ diff --git a/packages/backend/assets/tabler-badges/arrow-back-up.png b/packages/backend/assets/tabler-badges/arrow-back-up.png new file mode 100644 index 0000000000..a253384c72 Binary files /dev/null and b/packages/backend/assets/tabler-badges/arrow-back-up.png differ diff --git a/packages/backend/assets/tabler-badges/at.png b/packages/backend/assets/tabler-badges/at.png new file mode 100644 index 0000000000..cbf8df4925 Binary files /dev/null and b/packages/backend/assets/tabler-badges/at.png differ diff --git a/packages/backend/assets/tabler-badges/chart-arrows.png b/packages/backend/assets/tabler-badges/chart-arrows.png new file mode 100644 index 0000000000..b2b8a2d993 Binary files /dev/null and b/packages/backend/assets/tabler-badges/chart-arrows.png differ diff --git a/packages/backend/assets/tabler-badges/circle-check.png b/packages/backend/assets/tabler-badges/circle-check.png new file mode 100644 index 0000000000..6464d5133c Binary files /dev/null and b/packages/backend/assets/tabler-badges/circle-check.png differ diff --git a/packages/backend/assets/tabler-badges/messages.png b/packages/backend/assets/tabler-badges/messages.png new file mode 100644 index 0000000000..fa5072ebba Binary files /dev/null and b/packages/backend/assets/tabler-badges/messages.png differ diff --git a/packages/backend/assets/notification-badges/null.png b/packages/backend/assets/tabler-badges/null.png similarity index 100% rename from packages/backend/assets/notification-badges/null.png rename to packages/backend/assets/tabler-badges/null.png diff --git a/packages/backend/assets/tabler-badges/plus.png b/packages/backend/assets/tabler-badges/plus.png new file mode 100644 index 0000000000..f13a86f4cd Binary files /dev/null and b/packages/backend/assets/tabler-badges/plus.png differ diff --git a/packages/backend/assets/tabler-badges/quote.png b/packages/backend/assets/tabler-badges/quote.png new file mode 100644 index 0000000000..e0fc6f3fb4 Binary files /dev/null and b/packages/backend/assets/tabler-badges/quote.png differ diff --git a/packages/backend/assets/tabler-badges/repeat.png b/packages/backend/assets/tabler-badges/repeat.png new file mode 100644 index 0000000000..ab548043f7 Binary files /dev/null and b/packages/backend/assets/tabler-badges/repeat.png differ diff --git a/packages/backend/assets/tabler-badges/user-plus.png b/packages/backend/assets/tabler-badges/user-plus.png new file mode 100644 index 0000000000..2ae96f0b73 Binary files /dev/null and b/packages/backend/assets/tabler-badges/user-plus.png differ diff --git a/packages/backend/assets/tabler-badges/users.png b/packages/backend/assets/tabler-badges/users.png new file mode 100644 index 0000000000..7862963327 Binary files /dev/null and b/packages/backend/assets/tabler-badges/users.png differ diff --git a/packages/backend/package.json b/packages/backend/package.json index 6c1a217b60..fbce696a3e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -72,7 +72,7 @@ "json5-loader": "4.0.1", "jsonld": "8.1.0", "jsrsasign": "10.6.1", - "mfm-js": "0.23.0", + "mfm-js": "0.23.1", "mime-types": "2.1.35", "misskey-js": "0.0.14", "ms": "3.0.0-canary.1", diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts index d6f326f616..1b5abce29a 100644 --- a/packages/backend/src/core/AntennaService.ts +++ b/packages/backend/src/core/AntennaService.ts @@ -15,8 +15,8 @@ import type { Packed } from '@/misc/schema.js'; import { DI } from '@/di-symbols.js'; import type { MutingsRepository, BlockingsRepository, NotesRepository, AntennaNotesRepository, AntennasRepository, UserGroupJoiningsRepository, UserListJoiningsRepository } from '@/models/index.js'; import { UtilityService } from '@/core/UtilityService.js'; -import type { OnApplicationShutdown } from '@nestjs/common'; import { bindThis } from '@/decorators.js'; +import type { OnApplicationShutdown } from '@nestjs/common'; @Injectable() export class AntennaService implements OnApplicationShutdown { @@ -135,7 +135,7 @@ export class AntennaService implements OnApplicationShutdown { this.globalEventServie.publishMainStream(antenna.userId, 'unreadAntenna', antenna); this.pushNotificationService.pushNotification(antenna.userId, 'unreadAntennaNote', { antenna: { id: antenna.id, name: antenna.name }, - note: await this.noteEntityService.pack(note) + note: await this.noteEntityService.pack(note), }); } }, 2000); @@ -144,27 +144,19 @@ export class AntennaService implements OnApplicationShutdown { // NOTE: フォローしているユーザーのノート、リストのユーザーのノート、グループのユーザーのノート指定はパフォーマンス上の理由で無効になっている - /** - * noteUserFollowers / antennaUserFollowing はどちらか一方が指定されていればよい - */ @bindThis - public async checkHitAntenna(antenna: Antenna, note: (Note | Packed<'Note'>), noteUser: { id: User['id']; username: string; host: string | null; }, noteUserFollowers?: User['id'][], antennaUserFollowing?: User['id'][]): Promise { + public async checkHitAntenna(antenna: Antenna, note: (Note | Packed<'Note'>), noteUser: { id: User['id']; username: string; host: string | null; }): Promise { if (note.visibility === 'specified') return false; - + if (note.visibility === 'followers') return false; + // アンテナ作成者がノート作成者にブロックされていたらスキップ const blockings = await this.blockingCache.fetch(noteUser.id, () => this.blockingsRepository.findBy({ blockerId: noteUser.id }).then(res => res.map(x => x.blockeeId))); if (blockings.some(blocking => blocking === antenna.userId)) return false; - if (note.visibility === 'followers') { - if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) return false; - if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) return false; - } - if (!antenna.withReplies && note.replyId != null) return false; if (antenna.src === 'home') { - if (noteUserFollowers && !noteUserFollowers.includes(antenna.userId)) return false; - if (antennaUserFollowing && !antennaUserFollowing.includes(note.userId)) return false; + // TODO } else if (antenna.src === 'list') { const listUsers = (await this.userListJoiningsRepository.findBy({ userListId: antenna.userListId!, diff --git a/packages/backend/src/core/FileInfoService.ts b/packages/backend/src/core/FileInfoService.ts index dad94da421..67337b5056 100644 --- a/packages/backend/src/core/FileInfoService.ts +++ b/packages/backend/src/core/FileInfoService.ts @@ -398,13 +398,13 @@ export class FileInfoService { .raw() .ensureAlpha() .resize(64, 64, { fit: 'inside' }) - .toBuffer((err, buffer, { width, height }) => { + .toBuffer((err, buffer, info) => { if (err) return reject(err); let hash; try { - hash = encode(new Uint8ClampedArray(buffer), width, height, 5, 5); + hash = encode(new Uint8ClampedArray(buffer), info.width, info.height, 5, 5); } catch (e) { return reject(e); } diff --git a/packages/backend/src/core/PollService.ts b/packages/backend/src/core/PollService.ts index 3cc9b0cc9b..abc598ab76 100644 --- a/packages/backend/src/core/PollService.ts +++ b/packages/backend/src/core/PollService.ts @@ -92,13 +92,6 @@ export class PollService { choice: choice, userId: user.id, }); - - // Notify - this.createNotificationService.createNotification(note.userId, 'pollVote', { - notifierId: user.id, - noteId: note.id, - choice: choice, - }); } @bindThis diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts index 8a2dc70eda..2a4e09519f 100644 --- a/packages/backend/src/core/entities/EmojiEntityService.ts +++ b/packages/backend/src/core/entities/EmojiEntityService.ts @@ -22,23 +22,25 @@ export class EmojiEntityService { @bindThis public async pack( src: Emoji['id'] | Emoji, + opts: { omitHost?: boolean; omitId?: boolean; } = {}, ): Promise> { const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src }); return { - id: emoji.id, + id: opts.omitId ? undefined : emoji.id, aliases: emoji.aliases, name: emoji.name, category: emoji.category, - host: emoji.host, + host: opts.omitHost ? undefined : emoji.host, }; } @bindThis public packMany( emojis: any[], + opts: { omitHost?: boolean; omitId?: boolean; } = {}, ) { - return Promise.all(emojis.map(x => this.pack(x))); + return Promise.all(emojis.map(x => this.pack(x, opts))); } } diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index 208d653877..a1c2c9cffb 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -98,7 +98,7 @@ export class NotificationEntityService implements OnModuleInit { }), reaction: notification.reaction, } : {}), - ...(notification.type === 'pollVote' ? { + ...(notification.type === 'pollVote' ? { // TODO: そのうち消す note: this.noteEntityService.pack(notification.note ?? notification.noteId!, { id: notification.notifieeId }, { detail: true, _hint_: options._hintForEachNotes_, diff --git a/packages/backend/src/misc/sql-like-escape.ts b/packages/backend/src/misc/sql-like-escape.ts new file mode 100644 index 0000000000..8470dca3de --- /dev/null +++ b/packages/backend/src/misc/sql-like-escape.ts @@ -0,0 +1,3 @@ +export function sqlLikeEscape(s: string) { + return s.replace(/([%_])/g, '\\$1'); +} diff --git a/packages/backend/src/models/entities/Notification.ts b/packages/backend/src/models/entities/Notification.ts index 53a7dda43a..6679cdb809 100644 --- a/packages/backend/src/models/entities/Notification.ts +++ b/packages/backend/src/models/entities/Notification.ts @@ -55,11 +55,11 @@ export class Notification { * 通知の種類。 * follow - フォローされた * mention - 投稿で自分が言及された - * reply - (自分または自分がWatchしている)投稿が返信された - * renote - (自分または自分がWatchしている)投稿がRenoteされた - * quote - (自分または自分がWatchしている)投稿が引用Renoteされた - * reaction - (自分または自分がWatchしている)投稿にリアクションされた - * pollVote - (自分または自分がWatchしている)投稿のアンケートに投票された + * reply - 投稿に返信された + * renote - 投稿がRenoteされた + * quote - 投稿が引用Renoteされた + * reaction - 投稿にリアクションされた + * pollVote - 投稿のアンケートに投票された (廃止) * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した * receiveFollowRequest - フォローリクエストされた * followRequestAccepted - 自分の送ったフォローリクエストが承認された diff --git a/packages/backend/src/models/schema/emoji.ts b/packages/backend/src/models/schema/emoji.ts index 9a52609b68..d897a0fc05 100644 --- a/packages/backend/src/models/schema/emoji.ts +++ b/packages/backend/src/models/schema/emoji.ts @@ -3,7 +3,7 @@ export const packedEmojiSchema = { properties: { id: { type: 'string', - optional: false, nullable: false, + optional: true, nullable: false, format: 'id', example: 'xxxxxxxxxx', }, @@ -26,12 +26,8 @@ export const packedEmojiSchema = { }, host: { type: 'string', - optional: false, nullable: true, + optional: true, nullable: true, description: 'The local host is represented with `null`.', }, - url: { - type: 'string', - optional: true, nullable: false, - }, }, } as const; diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 60beca4f47..ab9349966d 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -220,6 +220,7 @@ import * as ep___messaging_messages_create from './endpoints/messaging/messages/ import * as ep___messaging_messages_delete from './endpoints/messaging/messages/delete.js'; import * as ep___messaging_messages_read from './endpoints/messaging/messages/read.js'; import * as ep___meta from './endpoints/meta.js'; +import * as ep___emojis from './endpoints/emojis.js'; import * as ep___miauth_genToken from './endpoints/miauth/gen-token.js'; import * as ep___mute_create from './endpoints/mute/create.js'; import * as ep___mute_delete from './endpoints/mute/delete.js'; @@ -550,6 +551,7 @@ const $messaging_messages_create: Provider = { provide: 'ep:messaging/messages/c const $messaging_messages_delete: Provider = { provide: 'ep:messaging/messages/delete', useClass: ep___messaging_messages_delete.default }; const $messaging_messages_read: Provider = { provide: 'ep:messaging/messages/read', useClass: ep___messaging_messages_read.default }; const $meta: Provider = { provide: 'ep:meta', useClass: ep___meta.default }; +const $emojis: Provider = { provide: 'ep:emojis', useClass: ep___emojis.default }; const $miauth_genToken: Provider = { provide: 'ep:miauth/gen-token', useClass: ep___miauth_genToken.default }; const $mute_create: Provider = { provide: 'ep:mute/create', useClass: ep___mute_create.default }; const $mute_delete: Provider = { provide: 'ep:mute/delete', useClass: ep___mute_delete.default }; @@ -884,6 +886,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $messaging_messages_delete, $messaging_messages_read, $meta, + $emojis, $miauth_genToken, $mute_create, $mute_delete, @@ -1212,6 +1215,7 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $messaging_messages_delete, $messaging_messages_read, $meta, + $emojis, $miauth_genToken, $mute_create, $mute_delete, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index d4f8be5b85..f9749ad660 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -219,6 +219,7 @@ import * as ep___messaging_messages_create from './endpoints/messaging/messages/ import * as ep___messaging_messages_delete from './endpoints/messaging/messages/delete.js'; import * as ep___messaging_messages_read from './endpoints/messaging/messages/read.js'; import * as ep___meta from './endpoints/meta.js'; +import * as ep___emojis from './endpoints/emojis.js'; import * as ep___miauth_genToken from './endpoints/miauth/gen-token.js'; import * as ep___mute_create from './endpoints/mute/create.js'; import * as ep___mute_delete from './endpoints/mute/delete.js'; @@ -547,6 +548,7 @@ const eps = [ ['messaging/messages/delete', ep___messaging_messages_delete], ['messaging/messages/read', ep___messaging_messages_read], ['meta', ep___meta], + ['emojis', ep___emojis], ['miauth/gen-token', ep___miauth_genToken], ['mute/create', ep___mute_create], ['mute/delete', ep___mute_delete], diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index c03d27878c..08ffc73fea 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -5,6 +5,7 @@ import { QueryService } from '@/core/QueryService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['admin'], @@ -92,7 +93,7 @@ export default class extends Endpoint { } if (ps.query) { - q.andWhere('emoji.name like :query', { query: '%' + ps.query + '%' }); + q.andWhere('emoji.name like :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); } const emojis = await q diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 271b142126..6bcd4973d6 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -5,6 +5,7 @@ import type { Emoji } from '@/models/entities/Emoji.js'; import { QueryService } from '@/core/QueryService.js'; import { DI } from '@/di-symbols.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +//import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['admin'], @@ -82,7 +83,7 @@ export default class extends Endpoint { let emojis: Emoji[]; if (ps.query) { - //q.andWhere('emoji.name ILIKE :q', { q: `%${ps.query}%` }); + //q.andWhere('emoji.name ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` }); //const emojis = await q.take(ps.limit).getMany(); emojis = await q.getMany(); diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index 33e1be8041..5a67cf522a 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -3,6 +3,7 @@ import type { UsersRepository } from '@/models/index.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['admin'], @@ -68,7 +69,7 @@ export default class extends Endpoint { } if (ps.username) { - query.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' }); + query.andWhere('user.usernameLower like :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }); } if (ps.hostname) { diff --git a/packages/backend/src/server/api/endpoints/emojis.ts b/packages/backend/src/server/api/endpoints/emojis.ts new file mode 100644 index 0000000000..97dcfde596 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/emojis.ts @@ -0,0 +1,90 @@ +import { IsNull, MoreThan } from 'typeorm'; +import { Inject, Injectable } from '@nestjs/common'; +import type { EmojisRepository } from '@/models/index.js'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; +import type { Config } from '@/config.js'; +import { DI } from '@/di-symbols.js'; + +export const meta = { + tags: ['meta'], + + requireCredential: false, + + res: { + type: 'object', + optional: false, nullable: false, + properties: { + emojis: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + optional: false, nullable: false, + properties: { + name: { + type: 'string', + optional: false, nullable: false, + }, + aliases: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'string', + optional: false, nullable: false, + }, + }, + category: { + type: 'string', + optional: false, nullable: true, + }, + }, + }, + }, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + }, + required: [], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.config) + private config: Config, + + @Inject(DI.emojisRepository) + private emojisRepository: EmojisRepository, + + private emojiEntityService: EmojiEntityService, + ) { + super(meta, paramDef, async (ps, me) => { + const emojis = await this.emojisRepository.find({ + where: { + host: IsNull(), + }, + order: { + category: 'ASC', + name: 'ASC', + }, + cache: { + id: 'meta_emojis', + milliseconds: 3600000, // 1 hour + }, + }); + + return { + emojis: await this.emojiEntityService.packMany(emojis, { + omitId: true, + omitHost: true, + }), + }; + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 5e2f204661..4c19988eb8 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -4,6 +4,7 @@ import type { InstancesRepository } from '@/models/index.js'; import { InstanceEntityService } from '@/core/entities/InstanceEntityService.js'; import { MetaService } from '@/core/MetaService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['federation'], @@ -120,7 +121,7 @@ export default class extends Endpoint { } if (ps.host) { - query.andWhere('instance.host like :host', { host: '%' + ps.host.toLowerCase() + '%' }); + query.andWhere('instance.host like :host', { host: '%' + sqlLikeEscape(ps.host.toLowerCase()) + '%' }); } const instances = await query.take(ps.limit).skip(ps.offset).getMany(); diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index 7f787ea38f..4f5f979767 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -2,6 +2,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { HashtagsRepository } from '@/models/index.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['hashtags'], @@ -37,7 +38,7 @@ export default class extends Endpoint { ) { super(meta, paramDef, async (ps, me) => { const hashtags = await this.hashtagsRepository.createQueryBuilder('tag') - .where('tag.name like :q', { q: ps.query.toLowerCase() + '%' }) + .where('tag.name like :q', { q: sqlLikeEscape(ps.query.toLowerCase()) + '%' }) .orderBy('tag.count', 'DESC') .groupBy('tag.id') .take(ps.limit) diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 05da011979..c44d63d64b 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -4,7 +4,6 @@ import type { AdsRepository, EmojisRepository, UsersRepository } from '@/models/ import { MAX_NOTE_TEXT_LENGTH, DB_MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { MetaService } from '@/core/MetaService.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; @@ -152,43 +151,6 @@ export const meta = { type: 'number', optional: false, nullable: false, }, - emojis: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - properties: { - id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - aliases: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'string', - optional: false, nullable: false, - }, - }, - category: { - type: 'string', - optional: false, nullable: true, - }, - host: { - type: 'string', - optional: false, nullable: true, - description: 'The local host is represented with `null`.', - }, - url: { - type: 'string', - optional: false, nullable: false, - format: 'url', - }, - }, - }, - }, ads: { type: 'array', optional: false, nullable: false, @@ -326,30 +288,12 @@ export default class extends Endpoint { @Inject(DI.adsRepository) private adsRepository: AdsRepository, - @Inject(DI.emojisRepository) - private emojisRepository: EmojisRepository, - private userEntityService: UserEntityService, - private emojiEntityService: EmojiEntityService, private metaService: MetaService, ) { super(meta, paramDef, async (ps, me) => { const instance = await this.metaService.fetch(true); - const emojis = await this.emojisRepository.find({ - where: { - host: IsNull(), - }, - order: { - category: 'ASC', - name: 'ASC', - }, - cache: { - id: 'meta_emojis', - milliseconds: 3600000, // 1 hour - }, - }); - const ads = await this.adsRepository.find({ where: { expiresAt: MoreThan(new Date()), @@ -390,7 +334,6 @@ export default class extends Endpoint { backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため - emojis: await this.emojiEntityService.packMany(emojis), defaultLightTheme: instance.defaultLightTheme, defaultDarkTheme: instance.defaultDarkTheme, ads: ads.map(ad => ({ diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index 793d7c5408..d583dfb936 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -162,13 +162,6 @@ export default class extends Endpoint { userId: me.id, }); - // Notify - this.createNotificationService.createNotification(note.userId, 'pollVote', { - notifierId: me.id, - noteId: note.id, - choice: ps.choice, - }); - // リモート投票の場合リプライ送信 if (note.userHost != null) { const pollOwner = await this.usersRepository.findOneByOrFail({ id: note.userId }) as IRemoteUser; diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 27b477e141..8eb031dfe3 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -6,6 +6,7 @@ import { QueryService } from '@/core/QueryService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['notes'], @@ -70,7 +71,7 @@ export default class extends Endpoint { } query - .andWhere('note.text ILIKE :q', { q: `%${ps.query}%` }) + .andWhere('note.text ILIKE :q', { q: `%${ sqlLikeEscape(ps.query) }%` }) .innerJoinAndSelect('note.user', 'user') .leftJoinAndSelect('user.avatar', 'avatar') .leftJoinAndSelect('user.banner', 'banner') diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index f13df3ee9d..95491211bc 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -6,6 +6,7 @@ import type { User } from '@/models/entities/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['users'], @@ -59,10 +60,10 @@ export default class extends Endpoint { if (ps.host) { const q = this.usersRepository.createQueryBuilder('user') .where('user.isSuspended = FALSE') - .andWhere('user.host LIKE :host', { host: ps.host.toLowerCase() + '%' }); + .andWhere('user.host LIKE :host', { host: sqlLikeEscape(ps.host.toLowerCase()) + '%' }); if (ps.username) { - q.andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }); + q.andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }); } q.andWhere('user.updatedAt IS NOT NULL'); @@ -83,7 +84,7 @@ export default class extends Endpoint { .where(`user.id IN (${ followingQuery.getQuery() })`) .andWhere('user.id != :meId', { meId: me.id }) .andWhere('user.isSuspended = FALSE') - .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }) + .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }) .andWhere(new Brackets(qb => { qb .where('user.updatedAt IS NULL') .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); @@ -101,7 +102,7 @@ export default class extends Endpoint { .where(`user.id NOT IN (${ followingQuery.getQuery() })`) .andWhere('user.id != :meId', { meId: me.id }) .andWhere('user.isSuspended = FALSE') - .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }) + .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }) .andWhere('user.updatedAt IS NOT NULL'); otherQuery.setParameters(followingQuery.getParameters()); @@ -116,7 +117,7 @@ export default class extends Endpoint { } else { users = await this.usersRepository.createQueryBuilder('user') .where('user.isSuspended = FALSE') - .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }) + .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }) .andWhere('user.updatedAt IS NOT NULL') .orderBy('user.updatedAt', 'DESC') .take(ps.limit - users.length) diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index ba07714972..d7a60f0437 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -5,6 +5,7 @@ import type { User } from '@/models/entities/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['users'], @@ -57,7 +58,7 @@ export default class extends Endpoint { if (isUsername) { const usernameQuery = this.usersRepository.createQueryBuilder('user') - .where('user.usernameLower LIKE :username', { username: ps.query.replace('@', '').toLowerCase() + '%' }) + .where('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.query.replace('@', '').toLowerCase()) + '%' }) .andWhere(new Brackets(qb => { qb .where('user.updatedAt IS NULL') .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); @@ -78,11 +79,11 @@ export default class extends Endpoint { } else { const nameQuery = this.usersRepository.createQueryBuilder('user') .where(new Brackets(qb => { - qb.where('user.name ILIKE :query', { query: '%' + ps.query + '%' }); + qb.where('user.name ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); // Also search username if it qualifies as username if (this.userEntityService.validateLocalUsername(ps.query)) { - qb.orWhere('user.usernameLower LIKE :username', { username: '%' + ps.query.toLowerCase() + '%' }); + qb.orWhere('user.usernameLower LIKE :username', { username: '%' + sqlLikeEscape(ps.query.toLowerCase()) + '%' }); } })) .andWhere(new Brackets(qb => { qb @@ -106,7 +107,7 @@ export default class extends Endpoint { if (users.length < ps.limit) { const profQuery = this.userProfilesRepository.createQueryBuilder('prof') .select('prof.userId') - .where('prof.description ILIKE :query', { query: '%' + ps.query + '%' }); + .where('prof.description ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); if (ps.origin === 'local') { profQuery.andWhere('prof.userHost IS NULL'); diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index c69975fd79..5c29224019 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -312,7 +312,7 @@ export class ClientServerService { fastify.get('/opensearch.xml', async (request, reply) => { const meta = await this.metaService.fetch(); - const name = meta.name || 'Misskey'; + const name = meta.name ?? 'Misskey'; let content = ''; content += ''; content += `${name}`; @@ -533,13 +533,12 @@ export class ClientServerService { }); // Clip - // TODO: 非publicなclipのハンドリング fastify.get<{ Params: { clip: string; } }>('/clips/:clip', async (request, reply) => { const clip = await this.clipsRepository.findOneBy({ id: request.params.clip, }); - if (clip) { + if (clip && clip.isPublic) { const _clip = await this.clipEntityService.pack(clip); const profile = await this.userProfilesRepository.findOneByOrFail({ userId: clip.userId }); const meta = await this.metaService.fetch(); diff --git a/packages/frontend/assets/cookie.png b/packages/frontend/assets/cookie.png new file mode 100644 index 0000000000..4a7f040613 Binary files /dev/null and b/packages/frontend/assets/cookie.png differ diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 234490e506..72a9532c61 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -38,7 +38,7 @@ "json5": "2.2.3", "katex": "0.16.4", "matter-js": "0.18.0", - "mfm-js": "0.23.0", + "mfm-js": "0.23.1", "misskey-js": "0.0.14", "photoswipe": "5.3.4", "prismjs": "1.29.0", diff --git a/packages/frontend/src/components/MkAsUi.vue b/packages/frontend/src/components/MkAsUi.vue index b6b49725d2..5844a18633 100644 --- a/packages/frontend/src/components/MkAsUi.vue +++ b/packages/frontend/src/components/MkAsUi.vue @@ -33,12 +33,12 @@ {{ c.text }} - + - +