Merge branch 'develop' into qr

This commit is contained in:
tamaina 2025-09-08 18:33:31 +09:00 committed by GitHub
commit d6a0e6f388
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 2141 additions and 1698 deletions

View File

@ -1,15 +1,18 @@
## Unreleased ## 2025.9.0
### General
-
### Client ### Client
- Enhance: AiScriptAppウィジェットで構文エラーを検知してもダイアログではなくウィジェット内にエラーを表示するように
- Enhance: /flushページでサイトキャッシュをクリアできるようになりました
- Enhance: クリップ/リスト/アンテナ/ロール追加系メニュー項目において、表示件数を拡張
- Enhance: 「キャッシュを削除」ボタンでブラウザの内部キャッシュの削除も行えるように
- Enhance: CtrlキーCommandキーを押下しながらリンクをクリックすると新しいタブで開くように
- Fix: プッシュ通知を有効にできない問題を修正
- Fix: RSSティッカーウィジェットが正しく動作しない問題を修正 - Fix: RSSティッカーウィジェットが正しく動作しない問題を修正
- Fix: プロファイルを復元後アカウントの切り替えができない問題を修正
- Fix: エラー画像が横に引き伸ばされてしまう問題に対応 - Fix: エラー画像が横に引き伸ばされてしまう問題に対応
### Server ### Server
- - Fix: webpなどの画像に対してセンシティブなメディアの検出が適用されていなかった問題を修正
## 2025.8.0 ## 2025.8.0

View File

@ -1644,7 +1644,7 @@ _serverSettings:
reactionsBufferingDescription: "Quan s'activa aquesta opció millora bastant el rendiment en recuperar les línies de temps reduint la càrrega de la base. Com a contrapunt, augmentarà l'ús de memòria de Redís. Desactiva aquesta opció en cas de tenir un servidor amb poca memòria o si tens problemes d'inestabilitat." reactionsBufferingDescription: "Quan s'activa aquesta opció millora bastant el rendiment en recuperar les línies de temps reduint la càrrega de la base. Com a contrapunt, augmentarà l'ús de memòria de Redís. Desactiva aquesta opció en cas de tenir un servidor amb poca memòria o si tens problemes d'inestabilitat."
remoteNotesCleaning: "Neteja automàtica de notes remotes" remoteNotesCleaning: "Neteja automàtica de notes remotes"
remoteNotesCleaning_description: "Quan activis aquesta opció, periòdicament es netejaran les notes remotes que no es consultin, això evitarà que la base de dades se" remoteNotesCleaning_description: "Quan activis aquesta opció, periòdicament es netejaran les notes remotes que no es consultin, això evitarà que la base de dades se"
remoteNotesCleaningMaxProcessingDuration: "D'oració màxima del temps de funcionament del procés de neteja" remoteNotesCleaningMaxProcessingDuration: "Duració màxima del temps de funcionament del procés de neteja"
remoteNotesCleaningExpiryDaysForEachNotes: "Duració mínima de conservació de les notes" remoteNotesCleaningExpiryDaysForEachNotes: "Duració mínima de conservació de les notes"
inquiryUrl: "URL de consulta " inquiryUrl: "URL de consulta "
inquiryUrlDescription: "Escriu adreça URL per al formulari de consulta per al mantenidor del servidor o una pàgina web amb el contacte d'informació." inquiryUrlDescription: "Escriu adreça URL per al formulari de consulta per al mantenidor del servidor o una pàgina web amb el contacte d'informació."

View File

@ -2137,7 +2137,7 @@ _aboutMisskey:
_displayOfSensitiveMedia: _displayOfSensitiveMedia:
respect: "Esconder medios marcados como sensibles" respect: "Esconder medios marcados como sensibles"
ignore: "Mostrar medios marcados como sensibles" ignore: "Mostrar medios marcados como sensibles"
force: "Esconder todala multimedia" force: "Esconder toda la multimedia"
_instanceTicker: _instanceTicker:
none: "No mostrar" none: "No mostrar"
remote: "Mostrar a usuarios remotos" remote: "Mostrar a usuarios remotos"

View File

@ -1215,6 +1215,7 @@ privacyPolicyUrl: "Ссылка на Политику Конфиденциаль
tosAndPrivacyPolicy: "Условия использования и политика конфиденциальности" tosAndPrivacyPolicy: "Условия использования и политика конфиденциальности"
avatarDecorations: "Украшения для аватара" avatarDecorations: "Украшения для аватара"
attach: "Прикрепить" attach: "Прикрепить"
detachAll: "Убрать всё"
angle: "Угол" angle: "Угол"
flip: "Переворот" flip: "Переворот"
showAvatarDecorations: "Показать украшения для аватара" showAvatarDecorations: "Показать украшения для аватара"
@ -1253,7 +1254,7 @@ clipNoteLimitExceeded: "К этому клипу больше нельзя до
performance: "Производительность" performance: "Производительность"
modified: "Изменено" modified: "Изменено"
signinWithPasskey: "Войдите в систему, используя свой пароль" signinWithPasskey: "Войдите в систему, используя свой пароль"
unknownWebAuthnKey: "Не известный ключ " unknownWebAuthnKey: "Неизвестный ключ"
passkeyVerificationFailed: "Ошибка проверка ключа доступа " passkeyVerificationFailed: "Ошибка проверка ключа доступа "
messageToFollower: "Сообщение подписчикам" messageToFollower: "Сообщение подписчикам"
testCaptchaWarning: "Эта функция предназначена для тестирования CAPTCHA. <strong>Не использовать это в рабочей среде</strong>" testCaptchaWarning: "Эта функция предназначена для тестирования CAPTCHA. <strong>Не использовать это в рабочей среде</strong>"
@ -1268,8 +1269,11 @@ availableRoles: "Доступные роли"
federationDisabled: "Федерация отключена для этого сервера. Вы не можете взаимодействовать с пользователями на других серверах." federationDisabled: "Федерация отключена для этого сервера. Вы не можете взаимодействовать с пользователями на других серверах."
draft: "Черновик" draft: "Черновик"
markAsSensitiveConfirm: "Отметить контент как чувствительный?" markAsSensitiveConfirm: "Отметить контент как чувствительный?"
preferences: "Основное"
resetToDefaultValue: "Сбросить настройки до стандартных" resetToDefaultValue: "Сбросить настройки до стандартных"
syncBetweenDevices: "Синхронизировать между устройствами"
postForm: "Форма отправки" postForm: "Форма отправки"
textCount: "Количество символов"
information: "Описание" information: "Описание"
inMinutes: "мин" inMinutes: "мин"
inDays: "сут" inDays: "сут"
@ -1281,6 +1285,11 @@ _chat:
send: "Отправить" send: "Отправить"
_settings: _settings:
webhook: "Вебхук" webhook: "Вебхук"
preferencesBanner: "Вы можете настроить общее поведение клиента по вашим предпочтениям"
timelineAndNote: "Лента и заметки"
_chat:
showSenderName: "Показывать имя отправителя"
sendOnEnter: "Использовать Enter для отправки"
_delivery: _delivery:
stop: "Заморожено" stop: "Заморожено"
_type: _type:
@ -1529,7 +1538,7 @@ _achievements:
description: "Нажато здесь" description: "Нажато здесь"
_justPlainLucky: _justPlainLucky:
title: "Чистая удача" title: "Чистая удача"
description: "Может достаться с вероятностью 0,01% каждые 10 секунд." description: "Может достаться с вероятностью 0,005% каждые 10 секунд."
_setNameToSyuilo: _setNameToSyuilo:
title: "Комплекс бога" title: "Комплекс бога"
description: "Установлено «syuilo» в качестве имени" description: "Установлено «syuilo» в качестве имени"
@ -1557,6 +1566,12 @@ _achievements:
title: "Brain Diver" title: "Brain Diver"
description: "Опубликована ссылка на песню «Brain Diver»" description: "Опубликована ссылка на песню «Brain Diver»"
flavor: "Мисски-Мисски Ла-Ту-Ма" flavor: "Мисски-Мисски Ла-Ту-Ма"
_bubbleGameExplodingHead:
title: "🤯"
description: "Самый большой объект в Bubble game"
_bubbleGameDoubleExplodingHead:
title: "Двойной🤯"
description: "Два самых больших объекта в Bubble game одновременно!"
_role: _role:
new: "Новая роль" new: "Новая роль"
edit: "Изменить роль" edit: "Изменить роль"

View File

@ -360,7 +360,7 @@ whenServerDisconnected: "Sunucu ile bağlantı kesildiğinde"
disconnectedFromServer: "Sunucu bağlantısı kesildi" disconnectedFromServer: "Sunucu bağlantısı kesildi"
reload: "Yenile" reload: "Yenile"
doNothing: "Yoksay" doNothing: "Yoksay"
reloadConfirm: "Zaman çizelgesini yenilemek ister misin?" reloadConfirm: "Panoyu yenilemek ister misin?"
watch: "İzle" watch: "İzle"
unwatch: "İzlemeyi bırak" unwatch: "İzlemeyi bırak"
accept: "Kabul et" accept: "Kabul et"
@ -573,9 +573,9 @@ objectStorageSetPublicRead: "Yükleme sırasında \"genel-okuma\" ayarını yap
s3ForcePathStyleDesc: "s3ForcePathStyle etkinleştirilirse, kova adı URL'nin ana bilgisayar adı yerine URL yoluna eklenmelidir. Kendi kendine barındırılan bir Minio örneği gibi hizmetleri kullanırken bu ayarı etkinleştirmen gerekebilir." s3ForcePathStyleDesc: "s3ForcePathStyle etkinleştirilirse, kova adı URL'nin ana bilgisayar adı yerine URL yoluna eklenmelidir. Kendi kendine barındırılan bir Minio örneği gibi hizmetleri kullanırken bu ayarı etkinleştirmen gerekebilir."
serverLogs: "Sunucu log kayıtları" serverLogs: "Sunucu log kayıtları"
deleteAll: "Tümünü sil" deleteAll: "Tümünü sil"
showFixedPostForm: "Gönderi formunu zaman çizelgesinin en üstünde görüntüle" showFixedPostForm: "Gönderi formunu pano üstünde görüntüle"
showFixedPostFormInChannel: "Gönderi formunu zaman çizelgesinin en üstünde görüntüle (Kanallar)" showFixedPostFormInChannel: "Gönderi formunu pano üstünde görüntüle (Kanallar)"
withRepliesByDefaultForNewlyFollowed: "Yeni takip edilen kullanıcıların yanıtlarını varsayılan olarak zaman çizelgesine dahil et" withRepliesByDefaultForNewlyFollowed: "Yeni takip edilen kullanıcıların yanıtlarını varsayılan olarak panoya dahil et"
newNoteRecived: "Yeni Not'lar var" newNoteRecived: "Yeni Not'lar var"
newNote: "Yeni Not" newNote: "Yeni Not"
sounds: "Sesler" sounds: "Sesler"
@ -1059,7 +1059,7 @@ achievements: "Başarılar"
gotInvalidResponseError: "Geçersiz sunucu yanıtı" gotInvalidResponseError: "Geçersiz sunucu yanıtı"
gotInvalidResponseErrorDescription: "Sunucu erişilemez durumda olabilir veya bakım çalışması yapılmaktadır. Lütfen daha sonra tekrar dene." gotInvalidResponseErrorDescription: "Sunucu erişilemez durumda olabilir veya bakım çalışması yapılmaktadır. Lütfen daha sonra tekrar dene."
thisPostMayBeAnnoying: "Bu not başkalarını rahatsız edebilir." thisPostMayBeAnnoying: "Bu not başkalarını rahatsız edebilir."
thisPostMayBeAnnoyingHome: "Ana zaman çizelgesine gönder" thisPostMayBeAnnoyingHome: "Ana panoya gönder"
thisPostMayBeAnnoyingCancel: "İptal" thisPostMayBeAnnoyingCancel: "İptal"
thisPostMayBeAnnoyingIgnore: "Yine de gönder" thisPostMayBeAnnoyingIgnore: "Yine de gönder"
collapseRenotes: "Daha önce görüntülenen Renote'lari kısaltılmış olarak göster" collapseRenotes: "Daha önce görüntülenen Renote'lari kısaltılmış olarak göster"
@ -1218,8 +1218,8 @@ showRepliesToOthersInTimeline: "Pano'da diğer kişilere verilen yanıtları
hideRepliesToOthersInTimeline: "Pano'dan diğer kişilerin yanıtlarını gizle" hideRepliesToOthersInTimeline: "Pano'dan diğer kişilerin yanıtlarını gizle"
showRepliesToOthersInTimelineAll: "Pano'da takip ettiğin herkesin diğerlerine verdiği yanıtları göster" showRepliesToOthersInTimelineAll: "Pano'da takip ettiğin herkesin diğerlerine verdiği yanıtları göster"
hideRepliesToOthersInTimelineAll: "Pano'da takip ettiğin herkesten diğer kişilere verilen yanıtları gizle" hideRepliesToOthersInTimelineAll: "Pano'da takip ettiğin herkesten diğer kişilere verilen yanıtları gizle"
confirmShowRepliesAll: "Bu işlem geri alınamaz. Takip ettiğin herkesin yanıtlarını zaman çizelgende diğer kullanıcılara göstermek istiyor musun?" confirmShowRepliesAll: "Bu işlem geri alınamaz. Takip ettiğin herkesin yanıtlarını panoda diğer kullanıcılara göstermek istiyor musun?"
confirmHideRepliesAll: "Bu işlem geri alınamaz. Şu anda takip ettiğin tüm kullanıcıların yanıtlarını zaman tünelinde cidden göstermeyecek misin?" confirmHideRepliesAll: "Bu işlem geri alınamaz. Şu anda takip ettiğin tüm kullanıcıların yanıtlarını panoda cidden göstermeyecek misin?"
externalServices: "Dış Hizmetler" externalServices: "Dış Hizmetler"
sourceCode: "Kaynak kodu" sourceCode: "Kaynak kodu"
sourceCodeIsNotYetProvided: "Kaynak kodu henüz mevcut değildir. Bu sorunu gidermek için yöneticiyle iletişime geçin." sourceCodeIsNotYetProvided: "Kaynak kodu henüz mevcut değildir. Bu sorunu gidermek için yöneticiyle iletişime geçin."
@ -1570,9 +1570,9 @@ _initialTutorial:
description: "Burada, Misskey'i kullanmanın temellerini ve özelliklerini öğrenebilirsin." description: "Burada, Misskey'i kullanmanın temellerini ve özelliklerini öğrenebilirsin."
_note: _note:
title: "Not nedir?" title: "Not nedir?"
description: "Misskey'deki gönderiler “Notlar” olarak adlandırılır. Notlar zaman çizelgesinde kronolojik olarak düzenlenir ve gerçek zamanlı olarak güncellenir." description: "Misskey'deki gönderiler “Notlar” olarak adlandırılır. Notlar panoda kronolojik olarak düzenlenir ve gerçek zamanlı olarak güncellenir."
reply: "Bir mesaja yanıt vermek için bu düğmeye tıklayın. Yanıtlara yanıt vermek de mümkündür, böylece konuşma bir konu başlığı gibi devam eder." reply: "Bir mesaja yanıt vermek için bu düğmeye tıklayın. Yanıtlara yanıt vermek de mümkündür, böylece konuşma bir konu başlığı gibi devam eder."
renote: "Bu notu kendi zaman çizelgende paylaşabilirsiniz. Ayrıca yorumlarınızla birlikte alıntı da yapabilirsin." renote: "Bu notu kendi panonda paylaşabilirsin. Ayrıca yorumlarınla birlikte alıntı da yapabilirsin."
reaction: "Not'a tepkiler ekleyebilirsin. Daha fazla ayrıntı bir sonraki sayfada açıklanacak." reaction: "Not'a tepkiler ekleyebilirsin. Daha fazla ayrıntı bir sonraki sayfada açıklanacak."
menu: "Not ayrıntılarını görüntüleyebilir, bağlantıları kopyalayabilir ve çeşitli diğer işlemleri gerçekleştirebilirsin." menu: "Not ayrıntılarını görüntüleyebilir, bağlantıları kopyalayabilir ve çeşitli diğer işlemleri gerçekleştirebilirsin."
_reaction: _reaction:
@ -1640,7 +1640,7 @@ _serverSettings:
shortNameDescription: "Resmi adın uzun olması durumunda görüntülenebilen, örneğin adının kısaltması." shortNameDescription: "Resmi adın uzun olması durumunda görüntülenebilen, örneğin adının kısaltması."
fanoutTimelineDescription: "Etkinleştirildiğinde Pano alma performansını büyük ölçüde artırır ve veritabanı yükünü azaltır. Bunun karşılığında Redis'in bellek kullanımı artacaktır. Sunucu belleği düşükse veya sunucu kararsızsa bunu devre dışı bırakmayı düşün." fanoutTimelineDescription: "Etkinleştirildiğinde Pano alma performansını büyük ölçüde artırır ve veritabanı yükünü azaltır. Bunun karşılığında Redis'in bellek kullanımı artacaktır. Sunucu belleği düşükse veya sunucu kararsızsa bunu devre dışı bırakmayı düşün."
fanoutTimelineDbFallback: "Veritabanına geri dön" fanoutTimelineDbFallback: "Veritabanına geri dön"
fanoutTimelineDbFallbackDescription: "Etkinleştirildiğinde, Pano önbelleğe alınmamışsa ek sorgular için veritabanına geri döner. Bu özelliği devre dışı bırakmak, geri dönüş sürecini ortadan kaldırarak sunucu yükünü daha da azaltır, ancak alınabilecek zaman çizelgelerinin aralığını sınırlar." fanoutTimelineDbFallbackDescription: "Etkinleştirildiğinde, Pano önbelleğe alınmamışsa ek sorgular için veritabanına geri döner. Bu özelliği devre dışı bırakmak, geri dönüş sürecini ortadan kaldırarak sunucu yükünü daha da azaltır, ancak alınabilecek panoların aralığını sınırlar."
reactionsBufferingDescription: "Etkinleştirildiğinde, reaksiyon oluşturma sırasında performans büyük ölçüde artacak ve veritabanı üzerindeki yük azalacaktır. Ancak, Redis bellek kullanımı artacakt." reactionsBufferingDescription: "Etkinleştirildiğinde, reaksiyon oluşturma sırasında performans büyük ölçüde artacak ve veritabanı üzerindeki yük azalacaktır. Ancak, Redis bellek kullanımı artacakt."
remoteNotesCleaning: "Uzak notların otomatik olarak temizlenmesi" remoteNotesCleaning: "Uzak notların otomatik olarak temizlenmesi"
remoteNotesCleaning_description: "Etkinleştirildiğinde, kullanılmayan ve güncelliğini yitirmiş uzak notlar, veritabanının şişmesini önlemek için periyodik olarak temizlenecek." remoteNotesCleaning_description: "Etkinleştirildiğinde, kullanılmayan ve güncelliğini yitirmiş uzak notlar, veritabanının şişmesini önlemek için periyodik olarak temizlenecek."
@ -1668,6 +1668,7 @@ _serverSettings:
restartServerSetupWizardConfirm_text: "Bazı mevcut ayarlar sıfırlanacaktır." restartServerSetupWizardConfirm_text: "Bazı mevcut ayarlar sıfırlanacaktır."
entrancePageStyle: "Giriş sayfası stili" entrancePageStyle: "Giriş sayfası stili"
showTimelineForVisitor: "Panoyu göster" showTimelineForVisitor: "Panoyu göster"
showActivitiesForVisitor: "Aktiviteleri göster"
_userGeneratedContentsVisibilityForVisitor: _userGeneratedContentsVisibilityForVisitor:
all: "Her şey halka açıktır." all: "Her şey halka açıktır."
localOnly: "Yalnızca yerel içerik yayınlanır, uzak içerik gizli tutulur." localOnly: "Yalnızca yerel içerik yayınlanır, uzak içerik gizli tutulur."
@ -1876,7 +1877,7 @@ _achievements:
title: "Öz Referans" title: "Öz Referans"
description: "Kendi notunuzu alıntı yapın" description: "Kendi notunuzu alıntı yapın"
_htl20npm: _htl20npm:
title: "Akış Zaman Çizelgesi" title: "Akış Panosu"
description: "Ev zaman çizelgenizin hızı 20 npm'yi (dakika başına not sayısı) aşıyor mu?" description: "Ev zaman çizelgenizin hızı 20 npm'yi (dakika başına not sayısı) aşıyor mu?"
_viewInstanceChart: _viewInstanceChart:
title: "Analist" title: "Analist"
@ -1965,7 +1966,7 @@ _role:
asBadge: "Rozet olarak göster" asBadge: "Rozet olarak göster"
descriptionOfAsBadge: "This role's icon will be displayed next to the username of users with this role if turned on." descriptionOfAsBadge: "This role's icon will be displayed next to the username of users with this role if turned on."
isExplorable: "Rolü keşfedilebilir hale getir" isExplorable: "Rolü keşfedilebilir hale getir"
descriptionOfIsExplorable: "Bu rolün zaman çizelgesi ve bu role sahip kullanıcıların listesi, etkinleştirilirse kamuya açık hale getirilecek." descriptionOfIsExplorable: "Bu rolün panosu ve bu role sahip kullanıcıların listesi, etkinleştirilirse kamuya açık hale getirilecek."
displayOrder: "Pozisyon" displayOrder: "Pozisyon"
descriptionOfDisplayOrder: "Sayı ne kadar yüksekse, UI pozisyonu da o kadar yüksek olur." descriptionOfDisplayOrder: "Sayı ne kadar yüksekse, UI pozisyonu da o kadar yüksek olur."
preserveAssignmentOnMoveAccount: "Geçiş sırasında rol atamalarını koruyun" preserveAssignmentOnMoveAccount: "Geçiş sırasında rol atamalarını koruyun"
@ -1979,7 +1980,7 @@ _role:
high: "Yüksek" high: "Yüksek"
_options: _options:
gtlAvailable: "Global Pano'yu görüntüleyebilir" gtlAvailable: "Global Pano'yu görüntüleyebilir"
ltlAvailable: "Yerel zaman çizelgesini görüntüleyebilir" ltlAvailable: "Yerel panoyu görüntüleyebilir"
canPublicNote: "Halka açık notlar gönderebilir" canPublicNote: "Halka açık notlar gönderebilir"
mentionMax: "Bir notta maksimum bahsetme sayısı" mentionMax: "Bir notta maksimum bahsetme sayısı"
canInvite: "Sunucu davet kodları oluşturabilir" canInvite: "Sunucu davet kodları oluşturabilir"
@ -2484,7 +2485,7 @@ _visibility:
public: "Halka açık" public: "Halka açık"
publicDescription: "Notunuz tüm kullanıcılar tarafından görülebilir olacaktır." publicDescription: "Notunuz tüm kullanıcılar tarafından görülebilir olacaktır."
home: "Pano" home: "Pano"
homeDescription: "Yalnızca ana zaman çizelgesine gönder" homeDescription: "Yalnızca ana panoya gönder"
followers: "Takipçiler" followers: "Takipçiler"
followersDescription: "Sadece takipçilerine görünür hale getir" followersDescription: "Sadece takipçilerine görünür hale getir"
specified: "Doğrudan" specified: "Doğrudan"
@ -2531,7 +2532,7 @@ _exportOrImport:
userLists: "Kullanıcı listeleri" userLists: "Kullanıcı listeleri"
excludeMutingUsers: "Sessize alınan kullanıcıları hariç tut" excludeMutingUsers: "Sessize alınan kullanıcıları hariç tut"
excludeInactiveUsers: "Etkin olmayan kullanıcıları hariç tut" excludeInactiveUsers: "Etkin olmayan kullanıcıları hariç tut"
withReplies: "İçe aktarılan kullanıcıların yanıtlarını zaman çizelgesine dahil edin" withReplies: "İçe aktarılan kullanıcıların yanıtlarını panoya dahil edin"
_charts: _charts:
federation: "Federasyon" federation: "Federasyon"
apRequest: "Talepler" apRequest: "Talepler"
@ -2925,7 +2926,7 @@ _reversi:
freeMatch: "Ücretsiz Eşleştirme" freeMatch: "Ücretsiz Eşleştirme"
lookingForPlayer: "Rakip aranıyor..." lookingForPlayer: "Rakip aranıyor..."
gameCanceled: "Oyun iptal edildi." gameCanceled: "Oyun iptal edildi."
shareToTlTheGameWhenStart: "Oyun başlatıldığında zaman çizelgesinde paylaş" shareToTlTheGameWhenStart: "Oyun başlatıldığında panoda paylaş"
iStartedAGame: "Oyun başladı! #MisskeyReversi" iStartedAGame: "Oyun başladı! #MisskeyReversi"
opponentHasSettingsChanged: "Rakip ayarlarını değiştirmiş." opponentHasSettingsChanged: "Rakip ayarlarını değiştirmiş."
allowIrregularRules: "Düzensiz kurallar (tamamen ücretsiz)" allowIrregularRules: "Düzensiz kurallar (tamamen ücretsiz)"
@ -3153,7 +3154,7 @@ _clientPerformanceIssueTip:
_clip: _clip:
tip: "Klip, notları gruplandırmanıza olanak tanıyan bir özelliktir." tip: "Klip, notları gruplandırmanıza olanak tanıyan bir özelliktir."
_userLists: _userLists:
tip: "Listeler, oluşturulurken belirttiğin herhangi bir kullanıcıyı içerebilir. Oluşturulan liste, yalnızca belirtilen kullanıcıları gösteren bir zaman çizelgesi olarak görüntülenebilir." tip: "Listeler, oluşturulurken belirttiğin herhangi bir kullanıcıyı içerebilir. Oluşturulan liste, yalnızca belirtilen kullanıcıları gösteren bir pano olarak görüntülenebilir."
watermark: "Filigran" watermark: "Filigran"
defaultPreset: "Varsayılan Ön Ayar" defaultPreset: "Varsayılan Ön Ayar"
_watermarkEditor: _watermarkEditor:

View File

@ -1,12 +1,12 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2025.8.0", "version": "2025.9.0-beta.0",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/misskey-dev/misskey.git" "url": "https://github.com/misskey-dev/misskey.git"
}, },
"packageManager": "pnpm@10.15.0", "packageManager": "pnpm@10.15.1",
"workspaces": [ "workspaces": [
"packages/frontend-shared", "packages/frontend-shared",
"packages/frontend", "packages/frontend",
@ -62,22 +62,22 @@
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"postcss": "8.5.6", "postcss": "8.5.6",
"tar": "7.4.3", "tar": "7.4.3",
"terser": "5.43.1", "terser": "5.44.0",
"typescript": "5.9.2" "typescript": "5.9.2"
}, },
"devDependencies": { "devDependencies": {
"@misskey-dev/eslint-plugin": "2.1.0", "@misskey-dev/eslint-plugin": "2.1.0",
"@types/js-yaml": "4.0.9", "@types/js-yaml": "4.0.9",
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"cypress": "14.5.4", "cypress": "14.5.4",
"eslint": "9.34.0", "eslint": "9.35.0",
"globals": "16.3.0", "globals": "16.3.0",
"ncp": "2.0.0", "ncp": "2.0.0",
"pnpm": "10.15.0", "pnpm": "10.15.1",
"start-server-and-test": "2.0.13" "start-server-and-test": "2.1.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@tensorflow/tfjs-core": "4.22.0" "@tensorflow/tfjs-core": "4.22.0"

View File

@ -39,17 +39,17 @@
}, },
"optionalDependencies": { "optionalDependencies": {
"@swc/core-android-arm64": "1.3.11", "@swc/core-android-arm64": "1.3.11",
"@swc/core-darwin-arm64": "1.13.4", "@swc/core-darwin-arm64": "1.13.5",
"@swc/core-darwin-x64": "1.13.4", "@swc/core-darwin-x64": "1.13.5",
"@swc/core-freebsd-x64": "1.3.11", "@swc/core-freebsd-x64": "1.3.11",
"@swc/core-linux-arm-gnueabihf": "1.13.4", "@swc/core-linux-arm-gnueabihf": "1.13.5",
"@swc/core-linux-arm64-gnu": "1.13.4", "@swc/core-linux-arm64-gnu": "1.13.5",
"@swc/core-linux-arm64-musl": "1.13.4", "@swc/core-linux-arm64-musl": "1.13.5",
"@swc/core-linux-x64-gnu": "1.13.4", "@swc/core-linux-x64-gnu": "1.13.5",
"@swc/core-linux-x64-musl": "1.13.4", "@swc/core-linux-x64-musl": "1.13.5",
"@swc/core-win32-arm64-msvc": "1.13.4", "@swc/core-win32-arm64-msvc": "1.13.5",
"@swc/core-win32-ia32-msvc": "1.13.4", "@swc/core-win32-ia32-msvc": "1.13.5",
"@swc/core-win32-x64-msvc": "1.13.4", "@swc/core-win32-x64-msvc": "1.13.5",
"@tensorflow/tfjs": "4.22.0", "@tensorflow/tfjs": "4.22.0",
"@tensorflow/tfjs-node": "4.22.0", "@tensorflow/tfjs-node": "4.22.0",
"bufferutil": "4.0.9", "bufferutil": "4.0.9",
@ -69,20 +69,20 @@
"utf-8-validate": "6.0.5" "utf-8-validate": "6.0.5"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "3.873.0", "@aws-sdk/client-s3": "3.883.0",
"@aws-sdk/lib-storage": "3.873.0", "@aws-sdk/lib-storage": "3.883.0",
"@discordapp/twemoji": "16.0.1", "@discordapp/twemoji": "16.0.1",
"@fastify/accepts": "5.0.2", "@fastify/accepts": "5.0.2",
"@fastify/cookie": "11.0.2", "@fastify/cookie": "11.0.2",
"@fastify/cors": "10.1.0", "@fastify/cors": "10.1.0",
"@fastify/express": "4.0.2", "@fastify/express": "4.0.2",
"@fastify/http-proxy": "10.0.2", "@fastify/http-proxy": "10.0.2",
"@fastify/multipart": "9.0.3", "@fastify/multipart": "9.2.1",
"@fastify/static": "8.2.0", "@fastify/static": "8.2.0",
"@fastify/view": "10.0.2", "@fastify/view": "10.0.2",
"@misskey-dev/sharp-read-bmp": "1.2.0", "@misskey-dev/sharp-read-bmp": "1.2.0",
"@misskey-dev/summaly": "5.2.3", "@misskey-dev/summaly": "5.2.3",
"@napi-rs/canvas": "0.1.77", "@napi-rs/canvas": "0.1.79",
"@nestjs/common": "11.1.6", "@nestjs/common": "11.1.6",
"@nestjs/core": "11.1.6", "@nestjs/core": "11.1.6",
"@nestjs/testing": "11.1.6", "@nestjs/testing": "11.1.6",
@ -93,7 +93,7 @@
"@sinonjs/fake-timers": "11.3.1", "@sinonjs/fake-timers": "11.3.1",
"@smithy/node-http-handler": "2.5.0", "@smithy/node-http-handler": "2.5.0",
"@swc/cli": "0.7.8", "@swc/cli": "0.7.8",
"@swc/core": "1.13.4", "@swc/core": "1.13.5",
"@twemoji/parser": "16.0.0", "@twemoji/parser": "16.0.0",
"@types/redis-info": "3.0.3", "@types/redis-info": "3.0.3",
"accepts": "1.3.8", "accepts": "1.3.8",
@ -103,7 +103,7 @@
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"blurhash": "2.0.5", "blurhash": "2.0.5",
"body-parser": "1.20.3", "body-parser": "1.20.3",
"bullmq": "5.58.1", "bullmq": "5.58.5",
"cacheable-lookup": "7.0.0", "cacheable-lookup": "7.0.0",
"cbor": "9.0.2", "cbor": "9.0.2",
"chalk": "5.6.0", "chalk": "5.6.0",
@ -114,13 +114,13 @@
"content-disposition": "0.5.4", "content-disposition": "0.5.4",
"date-fns": "2.30.0", "date-fns": "2.30.0",
"deep-email-validator": "0.1.21", "deep-email-validator": "0.1.21",
"fastify": "5.5.0", "fastify": "5.6.0",
"fastify-raw-body": "5.0.0", "fastify-raw-body": "5.0.0",
"feed": "4.2.2", "feed": "4.2.2",
"file-type": "19.6.0", "file-type": "19.6.0",
"fluent-ffmpeg": "2.1.3", "fluent-ffmpeg": "2.1.3",
"form-data": "4.0.4", "form-data": "4.0.4",
"got": "14.4.7", "got": "14.4.8",
"happy-dom": "16.8.1", "happy-dom": "16.8.1",
"hpagent": "1.2.0", "hpagent": "1.2.0",
"htmlescape": "1.1.1", "htmlescape": "1.1.1",
@ -141,7 +141,7 @@
"mime-types": "2.1.35", "mime-types": "2.1.35",
"misskey-js": "workspace:*", "misskey-js": "workspace:*",
"misskey-reversi": "workspace:*", "misskey-reversi": "workspace:*",
"ms": "3.0.0-canary.1", "ms": "3.0.0-canary.202508261828",
"nanoid": "5.1.5", "nanoid": "5.1.5",
"nested-property": "4.0.0", "nested-property": "4.0.0",
"node-fetch": "3.3.2", "node-fetch": "3.3.2",
@ -175,7 +175,7 @@
"slacc": "0.0.10", "slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0", "strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0", "stringz": "2.1.0",
"systeminformation": "5.27.7", "systeminformation": "5.27.8",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tmp": "0.2.5", "tmp": "0.2.5",
"tsc-alias": "1.8.16", "tsc-alias": "1.8.16",
@ -210,7 +210,7 @@
"@types/jsrsasign": "10.5.15", "@types/jsrsasign": "10.5.15",
"@types/mime-types": "2.1.4", "@types/mime-types": "2.1.4",
"@types/ms": "0.7.34", "@types/ms": "0.7.34",
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@types/nodemailer": "6.4.19", "@types/nodemailer": "6.4.19",
"@types/oauth": "0.9.6", "@types/oauth": "0.9.6",
"@types/oauth2orize": "1.11.5", "@types/oauth2orize": "1.11.5",
@ -222,7 +222,7 @@
"@types/ratelimiter": "3.4.6", "@types/ratelimiter": "3.4.6",
"@types/rename": "1.0.7", "@types/rename": "1.0.7",
"@types/sanitize-html": "2.16.0", "@types/sanitize-html": "2.16.0",
"@types/semver": "7.7.0", "@types/semver": "7.7.1",
"@types/simple-oauth2": "5.0.7", "@types/simple-oauth2": "5.0.7",
"@types/sinonjs__fake-timers": "8.1.5", "@types/sinonjs__fake-timers": "8.1.5",
"@types/supertest": "6.0.3", "@types/supertest": "6.0.3",
@ -231,8 +231,8 @@
"@types/vary": "1.1.3", "@types/vary": "1.1.3",
"@types/web-push": "3.6.4", "@types/web-push": "3.6.4",
"@types/ws": "8.18.1", "@types/ws": "8.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"aws-sdk-client-mock": "4.1.0", "aws-sdk-client-mock": "4.1.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"eslint-plugin-import": "2.32.0", "eslint-plugin-import": "2.32.0",

View File

@ -29,7 +29,7 @@ export class AiService {
} }
@bindThis @bindThis
public async detectSensitive(path: string): Promise<nsfw.PredictionType[] | null> { public async detectSensitive(source: string | Buffer): Promise<nsfw.PredictionType[] | null> {
try { try {
if (isSupportedCpu === undefined) { if (isSupportedCpu === undefined) {
isSupportedCpu = await this.computeIsSupportedCpu(); isSupportedCpu = await this.computeIsSupportedCpu();
@ -51,7 +51,7 @@ export class AiService {
}); });
} }
const buffer = await fs.promises.readFile(path); const buffer = source instanceof Buffer ? source : await fs.promises.readFile(source);
const image = await tf.node.decodeImage(buffer, 3) as any; const image = await tf.node.decodeImage(buffer, 3) as any;
try { try {
const predictions = await this.model.classify(image); const predictions = await this.model.classify(image);

View File

@ -21,6 +21,7 @@ import { LoggerService } from '@/core/LoggerService.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import type { PredictionType } from 'nsfwjs'; import type { PredictionType } from 'nsfwjs';
import { isMimeImage } from '@/misc/is-mime-image.js';
export type FileInfo = { export type FileInfo = {
size: number; size: number;
@ -204,16 +205,7 @@ export class FileInfoService {
return [sensitive, porn]; return [sensitive, porn];
} }
if ([ if (analyzeVideo && (mime === 'image/apng' || mime.startsWith('video/'))) {
'image/jpeg',
'image/png',
'image/webp',
].includes(mime)) {
const result = await this.aiService.detectSensitive(source);
if (result) {
[sensitive, porn] = judgePrediction(result);
}
} else if (analyzeVideo && (mime === 'image/apng' || mime.startsWith('video/'))) {
const [outDir, disposeOutDir] = await createTempDir(); const [outDir, disposeOutDir] = await createTempDir();
try { try {
const command = FFmpeg() const command = FFmpeg()
@ -281,6 +273,23 @@ export class FileInfoService {
} finally { } finally {
disposeOutDir(); disposeOutDir();
} }
} else if (isMimeImage(mime, 'sharp-convertible-image-with-bmp')) {
/*
* tfjs-node sharp PNG
* 使299x299に事前にリサイズする
*/
const png = await (await sharpBmp(source, mime))
.resize(299, 299, {
withoutEnlargement: false,
})
.rotate()
.flatten({ background: { r: 119, g: 119, b: 119 } }) // 透過部分を18%グレーで塗りつぶす
.png()
.toBuffer();
const result = await this.aiService.detectSensitive(png);
if (result) {
[sensitive, porn] = judgePrediction(result);
}
} }
return [sensitive, porn]; return [sensitive, porn];

View File

@ -756,8 +756,8 @@ export class QueueService {
@bindThis @bindThis
public async queueRetryJob(queueType: typeof QUEUE_TYPES[number], jobId: string) { public async queueRetryJob(queueType: typeof QUEUE_TYPES[number], jobId: string) {
const queue = this.getQueue(queueType); const queue = this.getQueue(queueType);
const job: Bull.Job | null = await queue.getJob(jobId); const job = await queue.getJob(jobId);
if (job) { if (job != null) {
if (job.finishedOn != null) { if (job.finishedOn != null) {
await job.retry(); await job.retry();
} else { } else {
@ -769,8 +769,8 @@ export class QueueService {
@bindThis @bindThis
public async queueRemoveJob(queueType: typeof QUEUE_TYPES[number], jobId: string) { public async queueRemoveJob(queueType: typeof QUEUE_TYPES[number], jobId: string) {
const queue = this.getQueue(queueType); const queue = this.getQueue(queueType);
const job: Bull.Job | null = await queue.getJob(jobId); const job = await queue.getJob(jobId);
if (job) { if (job != null) {
await job.remove(); await job.remove();
} }
} }
@ -803,8 +803,8 @@ export class QueueService {
@bindThis @bindThis
public async queueGetJob(queueType: typeof QUEUE_TYPES[number], jobId: string) { public async queueGetJob(queueType: typeof QUEUE_TYPES[number], jobId: string) {
const queue = this.getQueue(queueType); const queue = this.getQueue(queueType);
const job: Bull.Job | null = await queue.getJob(jobId); const job = await queue.getJob(jobId);
if (job) { if (job != null) {
return this.packJobData(job); return this.packJobData(job);
} else { } else {
throw new Error(`Job not found: ${jobId}`); throw new Error(`Job not found: ${jobId}`);

View File

@ -176,6 +176,17 @@ export class ApiServerService {
} }
}); });
fastify.all('/clear-browser-cache', (request, reply) => {
if (['GET', 'POST'].includes(request.method)) {
reply.header('Clear-Site-Data', '"cache", "prefetchCache", "prerenderCache", "executionContexts"');
reply.code(204);
reply.send();
} else {
reply.code(405);
reply.send();
}
});
// Make sure any unknown path under /api returns HTTP 404 Not Found, // Make sure any unknown path under /api returns HTTP 404 Not Found,
// because otherwise ClientServerService will return the base client HTML // because otherwise ClientServerService will return the base client HTML
// page with HTTP 200. // page with HTTP 200.

View File

@ -201,6 +201,8 @@ export class ClientServerService {
@bindThis @bindThis
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) { public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
const configUrl = new URL(this.config.url);
fastify.register(fastifyView, { fastify.register(fastifyView, {
root: _dirname + '/views', root: _dirname + '/views',
engine: { engine: {
@ -239,7 +241,6 @@ export class ClientServerService {
done(); done();
}); });
} else { } else {
const configUrl = new URL(this.config.url);
const urlOriginWithoutPort = configUrl.origin.replace(/:\d+$/, ''); const urlOriginWithoutPort = configUrl.origin.replace(/:\d+$/, '');
const port = (process.env.VITE_PORT ?? '5173'); const port = (process.env.VITE_PORT ?? '5173');
@ -887,6 +888,22 @@ export class ClientServerService {
[, ...target.split('/').filter(x => x), ...source.split('/').filter(x => x).splice(depth)].join('/'); [, ...target.split('/').filter(x => x), ...source.split('/').filter(x => x).splice(depth)].join('/');
fastify.get('/flush', async (request, reply) => { fastify.get('/flush', async (request, reply) => {
let sendHeader = true;
if (request.headers['origin']) {
const originURL = new URL(request.headers['origin']);
if (originURL.protocol !== 'https:') { // Clear-Site-Data only supports https
sendHeader = false;
}
if (originURL.host !== configUrl.host) {
sendHeader = false;
}
}
if (sendHeader) {
reply.header('Clear-Site-Data', '"*"');
}
reply.header('Set-Cookie', 'http-flush-failed=1; Path=/flush; Max-Age=60');
return await reply.view('flush'); return await reply.view('flush');
}); });

View File

@ -6,8 +6,11 @@ html
const msg = document.getElementById('msg'); const msg = document.getElementById('msg');
const successText = `\nSuccess Flush! <a href="/">Back to Misskey</a>\n成功しました。<a href="/">Misskeyを開き直してください。</a>`; const successText = `\nSuccess Flush! <a href="/">Back to Misskey</a>\n成功しました。<a href="/">Misskeyを開き直してください。</a>`;
message('Start flushing.'); if (!document.cookie) {
message('Your site data is fully cleared by your browser.');
message(successText);
} else {
message('Your browser does not support Clear-Site-Data header. Start opportunistic flushing.');
(async function() { (async function() {
try { try {
localStorage.clear(); localStorage.clear();
@ -33,7 +36,7 @@ html
message(successText); message(successText);
} catch (e) { } catch (e) {
message(`\n${e}\n\nFlush Failed. <a href="/flush">Please retry.</a>\n失敗しました。<a href="/flush">もう一度試してみてください。</a>`); message(`\n${e}\n\nFlush Failed. <a href="/flush">Please retry.</a>\n失敗しました。<a href="/flush">もう一度試してみてください。</a>`);
message(`\nIf you retry more than 3 times, clear the browser cache or contact to instance admin.\n3回以上試しても失敗する場合、ブラウザのキャッシュを消去し、それでもだめならインスタンス管理者に連絡してみてください。\n`) message(`\nIf you retry more than 3 times, try manually clearing the browser cache or contact to instance admin.\n3回以上試しても失敗する場合、ブラウザのキャッシュを手動で消去し、それでもだめならインスタンス管理者に連絡してみてください。\n`)
console.error(e); console.error(e);
setTimeout(() => { setTimeout(() => {
@ -41,6 +44,7 @@ html
}, 10000) }, 10000)
} }
})(); })();
}
function message(text) { function message(text) {
msg.insertAdjacentHTML('beforeend', `<p>[${(new Date()).toString()}] ${text.replace(/\n/g,'<br>')}</p>`) msg.insertAdjacentHTML('beforeend', `<p>[${(new Date()).toString()}] ${text.replace(/\n/g,'<br>')}</p>`)

View File

@ -13,10 +13,10 @@
"@discordapp/twemoji": "16.0.1", "@discordapp/twemoji": "16.0.1",
"@rollup/plugin-json": "6.1.0", "@rollup/plugin-json": "6.1.0",
"@rollup/plugin-replace": "6.0.2", "@rollup/plugin-replace": "6.0.2",
"@rollup/pluginutils": "5.2.0", "@rollup/pluginutils": "5.3.0",
"@twemoji/parser": "16.0.0", "@twemoji/parser": "16.0.0",
"@vitejs/plugin-vue": "6.0.1", "@vitejs/plugin-vue": "6.0.1",
"@vue/compiler-sfc": "3.5.19", "@vue/compiler-sfc": "3.5.21",
"astring": "1.9.0", "astring": "1.9.0",
"buraha": "0.0.1", "buraha": "0.0.1",
"estree-walker": "3.0.3", "estree-walker": "3.0.3",
@ -26,16 +26,16 @@
"mfm-js": "0.25.0", "mfm-js": "0.25.0",
"misskey-js": "workspace:*", "misskey-js": "workspace:*",
"punycode.js": "2.3.1", "punycode.js": "2.3.1",
"rollup": "4.48.0", "rollup": "4.50.1",
"sass": "1.90.0", "sass": "1.92.1",
"shiki": "3.11.0", "shiki": "3.12.2",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tsc-alias": "1.8.16", "tsc-alias": "1.8.16",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"typescript": "5.9.2", "typescript": "5.9.2",
"uuid": "11.1.0", "uuid": "11.1.0",
"vite": "7.1.3", "vite": "7.1.4",
"vue": "3.5.19" "vue": "3.5.21"
}, },
"devDependencies": { "devDependencies": {
"@misskey-dev/summaly": "5.2.3", "@misskey-dev/summaly": "5.2.3",
@ -43,14 +43,14 @@
"@testing-library/vue": "8.1.0", "@testing-library/vue": "8.1.0",
"@types/estree": "1.0.8", "@types/estree": "1.0.8",
"@types/micromatch": "4.0.9", "@types/micromatch": "4.0.9",
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@types/punycode.js": "npm:@types/punycode@2.1.4", "@types/punycode.js": "npm:@types/punycode@2.1.4",
"@types/tinycolor2": "1.4.6", "@types/tinycolor2": "1.4.6",
"@types/ws": "8.18.1", "@types/ws": "8.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"@vitest/coverage-v8": "3.2.4", "@vitest/coverage-v8": "3.2.4",
"@vue/runtime-core": "3.5.19", "@vue/runtime-core": "3.5.21",
"acorn": "8.15.0", "acorn": "8.15.0",
"cross-env": "10.0.0", "cross-env": "10.0.0",
"eslint-plugin-import": "2.32.0", "eslint-plugin-import": "2.32.0",
@ -59,11 +59,11 @@
"happy-dom": "18.0.1", "happy-dom": "18.0.1",
"intersection-observer": "0.12.2", "intersection-observer": "0.12.2",
"micromatch": "4.0.8", "micromatch": "4.0.8",
"msw": "2.10.5", "msw": "2.11.1",
"nodemon": "3.1.10", "nodemon": "3.1.10",
"prettier": "3.6.2", "prettier": "3.6.2",
"start-server-and-test": "2.0.13", "start-server-and-test": "2.1.0",
"tsx": "4.20.4", "tsx": "4.20.5",
"vite-plugin-turbosnap": "1.0.3", "vite-plugin-turbosnap": "1.0.3",
"vue-component-type-helpers": "3.0.6", "vue-component-type-helpers": "3.0.6",
"vue-eslint-parser": "10.2.0", "vue-eslint-parser": "10.2.0",

View File

@ -21,9 +21,9 @@
"lint": "pnpm typecheck && pnpm eslint" "lint": "pnpm typecheck && pnpm eslint"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"esbuild": "0.25.9", "esbuild": "0.25.9",
"eslint-plugin-vue": "10.4.0", "eslint-plugin-vue": "10.4.0",
"nodemon": "3.1.10", "nodemon": "3.1.10",
@ -35,6 +35,6 @@
], ],
"dependencies": { "dependencies": {
"misskey-js": "workspace:*", "misskey-js": "workspace:*",
"vue": "3.5.19" "vue": "3.5.21"
} }
} }

View File

@ -23,13 +23,13 @@
"@misskey-dev/browser-image-resizer": "2024.1.0", "@misskey-dev/browser-image-resizer": "2024.1.0",
"@rollup/plugin-json": "6.1.0", "@rollup/plugin-json": "6.1.0",
"@rollup/plugin-replace": "6.0.2", "@rollup/plugin-replace": "6.0.2",
"@rollup/pluginutils": "5.2.0", "@rollup/pluginutils": "5.3.0",
"@sentry/vue": "10.5.0", "@sentry/vue": "10.10.0",
"@syuilo/aiscript": "1.1.0", "@syuilo/aiscript": "1.1.0",
"@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0", "@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0",
"@twemoji/parser": "16.0.0", "@twemoji/parser": "16.0.0",
"@vitejs/plugin-vue": "6.0.1", "@vitejs/plugin-vue": "6.0.1",
"@vue/compiler-sfc": "3.5.19", "@vue/compiler-sfc": "3.5.21",
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.15", "aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.15",
"analytics": "0.8.19", "analytics": "0.8.19",
"astring": "1.9.0", "astring": "1.9.0",
@ -41,7 +41,7 @@
"chartjs-chart-matrix": "3.0.0", "chartjs-chart-matrix": "3.0.0",
"chartjs-plugin-gradient": "0.6.1", "chartjs-plugin-gradient": "0.6.1",
"chartjs-plugin-zoom": "2.2.0", "chartjs-plugin-zoom": "2.2.0",
"chromatic": "13.1.3", "chromatic": "13.1.4",
"compare-versions": "6.1.1", "compare-versions": "6.1.1",
"cropperjs": "2.0.1", "cropperjs": "2.0.1",
"date-fns": "4.1.0", "date-fns": "4.1.0",
@ -65,21 +65,21 @@
"punycode.js": "2.3.1", "punycode.js": "2.3.1",
"qr-code-styling": "1.9.2", "qr-code-styling": "1.9.2",
"qr-scanner": "1.4.2", "qr-scanner": "1.4.2",
"rollup": "4.48.0", "rollup": "4.50.1",
"sanitize-html": "2.17.0", "sanitize-html": "2.17.0",
"sass": "1.90.0", "sass": "1.92.1",
"shiki": "3.11.0", "shiki": "3.12.2",
"strict-event-emitter-types": "2.0.0", "strict-event-emitter-types": "2.0.0",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
"three": "0.179.1", "three": "0.180.0",
"throttle-debounce": "5.0.2", "throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tsc-alias": "1.8.16", "tsc-alias": "1.8.16",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"typescript": "5.9.2", "typescript": "5.9.2",
"v-code-diff": "1.13.1", "v-code-diff": "1.13.1",
"vite": "7.1.3", "vite": "7.1.4",
"vue": "3.5.19", "vue": "3.5.21",
"vuedraggable": "next", "vuedraggable": "next",
"wanakana": "5.3.1" "wanakana": "5.3.1"
}, },
@ -87,7 +87,7 @@
"@misskey-dev/summaly": "5.2.3", "@misskey-dev/summaly": "5.2.3",
"@storybook/addon-essentials": "8.6.14", "@storybook/addon-essentials": "8.6.14",
"@storybook/addon-interactions": "8.6.14", "@storybook/addon-interactions": "8.6.14",
"@storybook/addon-links": "9.1.3", "@storybook/addon-links": "9.1.5",
"@storybook/addon-mdx-gfm": "8.6.14", "@storybook/addon-mdx-gfm": "8.6.14",
"@storybook/addon-storysource": "8.6.14", "@storybook/addon-storysource": "8.6.14",
"@storybook/blocks": "8.6.14", "@storybook/blocks": "8.6.14",
@ -95,31 +95,31 @@
"@storybook/core-events": "8.6.14", "@storybook/core-events": "8.6.14",
"@storybook/manager-api": "8.6.14", "@storybook/manager-api": "8.6.14",
"@storybook/preview-api": "8.6.14", "@storybook/preview-api": "8.6.14",
"@storybook/react": "9.1.3", "@storybook/react": "9.1.5",
"@storybook/react-vite": "9.1.3", "@storybook/react-vite": "9.1.5",
"@storybook/test": "8.6.14", "@storybook/test": "8.6.14",
"@storybook/theming": "8.6.14", "@storybook/theming": "8.6.14",
"@storybook/types": "8.6.14", "@storybook/types": "8.6.14",
"@storybook/vue3": "9.1.3", "@storybook/vue3": "9.1.5",
"@storybook/vue3-vite": "9.1.3", "@storybook/vue3-vite": "9.1.5",
"@tabler/icons-webfont": "3.34.1", "@tabler/icons-webfont": "3.34.1",
"@testing-library/vue": "8.1.0", "@testing-library/vue": "8.1.0",
"@types/canvas-confetti": "1.9.0", "@types/canvas-confetti": "1.9.0",
"@types/estree": "1.0.8", "@types/estree": "1.0.8",
"@types/matter-js": "0.20.0", "@types/matter-js": "0.20.0",
"@types/micromatch": "4.0.9", "@types/micromatch": "4.0.9",
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@types/punycode.js": "npm:@types/punycode@2.1.4", "@types/punycode.js": "npm:@types/punycode@2.1.4",
"@types/sanitize-html": "2.16.0", "@types/sanitize-html": "2.16.0",
"@types/seedrandom": "3.0.8", "@types/seedrandom": "3.0.8",
"@types/throttle-debounce": "5.0.2", "@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6", "@types/tinycolor2": "1.4.6",
"@types/ws": "8.18.1", "@types/ws": "8.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"@vitest/coverage-v8": "3.2.4", "@vitest/coverage-v8": "3.2.4",
"@vue/compiler-core": "3.5.19", "@vue/compiler-core": "3.5.21",
"@vue/runtime-core": "3.5.19", "@vue/runtime-core": "3.5.21",
"acorn": "8.15.0", "acorn": "8.15.0",
"cross-env": "10.0.0", "cross-env": "10.0.0",
"cypress": "14.5.4", "cypress": "14.5.4",
@ -130,17 +130,17 @@
"intersection-observer": "0.12.2", "intersection-observer": "0.12.2",
"micromatch": "4.0.8", "micromatch": "4.0.8",
"minimatch": "10.0.3", "minimatch": "10.0.3",
"msw": "2.10.5", "msw": "2.11.1",
"msw-storybook-addon": "2.0.5", "msw-storybook-addon": "2.0.5",
"nodemon": "3.1.10", "nodemon": "3.1.10",
"prettier": "3.6.2", "prettier": "3.6.2",
"react": "19.1.1", "react": "19.1.1",
"react-dom": "19.1.1", "react-dom": "19.1.1",
"seedrandom": "3.0.5", "seedrandom": "3.0.5",
"start-server-and-test": "2.0.13", "start-server-and-test": "2.1.0",
"storybook": "9.1.3", "storybook": "9.1.5",
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
"tsx": "4.20.4", "tsx": "4.20.5",
"vite-plugin-turbosnap": "1.0.3", "vite-plugin-turbosnap": "1.0.3",
"vitest": "3.2.4", "vitest": "3.2.4",
"vitest-fetch-mock": "0.4.5", "vitest-fetch-mock": "0.4.5",

View File

@ -251,13 +251,30 @@ export async function openAccountMenu(opts: {
} }
}, },
}; };
} else { } else { // プロファイルを復元した場合などはアカウントのトークンや詳細情報はstoreにキャッシュされていない
return { return {
type: 'button' as const, type: 'button' as const,
text: username, text: username,
active: opts.active != null ? opts.active === id : false, active: opts.active != null ? opts.active === id : false,
action: async () => { action: async () => {
// TODO const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {
initialUsername: username,
}, {
done: async (res: Misskey.entities.SigninFlowResponse & { finished: true }) => {
store.set('accountTokens', { ...store.s.accountTokens, [host + '/' + res.id]: res.i });
if (callback) {
fetchAccount(res.i, id).then(account => {
callback(account);
});
} else {
switchAccount(host, id);
}
},
closed: () => {
dispose();
},
});
}, },
}; };
} }

View File

@ -7,8 +7,8 @@ import * as Misskey from 'misskey-js';
import { Cache } from '@/utility/cache.js'; import { Cache } from '@/utility/cache.js';
import { misskeyApi } from '@/utility/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
export const clipsCache = new Cache<Misskey.entities.Clip[]>(1000 * 60 * 30, () => misskeyApi('clips/list')); export const clipsCache = new Cache<Misskey.entities.Clip[]>(1000 * 60 * 30, () => misskeyApi('clips/list', { limit: 30 }));
export const rolesCache = new Cache(1000 * 60 * 30, () => misskeyApi('admin/roles/list')); export const rolesCache = new Cache(1000 * 60 * 30, () => misskeyApi('admin/roles/list', { limit: 30 }));
export const userListsCache = new Cache<Misskey.entities.UserList[]>(1000 * 60 * 30, () => misskeyApi('users/lists/list')); export const userListsCache = new Cache<Misskey.entities.UserList[]>(1000 * 60 * 30, () => misskeyApi('users/lists/list'));
export const antennasCache = new Cache<Misskey.entities.Antenna[]>(1000 * 60 * 30, () => misskeyApi('antennas/list')); export const antennasCache = new Cache<Misskey.entities.Antenna[]>(1000 * 60 * 30, () => misskeyApi('antennas/list', { limit: 30 }));
export const favoritedChannelsCache = new Cache<Misskey.entities.Channel[]>(1000 * 60 * 30, () => misskeyApi('channels/my-favorites', { limit: 100 })); export const favoritedChannelsCache = new Cache<Misskey.entities.Channel[]>(1000 * 60 * 30, () => misskeyApi('channels/my-favorites', { limit: 100 }));

View File

@ -78,7 +78,7 @@ function subscribe() {
// SEE: https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe#Parameters // SEE: https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe#Parameters
return promiseDialog(registration.value.pushManager.subscribe({ return promiseDialog(registration.value.pushManager.subscribe({
userVisibleOnly: true, userVisibleOnly: true,
applicationServerKey: urlBase64ToBase64(instance.swPublickey), applicationServerKey: urlBase64ToUint8Array(instance.swPublickey),
}) })
.then(async subscription => { .then(async subscription => {
pushSubscription.value = subscription; pushSubscription.value = subscription;
@ -131,16 +131,22 @@ function encode(buffer: ArrayBuffer | null) {
} }
/** /**
* Convert the URL safe base64 string to a base64 string * Convert the URL safe base64 string to a Uint8Array
* @param base64String base64 string * @param base64String base64 string
*/ */
function urlBase64ToBase64(base64String: string): string { function urlBase64ToUint8Array(base64String: string): Uint8Array {
const padding = '='.repeat((4 - base64String.length % 4) % 4); const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding) const base64 = (base64String + padding)
.replace(/-/g, '+') .replace(/-/g, '+')
.replace(/_/g, '/'); .replace(/_/g, '/');
return base64; const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
} }
if (navigator.serviceWorker == null) { if (navigator.serviceWorker == null) {

View File

@ -69,9 +69,11 @@ import MkInfo from '@/components/MkInfo.vue';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
message?: string, message?: string,
openOnRemote?: OpenOnRemoteOptions, openOnRemote?: OpenOnRemoteOptions,
initialUsername?: string;
}>(), { }>(), {
message: '', message: '',
openOnRemote: undefined, openOnRemote: undefined,
initialUsername: undefined,
}); });
const emit = defineEmits<{ const emit = defineEmits<{
@ -81,7 +83,7 @@ const emit = defineEmits<{
const host = toUnicode(configHost); const host = toUnicode(configHost);
const username = ref(''); const username = ref(props.initialUsername ?? '');
//#region Open on remote //#region Open on remote
function openRemote(options: OpenOnRemoteOptions, targetHost?: string): void { function openRemote(options: OpenOnRemoteOptions, targetHost?: string): void {

View File

@ -20,6 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
key="input" key="input"
:message="message" :message="message"
:openOnRemote="openOnRemote" :openOnRemote="openOnRemote"
:initialUsername="initialUsername"
@usernameSubmitted="onUsernameSubmitted" @usernameSubmitted="onUsernameSubmitted"
@passkeyClick="onPasskeyLogin" @passkeyClick="onPasskeyLogin"
@ -89,10 +90,12 @@ const props = withDefaults(defineProps<{
autoSet?: boolean; autoSet?: boolean;
message?: string, message?: string,
openOnRemote?: OpenOnRemoteOptions, openOnRemote?: OpenOnRemoteOptions,
initialUsername?: string;
}>(), { }>(), {
autoSet: false, autoSet: false,
message: '', message: '',
openOnRemote: undefined, openOnRemote: undefined,
initialUsername: undefined,
}); });
const page = ref<'input' | 'password' | 'totp' | 'passkey'>('input'); const page = ref<'input' | 'password' | 'totp' | 'passkey'>('input');

View File

@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button :class="$style.closeButton" class="_button" @click="onClose"><i class="ti ti-x"></i></button> <button :class="$style.closeButton" class="_button" @click="onClose"><i class="ti ti-x"></i></button>
</div> </div>
<div :class="$style.content"> <div :class="$style.content">
<MkSignin :autoSet="autoSet" :message="message" :openOnRemote="openOnRemote" @login="onLogin"/> <MkSignin :autoSet="autoSet" :message="message" :openOnRemote="openOnRemote" :initialUsername="initialUsername" @login="onLogin"/>
</div> </div>
</div> </div>
</MkModal> </MkModal>
@ -34,10 +34,12 @@ withDefaults(defineProps<{
autoSet?: boolean; autoSet?: boolean;
message?: string, message?: string,
openOnRemote?: OpenOnRemoteOptions, openOnRemote?: OpenOnRemoteOptions,
initialUsername?: string;
}>(), { }>(), {
autoSet: false, autoSet: false,
message: '', message: '',
openOnRemote: undefined, openOnRemote: undefined,
initialUsername: undefined,
}); });
const emit = defineEmits<{ const emit = defineEmits<{

View File

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<a ref="el" :href="to" :class="active ? activeClass : null" @click.prevent="nav" @contextmenu.prevent.stop="onContextmenu"> <a ref="el" :href="to" :class="active ? activeClass : null" @click="nav" @contextmenu.prevent.stop="onContextmenu">
<slot></slot> <slot></slot>
</a> </a>
</template> </template>
@ -86,6 +86,11 @@ function openWindow() {
} }
function nav(ev: MouseEvent) { function nav(ev: MouseEvent) {
// shift
if (ev.metaKey || ev.altKey || ev.ctrlKey) return;
ev.preventDefault();
if (behavior === 'browser') { if (behavior === 'browser') {
window.location.href = props.to; window.location.href = props.to;
return; return;

View File

@ -1,4 +1,3 @@
@ -1,70 +0,0 @@
<!-- <!--
SPDX-FileCopyrightText: syuilo and misskey-project SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only SPDX-License-Identifier: AGPL-3.0-only

View File

@ -131,6 +131,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<hr> <hr>
<MkButton @click="forceCloudBackup">Force cloud backup</MkButton>
<hr>
<template v-if="$i.policies.chatAvailability !== 'unavailable'"> <template v-if="$i.policies.chatAvailability !== 'unavailable'">
<MkButton @click="readAllChatMessages">Read all chat messages</MkButton> <MkButton @click="readAllChatMessages">Read all chat messages</MkButton>
@ -167,6 +171,7 @@ import { signout } from '@/signout.js';
import { migrateOldSettings } from '@/pref-migrate.js'; import { migrateOldSettings } from '@/pref-migrate.js';
import { hideAllTips as _hideAllTips, resetAllTips as _resetAllTips } from '@/tips.js'; import { hideAllTips as _hideAllTips, resetAllTips as _resetAllTips } from '@/tips.js';
import { suggestReload } from '@/utility/reload-suggest.js'; import { suggestReload } from '@/utility/reload-suggest.js';
import { cloudBackup } from '@/preferences/utility.js';
const $i = ensureSignin(); const $i = ensureSignin();
@ -224,6 +229,11 @@ function readAllChatMessages() {
os.apiWithDialog('chat/read-all', {}); os.apiWithDialog('chat/read-all', {});
} }
async function forceCloudBackup() {
await cloudBackup();
os.success();
}
const headerActions = computed(() => []); const headerActions = computed(() => []);
const headerTabs = computed(() => []); const headerTabs = computed(() => []);

View File

@ -34,7 +34,7 @@ import { instance as meta } from '@/instance.js';
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
width: 80vw; // 100%shape width: 100vw;
height: 100vh; height: 100vh;
} }

View File

@ -205,7 +205,7 @@ type HandlerDef = {
handler: (note: Misskey.entities.Note) => void; handler: (note: Misskey.entities.Note) => void;
}; };
note_view_interruptor: { note_view_interruptor: {
handler: (note: Misskey.entities.Note) => Misskey.entities.Note; handler: (note: Misskey.entities.Note) => Misskey.entities.Note | null;
}; };
note_post_interruptor: { note_post_interruptor: {
handler: (note: FIXME) => unknown; handler: (note: FIXME) => unknown;

View File

@ -4,6 +4,7 @@
*/ */
import { unisonReload } from '@/utility/unison-reload.js'; import { unisonReload } from '@/utility/unison-reload.js';
import { misskeyApiGet } from '@/utility/misskey-api.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { miLocalStorage } from '@/local-storage.js'; import { miLocalStorage } from '@/local-storage.js';
import { fetchCustomEmojis } from '@/custom-emojis.js'; import { fetchCustomEmojis } from '@/custom-emojis.js';
@ -16,6 +17,9 @@ export async function clearCache() {
miLocalStorage.removeItem('theme'); miLocalStorage.removeItem('theme');
miLocalStorage.removeItem('emojis'); miLocalStorage.removeItem('emojis');
miLocalStorage.removeItem('lastEmojisFetchedAt'); miLocalStorage.removeItem('lastEmojisFetchedAt');
await misskeyApiGet('clear-browser-cache', {}).catch(() => {
// ignore
});
await fetchInstance(true); await fetchInstance(true);
await fetchCustomEmojis(true); await fetchCustomEmojis(true);
unisonReload(); unisonReload();

View File

@ -7,25 +7,26 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkContainer :showHeader="widgetProps.showHeader" class="mkw-aiscriptApp"> <MkContainer :showHeader="widgetProps.showHeader" class="mkw-aiscriptApp">
<template #header>App</template> <template #header>App</template>
<div :class="$style.root"> <div :class="$style.root">
<MkAsUi v-if="root" :component="root" :components="components" size="small"/> <div v-if="isSyntaxError">Syntax error :(</div>
<MkAsUi v-else-if="root" :component="root" :components="components" size="small"/>
</div> </div>
</MkContainer> </MkContainer>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import type { Ref } from 'vue';
import { Interpreter, Parser } from '@syuilo/aiscript'; import { Interpreter, Parser } from '@syuilo/aiscript';
import { useWidgetPropsManager } from './widget.js'; import { useWidgetPropsManager } from './widget.js';
import type { Ref } from 'vue';
import type { WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js'; import type { WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js';
import type { FormWithDefault, GetFormResultType } from '@/utility/form.js'; import type { FormWithDefault, GetFormResultType } from '@/utility/form.js';
import type { AsUiComponent, AsUiRoot } from '@/aiscript/ui.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js';
import { $i } from '@/i.js'; import { $i } from '@/i.js';
import MkAsUi from '@/components/MkAsUi.vue'; import MkAsUi from '@/components/MkAsUi.vue';
import MkContainer from '@/components/MkContainer.vue'; import MkContainer from '@/components/MkContainer.vue';
import { registerAsUiLib } from '@/aiscript/ui.js'; import { registerAsUiLib } from '@/aiscript/ui.js';
import type { AsUiComponent, AsUiRoot } from '@/aiscript/ui.js';
const name = 'aiscriptApp'; const name = 'aiscriptApp';
@ -56,8 +57,11 @@ const parser = new Parser();
const root = ref<AsUiRoot>(); const root = ref<AsUiRoot>();
const components = ref<Ref<AsUiComponent>[]>([]); const components = ref<Ref<AsUiComponent>[]>([]);
const isSyntaxError = ref(false);
async function run() { async function run() {
isSyntaxError.value = false;
const aiscript = new Interpreter({ const aiscript = new Interpreter({
...createAiScriptEnv({ ...createAiScriptEnv({
storageKey: 'widget', storageKey: 'widget',
@ -80,10 +84,7 @@ async function run() {
try { try {
ast = parser.parse(widgetProps.script); ast = parser.parse(widgetProps.script);
} catch (err) { } catch (err) {
os.alert({ isSyntaxError.value = true;
type: 'error',
text: 'Syntax error :(',
});
return; return;
} }
try { try {

View File

@ -52,7 +52,7 @@ const { widgetProps, configure } = useWidgetPropsManager(name,
const parser = new Parser(); const parser = new Parser();
const run = async () => { async function run() {
const aiscript = new Interpreter(createAiScriptEnv({ const aiscript = new Interpreter(createAiScriptEnv({
storageKey: 'widget', storageKey: 'widget',
token: $i?.token, token: $i?.token,
@ -84,7 +84,7 @@ const run = async () => {
text: err instanceof Error ? err.message : String(err), text: err instanceof Error ? err.message : String(err),
}); });
} }
}; }
defineExpose<WidgetComponentExpose>({ defineExpose<WidgetComponentExpose>({
name, name,

View File

@ -11,16 +11,16 @@
"lint": "pnpm typecheck && pnpm eslint" "lint": "pnpm typecheck && pnpm eslint"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@types/wawoff2": "1.0.2", "@types/wawoff2": "1.0.2",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0" "@typescript-eslint/parser": "8.42.0"
}, },
"dependencies": { "dependencies": {
"@tabler/icons-webfont": "3.34.1", "@tabler/icons-webfont": "3.34.1",
"harfbuzzjs": "0.4.9", "harfbuzzjs": "0.4.11",
"tiny-glob": "0.2.9", "tiny-glob": "0.2.9",
"tsx": "4.20.4", "tsx": "4.20.5",
"typescript": "5.9.2", "typescript": "5.9.2",
"wawoff2": "2.0.1" "wawoff2": "2.0.1"
}, },

View File

@ -24,9 +24,9 @@
"devDependencies": { "devDependencies": {
"@types/matter-js": "0.20.0", "@types/matter-js": "0.20.0",
"@types/seedrandom": "3.0.8", "@types/seedrandom": "3.0.8",
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"nodemon": "3.1.10", "nodemon": "3.1.10",
"execa": "9.6.0", "execa": "9.6.0",
"typescript": "5.9.2", "typescript": "5.9.2",

View File

@ -1449,6 +1449,10 @@ export type Endpoints = Overwrite<Endpoints_2, {
}>; }>;
res: AdminRolesCreateResponse; res: AdminRolesCreateResponse;
}; };
'clear-browser-cache': {
req: EmptyRequest;
res: EmptyResponse;
};
}>; }>;
// @public (undocumented) // @public (undocumented)

View File

@ -8,9 +8,9 @@
}, },
"devDependencies": { "devDependencies": {
"@readme/openapi-parser": "5.0.1", "@readme/openapi-parser": "5.0.1",
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"openapi-types": "12.1.3", "openapi-types": "12.1.3",
"openapi-typescript": "7.9.1", "openapi-typescript": "7.9.1",
"ts-case-convert": "2.1.0", "ts-case-convert": "2.1.0",

View File

@ -1,7 +1,7 @@
{ {
"type": "module", "type": "module",
"name": "misskey-js", "name": "misskey-js",
"version": "2025.8.0", "version": "2025.9.0-beta.0",
"description": "Misskey SDK for JavaScript", "description": "Misskey SDK for JavaScript",
"license": "MIT", "license": "MIT",
"main": "./built/index.js", "main": "./built/index.js",
@ -36,9 +36,9 @@
}, },
"devDependencies": { "devDependencies": {
"@microsoft/api-extractor": "7.52.11", "@microsoft/api-extractor": "7.52.11",
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"@vitest/coverage-v8": "3.2.4", "@vitest/coverage-v8": "3.2.4",
"esbuild": "0.25.9", "esbuild": "0.25.9",
"execa": "9.6.0", "execa": "9.6.0",

View File

@ -1,6 +1,12 @@
import { Endpoints as Gen } from './autogen/endpoint.js'; import { Endpoints as Gen } from './autogen/endpoint.js';
import { UserDetailed } from './autogen/models.js'; import { UserDetailed } from './autogen/models.js';
import { AdminRolesCreateRequest, AdminRolesCreateResponse, UsersShowRequest } from './autogen/entities.js'; import {
AdminRolesCreateRequest,
AdminRolesCreateResponse,
EmptyRequest,
EmptyResponse,
UsersShowRequest,
} from './autogen/entities.js';
import { import {
PartialRolePolicyOverride, PartialRolePolicyOverride,
SigninFlowRequest, SigninFlowRequest,
@ -106,6 +112,10 @@ export type Endpoints = Overwrite<
'admin/roles/create': { 'admin/roles/create': {
req: Overwrite<AdminRolesCreateRequest, { policies: PartialRolePolicyOverride }>; req: Overwrite<AdminRolesCreateRequest, { policies: PartialRolePolicyOverride }>;
res: AdminRolesCreateResponse; res: AdminRolesCreateResponse;
} },
'clear-browser-cache': {
req: EmptyRequest;
res: EmptyResponse;
},
} }
>; >;

View File

@ -22,9 +22,9 @@
"lint": "pnpm typecheck && pnpm eslint" "lint": "pnpm typecheck && pnpm eslint"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "22.17.2", "@types/node": "22.18.1",
"@typescript-eslint/eslint-plugin": "8.40.0", "@typescript-eslint/eslint-plugin": "8.42.0",
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"execa": "9.6.0", "execa": "9.6.0",
"nodemon": "3.1.10", "nodemon": "3.1.10",
"typescript": "5.9.2", "typescript": "5.9.2",

View File

@ -14,7 +14,7 @@
"misskey-js": "workspace:*" "misskey-js": "workspace:*"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/parser": "8.40.0", "@typescript-eslint/parser": "8.42.0",
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.74", "@typescript/lib-webworker": "npm:@types/serviceworker@0.0.74",
"eslint-plugin-import": "2.32.0", "eslint-plugin-import": "2.32.0",
"nodemon": "3.1.10", "nodemon": "3.1.10",

File diff suppressed because it is too large Load Diff