diff --git a/.config/example.yml b/.config/example.yml index 8b9d9b482..d78a3b678 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -72,24 +72,6 @@ redis: # user: # pass: -# ┌───────────────┐ -#───┘ ID generation └─────────────────────────────────────────── - -# You can select the ID generation method. -# You don't usually need to change this setting, but you can -# change it according to your preferences. - -# Available methods: -# aid ... Short, Millisecond accuracy -# meid ... Similar to ObjectID, Millisecond accuracy -# ulid ... Millisecond accuracy -# objectid ... This is left for backward compatibility - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# ID SETTINGS AFTER THAT! - -id: 'aid' - # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index c6b2a1611..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -# These are supported funding model platforms - -patreon: syuilo diff --git a/.github/ISSUE_TEMPLATE/01_bug-report.md b/.github/ISSUE_TEMPLATE/01_bug-report.md deleted file mode 100644 index 0fecce2ee..000000000 --- a/.github/ISSUE_TEMPLATE/01_bug-report.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -name: 🐛 Bug Report -about: Create a report to help us improve -title: '' -labels: ⚠️bug? -assignees: '' - ---- - - - -## 💡 Summary - - - -## 🥰 Expected Behavior - - - -## 🤬 Actual Behavior - - - -## 📝 Steps to Reproduce - -1. -2. -3. - -## 📌 Environment - - - -Misskey version: -Your OS: -Your browser: diff --git a/.github/ISSUE_TEMPLATE/02_feature-request.md b/.github/ISSUE_TEMPLATE/02_feature-request.md deleted file mode 100644 index 5045b1771..000000000 --- a/.github/ISSUE_TEMPLATE/02_feature-request.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: ✨ Feature Request -about: Suggest an idea for this project -title: '' -labels: ✨Feature -assignees: '' - ---- - -## Summary - - diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 730647b08..000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,7 +0,0 @@ -contact_links: - - name: 👪 Misskey Forum - url: https://forum.misskey.io/ - about: Ask questions and share knowledge - - name: 💬 Misskey official Discord - url: https://discord.gg/Wp8gVStHW3 - about: Chat freely about Misskey diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 79ca97dfa..000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ - - -# What - - - -# Why - - - -# Additional info (optional) - - diff --git a/CHANGELOG.md b/CHANGELOG.md index f97912c81..b168a19d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,15 +11,25 @@ You should also include the user name that made the change. ## 12.x.x (unreleased) +### Changes +- ハイライトがみつけるに統合されました +- カスタム絵文字ページはインスタンス情報ページに統合されました +- 連合ページはインスタンス情報ページに統合されました + ### Improvements +- Client: Fix URL-encoded routing - Server: Allow GET method for some endpoints @syuilo - Server: Add rate limit to i/notifications @tamaina - Client: Improve control panel @syuilo - Client: Show warning in control panel when there is an unresolved abuse report @syuilo +- Client: For notes with specified visibility, show recipients when hovering over visibility symbol. @Johann150 +- Client: Add rss-ticker widget @syuilo +- Client: Removing entries from a clip @futchitwo +- Client: Poll highlights in explore page @syuilo - Make possible to delete an account by admin @syuilo - Improve player detection in URL preview @mei23 - Add Badge Image to Push Notification #8012 @tamaina -- Client: Removing entries from a clip @futchitwo +- Server: Improve performance - Server: Supports IPv6 on Redis transport. @mei23 IPv4/IPv6 is used by default. You can tune this behavior via `redis.family`. diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 421271639..2f5658a96 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -734,7 +734,6 @@ gallery: "المعرض" recentPosts: "المشاركات الحديثة" popularPosts: "المشاركات المتداولة" shareWithNote: "شاركه في ملاحظة" -ads: "الإعلانات" expiration: "ينتهي استطلاع الرأي في" memo: "تذكير" priority: "الأولوية" @@ -786,7 +785,6 @@ voteConfirm: "متيقِّن من تصويتك لـ {choice}؟" hide: "إخفاء" leaveGroup: "مغادرة الفريق" leaveGroupConfirm: "متيقن من مغادرة \"{name}\"؟" -welcomeBackWithName: "مرحبًا بك مجددًا {name}" clickToFinishEmailVerification: "انقر [{ok}] لاستيثاق بريدك الإلكتروني." overridedDeviceKind: "نوع الجهاز" smartphone: "هاتف ذكي" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index d0aef3073..24255a1e8 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -765,7 +765,6 @@ gallery: "গ্যালারী" recentPosts: "নতুন পোস্ট" popularPosts: "জনপ্রিয় পোস্ট" shareWithNote: "নোটের মাধ্যমে শেয়ার করুন" -ads: "বিজ্ঞাপন" expiration: "নির্দিষ্ট সময়সীমা" memo: "মেমো" priority: "অগ্রাধিকার" @@ -821,7 +820,6 @@ hide: "লুকান" leaveGroup: "গ্রুপ ছেড়ে চলে যান" leaveGroupConfirm: "\"{name}\" গ্রুপ ছেড়ে চলে যেতে চান?" useDrawerReactionPickerForMobile: "মোবাইলে রিঅ্যাকশন পিকারকে ড্রয়ারে প্রদর্শন করুন" -welcomeBackWithName: "আবার স্বাগতম, {name}" clickToFinishEmailVerification: " [{ok}] ক্লিক করার মাধ্যমে আপনার ইমেল ঠিকানা নিশ্চিত করুন।" overridedDeviceKind: "ডিভাইসের ধরন" smartphone: "স্মার্টফোন" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index c34137a5d..c1114933b 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -766,7 +766,6 @@ gallery: "Galerie" recentPosts: "Neue Beiträge" popularPosts: "Beliebte Beiträge" shareWithNote: "Mit Notiz teilen" -ads: "Werbung" expiration: "Frist" memo: "Merkzettel" priority: "Priorität" @@ -822,7 +821,6 @@ hide: "Inhalt verbergen" leaveGroup: "Gruppe verlassen" leaveGroupConfirm: "Möchtest du „{name}“ wirklich verlassen?" useDrawerReactionPickerForMobile: "Auf mobilen Geräten ausfahrbare Reaktionsauswahl anzeigen" -welcomeBackWithName: "Willkommen zurück, {name}" clickToFinishEmailVerification: "Drücke bitte auf [{ok}], um die Email-Bestätigung abzuschließen." overridedDeviceKind: "Gerätetyp" smartphone: "Smartphone" @@ -1659,3 +1657,17 @@ _deck: list: "Listen" mentions: "Erwähnungen" direct: "Direktnachrichten" +recentNHours: "Letzten {n} Stunden" +recentNDays: "Letzten {n} Tage" +isSystemAccount: "Ein Benutzerkonto, dass durch das System erstellt und automatisch kontrolliert wird." +typeToConfirm: "Bitte gib zur Bestätigung {x} ein" +deleteAccount: "Benutzerkonto löschen" +numberOfPageCache: "Seitencachegröße" +numberOfPageCacheDescription: "Das Erhöhen dieses Caches führt zu einer angenehmerern Benutzererfahrung, erhöht aber Serverlast und Arbeitsspeicherauslastung." +file: "Datei" +unclip: "Aus Clip entfernen" +confirmToUnclipAlreadyClippedNote: "Diese Notiz ist bereits im \"{name}\" Clip enthalten. Möchtest du sie aus diesem Clip entfernen?" +noEmailServerWarning: "Es ist kein Email-Server konfiguriert." +thereIsUnresolvedAbuseReportWarning: "Es liegen ungelöste Meldungen vor." +recommended: "Empfehlung" +check: "Check" diff --git a/locales/en-US.yml b/locales/en-US.yml index a18c7fdb6..86df4ef57 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -766,7 +766,6 @@ gallery: "Gallery" recentPosts: "Recent posts" popularPosts: "Popular posts" shareWithNote: "Share with note" -ads: "Advertisements" expiration: "Deadline" memo: "Memo" priority: "Priority" @@ -822,7 +821,6 @@ hide: "Hide" leaveGroup: "Leave group" leaveGroupConfirm: "Are you sure you want to leave \"{name}\"?" useDrawerReactionPickerForMobile: "Display reaction picker as drawer on mobile" -welcomeBackWithName: "Welcome back, {name}" clickToFinishEmailVerification: "Please click [{ok}] to complete email verification." overridedDeviceKind: "Device type" smartphone: "Smartphone" @@ -852,6 +850,13 @@ typeToConfirm: "Please enter {x} to confirm" deleteAccount: "Delete account" numberOfPageCache: "Number of cached pages" numberOfPageCacheDescription: "Increasing this number will improve convenience for users but cause more server load as well as more memory to be used." +file: "File" +unclip: "Unclip" +confirmToUnclipAlreadyClippedNote: "This note is already part of the \"{name}\" clip. Do you want to remove it from this clip instead?" +noEmailServerWarning: "Email server not configured." +thereIsUnresolvedAbuseReportWarning: "There are unsolved reports." +recommended: "Recommended" +check: "Check" _emailUnavailable: used: "This email address is already being used" format: "The format of this email address is invalid" @@ -1206,6 +1211,7 @@ _widgets: trends: "Trending" clock: "Clock" rss: "RSS reader" + rssMarquee: "RSS ticker" activity: "Activity" photos: "Photos" digitalClock: "Digital clock" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 8e18af4aa..ec2ad6595 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -761,7 +761,6 @@ gallery: "Galería" recentPosts: "Posts recientes" popularPosts: "Más vistos" shareWithNote: "Compartir con una nota" -ads: "Anuncios" expiration: "Termina el" memo: "Notas" priority: "Prioridad" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 728dec0ca..259f93941 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -760,7 +760,6 @@ gallery: "Galerie" recentPosts: "Les plus récentes" popularPosts: "Les plus consultées" shareWithNote: "Partager dans une note" -ads: "Publicité" expiration: "Échéance" memo: "Pense-bête" priority: "Priorité" @@ -815,7 +814,6 @@ voteConfirm: "Confirmez-vous votre vote pour « {choice} » ?" hide: "Masquer" leaveGroup: "Quitter le groupe" leaveGroupConfirm: "Êtes vous sûr de vouloir quitter \"{name}\" ?" -welcomeBackWithName: "Heureux de vous revoir, {name}" clickToFinishEmailVerification: "Veuillez cliquer sur [{ok}] afin de compléter la vérification par courriel." overridedDeviceKind: "Type d’appareil" smartphone: "Smartphone" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index 9ff94ef62..a54f45b9d 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -765,7 +765,6 @@ gallery: "Galeri" recentPosts: "Postingan terbaru" popularPosts: "Postingan populer" shareWithNote: "Bagikan dengan catatan" -ads: "Iklan" expiration: "Batas akhir" memo: "Memo" priority: "Prioritas" @@ -821,7 +820,6 @@ hide: "Sembunyikan" leaveGroup: "Keluar grup" leaveGroupConfirm: "Apakah kamu yakin untuk keluar dari \"{name}\"?" useDrawerReactionPickerForMobile: "Tampilkan bilah reaksi sebagai laci di ponsel" -welcomeBackWithName: "Selamat datang kembali, {name}." clickToFinishEmailVerification: "Mohon klik [{ok}] untuk menyelesaikan verifikasi email." overridedDeviceKind: "Tipe perangkat" smartphone: "Ponsel" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 05e8ef5e5..94b480cf5 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -753,7 +753,6 @@ gallery: "Galleria" recentPosts: "Le più recenti" popularPosts: "Le più visualizzate" shareWithNote: "Condividere in nota" -ads: "Pubblicità" expiration: "Scadenza" memo: "Promemoria" priority: "Priorità" @@ -801,7 +800,6 @@ hide: "Nascondere" leaveGroup: "Esci dal gruppo" leaveGroupConfirm: "Uscire da「{name}」?" useDrawerReactionPickerForMobile: "Mostra sul drawer da dispositivo mobile" -welcomeBackWithName: "Bentornato/a, {name}" clickToFinishEmailVerification: "Fai click su [{ok}] per completare la verifica dell'indirizzo email." indefinitely: "Non scade" tenMinutes: "10 minuti" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 069ecf278..c263cba88 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -768,7 +768,6 @@ gallery: "ギャラリー" recentPosts: "最近の投稿" popularPosts: "人気の投稿" shareWithNote: "ノートで共有" -ads: "広告" expiration: "期限" memo: "メモ" priority: "優先度" @@ -824,7 +823,6 @@ hide: "隠す" leaveGroup: "グループから抜ける" leaveGroupConfirm: "「{name}」から抜けますか?" useDrawerReactionPickerForMobile: "モバイルデバイスのときドロワーで表示" -welcomeBackWithName: "おかえりなさい、{name}さん" clickToFinishEmailVerification: "[{ok}]を押して、メールアドレスの確認を完了してください。" overridedDeviceKind: "デバイスタイプ" smartphone: "スマートフォン" @@ -1244,6 +1242,7 @@ _widgets: trends: "トレンド" clock: "時計" rss: "RSSリーダー" + rssTicker: "RSSティッカー" activity: "アクティビティ" photos: "フォト" digitalClock: "デジタル時計" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 53779086c..d5ea43d4e 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -645,7 +645,6 @@ goBack: "戻る" info: "情報" user: "ユーザー" administration: "管理" -ads: "広告" expiration: "期限" memo: "メモ" high: "高い" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 0cc889f24..620b9f430 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -765,7 +765,6 @@ gallery: "갤러리" recentPosts: "최근 포스트" popularPosts: "인기 포스트" shareWithNote: "노트로 공유" -ads: "광고" expiration: "기한" memo: "메모" priority: "우선순위" @@ -821,7 +820,6 @@ hide: "숨기기" leaveGroup: "그룹 나가기" leaveGroupConfirm: "\"{name}\"에서 나갈까요?" useDrawerReactionPickerForMobile: "모바일에서 드로어 메뉴로 표시" -welcomeBackWithName: "환영합니다, {name}님" clickToFinishEmailVerification: "[{ok}]를 눌러 이메일 인증을 완료하세요." overridedDeviceKind: "장치 유형" smartphone: "스마트폰" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index d8d7cdf0f..08552f3bc 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -739,7 +739,6 @@ gallery: "Galeria" recentPosts: "Ostatnie wpisy" popularPosts: "Popularne wpisy" shareWithNote: "Udostępnij z wpisem" -ads: "Reklamy" expiration: "Ankieta kończy się" memo: "Notatki" priority: "Priorytet" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 8e76fc25f..b983ecca8 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -763,7 +763,6 @@ gallery: "Галерея" recentPosts: "Недавние публикации" popularPosts: "Популярные публикации" shareWithNote: "Поделиться заметкой" -ads: "Реклама" expiration: "Опрос длится" memo: "Памятка" priority: "Приоритет" @@ -819,7 +818,6 @@ hide: "Спрятать" leaveGroup: "Покинуть группу" leaveGroupConfirm: "Покинуть группу «{name}»?" useDrawerReactionPickerForMobile: "Выдвижная палитра на мобильном устройстве" -welcomeBackWithName: "С возвращением, {name}!" clickToFinishEmailVerification: "Пожалуйста, нажмите [{ok}], чтобы завершить подтверждение адреса электронной почты." overridedDeviceKind: "Тип устройства" smartphone: "Смартфон" diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index dfd02dd42..34cb03aec 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -764,7 +764,6 @@ gallery: "Galéria" recentPosts: "Najnovšie príspevky" popularPosts: "Populárne príspevky" shareWithNote: "Zdieľať s poznámkou" -ads: "Reklamy" expiration: "Ukončiť hlasovanie" memo: "Memo" priority: "Priorita" @@ -820,7 +819,6 @@ hide: "Skryť" leaveGroup: "Opustiť skupiny" leaveGroupConfirm: "Naozaj chcete opustiť \"{name}\"?" useDrawerReactionPickerForMobile: "Zobraziť výber reakcií ako šuflík na mobile" -welcomeBackWithName: "Vitajte späť, {name}" clickToFinishEmailVerification: "Kliknutím na [{ok}] dokončíte overeniu emailu." overridedDeviceKind: "Typ zariadenia" smartphone: "Smartfón" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index de1455e2e..398028765 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -765,7 +765,6 @@ gallery: "Thư viện ảnh" recentPosts: "Tút gần đây" popularPosts: "Tút được xem nhiều nhất" shareWithNote: "Chia sẻ kèm với tút" -ads: "Quảng cáo" expiration: "Thời hạn" memo: "Lưu ý" priority: "Ưu tiên" @@ -821,7 +820,6 @@ hide: "Ẩn" leaveGroup: "Rời khỏi nhóm" leaveGroupConfirm: "Bạn có chắc muốn rời khỏi nhóm \"{name}\"?" useDrawerReactionPickerForMobile: "Hiện bộ chọn biểu cảm dạng xổ ra trên điện thoại" -welcomeBackWithName: "Chào mừng trở lại, {name}" clickToFinishEmailVerification: "Vui lòng nhấn [{ok}] để hoàn tất việc đăng ký." overridedDeviceKind: "Loại thiết bị" smartphone: "Điện thoại" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index ffe998e72..a3811804b 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -765,7 +765,6 @@ gallery: "图库" recentPosts: "最新发布" popularPosts: "热门投稿" shareWithNote: "在帖子中分享" -ads: "广告" expiration: "截止时间" memo: "便笺" priority: "优先级" @@ -821,7 +820,6 @@ hide: "隐藏" leaveGroup: "离开群组" leaveGroupConfirm: "确定离开「{name}」?" useDrawerReactionPickerForMobile: "在移动设备上使用抽屉显示" -welcomeBackWithName: "欢迎回来,{name}" clickToFinishEmailVerification: "点击 [{ok}] 完成电子邮件地址认证。" overridedDeviceKind: "设备类型" smartphone: "智能手机" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 4e1ad09de..d40d443c8 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -765,7 +765,6 @@ gallery: "相簿" recentPosts: "最新貼文" popularPosts: "熱門的貼文" shareWithNote: "在貼文中分享" -ads: "廣告" expiration: "期限" memo: "備忘錄" priority: "優先級" @@ -821,7 +820,6 @@ hide: "隱藏" leaveGroup: "離開群組" leaveGroupConfirm: "確定離開「{name}」?" useDrawerReactionPickerForMobile: "在移動設備上使用抽屜顯示" -welcomeBackWithName: "歡迎回來,{name}" clickToFinishEmailVerification: "點擊 [{ok}] 完成電子郵件地址認證。" overridedDeviceKind: "裝置類型" smartphone: "智慧型手機" diff --git a/package.json b/package.json index fd565f7ce..ffec400f9 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,9 @@ { - "name": "misskey", + "name": "foundkey", "version": "12.111.1-test.1", - "codename": "indigo", "repository": { "type": "git", - "url": "https://github.com/misskey-dev/misskey.git" + "url": "https://akkoma.dev/FoundKeyGang/FoundKey.git" }, "private": true, "scripts": { @@ -41,10 +40,10 @@ "devDependencies": { "@types/gulp": "4.0.9", "@types/gulp-rename": "2.0.1", - "@typescript-eslint/parser": "5.27.1", + "@typescript-eslint/parser": "5.30.0", "cross-env": "7.0.3", - "cypress": "10.0.3", + "cypress": "10.3.0", "start-server-and-test": "1.14.0", - "typescript": "4.7.3" + "typescript": "4.7.4" } } diff --git a/packages/backend/migration/1657570176749-remove-ads.ts b/packages/backend/migration/1657570176749-remove-ads.ts new file mode 100644 index 000000000..03a4168aa --- /dev/null +++ b/packages/backend/migration/1657570176749-remove-ads.ts @@ -0,0 +1,12 @@ +export class removeAds1657570176749 { + name = 'removeAds1657570176749' + + async up(queryRunner) { + await queryRunner.query(`DROP TABLE "ad"`); + } + + async down(queryRunner) { + await queryRunner.query(`CREATE TABLE public.ad ("id" character varying(32) NOT NULL, "createdAt" timestamp with time zone NOT NULL, "expiresAt" timestamp with time zone NOT NULL, "place" character varying(32) NOT NULL, "priority" character varying(32) NOT NULL, "url" character varying(1024) NOT NULL, "imageUrl" character varying(1024) NOT NULL, "memo" character varying(8192) NOT NULL, "ratio" integer DEFAULT 1 NOT NULL)`); + } + +} diff --git a/packages/backend/migration/1658146000392-remove-repo-url.js b/packages/backend/migration/1658146000392-remove-repo-url.js new file mode 100644 index 000000000..71309650b --- /dev/null +++ b/packages/backend/migration/1658146000392-remove-repo-url.js @@ -0,0 +1,13 @@ +export class removeRepoUrl1658146000392 { + name = 'removeRepoUrl1658146000392'; + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "repositoryUrl"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "feedbackUrl"`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) not null default 'https://github.com/misskey-dev/misskey'`); + await queryRunner.query(`ALTER TABLE "meta" ADD "feedbackUrl" character varying(512) default 'https://github.com/misskey-dev/misskey/issues/new'`); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index c6c76b30a..ac27a242a 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -5,7 +5,7 @@ "scripts": { "build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", "watch": "node watch.mjs", - "lint": "eslint --quiet \"src/**/*.ts\"", + "lint": "eslint --quiet src --ext .ts", "mocha": "cross-env NODE_ENV=test TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha", "test": "npm run mocha" }, @@ -14,7 +14,7 @@ "lodash": "^4.17.21" }, "dependencies": { - "@bull-board/koa": "3.11.1", + "@bull-board/koa": "4.0.0", "@discordapp/twemoji": "14.0.2", "@elastic/elasticsearch": "7.11.0", "@koa/cors": "3.1.0", @@ -28,10 +28,10 @@ "archiver": "5.3.1", "autobind-decorator": "2.4.0", "autwh": "0.1.0", - "aws-sdk": "2.1152.0", + "aws-sdk": "2.1165.0", "bcryptjs": "2.4.3", "blurhash": "1.1.5", - "bull": "4.8.3", + "bull": "4.8.4", "cacheable-lookup": "6.0.4", "cbor": "8.1.0", "chalk": "5.0.1", @@ -51,7 +51,7 @@ "ip-cidr": "3.0.10", "is-svg": "4.3.2", "js-yaml": "4.1.0", - "jsdom": "19.0.0", + "jsdom": "20.0.0", "json5": "2.2.1", "json5-loader": "4.0.1", "jsonld": "6.0.0", @@ -69,29 +69,29 @@ "mime-types": "2.1.35", "misskey-js": "0.0.14", "mocha": "10.0.0", - "ms": "3.0.0-canary.1", "multer": "1.4.4", "nested-property": "4.0.0", "node-fetch": "3.2.6", - "nodemailer": "6.7.5", + "nodemailer": "6.7.6", "os-utils": "0.0.14", - "parse5": "6.0.1", + "parse5": "7.0.0", "pg": "8.7.3", "private-ip": "2.3.3", "probe-image-size": "7.2.3", "promise-limit": "2.7.0", "pug": "3.0.2", "punycode": "2.1.1", - "pureimage": "0.3.8", + "pureimage": "0.3.14", "qrcode": "1.5.0", "random-seed": "0.3.0", "ratelimiter": "3.4.1", - "re2": "1.17.4", + "re2": "1.17.7", "redis-lock": "0.1.4", "reflect-metadata": "0.1.13", "rename": "1.0.4", "require-all": "3.0.0", "rndstr": "1.0.0", + "rss-parser": "3.12.0", "s-age": "1.1.2", "sanitize-html": "2.7.0", "semver": "7.3.7", @@ -102,16 +102,15 @@ "style-loader": "3.3.1", "summaly": "2.6.0", "syslog-pro": "1.0.0", - "systeminformation": "5.11.16", + "systeminformation": "5.11.22", "tinycolor2": "1.4.2", "tmp": "0.2.1", - "ts-loader": "9.3.0", + "ts-loader": "9.3.1", "ts-node": "10.8.1", - "tsc-alias": "1.6.9", + "tsc-alias": "1.6.11", "tsconfig-paths": "4.0.0", "twemoji-parser": "14.0.0", - "typeorm": "0.3.6", - "ulid": "2.3.0", + "typeorm": "0.3.7", "unzipper": "0.10.11", "uuid": "8.3.2", "web-push": "3.5.0", @@ -121,7 +120,6 @@ }, "devDependencies": { "@redocly/openapi-core": "1.0.0-beta.97", - "@types/semver": "7.3.9", "@types/bcryptjs": "2.4.2", "@types/bull": "3.15.8", "@types/cbor": "6.0.0", @@ -144,11 +142,10 @@ "@types/koa__multer": "2.0.4", "@types/koa__router": "8.0.11", "@types/mocha": "9.1.1", - "@types/node": "17.0.41", + "@types/node": "18.0.0", "@types/node-fetch": "3.0.3", "@types/nodemailer": "6.4.4", "@types/oauth": "0.9.1", - "@types/parse5": "6.0.3", "@types/pug": "2.0.6", "@types/punycode": "2.1.0", "@types/qrcode": "1.4.2", @@ -157,7 +154,8 @@ "@types/redis": "4.0.11", "@types/rename": "1.0.4", "@types/sanitize-html": "2.6.2", - "@types/sharp": "0.30.2", + "@types/semver": "7.3.10", + "@types/sharp": "0.30.4", "@types/sinonjs__fake-timers": "8.1.2", "@types/speakeasy": "2.0.7", "@types/tinycolor2": "1.4.3", @@ -166,12 +164,12 @@ "@types/web-push": "3.3.2", "@types/websocket": "1.0.5", "@types/ws": "8.5.3", - "@typescript-eslint/eslint-plugin": "5.27.1", - "@typescript-eslint/parser": "5.27.1", - "typescript": "4.7.3", - "eslint": "8.17.0", - "eslint-plugin-import": "2.26.0", + "@typescript-eslint/eslint-plugin": "^5.30.0", + "@typescript-eslint/parser": "^5.30.0", "cross-env": "7.0.3", - "execa": "6.1.0" + "eslint": "^8.20.0", + "eslint-plugin-import": "^2.26.0", + "execa": "6.1.0", + "typescript": "^4.7.4" } } diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts index 9654a4f3b..d82c8a396 100644 --- a/packages/backend/src/config/load.ts +++ b/packages/backend/src/config/load.ts @@ -28,6 +28,8 @@ export default function load() { const clientManifest = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/_client_dist_/manifest.json`, 'utf-8')); const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source; + if (config.id && config.id !== 'aid') throw new Error('Unsupported ID algorithm. Only "aid" is supported.'); + const mixin = {} as Mixin; const url = tryCreateUrl(config.url); diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index 6d3b9559e..fab369482 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,5 +1,10 @@ export const MAX_NOTE_TEXT_LENGTH = 3000; +export const SECOND = 1000; +export const MINUTE = 60 * SECOND; +export const HOUR = 60 * MINUTE; +export const DAY = 24 * HOUR; + export const USER_ONLINE_THRESHOLD = 1000 * 60 * 10; // 10min export const USER_ACTIVE_THRESHOLD = 1000 * 60 * 60 * 24 * 3; // 3days diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index f8e483939..95386f724 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -65,7 +65,6 @@ import { Channel } from '@/models/entities/channel.js'; import { ChannelFollowing } from '@/models/entities/channel-following.js'; import { ChannelNotePining } from '@/models/entities/channel-note-pining.js'; import { RegistryItem } from '@/models/entities/registry-item.js'; -import { Ad } from '@/models/entities/ad.js'; import { PasswordResetRequest } from '@/models/entities/password-reset-request.js'; import { UserPending } from '@/models/entities/user-pending.js'; @@ -168,7 +167,6 @@ export const entities = [ ChannelFollowing, ChannelNotePining, RegistryItem, - Ad, PasswordResetRequest, UserPending, Webhook, diff --git a/packages/backend/src/mfm/from-html.ts b/packages/backend/src/mfm/from-html.ts index 15110b6b7..7751bac56 100644 --- a/packages/backend/src/mfm/from-html.ts +++ b/packages/backend/src/mfm/from-html.ts @@ -1,8 +1,10 @@ -import * as parse5 from 'parse5'; -import treeAdapter from 'parse5/lib/tree-adapters/default.js'; import { URL } from 'node:url'; +import * as parse5 from 'parse5'; +import * as TreeAdapter from '../../node_modules/parse5/dist/tree-adapters/default.js'; -const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; +const treeAdapter = TreeAdapter.defaultTreeAdapter; + +const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/; export function fromHtml(html: string, hashtagNames?: string[]): string { @@ -19,7 +21,7 @@ export function fromHtml(html: string, hashtagNames?: string[]): string { return text.trim(); - function getText(node: parse5.Node): string { + function getText(node: TreeAdapter.Node): string { if (treeAdapter.isTextNode(node)) return node.value; if (!treeAdapter.isElementNode(node)) return ''; if (node.nodeName === 'br') return '\n'; @@ -31,7 +33,7 @@ export function fromHtml(html: string, hashtagNames?: string[]): string { return ''; } - function appendChildren(childNodes: parse5.ChildNode[]): void { + function appendChildren(childNodes: TreeAdapter.ChildNode[]): void { if (childNodes) { for (const n of childNodes) { analyze(n); @@ -39,7 +41,7 @@ export function fromHtml(html: string, hashtagNames?: string[]): string { } } - function analyze(node: parse5.Node) { + function analyze(node: TreeAdapter.Node) { if (treeAdapter.isTextNode(node)) { text += node.value; return; @@ -170,7 +172,7 @@ export function fromHtml(html: string, hashtagNames?: string[]): string { const t = getText(node); if (t) { text += '\n> '; - text += t.split('\n').join(`\n> `); + text += t.split('\n').join('\n> '); } break; } diff --git a/packages/backend/src/misc/gen-id.ts b/packages/backend/src/misc/gen-id.ts index fcf476857..1a7a511b6 100644 --- a/packages/backend/src/misc/gen-id.ts +++ b/packages/backend/src/misc/gen-id.ts @@ -1,21 +1,23 @@ -import { ulid } from 'ulid'; -import { genAid } from './id/aid.js'; -import { genMeid } from './id/meid.js'; -import { genMeidg } from './id/meidg.js'; -import { genObjectId } from './id/object-id.js'; -import config from '@/config/index.js'; +import * as crypto from 'node:crypto'; -const metohd = config.id.toLowerCase(); +// AID generation +// 8 chars: milliseconds elapsed since 2000-01-01 00:00:00.000Z encoded as base36 +// + 2 random chars + +const TIME2000 = 946684800000; +let counter = crypto.randomBytes(2).readUInt16LE(0); export function genId(date?: Date): string { if (!date || (date > new Date())) date = new Date(); - switch (metohd) { - case 'aid': return genAid(date); - case 'meid': return genMeid(date); - case 'meidg': return genMeidg(date); - case 'ulid': return ulid(date.getTime()); - case 'objectid': return genObjectId(date); - default: throw new Error('unrecognized id generation method'); - } + let t = date.getTime(); + t -= TIME2000; + if (t < 0) t = 0; + if (isNaN(t)) throw 'Failed to create AID: Invalid Date'; + const time = t.toString(36).padStart(8, '0'); + + counter++; + const noise = counter.toString(36).padStart(2, '0').slice(-2); + + return time + noise; } diff --git a/packages/backend/src/misc/id/aid.ts b/packages/backend/src/misc/id/aid.ts deleted file mode 100644 index 87e688826..000000000 --- a/packages/backend/src/misc/id/aid.ts +++ /dev/null @@ -1,25 +0,0 @@ -// AID -// 長さ8の[2000年1月1日からの経過ミリ秒をbase36でエンコードしたもの] + 長さ2の[ノイズ文字列] - -import * as crypto from 'node:crypto'; - -const TIME2000 = 946684800000; -let counter = crypto.randomBytes(2).readUInt16LE(0); - -function getTime(time: number) { - time = time - TIME2000; - if (time < 0) time = 0; - - return time.toString(36).padStart(8, '0'); -} - -function getNoise() { - return counter.toString(36).padStart(2, '0').slice(-2); -} - -export function genAid(date: Date): string { - const t = date.getTime(); - if (isNaN(t)) throw 'Failed to create AID: Invalid Date'; - counter++; - return getTime(t) + getNoise(); -} diff --git a/packages/backend/src/misc/id/meid.ts b/packages/backend/src/misc/id/meid.ts deleted file mode 100644 index 30bbdf169..000000000 --- a/packages/backend/src/misc/id/meid.ts +++ /dev/null @@ -1,26 +0,0 @@ -const CHARS = '0123456789abcdef'; - -function getTime(time: number) { - if (time < 0) time = 0; - if (time === 0) { - return CHARS[0]; - } - - time += 0x800000000000; - - return time.toString(16).padStart(12, CHARS[0]); -} - -function getRandom() { - let str = ''; - - for (let i = 0; i < 12; i++) { - str += CHARS[Math.floor(Math.random() * CHARS.length)]; - } - - return str; -} - -export function genMeid(date: Date): string { - return getTime(date.getTime()) + getRandom(); -} diff --git a/packages/backend/src/misc/id/meidg.ts b/packages/backend/src/misc/id/meidg.ts deleted file mode 100644 index d4aaaea1b..000000000 --- a/packages/backend/src/misc/id/meidg.ts +++ /dev/null @@ -1,28 +0,0 @@ -const CHARS = '0123456789abcdef'; - -// 4bit Fixed hex value 'g' -// 44bit UNIX Time ms in Hex -// 48bit Random value in Hex - -function getTime(time: number) { - if (time < 0) time = 0; - if (time === 0) { - return CHARS[0]; - } - - return time.toString(16).padStart(11, CHARS[0]); -} - -function getRandom() { - let str = ''; - - for (let i = 0; i < 12; i++) { - str += CHARS[Math.floor(Math.random() * CHARS.length)]; - } - - return str; -} - -export function genMeidg(date: Date): string { - return 'g' + getTime(date.getTime()) + getRandom(); -} diff --git a/packages/backend/src/misc/id/object-id.ts b/packages/backend/src/misc/id/object-id.ts deleted file mode 100644 index 392ea4330..000000000 --- a/packages/backend/src/misc/id/object-id.ts +++ /dev/null @@ -1,26 +0,0 @@ -const CHARS = '0123456789abcdef'; - -function getTime(time: number) { - if (time < 0) time = 0; - if (time === 0) { - return CHARS[0]; - } - - time = Math.floor(time / 1000); - - return time.toString(16).padStart(8, CHARS[0]); -} - -function getRandom() { - let str = ''; - - for (let i = 0; i < 16; i++) { - str += CHARS[Math.floor(Math.random() * CHARS.length)]; - } - - return str; -} - -export function genObjectId(date: Date): string { - return getTime(date.getTime()) + getRandom(); -} diff --git a/packages/backend/src/models/entities/ad.ts b/packages/backend/src/models/entities/ad.ts deleted file mode 100644 index 36b758f20..000000000 --- a/packages/backend/src/models/entities/ad.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Entity, Index, Column, PrimaryColumn } from 'typeorm'; -import { id } from '../id.js'; - -@Entity() -export class Ad { - @PrimaryColumn(id()) - public id: string; - - @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Ad.', - }) - public createdAt: Date; - - @Index() - @Column('timestamp with time zone', { - comment: 'The expired date of the Ad.', - }) - public expiresAt: Date; - - @Column('varchar', { - length: 32, nullable: false, - }) - public place: string; - - // 今は使われていないが将来的に活用される可能性はある - @Column('varchar', { - length: 32, nullable: false, - }) - public priority: string; - - @Column('integer', { - default: 1, nullable: false, - }) - public ratio: number; - - @Column('varchar', { - length: 1024, nullable: false, - }) - public url: string; - - @Column('varchar', { - length: 1024, nullable: false, - }) - public imageUrl: string; - - @Column('varchar', { - length: 8192, nullable: false, - }) - public memo: string; - - constructor(data: Partial) { - if (data == null) return; - - for (const [k, v] of Object.entries(data)) { - (this as any)[k] = v; - } - } -} diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 0de01e507..c6a4c9f41 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -316,20 +316,6 @@ export class Meta { }) public ToSUrl: string | null; - @Column('varchar', { - length: 512, - default: 'https://github.com/misskey-dev/misskey', - nullable: false, - }) - public repositoryUrl: string; - - @Column('varchar', { - length: 512, - default: 'https://github.com/misskey-dev/misskey/issues/new', - nullable: true, - }) - public feedbackUrl: string | null; - @Column('varchar', { length: 8192, nullable: true, diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index 577b4044b..1005f8c70 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -59,7 +59,6 @@ import { MutedNote } from './entities/muted-note.js'; import { ChannelFollowing } from './entities/channel-following.js'; import { ChannelNotePining } from './entities/channel-note-pining.js'; import { RegistryItem } from './entities/registry-item.js'; -import { Ad } from './entities/ad.js'; import { PasswordResetRequest } from './entities/password-reset-request.js'; import { UserPending } from './entities/user-pending.js'; import { InstanceRepository } from './repositories/instance.js'; @@ -126,5 +125,4 @@ export const ChannelFollowings = db.getRepository(ChannelFollowing); export const ChannelNotePinings = db.getRepository(ChannelNotePining); export const RegistryItems = db.getRepository(RegistryItem); export const Webhooks = db.getRepository(Webhook); -export const Ads = db.getRepository(Ad); export const PasswordResetRequests = db.getRepository(PasswordResetRequest); diff --git a/packages/backend/src/server/api/common/read-notification.ts b/packages/backend/src/server/api/common/read-notification.ts index 8c4ba41a3..cf993ade3 100644 --- a/packages/backend/src/server/api/common/read-notification.ts +++ b/packages/backend/src/server/api/common/read-notification.ts @@ -12,13 +12,15 @@ export async function readNotification( if (notificationIds.length === 0) return; // Update documents - await Notifications.update({ + const result = await Notifications.update({ id: In(notificationIds), isRead: false, }, { isRead: true, }); + if (result.affected === 0) return; + if (!await Users.getHasUnreadNotification(userId)) return postReadAllNotifications(userId); else return postReadNotifications(userId, notificationIds); } @@ -27,7 +29,7 @@ export async function readNotificationByQuery( userId: User['id'], query: Record ) { - const notificationIds = await Notifications.find({ + const notificationIds = await Notifications.findBy({ ...query, notifieeId: userId, isRead: false, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 1a3fc199d..9eedfd53c 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -4,10 +4,6 @@ import * as ep___admin_meta from './endpoints/admin/meta.js'; import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; -import * as ep___admin_ad_create from './endpoints/admin/ad/create.js'; -import * as ep___admin_ad_delete from './endpoints/admin/ad/delete.js'; -import * as ep___admin_ad_list from './endpoints/admin/ad/list.js'; -import * as ep___admin_ad_update from './endpoints/admin/ad/update.js'; import * as ep___admin_announcements_create from './endpoints/admin/announcements/create.js'; import * as ep___admin_announcements_delete from './endpoints/admin/announcements/delete.js'; import * as ep___admin_announcements_list from './endpoints/admin/announcements/list.js'; @@ -311,16 +307,13 @@ import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by import * as ep___users_search from './endpoints/users/search.js'; import * as ep___users_show from './endpoints/users/show.js'; import * as ep___users_stats from './endpoints/users/stats.js'; +import * as ep___fetchRss from './endpoints/fetch-rss.js'; const eps = [ ['admin/meta', ep___admin_meta], ['admin/abuse-user-reports', ep___admin_abuseUserReports], ['admin/accounts/create', ep___admin_accounts_create], ['admin/accounts/delete', ep___admin_accounts_delete], - ['admin/ad/create', ep___admin_ad_create], - ['admin/ad/delete', ep___admin_ad_delete], - ['admin/ad/list', ep___admin_ad_list], - ['admin/ad/update', ep___admin_ad_update], ['admin/announcements/create', ep___admin_announcements_create], ['admin/announcements/delete', ep___admin_announcements_delete], ['admin/announcements/list', ep___admin_announcements_list], @@ -624,6 +617,7 @@ const eps = [ ['users/search', ep___users_search], ['users/show', ep___users_show], ['users/stats', ep___users_stats], + ['fetch-rss', ep___fetchRss], ]; export interface IEndpointMeta { diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts deleted file mode 100644 index ab2c50b50..000000000 --- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts +++ /dev/null @@ -1,39 +0,0 @@ -import define from '../../../define.js'; -import { Ads } from '@/models/index.js'; -import { genId } from '@/misc/gen-id.js'; - -export const meta = { - tags: ['admin'], - - requireCredential: true, - requireModerator: true, -} as const; - -export const paramDef = { - type: 'object', - properties: { - url: { type: 'string', minLength: 1 }, - memo: { type: 'string' }, - place: { type: 'string' }, - priority: { type: 'string' }, - ratio: { type: 'integer' }, - expiresAt: { type: 'integer' }, - imageUrl: { type: 'string', minLength: 1 }, - }, - required: ['url', 'memo', 'place', 'priority', 'ratio', 'expiresAt', 'imageUrl'], -} as const; - -// eslint-disable-next-line import/no-default-export -export default define(meta, paramDef, async (ps) => { - await Ads.insert({ - id: genId(), - createdAt: new Date(), - expiresAt: new Date(ps.expiresAt), - url: ps.url, - imageUrl: ps.imageUrl, - priority: ps.priority, - ratio: ps.ratio, - place: ps.place, - memo: ps.memo, - }); -}); diff --git a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts deleted file mode 100644 index 0ead2be00..000000000 --- a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts +++ /dev/null @@ -1,35 +0,0 @@ -import define from '../../../define.js'; -import { Ads } from '@/models/index.js'; -import { ApiError } from '../../../error.js'; - -export const meta = { - tags: ['admin'], - - requireCredential: true, - requireModerator: true, - - errors: { - noSuchAd: { - message: 'No such ad.', - code: 'NO_SUCH_AD', - id: 'ccac9863-3a03-416e-b899-8a64041118b1', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { type: 'string', format: 'misskey:id' }, - }, - required: ['id'], -} as const; - -// eslint-disable-next-line import/no-default-export -export default define(meta, paramDef, async (ps, me) => { - const ad = await Ads.findOneBy({ id: ps.id }); - - if (ad == null) throw new ApiError(meta.errors.noSuchAd); - - await Ads.delete(ad.id); -}); diff --git a/packages/backend/src/server/api/endpoints/admin/ad/list.ts b/packages/backend/src/server/api/endpoints/admin/ad/list.ts deleted file mode 100644 index 74f154f27..000000000 --- a/packages/backend/src/server/api/endpoints/admin/ad/list.ts +++ /dev/null @@ -1,30 +0,0 @@ -import define from '../../../define.js'; -import { Ads } from '@/models/index.js'; -import { makePaginationQuery } from '../../../common/make-pagination-query.js'; - -export const meta = { - tags: ['admin'], - - requireCredential: true, - requireModerator: true, -} as const; - -export const paramDef = { - type: 'object', - properties: { - limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, - sinceId: { type: 'string', format: 'misskey:id' }, - untilId: { type: 'string', format: 'misskey:id' }, - }, - required: [], -} as const; - -// eslint-disable-next-line import/no-default-export -export default define(meta, paramDef, async (ps) => { - const query = makePaginationQuery(Ads.createQueryBuilder('ad'), ps.sinceId, ps.untilId) - .andWhere('ad.expiresAt > :now', { now: new Date() }); - - const ads = await query.take(ps.limit).getMany(); - - return ads; -}); diff --git a/packages/backend/src/server/api/endpoints/admin/ad/update.ts b/packages/backend/src/server/api/endpoints/admin/ad/update.ts deleted file mode 100644 index 650f8670e..000000000 --- a/packages/backend/src/server/api/endpoints/admin/ad/update.ts +++ /dev/null @@ -1,50 +0,0 @@ -import define from '../../../define.js'; -import { Ads } from '@/models/index.js'; -import { ApiError } from '../../../error.js'; - -export const meta = { - tags: ['admin'], - - requireCredential: true, - requireModerator: true, - - errors: { - noSuchAd: { - message: 'No such ad.', - code: 'NO_SUCH_AD', - id: 'b7aa1727-1354-47bc-a182-3a9c3973d300', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { type: 'string', format: 'misskey:id' }, - memo: { type: 'string' }, - url: { type: 'string', minLength: 1 }, - imageUrl: { type: 'string', minLength: 1 }, - place: { type: 'string' }, - priority: { type: 'string' }, - ratio: { type: 'integer' }, - expiresAt: { type: 'integer' }, - }, - required: ['id', 'memo', 'url', 'imageUrl', 'place', 'priority', 'ratio', 'expiresAt'], -} as const; - -// eslint-disable-next-line import/no-default-export -export default define(meta, paramDef, async (ps, me) => { - const ad = await Ads.findOneBy({ id: ps.id }); - - if (ad == null) throw new ApiError(meta.errors.noSuchAd); - - await Ads.update(ad.id, { - url: ps.url, - place: ps.place, - priority: ps.priority, - ratio: ps.ratio, - memo: ps.memo, - imageUrl: ps.imageUrl, - expiresAt: new Date(ps.expiresAt), - }); -}); diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 01f3c522c..5d7973669 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -97,30 +97,6 @@ export const meta = { }, }, }, - ads: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - properties: { - place: { - type: 'string', - optional: false, nullable: false, - }, - url: { - type: 'string', - optional: false, nullable: false, - format: 'url', - }, - imageUrl: { - type: 'string', - optional: false, nullable: false, - format: 'url', - }, - }, - }, - }, enableEmail: { type: 'boolean', optional: false, nullable: false, @@ -318,8 +294,6 @@ export default define(meta, paramDef, async (ps, me) => { description: instance.description, langs: instance.langs, tosUrl: instance.ToSUrl, - repositoryUrl: instance.repositoryUrl, - feedbackUrl: instance.feedbackUrl, disableRegistration: instance.disableRegistration, disableLocalTimeline: instance.disableLocalTimeline, disableGlobalTimeline: instance.disableGlobalTimeline, diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index a82af38f1..bd75e0f93 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -78,8 +78,6 @@ export const paramDef = { swPublicKey: { type: 'string', nullable: true }, swPrivateKey: { type: 'string', nullable: true }, tosUrl: { type: 'string', nullable: true }, - repositoryUrl: { type: 'string' }, - feedbackUrl: { type: 'string' }, useObjectStorage: { type: 'boolean' }, objectStorageBaseUrl: { type: 'string', nullable: true }, objectStorageBucket: { type: 'string', nullable: true }, @@ -313,14 +311,6 @@ export default define(meta, paramDef, async (ps, me) => { set.ToSUrl = ps.tosUrl; } - if (ps.repositoryUrl !== undefined) { - set.repositoryUrl = ps.repositoryUrl; - } - - if (ps.feedbackUrl !== undefined) { - set.feedbackUrl = ps.feedbackUrl; - } - if (ps.useObjectStorage !== undefined) { set.useObjectStorage = ps.useObjectStorage; } diff --git a/packages/backend/src/server/api/endpoints/ap/get.ts b/packages/backend/src/server/api/endpoints/ap/get.ts index 4c3dbecfa..559bc277f 100644 --- a/packages/backend/src/server/api/endpoints/ap/get.ts +++ b/packages/backend/src/server/api/endpoints/ap/get.ts @@ -1,6 +1,6 @@ import define from '../../define.js'; import Resolver from '@/remote/activitypub/resolver.js'; -import ms from 'ms'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['federation'], @@ -8,7 +8,7 @@ export const meta = { requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 30, }, diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 6442a1412..7426daeec 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -11,8 +11,8 @@ import { Note } from '@/models/entities/note.js'; import { CacheableLocalUser, User } from '@/models/entities/user.js'; import { fetchMeta } from '@/misc/fetch-meta.js'; import { isActor, isPost, getApId } from '@/remote/activitypub/type.js'; -import ms from 'ms'; import { SchemaType } from '@/misc/schema.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['federation'], @@ -20,7 +20,7 @@ export const meta = { requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 30, }, diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts index 0540e6ab0..4e88f32fb 100644 --- a/packages/backend/src/server/api/endpoints/blocking/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking/create.ts @@ -1,15 +1,15 @@ -import ms from 'ms'; import create from '@/services/blocking/create.js'; import define from '../../define.js'; import { ApiError } from '../../error.js'; import { getUser } from '../../common/getters.js'; import { Blockings, NoteWatchings, Users } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['account'], limit: { - duration: ms('1hour'), + duration: HOUR, max: 100, }, diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts index 77e17b3ba..37215bbd6 100644 --- a/packages/backend/src/server/api/endpoints/blocking/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts @@ -1,15 +1,15 @@ -import ms from 'ms'; import deleteBlocking from '@/services/blocking/delete.js'; import define from '../../define.js'; import { ApiError } from '../../error.js'; import { getUser } from '../../common/getters.js'; import { Blockings, Users } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['account'], limit: { - duration: ms('1hour'), + duration: HOUR, max: 100, }, diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index 7397fd9ce..68ddd586e 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -1,10 +1,10 @@ -import ms from 'ms'; import { addFile } from '@/services/drive/add-file.js'; import define from '../../../define.js'; import { apiLogger } from '../../../logger.js'; import { ApiError } from '../../../error.js'; import { DriveFiles } from '@/models/index.js'; import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['drive'], @@ -12,7 +12,7 @@ export const meta = { requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 120, }, diff --git a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts index 2a12f12a8..88a448f21 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts @@ -1,14 +1,14 @@ -import ms from 'ms'; import { uploadFromUrl } from '@/services/drive/upload-from-url.js'; import define from '../../../define.js'; import { DriveFiles } from '@/models/index.js'; import { publishMainStream } from '@/services/stream.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['drive'], limit: { - duration: ms('1hour'), + duration: HOUR, max: 60, }, diff --git a/packages/backend/src/server/api/endpoints/export-custom-emojis.ts b/packages/backend/src/server/api/endpoints/export-custom-emojis.ts index 5fe622932..3dc9d4e9f 100644 --- a/packages/backend/src/server/api/endpoints/export-custom-emojis.ts +++ b/packages/backend/src/server/api/endpoints/export-custom-emojis.ts @@ -1,12 +1,12 @@ -import ms from 'ms'; import { createExportCustomEmojisJob } from '@/queue/index.js'; import define from '../define.js'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 1, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/fetch-rss.ts b/packages/backend/src/server/api/endpoints/fetch-rss.ts new file mode 100644 index 000000000..05fa22a9e --- /dev/null +++ b/packages/backend/src/server/api/endpoints/fetch-rss.ts @@ -0,0 +1,39 @@ +import Parser from 'rss-parser'; +import { getResponse } from '@/misc/fetch.js'; +import config from '@/config/index.js'; +import define from '../define.js'; + +const rssParser = new Parser(); + +export const meta = { + tags: ['meta'], + + requireCredential: false, + allowGet: true, + cacheSec: 60 * 3, +} as const; + +export const paramDef = { + type: 'object', + properties: { + url: { type: 'string' }, + }, + required: ['url'], +} as const; + +// eslint-disable-next-line import/no-default-export +export default define(meta, paramDef, async (ps) => { + const res = await getResponse({ + url: ps.url, + method: 'GET', + headers: Object.assign({ + 'User-Agent': config.userAgent, + Accept: 'application/rss+xml, */*', + }), + timeout: 5000, + }); + + const text = await res.text(); + + return rssParser.parseString(text); +}); diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts index 02a030cd5..3a12a55b8 100644 --- a/packages/backend/src/server/api/endpoints/following/create.ts +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -1,16 +1,16 @@ -import ms from 'ms'; import create from '@/services/following/create.js'; import define from '../../define.js'; import { ApiError } from '../../error.js'; import { getUser } from '../../common/getters.js'; import { Followings, Users } from '@/models/index.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['following', 'users'], limit: { - duration: ms('1hour'), + duration: HOUR, max: 100, }, diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts index 2f41b16e9..a454f2d72 100644 --- a/packages/backend/src/server/api/endpoints/following/delete.ts +++ b/packages/backend/src/server/api/endpoints/following/delete.ts @@ -1,15 +1,15 @@ -import ms from 'ms'; import deleteFollowing from '@/services/following/delete.js'; import define from '../../define.js'; import { ApiError } from '../../error.js'; import { getUser } from '../../common/getters.js'; import { Followings, Users } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['following', 'users'], limit: { - duration: ms('1hour'), + duration: HOUR, max: 100, }, diff --git a/packages/backend/src/server/api/endpoints/following/invalidate.ts b/packages/backend/src/server/api/endpoints/following/invalidate.ts index 18ec5affe..cf3a21406 100644 --- a/packages/backend/src/server/api/endpoints/following/invalidate.ts +++ b/packages/backend/src/server/api/endpoints/following/invalidate.ts @@ -1,15 +1,15 @@ -import ms from 'ms'; import deleteFollowing from '@/services/following/delete.js'; import define from '../../define.js'; import { ApiError } from '../../error.js'; import { getUser } from '../../common/getters.js'; import { Followings, Users } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['following', 'users'], limit: { - duration: ms('1hour'), + duration: HOUR, max: 100, }, diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index c2f96560c..61bf99411 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -1,9 +1,9 @@ -import ms from 'ms'; import define from '../../../define.js'; import { DriveFiles, GalleryPosts } from '@/models/index.js'; import { genId } from '../../../../../misc/gen-id.js'; import { GalleryPost } from '@/models/entities/gallery-post.js'; import { DriveFile } from '@/models/entities/drive-file.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['gallery'], @@ -13,7 +13,7 @@ export const meta = { kind: 'write:gallery', limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, }, diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index 96ce5c72f..7e49d4e28 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -1,7 +1,7 @@ -import ms from 'ms'; import define from '../../../define.js'; import { DriveFiles, GalleryPosts } from '@/models/index.js'; import { DriveFile } from '@/models/entities/drive-file.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['gallery'], @@ -11,7 +11,7 @@ export const meta = { kind: 'write:gallery', limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, }, diff --git a/packages/backend/src/server/api/endpoints/i/export-blocking.ts b/packages/backend/src/server/api/endpoints/i/export-blocking.ts index aed4c2e0a..682d39552 100644 --- a/packages/backend/src/server/api/endpoints/i/export-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/export-blocking.ts @@ -1,12 +1,12 @@ import define from '../../define.js'; import { createExportBlockingJob } from '@/queue/index.js'; -import ms from 'ms'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 1, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/export-following.ts b/packages/backend/src/server/api/endpoints/i/export-following.ts index 058d77b3c..3d56ab7ee 100644 --- a/packages/backend/src/server/api/endpoints/i/export-following.ts +++ b/packages/backend/src/server/api/endpoints/i/export-following.ts @@ -1,12 +1,12 @@ import define from '../../define.js'; import { createExportFollowingJob } from '@/queue/index.js'; -import ms from 'ms'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 1, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/export-mute.ts b/packages/backend/src/server/api/endpoints/i/export-mute.ts index c0216fac0..b6cc1eea4 100644 --- a/packages/backend/src/server/api/endpoints/i/export-mute.ts +++ b/packages/backend/src/server/api/endpoints/i/export-mute.ts @@ -1,12 +1,12 @@ import define from '../../define.js'; import { createExportMuteJob } from '@/queue/index.js'; -import ms from 'ms'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 1, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/export-notes.ts b/packages/backend/src/server/api/endpoints/i/export-notes.ts index 4b85a4555..4856b84ab 100644 --- a/packages/backend/src/server/api/endpoints/i/export-notes.ts +++ b/packages/backend/src/server/api/endpoints/i/export-notes.ts @@ -1,12 +1,12 @@ import define from '../../define.js'; import { createExportNotesJob } from '@/queue/index.js'; -import ms from 'ms'; +import { DAY } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1day'), + duration: DAY, max: 1, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts index fa5c1f5e5..1aa02707d 100644 --- a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts @@ -1,12 +1,12 @@ import define from '../../define.js'; import { createExportUserListsJob } from '@/queue/index.js'; -import ms from 'ms'; +import { MINUTE } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1min'), + duration: MINUTE, max: 1, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/import-blocking.ts b/packages/backend/src/server/api/endpoints/i/import-blocking.ts index 0bcbf37dd..5e5bcba7a 100644 --- a/packages/backend/src/server/api/endpoints/i/import-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/import-blocking.ts @@ -1,15 +1,15 @@ import define from '../../define.js'; import { createImportBlockingJob } from '@/queue/index.js'; -import ms from 'ms'; import { ApiError } from '../../error.js'; import { DriveFiles } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 1, }, diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts index ee2abbea1..28d9d38fa 100644 --- a/packages/backend/src/server/api/endpoints/i/import-following.ts +++ b/packages/backend/src/server/api/endpoints/i/import-following.ts @@ -1,14 +1,14 @@ import define from '../../define.js'; import { createImportFollowingJob } from '@/queue/index.js'; -import ms from 'ms'; import { ApiError } from '../../error.js'; import { DriveFiles } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duratition: HOUR, max: 1, }, diff --git a/packages/backend/src/server/api/endpoints/i/import-muting.ts b/packages/backend/src/server/api/endpoints/i/import-muting.ts index b3b3b3923..4165da020 100644 --- a/packages/backend/src/server/api/endpoints/i/import-muting.ts +++ b/packages/backend/src/server/api/endpoints/i/import-muting.ts @@ -1,15 +1,15 @@ import define from '../../define.js'; import { createImportMutingJob } from '@/queue/index.js'; -import ms from 'ms'; import { ApiError } from '../../error.js'; import { DriveFiles } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 1, }, diff --git a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts index 64f5ec05f..6b3949c99 100644 --- a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts @@ -1,14 +1,14 @@ import define from '../../define.js'; import { createImportUserListsJob } from '@/queue/index.js'; -import ms from 'ms'; import { ApiError } from '../../error.js'; import { DriveFiles } from '@/models/index.js'; +import { HOUR } from '@/const.js'; export const meta = { secure: true, requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 1, }, diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index 331807852..7cfb88978 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -2,12 +2,12 @@ import { publishMainStream } from '@/services/stream.js'; import define from '../../define.js'; import rndstr from 'rndstr'; import config from '@/config/index.js'; -import ms from 'ms'; import bcrypt from 'bcryptjs'; import { Users, UserProfiles } from '@/models/index.js'; import { sendEmail } from '@/services/send-email.js'; import { ApiError } from '../../error.js'; import { validateEmailForAccount } from '@/services/validate-email-for-account.js'; +import { HOUR } from '@/const.js'; export const meta = { requireCredential: true, @@ -15,7 +15,7 @@ export const meta = { secure: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 3, }, diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts index f66d75873..17d295700 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts @@ -1,8 +1,8 @@ import define from '../../../define.js'; -import ms from 'ms'; import { ApiError } from '../../../error.js'; import { MessagingMessages } from '@/models/index.js'; import { deleteMessage } from '@/services/messages/delete.js'; +import { SECOND, HOUR } from '@/const.js'; export const meta = { tags: ['messaging'], @@ -12,9 +12,9 @@ export const meta = { kind: 'write:messaging', limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, - minInterval: ms('1sec'), + minInterval: SECOND, }, errors: { diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index c2ea75457..2b6de3756 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -1,7 +1,7 @@ import { IsNull, MoreThan } from 'typeorm'; import config from '@/config/index.js'; import { fetchMeta } from '@/misc/fetch-meta.js'; -import { Ads, Emojis, Users } from '@/models/index.js'; +import { Emojis, Users } from '@/models/index.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import define from '../define.js'; @@ -53,16 +53,6 @@ export const meta = { type: 'string', optional: false, nullable: true, }, - repositoryUrl: { - type: 'string', - optional: false, nullable: false, - default: 'https://github.com/misskey-dev/misskey', - }, - feedbackUrl: { - type: 'string', - optional: false, nullable: false, - default: 'https://github.com/misskey-dev/misskey/issues/new', - }, defaultDarkTheme: { type: 'string', optional: false, nullable: true, @@ -168,30 +158,6 @@ export const meta = { }, }, }, - ads: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - properties: { - place: { - type: 'string', - optional: false, nullable: false, - }, - url: { - type: 'string', - optional: false, nullable: false, - format: 'url', - }, - imageUrl: { - type: 'string', - optional: false, nullable: false, - format: 'url', - }, - }, - }, - }, requireSetup: { type: 'boolean', optional: false, nullable: false, @@ -310,12 +276,6 @@ export default define(meta, paramDef, async (ps, me) => { }, }); - const ads = await Ads.find({ - where: { - expiresAt: MoreThan(new Date()), - }, - }); - const response: any = { maintainerName: instance.maintainerName, maintainerEmail: instance.maintainerEmail, @@ -327,8 +287,6 @@ export default define(meta, paramDef, async (ps, me) => { description: instance.description, langs: instance.langs, tosUrl: instance.ToSUrl, - repositoryUrl: instance.repositoryUrl, - feedbackUrl: instance.feedbackUrl, disableRegistration: instance.disableRegistration, disableLocalTimeline: instance.disableLocalTimeline, disableGlobalTimeline: instance.disableGlobalTimeline, @@ -349,13 +307,6 @@ export default define(meta, paramDef, async (ps, me) => { emojis: await Emojis.packMany(emojis), defaultLightTheme: instance.defaultLightTheme, defaultDarkTheme: instance.defaultDarkTheme, - ads: ads.map(ad => ({ - id: ad.id, - url: ad.url, - place: ad.place, - ratio: ad.ratio, - imageUrl: ad.imageUrl, - })), enableEmail: instance.enableEmail, enableTwitterIntegration: instance.enableTwitterIntegration, diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 0baeb0230..aeac02d39 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -1,4 +1,3 @@ -import ms from 'ms'; import { In } from 'typeorm'; import create from '@/services/note/create.js'; import { User } from '@/models/entities/user.js'; @@ -10,6 +9,7 @@ import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { noteVisibilities } from '../../../../types.js'; import { ApiError } from '../../error.js'; import define from '../../define.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['notes'], @@ -17,7 +17,7 @@ export const meta = { requireCredential: true, limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, }, diff --git a/packages/backend/src/server/api/endpoints/notes/delete.ts b/packages/backend/src/server/api/endpoints/notes/delete.ts index c23ceeb5b..9c3ca136c 100644 --- a/packages/backend/src/server/api/endpoints/notes/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/delete.ts @@ -1,9 +1,9 @@ -import ms from 'ms'; import deleteNote from '@/services/note/delete.js'; import { Users } from '@/models/index.js'; import define from '../../define.js'; import { getNote } from '../../common/getters.js'; import { ApiError } from '../../error.js'; +import { SECOND, HOUR } from '@/const.js'; export const meta = { tags: ['notes'], @@ -13,9 +13,9 @@ export const meta = { kind: 'write:notes', limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, - minInterval: ms('1sec'), + minInterval: SECOND, }, errors: { diff --git a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts index 2150efaaf..5a04d68f3 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts @@ -60,12 +60,21 @@ export default define(meta, paramDef, async (ps, user) => { query.setParameters(mutingQuery.getParameters()); //#endregion - const polls = await query.take(ps.limit).skip(ps.offset).getMany(); + const polls = await query + .orderBy('poll.noteId', 'DESC') + .take(ps.limit) + .skip(ps.offset) + .getMany(); if (polls.length === 0) return []; - const notes = await Notes.findBy({ - id: In(polls.map(poll => poll.noteId)), + const notes = await Notes.find({ + where: { + id: In(polls.map(poll => poll.noteId)), + }, + order: { + createdAt: 'DESC', + }, }); return await Notes.packMany(notes, user, { diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts index 56f278326..d56bad965 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts @@ -8,6 +8,9 @@ export const meta = { requireCredential: false, + allowGet: true, + cacheSec: 60, + res: { type: 'array', optional: false, nullable: false, diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts index c13cafa21..83fdf6959 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts @@ -1,8 +1,8 @@ -import ms from 'ms'; import deleteReaction from '@/services/note/reaction/delete.js'; import define from '../../../define.js'; import { getNote } from '../../../common/getters.js'; import { ApiError } from '../../../error.js'; +import { SECOND, HOUR } from '@/const.js'; export const meta = { tags: ['reactions', 'notes'], @@ -12,9 +12,9 @@ export const meta = { kind: 'write:reactions', limit: { - duration: ms('1hour'), + duration: HOUR, max: 60, - minInterval: ms('3sec'), + minInterval: 3 * SECOND, }, errors: { diff --git a/packages/backend/src/server/api/endpoints/notes/unrenote.ts b/packages/backend/src/server/api/endpoints/notes/unrenote.ts index 3fba0efe0..1c7fa6812 100644 --- a/packages/backend/src/server/api/endpoints/notes/unrenote.ts +++ b/packages/backend/src/server/api/endpoints/notes/unrenote.ts @@ -1,9 +1,9 @@ -import ms from 'ms'; import deleteNote from '@/services/note/delete.js'; import { Notes, Users } from '@/models/index.js'; import define from '../../define.js'; import { getNote } from '../../common/getters.js'; import { ApiError } from '../../error.js'; +import { SECOND, HOUR } from '@/const.js'; export const meta = { tags: ['notes'], @@ -13,9 +13,9 @@ export const meta = { kind: 'write:notes', limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, - minInterval: ms('1sec'), + minInterval: SECOND, }, errors: { diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index b008cde84..e7b78fb38 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -1,9 +1,9 @@ -import ms from 'ms'; import { Pages, DriveFiles } from '@/models/index.js'; import { genId } from '@/misc/gen-id.js'; import { Page } from '@/models/entities/page.js'; import define from '../../define.js'; import { ApiError } from '../../error.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['pages'], @@ -13,7 +13,7 @@ export const meta = { kind: 'write:pages', limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, }, diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index d241f585a..8230ea09b 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -1,8 +1,8 @@ -import ms from 'ms'; import { Not } from 'typeorm'; import { Pages, DriveFiles } from '@/models/index.js'; import define from '../../define.js'; import { ApiError } from '../../error.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['pages'], @@ -12,7 +12,7 @@ export const meta = { kind: 'write:pages', limit: { - duration: ms('1hour'), + duration: HOUR, max: 300, }, diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts index 9c2462312..d76f3254a 100644 --- a/packages/backend/src/server/api/endpoints/request-reset-password.ts +++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts @@ -1,11 +1,11 @@ import rndstr from 'rndstr'; -import ms from 'ms'; import { IsNull } from 'typeorm'; import config from '@/config/index.js'; import { Users, UserProfiles, PasswordResetRequests } from '@/models/index.js'; import { sendEmail } from '@/services/send-email.js'; import { genId } from '@/misc/gen-id.js'; import define from '../define.js'; +import { HOUR } from '@/const.js'; export const meta = { tags: ['reset password'], @@ -15,7 +15,7 @@ export const meta = { description: 'Request a users password to be reset.', limit: { - duration: ms('1hour'), + duration: HOUR, max: 3, }, diff --git a/packages/backend/src/server/api/endpoints/users/recommendation.ts b/packages/backend/src/server/api/endpoints/users/recommendation.ts index e7654e171..d4dc524d9 100644 --- a/packages/backend/src/server/api/endpoints/users/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/users/recommendation.ts @@ -1,8 +1,8 @@ -import ms from 'ms'; import { Users, Followings } from '@/models/index.js'; import define from '../../define.js'; import { generateMutedUserQueryForUsers } from '../../common/generate-muted-user-query.js'; import { generateBlockedUserQuery, generateBlockQueryForUsers } from '../../common/generate-block-query.js'; +import { DAY } from '@/const.js'; export const meta = { tags: ['users'], @@ -39,7 +39,7 @@ export default define(meta, paramDef, async (ps, me) => { .where('user.isLocked = FALSE') .andWhere('user.isExplorable = TRUE') .andWhere('user.host IS NULL') - .andWhere('user.updatedAt >= :date', { date: new Date(Date.now() - ms('7days')) }) + .andWhere('user.updatedAt >= :date', { date: new Date(Date.now() - (7 * DAY)) }) .andWhere('user.id != :meId', { meId: me.id }) .orderBy('user.followersCount', 'DESC'); diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index 8bb927987..f01f47723 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -51,7 +51,7 @@ export default class extends Channel { } // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する - if (iUserRelated(note, this.muting)) return; + if (isUserRelated(note, this.muting)) return; // 流れてきたNoteがブロックされているユーザーが関わるものだったら無視する if (isUserRelated(note, this.blocking)) return; diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index f139d203d..764718f30 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -11,10 +11,10 @@ const router = new Router(); const nodeinfo2_1path = '/nodeinfo/2.1'; const nodeinfo2_0path = '/nodeinfo/2.0'; -export const links = [/* (awaiting release) { +export const links = [{ rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1', href: config.url + nodeinfo2_1path -}, */{ +}, { rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0', href: config.url + nodeinfo2_0path, }]; @@ -39,9 +39,9 @@ const nodeinfo2 = async () => { return { software: { - name: 'misskey', + name: 'foundkey', version: config.version, - repository: meta.repositoryUrl, + repository: 'https://akkoma.dev/FoundKeyGang/FoundKey', }, protocols: ['activitypub'], services: { @@ -64,7 +64,7 @@ const nodeinfo2 = async () => { langs: meta.langs, tosUrl: meta.ToSUrl, repositoryUrl: meta.repositoryUrl, - feedbackUrl: meta.feedbackUrl, + feedbackUrl: 'ircs://irc.akkoma.dev/foundkey', disableRegistration: meta.disableRegistration, disableLocalTimeline: meta.disableLocalTimeline, disableGlobalTimeline: meta.disableGlobalTimeline, diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 9fc536555..e82de8e14 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -106,15 +106,39 @@ function renderError(code, details) { let errorsElement = document.getElementById('errors'); if (!errorsElement) { + document.getElementsByTagName("head")[0].insertAdjacentHTML( + "beforeend", + ``); document.documentElement.innerHTML = ` -

⚠ An error has occurred. ⚠

-

If the problem persists, please contact the administrator. You may also try the following options:

- -
+ + + + + +

An error has occurred!

+ +

Don't worry, it's (probably) not your fault.

+

If the problem persists after refreshing, please contact your instance's administrator.
You may also try the following options:

+ + + +
+ + + +
+ + + +
`; @@ -122,8 +146,7 @@ } const detailsElement = document.createElement('details'); - detailsElement.innerHTML = `ERROR CODE: ${code}${JSON.stringify(details)}`; - + detailsElement.innerHTML = `
ERROR CODE: ${code}${JSON.stringify(details)}`; errorsElement.appendChild(detailsElement); } diff --git a/packages/backend/src/server/web/error.css b/packages/backend/src/server/web/error.css new file mode 100644 index 000000000..9f8f90501 --- /dev/null +++ b/packages/backend/src/server/web/error.css @@ -0,0 +1,98 @@ +* { + font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif; +} + +body, +html { + background-color: #222; + color: #dfddcc; + justify-content: center; + margin: auto; + width: 80%; + padding: 10px; + text-align: center; +} + +button { + border-radius: 999px; + padding: 0px 12px 0px 12px; + border: none; + cursor: pointer; + margin-bottom: 12px; +} + +.button-big { + background: linear-gradient(90deg, rgb(134, 179, 0), rgb(74, 179, 0)); + line-height: 50px; +} + +.button-big:hover { + background: rgb(153, 204, 0); +} + +.button-small { + background: #444; + line-height: 40px; +} + +.button-small:hover { + background: #555; +} + +.button-label-big { + color: #222; + font-weight: bold; + font-size: 20px; + padding: 12px; +} + +.button-label-small { + color: rgb(153, 204, 0); + font-size: 16px; + padding: 12px; +} + +a { + color: rgb(134, 179, 0); + text-decoration: none; +} + +p, +li { + font-size: 16px; +} + +.dont-worry, +#msg { + font-size: 18px; +} + +.icon-warning { + color: #dec340; + height: 4rem; +} + +h1 { + font-size: 32px; +} + +code { + font-family: Fira, FiraCode, monospace; +} + +details { + background: #333; + margin-bottom: 2rem; + padding: 0.5rem 1rem; + border-radius: 5px; + justify-content: center; + margin: auto; +} + +summary { + cursor: pointer; +} + +summary > * { + display: inline; +} diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 682497e28..3e2011587 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -5,7 +5,6 @@ import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { readFileSync } from 'node:fs'; -import ms from 'ms'; import Koa from 'koa'; import Router from '@koa/router'; import send from 'koa-send'; @@ -27,6 +26,7 @@ import { genOpenapiSpec } from '../api/openapi/gen-spec.js'; import { urlPreviewHandler } from './url-preview.js'; import { manifestHandler } from './manifest.js'; import packFeed from './feed.js'; +import { MINUTE, DAY } from '@/const.js'; const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); @@ -100,21 +100,21 @@ const router = new Router(); router.get('/static-assets/(.*)', async ctx => { await send(ctx as any, ctx.path.replace('/static-assets/', ''), { root: staticAssets, - maxage: ms('7 days'), + maxage: 7 * DAY, }); }); router.get('/client-assets/(.*)', async ctx => { await send(ctx as any, ctx.path.replace('/client-assets/', ''), { root: clientAssets, - maxage: ms('7 days'), + maxage: 7 * DAY, }); }); router.get('/assets/(.*)', async ctx => { await send(ctx as any, ctx.path.replace('/assets/', ''), { root: assets, - maxage: ms('7 days'), + maxage: 7 * DAY, }); }); @@ -137,7 +137,7 @@ router.get('/twemoji/(.*)', async ctx => { await send(ctx as any, path, { root: `${_dirname}/../../../node_modules/@discordapp/twemoji/dist/svg/`, - maxage: ms('30 days'), + maxage: 30 * DAY, }); }); @@ -188,7 +188,7 @@ router.get('/twemoji-badge/(.*)', async ctx => { router.get(`/sw.js`, async ctx => { await send(ctx as any, `/sw.js`, { root: swAssets, - maxage: ms('10 minutes'), + maxage: 10 * MINUTE, }); }); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 5bb156f0f..32499aa45 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -53,7 +53,7 @@ html block meta block og - meta(property='og:title' content= title || 'Misskey') + meta(property='og:title' content= title || 'Misskey') meta(property='og:description' content= desc || '✨🌎✨ A interplanetary communication platform ✨🚀✨') meta(property='og:image' content= img) diff --git a/packages/backend/src/server/web/views/bios.pug b/packages/backend/src/server/web/views/bios.pug index d81a3ee67..39a151a29 100644 --- a/packages/backend/src/server/web/views/bios.pug +++ b/packages/backend/src/server/web/views/bios.pug @@ -5,7 +5,7 @@ html head meta(charset='utf-8') meta(name='application-name' content='Misskey') - title Misskey BIOS + title Misskey Repair Tool style include ../bios.css script @@ -13,7 +13,7 @@ html body header - h1 Misskey BIOS #{version} + h1 Misskey Repair Tool #{version} main div.tabs button#ls edit local storage diff --git a/packages/backend/src/server/web/views/flush.pug b/packages/backend/src/server/web/views/flush.pug index ec585a34d..b08f61c73 100644 --- a/packages/backend/src/server/web/views/flush.pug +++ b/packages/backend/src/server/web/views/flush.pug @@ -1,6 +1,12 @@ doctype html html + head + meta(charset='utf-8') + meta(name='application-name' content='Misskey') + title Flushing Misskey + style + include ../error.css #msg script. const msg = document.getElementById('msg'); diff --git a/packages/backend/test/streaming.ts b/packages/backend/test/streaming.ts index f080b71dd..621d07f9c 100644 --- a/packages/backend/test/streaming.ts +++ b/packages/backend/test/streaming.ts @@ -3,22 +3,12 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; import { Following } from '../src/models/entities/following.js'; -import { connectStream, signup, request, post, startServer, shutdownServer, initTestDb } from './utils.js'; +import { connectStream, signup, api, post, startServer, shutdownServer, initTestDb, waitFire } from './utils.js'; describe('Streaming', () => { let p: childProcess.ChildProcess; let Followings: any; - beforeEach(async () => { - p = await startServer(); - const connection = await initTestDb(true); - Followings = connection.getRepository(Following); - }); - - afterEach(async () => { - await shutdownServer(p); - }); - const follow = async (follower: any, followee: any) => { await Followings.save({ id: 'a', @@ -34,871 +24,522 @@ describe('Streaming', () => { }); }; - it('mention event', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); + describe('Streaming', () => { + // Local users + let ayano: any; + let kyoko: any; + let chitose: any; - const ws = await connectStream(bob, 'main', ({ type, body }) => { - if (type == 'mention') { - assert.deepStrictEqual(body.userId, alice.id); - ws.close(); - done(); - } - }); + // Remote users + let akari: any; + let chinatsu: any; - post(alice, { - text: 'foo @bob bar', - }); - })); + let kyokoNote: any; + let list: any; - it('renote event', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - const bobNote = await post(bob, { - text: 'foo', - }); + before(async () => { + p = await startServer(); + const connection = await initTestDb(true); + Followings = connection.getRepository(Following); - const ws = await connectStream(bob, 'main', ({ type, body }) => { - if (type == 'renote') { - assert.deepStrictEqual(body.renoteId, bobNote.id); - ws.close(); - done(); - } - }); + ayano = await signup({ username: 'ayano' }); + kyoko = await signup({ username: 'kyoko' }); + chitose = await signup({ username: 'chitose' }); - post(alice, { - renoteId: bobNote.id, - }); - })); + akari = await signup({ username: 'akari', host: 'example.com' }); + chinatsu = await signup({ username: 'chinatsu', host: 'example.com' }); - describe('Home Timeline', () => { - it('自分の投稿が流れる', () => new Promise(async done => { - const post = { - text: 'foo', - }; + kyokoNote = await post(kyoko, { text: 'foo' }); - const me = await signup(); + // Follow: ayano => kyoko + await api('following/create', { userId: kyoko.id }, ayano); - const ws = await connectStream(me, 'homeTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.text, post.text); - ws.close(); - done(); - } - }); + // Follow: ayano => akari + await follow(ayano, akari); - request('/notes/create', post, me); - })); - - it('フォローしているユーザーの投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // Alice が Bob をフォロー - await request('/following/create', { - userId: bob.id, - }, alice); - - const ws = await connectStream(alice, 'homeTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - ws.close(); - done(); - } - }); - - post(bob, { - text: 'foo', - }); - })); - - it('フォローしていないユーザーの投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - let fired = false; - - const ws = await connectStream(alice, 'homeTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - post(bob, { - text: 'foo', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - it('フォローしているユーザーのダイレクト投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // Alice が Bob をフォロー - await request('/following/create', { - userId: bob.id, - }, alice); - - const ws = await connectStream(alice, 'homeTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - assert.deepStrictEqual(body.text, 'foo'); - ws.close(); - done(); - } - }); - - // Bob が Alice 宛てのダイレクト投稿 - post(bob, { - text: 'foo', - visibility: 'specified', - visibleUserIds: [alice.id], - }); - })); - - it('フォローしているユーザーでも自分が指定されていないダイレクト投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - const carol = await signup({ username: 'carol' }); - - // Alice が Bob をフォロー - await request('/following/create', { - userId: bob.id, - }, alice); - - let fired = false; - - const ws = await connectStream(alice, 'homeTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - // Bob が Carol 宛てのダイレクト投稿 - post(bob, { - text: 'foo', - visibility: 'specified', - visibleUserIds: [carol.id], - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - }); - - describe('Local Timeline', () => { - it('自分の投稿が流れる', () => new Promise(async done => { - const me = await signup(); - - const ws = await connectStream(me, 'localTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, me.id); - ws.close(); - done(); - } - }); - - post(me, { - text: 'foo', - }); - })); - - it('フォローしていないローカルユーザーの投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const ws = await connectStream(alice, 'localTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - ws.close(); - done(); - } - }); - - post(bob, { - text: 'foo', - }); - })); - - it('リモートユーザーの投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob', host: 'example.com' }); - - let fired = false; - - const ws = await connectStream(alice, 'localTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - post(bob, { - text: 'foo', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - it('フォローしてたとしてもリモートユーザーの投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob', host: 'example.com' }); - - // Alice が Bob をフォロー - await request('/following/create', { - userId: bob.id, - }, alice); - - let fired = false; - - const ws = await connectStream(alice, 'localTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - post(bob, { - text: 'foo', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - it('ホーム指定の投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - let fired = false; - - const ws = await connectStream(alice, 'localTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - // ホーム指定 - post(bob, { - text: 'foo', - visibility: 'home', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - it('フォローしているローカルユーザーのダイレクト投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // Alice が Bob をフォロー - await request('/following/create', { - userId: bob.id, - }, alice); - - let fired = false; - - const ws = await connectStream(alice, 'localTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - // Bob が Alice 宛てのダイレクト投稿 - post(bob, { - text: 'foo', - visibility: 'specified', - visibleUserIds: [alice.id], - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - it('フォローしていないローカルユーザーのフォロワー宛て投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - let fired = false; - - const ws = await connectStream(alice, 'localTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - // フォロワー宛て投稿 - post(bob, { - text: 'foo', - visibility: 'followers', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - }); - - describe('Hybrid Timeline', () => { - it('自分の投稿が流れる', () => new Promise(async done => { - const me = await signup(); - - const ws = await connectStream(me, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, me.id); - ws.close(); - done(); - } - }); - - post(me, { - text: 'foo', - }); - })); - - it('フォローしていないローカルユーザーの投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const ws = await connectStream(alice, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - ws.close(); - done(); - } - }); - - post(bob, { - text: 'foo', - }); - })); - - it('フォローしているリモートユーザーの投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob', host: 'example.com' }); - - // Alice が Bob をフォロー - await follow(alice, bob); - - const ws = await connectStream(alice, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - ws.close(); - done(); - } - }); - - post(bob, { - text: 'foo', - }); - })); - - it('フォローしていないリモートユーザーの投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob', host: 'example.com' }); - - let fired = false; - - const ws = await connectStream(alice, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - post(bob, { - text: 'foo', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - it('フォローしているユーザーのダイレクト投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // Alice が Bob をフォロー - await request('/following/create', { - userId: bob.id, - }, alice); - - const ws = await connectStream(alice, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - assert.deepStrictEqual(body.text, 'foo'); - ws.close(); - done(); - } - }); - - // Bob が Alice 宛てのダイレクト投稿 - post(bob, { - text: 'foo', - visibility: 'specified', - visibleUserIds: [alice.id], - }); - })); - - it('フォローしているユーザーのホーム投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // Alice が Bob をフォロー - await request('/following/create', { - userId: bob.id, - }, alice); - - const ws = await connectStream(alice, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - assert.deepStrictEqual(body.text, 'foo'); - ws.close(); - done(); - } - }); - - // ホーム投稿 - post(bob, { - text: 'foo', - visibility: 'home', - }); - })); - - it('フォローしていないローカルユーザーのホーム投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - let fired = false; - - const ws = await connectStream(alice, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - // ホーム投稿 - post(bob, { - text: 'foo', - visibility: 'home', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - it('フォローしていないローカルユーザーのフォロワー宛て投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - let fired = false; - - const ws = await connectStream(alice, 'hybridTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - // フォロワー宛て投稿 - post(bob, { - text: 'foo', - visibility: 'followers', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - }); - - describe('Global Timeline', () => { - it('フォローしていないローカルユーザーの投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const ws = await connectStream(alice, 'globalTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - ws.close(); - done(); - } - }); - - post(bob, { - text: 'foo', - }); - })); - - it('フォローしていないリモートユーザーの投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob', host: 'example.com' }); - - const ws = await connectStream(alice, 'globalTimeline', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - ws.close(); - done(); - } - }); - - post(bob, { - text: 'foo', - }); - })); - - it('ホーム投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - let fired = false; - - const ws = await connectStream(alice, 'globalTimeline', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }); - - // ホーム投稿 - post(bob, { - text: 'foo', - visibility: 'home', - }); - - setTimeout(() => { - assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - }); - - describe('UserList Timeline', () => { - it('リストに入れているユーザーの投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // リスト作成 - const list = await request('/users/lists/create', { + // List: chitose => ayano, kyoko + list = await api('users/lists/create', { name: 'my list', - }, alice).then(x => x.body); + }, chitose).then(x => x.body); - // Alice が Bob をリスイン - await request('/users/lists/push', { + await api('users/lists/push', { listId: list.id, - userId: bob.id, - }, alice); + userId: ayano.id, + }, chitose); - const ws = await connectStream(alice, 'userList', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - ws.close(); - done(); - } - }, { + await api('users/lists/push', { listId: list.id, + userId: kyoko.id, + }, chitose); + }); + + after(async () => { + await shutdownServer(p); + }); + + describe('Events', () => { + it('mention event', async () => { + const fired = await waitFire( + kyoko, 'main', // kyoko:main + () => post(ayano, { text: 'foo @kyoko bar' }), // ayano mention => kyoko + msg => msg.type === 'mention' && msg.body.userId === ayano.id // wait ayano + ); + + assert.strictEqual(fired, true); }); - post(bob, { - text: 'foo', + it('renote event', async () => { + const fired = await waitFire( + kyoko, 'main', // kyoko:main + () => post(ayano, { renoteId: kyokoNote.id }), // ayano renote + msg => msg.type === 'renote' && msg.body.renoteId === kyokoNote.id // wait renote + ); + + assert.strictEqual(fired, true); }); - })); + }); - it('リストに入れていないユーザーの投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); + describe('Home Timeline', () => { + it('自分の投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:Home + () => api('notes/create', { text: 'foo' }, ayano), // ayano posts + msg => msg.type === 'note' && msg.body.text === 'foo' + ); - // リスト作成 - const list = await request('/users/lists/create', { - name: 'my list', - }, alice).then(x => x.body); - - let fired = false; - - const ws = await connectStream(alice, 'userList', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }, { - listId: list.id, + assert.strictEqual(fired, true); }); - post(bob, { - text: 'foo', + it('フォローしているユーザーの投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:home + () => api('notes/create', { text: 'foo' }, kyoko), // kyoko posts + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); + + assert.strictEqual(fired, true); }); - setTimeout(() => { + it('フォローしていないユーザーの投稿は流れない', async () => { + const fired = await waitFire( + kyoko, 'homeTimeline', // kyoko:home + () => api('notes/create', { text: 'foo' }, ayano), // ayano posts + msg => msg.type === 'note' && msg.body.userId === ayano.id // wait ayano + ); + assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - - // #4471 - it('リストに入れているユーザーのダイレクト投稿が流れる', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // リスト作成 - const list = await request('/users/lists/create', { - name: 'my list', - }, alice).then(x => x.body); - - // Alice が Bob をリスイン - await request('/users/lists/push', { - listId: list.id, - userId: bob.id, - }, alice); - - const ws = await connectStream(alice, 'userList', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.userId, bob.id); - assert.deepStrictEqual(body.text, 'foo'); - ws.close(); - done(); - } - }, { - listId: list.id, }); - // Bob が Alice 宛てのダイレクト投稿 - post(bob, { - text: 'foo', - visibility: 'specified', - visibleUserIds: [alice.id], - }); - })); + it('フォローしているユーザーのダイレクト投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:home + () => api('notes/create', { text: 'foo', visibility: 'specified', visibleUserIds: [ayano.id], }, kyoko), // kyoko dm => ayano + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); - // #4335 - it('リストに入れているがフォローはしてないユーザーのフォロワー宛て投稿は流れない', () => new Promise(async done => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - // リスト作成 - const list = await request('/users/lists/create', { - name: 'my list', - }, alice).then(x => x.body); - - // Alice が Bob をリスイン - await request('/users/lists/push', { - listId: list.id, - userId: bob.id, - }, alice); - - let fired = false; - - const ws = await connectStream(alice, 'userList', ({ type, body }) => { - if (type == 'note') { - fired = true; - } - }, { - listId: list.id, + assert.strictEqual(fired, true); }); - // フォロワー宛て投稿 - post(bob, { - text: 'foo', - visibility: 'followers', - }); + it('フォローしているユーザーでも自分が指定されていないダイレクト投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'homeTimeline', // ayano:home + () => api('notes/create', { text: 'foo', visibility: 'specified', visibleUserIds: [chitose.id], }, kyoko), // kyoko dm => chitose + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); - setTimeout(() => { assert.strictEqual(fired, false); - ws.close(); - done(); - }, 3000); - })); - }); + }); + }); // Home - describe('Hashtag Timeline', () => { - it('指定したハッシュタグの投稿が流れる', () => new Promise(async done => { - const me = await signup(); + describe('Local Timeline', () => { + it('自分の投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'localTimeline', // ayano:Local + () => api('notes/create', { text: 'foo' }, ayano), // ayano posts + msg => msg.type === 'note' && msg.body.text === 'foo' + ); - const ws = await connectStream(me, 'hashtag', ({ type, body }) => { - if (type == 'note') { - assert.deepStrictEqual(body.text, '#foo'); + assert.strictEqual(fired, true); + }); + + it('フォローしていないローカルユーザーの投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'localTimeline', // ayano:Local + () => api('notes/create', { text: 'foo' }, chitose), // chitose posts + msg => msg.type === 'note' && msg.body.userId === chitose.id // wait chitose + ); + + assert.strictEqual(fired, true); + }); + + it('リモートユーザーの投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'localTimeline', // ayano:Local + () => api('notes/create', { text: 'foo' }, chinatsu), // chinatsu posts + msg => msg.type === 'note' && msg.body.userId === chinatsu.id // wait chinatsu + ); + + assert.strictEqual(fired, false); + }); + + it('フォローしてたとしてもリモートユーザーの投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'localTimeline', // ayano:Local + () => api('notes/create', { text: 'foo' }, akari), // akari posts + msg => msg.type === 'note' && msg.body.userId === akari.id // wait akari + ); + + assert.strictEqual(fired, false); + }); + + it('ホーム指定の投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'localTimeline', // ayano:Local + () => api('notes/create', { text: 'foo', visibility: 'home' }, kyoko), // kyoko home posts + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); + + assert.strictEqual(fired, false); + }); + + it('フォローしているローカルユーザーのダイレクト投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'localTimeline', // ayano:Local + () => api('notes/create', { text: 'foo', visibility: 'specified', visibleUserIds: [ayano.id] }, kyoko), // kyoko DM => ayano + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); + + assert.strictEqual(fired, false); + }); + + it('フォローしていないローカルユーザーのフォロワー宛て投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'localTimeline', // ayano:Local + () => api('notes/create', { text: 'foo', visibility: 'followers' }, chitose), + msg => msg.type === 'note' && msg.body.userId === chitose.id // wait chitose + ); + + assert.strictEqual(fired, false); + }); + }); + + describe('Hybrid Timeline', () => { + it('自分の投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo' }, ayano), // ayano posts + msg => msg.type === 'note' && msg.body.text === 'foo' + ); + + assert.strictEqual(fired, true); + }); + + it('フォローしていないローカルユーザーの投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo' }, chitose), // chitose posts + msg => msg.type === 'note' && msg.body.userId === chitose.id // wait chitose + ); + + assert.strictEqual(fired, true); + }); + + it('フォローしているリモートユーザーの投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo' }, akari), // akari posts + msg => msg.type === 'note' && msg.body.userId === akari.id // wait akari + ); + + assert.strictEqual(fired, true); + }); + + it('フォローしていないリモートユーザーの投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo' }, chinatsu), // chinatsu posts + msg => msg.type === 'note' && msg.body.userId === chinatsu.id // wait chinatsu + ); + + assert.strictEqual(fired, false); + }); + + it('フォローしているユーザーのダイレクト投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo', visibility: 'specified', visibleUserIds: [ayano.id] }, kyoko), + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); + + assert.strictEqual(fired, true); + }); + + it('フォローしているユーザーのホーム投稿が流れる', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo', visibility: 'home' }, kyoko), + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); + + assert.strictEqual(fired, true); + }); + + it('フォローしていないローカルユーザーのホーム投稿は流れない', async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo', visibility: 'home' }, chitose), + msg => msg.type === 'note' && msg.body.userId === chitose.id + ); + + assert.strictEqual(fired, false); + }); + + it('フォローしていないローカルユーザーのフォロワー宛て投稿は流れない', () => async () => { + const fired = await waitFire( + ayano, 'hybridTimeline', // ayano:Hybrid + () => api('notes/create', { text: 'foo', visibility: 'followers' }, chitose), + msg => msg.type === 'note' && msg.body.userId === chitose.id + ); + + assert.strictEqual(fired, false); + }); + }); + + describe('Global Timeline', () => { + it('フォローしていないローカルユーザーの投稿が流れる', () => async () => { + const fired = await waitFire( + ayano, 'globalTimeline', // ayano:Global + () => api('notes/create', { text: 'foo' }, chitose), // chitose posts + msg => msg.type === 'note' && msg.body.userId === chitose.id // wait chitose + ); + + assert.strictEqual(fired, true); + }); + + it('フォローしていないリモートユーザーの投稿が流れる', () => async () => { + const fired = await waitFire( + ayano, 'globalTimeline', // ayano:Global + () => api('notes/create', { text: 'foo' }, chinatsu), // chinatsu posts + msg => msg.type === 'note' && msg.body.userId === chinatsu.id // wait chinatsu + ); + + assert.strictEqual(fired, true); + }); + + it('ホーム投稿は流れない', () => async () => { + const fired = await waitFire( + ayano, 'globalTimeline', // ayano:Global + () => api('notes/create', { text: 'foo', visibility: 'home' }, kyoko), // kyoko posts + msg => msg.type === 'note' && msg.body.userId === kyoko.id // wait kyoko + ); + + assert.strictEqual(fired, false); + }); + }); + + describe('UserList Timeline', () => { + it('リストに入れているユーザーの投稿が流れる', () => async () => { + const fired = await waitFire( + chitose, 'userList', + () => api('notes/create', { text: 'foo' }, ayano), + msg => msg.type === 'note' && msg.body.userId === ayano.id, + { listId: list.id, } + ); + + assert.strictEqual(fired, true); + }); + + it('リストに入れていないユーザーの投稿は流れない', () => async () => { + const fired = await waitFire( + chitose, 'userList', + () => api('notes/create', { text: 'foo' }, chinatsu), + msg => msg.type === 'note' && msg.body.userId === chinatsu.id, + { listId: list.id, } + ); + + assert.strictEqual(fired, false); + }); + + // #4471 + it('リストに入れているユーザーのダイレクト投稿が流れる', () => async () => { + const fired = await waitFire( + chitose, 'userList', + () => api('notes/create', { text: 'foo', visibility: 'specified', visibleUserIds: [chitose.id] }, ayano), + msg => msg.type === 'note' && msg.body.userId === ayano.id, + { listId: list.id, } + ); + + assert.strictEqual(fired, true); + }); + + // #4335 + it('リストに入れているがフォローはしてないユーザーのフォロワー宛て投稿は流れない', () => async () => { + const fired = await waitFire( + chitose, 'userList', + () => api('notes/create', { text: 'foo', visibility: 'followers' }, kyoko), + msg => msg.type === 'note' && msg.body.userId === kyoko.id, + { listId: list.id, } + ); + + assert.strictEqual(fired, false); + }); + }); + + describe('Hashtag Timeline', () => { + it('指定したハッシュタグの投稿が流れる', () => new Promise(async done => { + const ws = await connectStream(chitose, 'hashtag', ({ type, body }) => { + if (type == 'note') { + assert.deepStrictEqual(body.text, '#foo'); + ws.close(); + done(); + } + }, { + q: [ + ['foo'], + ], + }); + + post(chitose, { + text: '#foo', + }); + })); + + it('指定したハッシュタグの投稿が流れる (AND)', () => new Promise(async done => { + let fooCount = 0; + let barCount = 0; + let fooBarCount = 0; + + const ws = await connectStream(chitose, 'hashtag', ({ type, body }) => { + if (type == 'note') { + if (body.text === '#foo') fooCount++; + if (body.text === '#bar') barCount++; + if (body.text === '#foo #bar') fooBarCount++; + } + }, { + q: [ + ['foo', 'bar'], + ], + }); + + post(chitose, { + text: '#foo', + }); + + post(chitose, { + text: '#bar', + }); + + post(chitose, { + text: '#foo #bar', + }); + + setTimeout(() => { + assert.strictEqual(fooCount, 0); + assert.strictEqual(barCount, 0); + assert.strictEqual(fooBarCount, 1); ws.close(); done(); - } - }, { - q: [ - ['foo'], - ], - }); + }, 3000); + })); - post(me, { - text: '#foo', - }); - })); + it('指定したハッシュタグの投稿が流れる (OR)', () => new Promise(async done => { + let fooCount = 0; + let barCount = 0; + let fooBarCount = 0; + let piyoCount = 0; - it('指定したハッシュタグの投稿が流れる (AND)', () => new Promise(async done => { - const me = await signup(); + const ws = await connectStream(chitose, 'hashtag', ({ type, body }) => { + if (type == 'note') { + if (body.text === '#foo') fooCount++; + if (body.text === '#bar') barCount++; + if (body.text === '#foo #bar') fooBarCount++; + if (body.text === '#piyo') piyoCount++; + } + }, { + q: [ + ['foo'], + ['bar'], + ], + }); - let fooCount = 0; - let barCount = 0; - let fooBarCount = 0; + post(chitose, { + text: '#foo', + }); - const ws = await connectStream(me, 'hashtag', ({ type, body }) => { - if (type == 'note') { - if (body.text === '#foo') fooCount++; - if (body.text === '#bar') barCount++; - if (body.text === '#foo #bar') fooBarCount++; - } - }, { - q: [ - ['foo', 'bar'], - ], - }); + post(chitose, { + text: '#bar', + }); - post(me, { - text: '#foo', - }); + post(chitose, { + text: '#foo #bar', + }); - post(me, { - text: '#bar', - }); + post(chitose, { + text: '#piyo', + }); - post(me, { - text: '#foo #bar', - }); + setTimeout(() => { + assert.strictEqual(fooCount, 1); + assert.strictEqual(barCount, 1); + assert.strictEqual(fooBarCount, 1); + assert.strictEqual(piyoCount, 0); + ws.close(); + done(); + }, 3000); + })); - setTimeout(() => { - assert.strictEqual(fooCount, 0); - assert.strictEqual(barCount, 0); - assert.strictEqual(fooBarCount, 1); - ws.close(); - done(); - }, 3000); - })); + it('指定したハッシュタグの投稿が流れる (AND + OR)', () => new Promise(async done => { + let fooCount = 0; + let barCount = 0; + let fooBarCount = 0; + let piyoCount = 0; + let waaaCount = 0; - it('指定したハッシュタグの投稿が流れる (OR)', () => new Promise(async done => { - const me = await signup(); + const ws = await connectStream(chitose, 'hashtag', ({ type, body }) => { + if (type == 'note') { + if (body.text === '#foo') fooCount++; + if (body.text === '#bar') barCount++; + if (body.text === '#foo #bar') fooBarCount++; + if (body.text === '#piyo') piyoCount++; + if (body.text === '#waaa') waaaCount++; + } + }, { + q: [ + ['foo', 'bar'], + ['piyo'], + ], + }); - let fooCount = 0; - let barCount = 0; - let fooBarCount = 0; - let piyoCount = 0; + post(chitose, { + text: '#foo', + }); - const ws = await connectStream(me, 'hashtag', ({ type, body }) => { - if (type == 'note') { - if (body.text === '#foo') fooCount++; - if (body.text === '#bar') barCount++; - if (body.text === '#foo #bar') fooBarCount++; - if (body.text === '#piyo') piyoCount++; - } - }, { - q: [ - ['foo'], - ['bar'], - ], - }); + post(chitose, { + text: '#bar', + }); - post(me, { - text: '#foo', - }); + post(chitose, { + text: '#foo #bar', + }); - post(me, { - text: '#bar', - }); + post(chitose, { + text: '#piyo', + }); - post(me, { - text: '#foo #bar', - }); + post(chitose, { + text: '#waaa', + }); - post(me, { - text: '#piyo', - }); - - setTimeout(() => { - assert.strictEqual(fooCount, 1); - assert.strictEqual(barCount, 1); - assert.strictEqual(fooBarCount, 1); - assert.strictEqual(piyoCount, 0); - ws.close(); - done(); - }, 3000); - })); - - it('指定したハッシュタグの投稿が流れる (AND + OR)', () => new Promise(async done => { - const me = await signup(); - - let fooCount = 0; - let barCount = 0; - let fooBarCount = 0; - let piyoCount = 0; - let waaaCount = 0; - - const ws = await connectStream(me, 'hashtag', ({ type, body }) => { - if (type == 'note') { - if (body.text === '#foo') fooCount++; - if (body.text === '#bar') barCount++; - if (body.text === '#foo #bar') fooBarCount++; - if (body.text === '#piyo') piyoCount++; - if (body.text === '#waaa') waaaCount++; - } - }, { - q: [ - ['foo', 'bar'], - ['piyo'], - ], - }); - - post(me, { - text: '#foo', - }); - - post(me, { - text: '#bar', - }); - - post(me, { - text: '#foo #bar', - }); - - post(me, { - text: '#piyo', - }); - - post(me, { - text: '#waaa', - }); - - setTimeout(() => { - assert.strictEqual(fooCount, 0); - assert.strictEqual(barCount, 0); - assert.strictEqual(fooBarCount, 1); - assert.strictEqual(piyoCount, 1); - assert.strictEqual(waaaCount, 0); - ws.close(); - done(); - }, 3000); - })); + setTimeout(() => { + assert.strictEqual(fooCount, 0); + assert.strictEqual(barCount, 0); + assert.strictEqual(fooBarCount, 1); + assert.strictEqual(piyoCount, 1); + assert.strictEqual(waaaCount, 0); + ws.close(); + done(); + }, 3000); + })); + }); }); }); diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index 0ee15067d..245cf858d 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -186,7 +186,7 @@ export function connectStream(user: any, channel: string, listener: (message: Re }); } -export const waitFire = async (user: any, channel: string, trgr: () => any, cond: (msg: Record) => boolean) => { +export const waitFire = async (user: any, channel: string, trgr: () => any, cond: (msg: Record) => boolean, params?: any) => { return new Promise(async (res, rej) => { let timer: NodeJS.Timeout; @@ -198,7 +198,7 @@ export const waitFire = async (user: any, channel: string, trgr: () => any, cond if (timer) clearTimeout(timer); res(true); } - }); + }, params); } catch (e) { rej(e); } @@ -208,7 +208,7 @@ export const waitFire = async (user: any, channel: string, trgr: () => any, cond timer = setTimeout(() => { ws.close(); res(false); - }, 5000); + }, 3000); try { await trgr(); diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock index 25c4ee9c2..c01c9b87f 100644 --- a/packages/backend/yarn.lock +++ b/packages/backend/yarn.lock @@ -21,20 +21,20 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@bull-board/api@3.11.1": - version "3.11.1" - resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-3.11.1.tgz#98b2c9556f643718bb5bde4a1306e6706af8192e" - integrity sha512-ElwX7sM+Ng4ZL9KUsbDubRE+r2hu/gss85OsROeE9bmyfkW14jOJkgr5MKUyjTTgPEeMs1Mw55TgQs2vxoWBiA== +"@bull-board/api@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-4.0.0.tgz#63931cbee56ff3b1525f8771d9b8a6df12838962" + integrity sha512-4STXOhQv07/8d/Ei6LA38D3aaYtMuOHJMejkkF2CTAW3gAzEtwhDHmrKlk7tG01Gq2jnPNIcYxbd4WIbtP/+fQ== dependencies: redis-info "^3.0.8" -"@bull-board/koa@3.11.1": - version "3.11.1" - resolved "https://registry.yarnpkg.com/@bull-board/koa/-/koa-3.11.1.tgz#1872aba2c65d116d1183b3003e4a2cb2c1e2fbbf" - integrity sha512-F/thrTuC1JWpdBO7DPdKD/wr8c+d7MJGu0sr5ARsT1WXhng7sU7OqBEP/5Y7HhByurjDFXDxcgk/mc78Tmeb/Q== +"@bull-board/koa@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@bull-board/koa/-/koa-4.0.0.tgz#e9d39f166abdc942c0d9e045bbc23941e9e47db1" + integrity sha512-8UN8h0NKkpND2w47YmvacG3TZPp0GHjw2By/fuX/MqoLG2Wtu58GCzhmKij8DHW5nfAr5c/0azWwyKJZ6jR5wA== dependencies: - "@bull-board/api" "3.11.1" - "@bull-board/ui" "3.11.1" + "@bull-board/api" "4.0.0" + "@bull-board/ui" "4.0.0" ejs "^3.1.7" koa "^2.13.1" koa-mount "^4.0.0" @@ -42,12 +42,12 @@ koa-static "^5.0.0" koa-views "^7.0.1" -"@bull-board/ui@3.11.1": - version "3.11.1" - resolved "https://registry.yarnpkg.com/@bull-board/ui/-/ui-3.11.1.tgz#17a2af5573f31811a543105b9a96249c95e93ce7" - integrity sha512-SRrfvxHF/WaBICiAFuWAoAlTvoBYUBmX94oRbSKzVILRFZMe3gs0hN071BFohrn4yOTFHAkWPN7cjMbaqHwCag== +"@bull-board/ui@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@bull-board/ui/-/ui-4.0.0.tgz#6702d2fa286ba54d3f18a0af2e2344c3fe21d836" + integrity sha512-sesp3n3e/Zkw7oFxrihB/AGsPWRzLywTXlcc3N6ttGLE1U5ow5yRSg6F/1LFe9OpHsYko0VsYJMcTAeZk7AJ+w== dependencies: - "@bull-board/api" "3.11.1" + "@bull-board/api" "4.0.0" "@cspotcode/source-map-support@^0.8.0": version "0.8.1" @@ -106,10 +106,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@gar/promisify@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210" - integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw== +"@gar/promisify@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== "@humanwhocodes/config-array@^0.9.2": version "0.9.2" @@ -217,18 +217,18 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" -"@npmcli/fs@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.0.tgz#bec1d1b89c170d40e1b73ad6c943b0b75e7d2951" - integrity sha512-VhP1qZLXcrXRIaPoqb4YA55JQxLNF3jNR4T55IdOJa3+IFJKNYHtPvtXx8slmeMavj37vCzCfrqQM1vWLsYKLA== +"@npmcli/fs@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.0.tgz#f2a21c28386e299d1a9fae8051d35ad180e33109" + integrity sha512-DmfBvNXGaetMxj9LTp8NAN9vEidXURrf5ZTslQzEAi/6GbW+4yjaLFQc6Tue5cpZ9Frlk4OBo/Snf1Bh/S7qTQ== dependencies: - "@gar/promisify" "^1.0.1" + "@gar/promisify" "^1.1.3" semver "^7.3.5" -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== +"@npmcli/move-file@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.0.tgz#417f585016081a0184cef3e38902cd917a9bbd02" + integrity sha512-UR6D5f4KEGWJV6BGPH3Qb2EtgH+t+1XQ1Tt85c7qicN6cezzuHPdZwwAxqZr4JLtnQu0LZsTza/5gmNmSl8XLg== dependencies: mkdirp "^1.0.4" rimraf "^3.0.2" @@ -327,11 +327,6 @@ resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== - "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" @@ -679,10 +674,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50" integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA== -"@types/node@17.0.41": - version "17.0.41" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.41.tgz#1607b2fd3da014ae5d4d1b31bc792a39348dfb9b" - integrity sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw== +"@types/node@18.0.0": + version "18.0.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.0.tgz#67c7b724e1bcdd7a8821ce0d5ee184d3b4dd525a" + integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA== "@types/node@^14.11.8": version "14.17.9" @@ -708,11 +703,6 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== -"@types/parse5@6.0.3": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb" - integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g== - "@types/pug@2.0.6": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.6.tgz#f830323c88172e66826d0bde413498b61054b5a6" @@ -785,10 +775,10 @@ dependencies: htmlparser2 "^6.0.0" -"@types/semver@7.3.9": - version "7.3.9" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc" - integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ== +"@types/semver@7.3.10": + version "7.3.10" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.10.tgz#5f19ee40cbeff87d916eedc8c2bfe2305d957f73" + integrity sha512-zsv3fsC7S84NN6nPK06u79oWgrPVd0NvOyqgghV1haPaFcVxIrP4DLomRwGAXk0ui4HZA7mOcSFL98sMVW9viw== "@types/serve-static@*": version "1.13.3" @@ -798,10 +788,10 @@ "@types/express-serve-static-core" "*" "@types/mime" "*" -"@types/sharp@0.30.2": - version "0.30.2" - resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.30.2.tgz#df5ff34140b3bad165482e6f3d26b08e42a0503a" - integrity sha512-uLCBwjDg/BTcQit0dpNGvkIjvH3wsb8zpaJePCjvONBBSfaKHoxXBIuq1MT8DMQEfk2fKYnpC9QExCgFhkGkMQ== +"@types/sharp@0.30.4": + version "0.30.4" + resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.30.4.tgz#7430b5fcf37f35dd860112c4cf6dcd6a1ba0011b" + integrity sha512-6oJEzKt7wZeS7e+6x9QFEOWGs0T/6of00+0onZGN1zSmcSjcTDZKgIGZ6YWJnHowpaKUCFBPH52mYljWqU32Eg== dependencies: "@types/node" "*" @@ -858,14 +848,14 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz#fdf59c905354139046b41b3ed95d1609913d0758" - integrity sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw== +"@typescript-eslint/eslint-plugin@^5.30.0": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz#9c6017b6c1d04894141b4a87816388967f64c359" + integrity sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg== dependencies: - "@typescript-eslint/scope-manager" "5.27.1" - "@typescript-eslint/type-utils" "5.27.1" - "@typescript-eslint/utils" "5.27.1" + "@typescript-eslint/scope-manager" "5.30.6" + "@typescript-eslint/type-utils" "5.30.6" + "@typescript-eslint/utils" "5.30.6" debug "^4.3.4" functional-red-black-tree "^1.0.1" ignore "^5.2.0" @@ -873,69 +863,69 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.27.1.tgz#3a4dcaa67e45e0427b6ca7bb7165122c8b569639" - integrity sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ== +"@typescript-eslint/parser@^5.30.0": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.6.tgz#add440db038fa9d777e4ebdaf66da9e7fb7abe92" + integrity sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA== dependencies: - "@typescript-eslint/scope-manager" "5.27.1" - "@typescript-eslint/types" "5.27.1" - "@typescript-eslint/typescript-estree" "5.27.1" + "@typescript-eslint/scope-manager" "5.30.6" + "@typescript-eslint/types" "5.30.6" + "@typescript-eslint/typescript-estree" "5.30.6" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz#4d1504392d01fe5f76f4a5825991ec78b7b7894d" - integrity sha512-fQEOSa/QroWE6fAEg+bJxtRZJTH8NTskggybogHt4H9Da8zd4cJji76gA5SBlR0MgtwF7rebxTbDKB49YUCpAg== +"@typescript-eslint/scope-manager@5.30.6": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz#ce1b49ff5ce47f55518d63dbe8fc9181ddbd1a33" + integrity sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g== dependencies: - "@typescript-eslint/types" "5.27.1" - "@typescript-eslint/visitor-keys" "5.27.1" + "@typescript-eslint/types" "5.30.6" + "@typescript-eslint/visitor-keys" "5.30.6" -"@typescript-eslint/type-utils@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.27.1.tgz#369f695199f74c1876e395ebea202582eb1d4166" - integrity sha512-+UC1vVUWaDHRnC2cQrCJ4QtVjpjjCgjNFpg8b03nERmkHv9JV9X5M19D7UFMd+/G7T/sgFwX2pGmWK38rqyvXw== +"@typescript-eslint/type-utils@5.30.6": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz#a64aa9acbe609ab77f09f53434a6af2b9685f3af" + integrity sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA== dependencies: - "@typescript-eslint/utils" "5.27.1" + "@typescript-eslint/utils" "5.30.6" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.27.1.tgz#34e3e629501349d38be6ae97841298c03a6ffbf1" - integrity sha512-LgogNVkBhCTZU/m8XgEYIWICD6m4dmEDbKXESCbqOXfKZxRKeqpiJXQIErv66sdopRKZPo5l32ymNqibYEH/xg== +"@typescript-eslint/types@5.30.6": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.6.tgz#86369d0a7af8c67024115ac1da3e8fb2d38907e1" + integrity sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg== -"@typescript-eslint/typescript-estree@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.1.tgz#7621ee78607331821c16fffc21fc7a452d7bc808" - integrity sha512-DnZvvq3TAJ5ke+hk0LklvxwYsnXpRdqUY5gaVS0D4raKtbznPz71UJGnPTHEFo0GDxqLOLdMkkmVZjSpET1hFw== +"@typescript-eslint/typescript-estree@5.30.6": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz#a84a0d6a486f9b54042da1de3d671a2c9f14484e" + integrity sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A== dependencies: - "@typescript-eslint/types" "5.27.1" - "@typescript-eslint/visitor-keys" "5.27.1" + "@typescript-eslint/types" "5.30.6" + "@typescript-eslint/visitor-keys" "5.30.6" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.27.1.tgz#b4678b68a94bc3b85bf08f243812a6868ac5128f" - integrity sha512-mZ9WEn1ZLDaVrhRaYgzbkXBkTPghPFsup8zDbbsYTxC5OmqrFE7skkKS/sraVsLP3TcT3Ki5CSyEFBRkLH/H/w== +"@typescript-eslint/utils@5.30.6": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.6.tgz#1de2da14f678e7d187daa6f2e4cdb558ed0609dc" + integrity sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.27.1" - "@typescript-eslint/types" "5.27.1" - "@typescript-eslint/typescript-estree" "5.27.1" + "@typescript-eslint/scope-manager" "5.30.6" + "@typescript-eslint/types" "5.30.6" + "@typescript-eslint/typescript-estree" "5.30.6" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.27.1": - version "5.27.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.1.tgz#05a62666f2a89769dac2e6baa48f74e8472983af" - integrity sha512-xYs6ffo01nhdJgPieyk7HAOpjhTsx7r/oB9LWEhwAXgwn33tkr+W8DI2ChboqhZlC4q3TC6geDYPoiX8ROqyOQ== +"@typescript-eslint/visitor-keys@5.30.6": + version "5.30.6" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz#94dd10bb481c8083378d24de1742a14b38a2678c" + integrity sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA== dependencies: - "@typescript-eslint/types" "5.27.1" + "@typescript-eslint/types" "5.30.6" eslint-visitor-keys "^3.3.0" "@ungap/promise-all-settled@1.1.2": @@ -943,10 +933,10 @@ resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== -abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== +abab@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== abbrev@1: version "1.1.1" @@ -1001,11 +991,6 @@ acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c" integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA== -acorn@^8.5.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - acorn@^8.7.1: version "8.7.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" @@ -1018,10 +1003,10 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" -agentkeepalive@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b" - integrity sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ== +agentkeepalive@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" + integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== dependencies: debug "^4.1.0" depd "^1.1.2" @@ -1274,10 +1259,10 @@ autwh@0.1.0: dependencies: oauth "0.9.15" -aws-sdk@2.1152.0: - version "2.1152.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1152.0.tgz#73e4fb81b3a9c289234b5d6848bcdb854f169bdf" - integrity sha512-Lqwk0bDhm3vzpYb3AAM9VgGHeDpbB8+o7UJnP9R+CO23kJfi/XRpKihAcbyKDD/AUQ+O1LJaUVpvaJYLS9Am7w== +aws-sdk@2.1165.0: + version "2.1165.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1165.0.tgz#4da669d1e9020344cef75d961882f52a7931a379" + integrity sha512-2oVkSuXsLeErt+H4M2OGIz4p1LPS+QRfY2WnW4QKMndASOcvHKZTfzuY8jmc9ZnDGyguiGdT3idYU8KpNg0sGw== dependencies: buffer "4.9.2" events "1.1.1" @@ -1486,10 +1471,10 @@ bufferutil@^4.0.1: dependencies: node-gyp-build "~3.7.0" -bull@4.8.3: - version "4.8.3" - resolved "https://registry.yarnpkg.com/bull/-/bull-4.8.3.tgz#4ab67029fee1183dcb7185895b20dc08c02d6bf2" - integrity sha512-oOHr+KTLu3JM5V9TXsg18/1xyVQceoYCFiGrXZOpu9abZn3W3vXJtMBrwB6Yvl/RxSKVVBpoa25RF/ya3750qg== +bull@4.8.4: + version "4.8.4" + resolved "https://registry.yarnpkg.com/bull/-/bull-4.8.4.tgz#c538610492050d5160dbd9180704145f135a0aa9" + integrity sha512-vDNhM/pvfFY3+msulMbqPBdBO7ntKxRZRtMfi3EguVW/Ozo4uez+B81I8ZoDxYCLgSOBfwRuPnFtcv7QNzm4Ew== dependencies: cron-parser "^4.2.1" debuglog "^1.0.0" @@ -1514,28 +1499,28 @@ bytes@3.1.0, bytes@^3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@^15.2.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" - integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== +cacache@^16.1.0: + version "16.1.1" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.1.tgz#4e79fb91d3efffe0630d5ad32db55cc1b870669c" + integrity sha512-VDKN+LHyCQXaaYZ7rA/qtkURU+/yYhviUdvqEv2LT6QPZU8jpyzEkEVAcKlKLt5dJ5BRp11ym8lo3NKLluEPLg== dependencies: - "@npmcli/fs" "^1.0.0" - "@npmcli/move-file" "^1.0.1" + "@npmcli/fs" "^2.1.0" + "@npmcli/move-file" "^2.0.0" chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" + fs-minipass "^2.1.0" + glob "^8.0.1" infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" + lru-cache "^7.7.1" + minipass "^3.1.6" minipass-collect "^1.0.2" minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" + minipass-pipeline "^1.2.4" + mkdirp "^1.0.4" p-map "^4.0.0" promise-inflight "^1.0.1" rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" + ssri "^9.0.0" + tar "^6.1.11" unique-filename "^1.1.1" cache-content-type@^1.0.0: @@ -2075,14 +2060,14 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== -data-urls@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.1.tgz#597fc2ae30f8bc4dbcf731fcd1b1954353afc6f8" - integrity sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw== +data-urls@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== dependencies: - abab "^2.0.3" + abab "^2.0.6" whatwg-mimetype "^3.0.0" - whatwg-url "^10.0.0" + whatwg-url "^11.0.0" date-fns@2.28.0, date-fns@^2.28.0: version "2.28.0" @@ -2468,7 +2453,7 @@ encodeurl@^1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -encoding@^0.1.12: +encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== @@ -2500,6 +2485,16 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== +entities@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +entities@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.0.tgz#62915f08d67353bb4eb67e3d62641a4059aec656" + integrity sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg== + env-paths@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" @@ -2624,7 +2619,7 @@ eslint-module-utils@^2.7.3: debug "^3.2.7" find-up "^2.1.0" -eslint-plugin-import@2.26.0: +eslint-plugin-import@^2.26.0: version "2.26.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== @@ -2676,10 +2671,10 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@8.17.0: - version "8.17.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.17.0.tgz#1cfc4b6b6912f77d24b874ca1506b0fe09328c21" - integrity sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw== +eslint@^8.20.0: + version "8.20.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.20.0.tgz#048ac56aa18529967da8354a478be4ec0a2bc81b" + integrity sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA== dependencies: "@eslint/eslintrc" "^1.3.0" "@humanwhocodes/config-array" "^0.9.2" @@ -3023,7 +3018,7 @@ fs-extra@^8.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^2.0.0: +fs-minipass@^2.0.0, fs-minipass@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== @@ -3190,6 +3185,17 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^8.0.1: + version "8.0.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" + integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + globals@^13.15.0: version "13.15.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" @@ -3404,15 +3410,6 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -3453,6 +3450,14 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + human-signals@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5" @@ -3562,10 +3567,10 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== -install-artifact-from-github@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.0.tgz#cab6ff821976b8a35b0c079da19a727c90381a40" - integrity sha512-iT8v1GwOAX0pPXifF/5ihnMhHOCo3OeK7z3TQa4CtSNCIg8k0UxqBEk9jRwz8OP68hHXvJ2gxRa89KYHtBkqGA== +install-artifact-from-github@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.1.tgz#eefaad9af35d632e5d912ad1569c1de38c3c2462" + integrity sha512-3l3Bymg2eKDsN5wQuMfgGEj2x6l5MCAv0zPL6rxHESufFVlEAKW/6oY9F1aGgvY/EgWm5+eWGRjINveL4X7Hgg== internal-slot@^1.0.3: version "1.0.3" @@ -3934,28 +3939,28 @@ jschardet@3.0.0: resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882" integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ== -jsdom@19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-19.0.0.tgz#93e67c149fe26816d38a849ea30ac93677e16b6a" - integrity sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A== +jsdom@20.0.0: + version "20.0.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.0.tgz#882825ac9cc5e5bbee704ba16143e1fa78361ebf" + integrity sha512-x4a6CKCgx00uCmP+QakBDFXwjAJ69IkkIWHmtmjd3wvXPcdOS44hfX2vqkOQrVrq8l9DhNNADZRXaCEWvgXtVA== dependencies: - abab "^2.0.5" - acorn "^8.5.0" + abab "^2.0.6" + acorn "^8.7.1" acorn-globals "^6.0.0" cssom "^0.5.0" cssstyle "^2.3.0" - data-urls "^3.0.1" + data-urls "^3.0.2" decimal.js "^10.3.1" domexception "^4.0.0" escodegen "^2.0.0" form-data "^4.0.0" html-encoding-sniffer "^3.0.0" http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" is-potential-custom-element-name "^1.0.1" nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" + parse5 "^7.0.0" + saxes "^6.0.0" symbol-tree "^3.2.4" tough-cookie "^4.0.0" w3c-hr-time "^1.0.2" @@ -3963,8 +3968,8 @@ jsdom@19.0.0: webidl-conversions "^7.0.0" whatwg-encoding "^2.0.0" whatwg-mimetype "^3.0.0" - whatwg-url "^10.0.0" - ws "^8.2.3" + whatwg-url "^11.0.0" + ws "^8.8.0" xml-name-validator "^4.0.0" json-buffer@3.0.1: @@ -4457,6 +4462,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@^7.7.1: + version "7.12.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.12.0.tgz#be2649a992c8a9116efda5c487538dcf715f3476" + integrity sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw== + luxon@^1.28.0: version "1.28.0" resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" @@ -4472,27 +4482,27 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -make-fetch-happen@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" - integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== +make-fetch-happen@^10.0.3: + version "10.1.8" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.1.8.tgz#3b6e93dd8d8fdb76c0d7bf32e617f37c3108435a" + integrity sha512-0ASJbG12Au6+N5I84W+8FhGS6iM8MyzvZady+zaQAu+6IOaESFzCLLD0AR1sAFF3Jufi8bxm586ABN6hWd3k7g== dependencies: - agentkeepalive "^4.1.3" - cacache "^15.2.0" + agentkeepalive "^4.2.1" + cacache "^16.1.0" http-cache-semantics "^4.1.0" - http-proxy-agent "^4.0.1" + http-proxy-agent "^5.0.0" https-proxy-agent "^5.0.0" is-lambda "^1.0.1" - lru-cache "^6.0.0" - minipass "^3.1.3" + lru-cache "^7.7.1" + minipass "^3.1.6" minipass-collect "^1.0.2" - minipass-fetch "^1.3.2" + minipass-fetch "^2.0.3" minipass-flush "^1.0.5" minipass-pipeline "^1.2.4" - negotiator "^0.6.2" + negotiator "^0.6.3" promise-retry "^2.0.1" - socks-proxy-agent "^6.0.0" - ssri "^8.0.0" + socks-proxy-agent "^7.0.0" + ssri "^9.0.0" media-typer@0.3.0: version "0.3.0" @@ -4607,16 +4617,16 @@ minipass-collect@^1.0.2: dependencies: minipass "^3.0.0" -minipass-fetch@^1.3.2: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.3.3.tgz#34c7cea038c817a8658461bf35174551dce17a0a" - integrity sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ== +minipass-fetch@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.0.tgz#ca1754a5f857a3be99a9271277246ac0b44c3ff8" + integrity sha512-H9U4UVBGXEyyWJnqYDCLp1PwD8XIkJ4akNHp1aGVI+2Ym7wQMlxDKi4IB4JbmyU+pl9pEs/cVrK6cOuvmbK4Sg== dependencies: - minipass "^3.1.0" + minipass "^3.1.6" minipass-sized "^1.0.3" - minizlib "^2.0.0" + minizlib "^2.1.2" optionalDependencies: - encoding "^0.1.12" + encoding "^0.1.13" minipass-flush@^1.0.5: version "1.0.5" @@ -4625,7 +4635,7 @@ minipass-flush@^1.0.5: dependencies: minipass "^3.0.0" -minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: +minipass-pipeline@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== @@ -4639,14 +4649,21 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: +minipass@^3.0.0, minipass@^3.1.1: version "3.1.6" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== dependencies: yallist "^4.0.0" -minizlib@^2.0.0, minizlib@^2.1.1: +minipass@^3.1.6: + version "3.3.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" + integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -4733,11 +4750,6 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -ms@3.0.0-canary.1: - version "3.0.0-canary.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" - integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== - msgpackr-extract@^1.0.14: version "1.0.16" resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-1.0.16.tgz#701c4f6e6f25c100ae84557092274e8fffeefe45" @@ -4781,11 +4793,16 @@ mz@^2.4.0, mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.14.2, nan@^2.15.0: +nan@^2.14.2: version "2.15.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== +nan@^2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" + integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== + nanoid@3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" @@ -4815,11 +4832,16 @@ needle@^2.5.2: iconv-lite "^0.4.4" sax "^1.2.4" -negotiator@0.6.2, negotiator@^0.6.2: +negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + nested-property@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/nested-property/-/nested-property-4.0.0.tgz#a67b5a31991e701e03cdbaa6453bc5b1011bb88d" @@ -4887,15 +4909,15 @@ node-gyp-build@~3.7.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.7.0.tgz#daa77a4f547b9aed3e2aac779eaf151afd60ec8d" integrity sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w== -node-gyp@^8.4.1: - version "8.4.1" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" - integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== +node-gyp@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.0.0.tgz#e1da2067427f3eb5bb56820cb62bc6b1e4bd2089" + integrity sha512-Ma6p4s+XCTPxCuAMrOA/IJRmVy16R8Sdhtwl4PrCr7IBlj4cPawF0vg/l7nOT1jPbuNS7lIRJpBSvVsXwEZuzw== dependencies: env-paths "^2.2.0" glob "^7.1.4" graceful-fs "^4.2.6" - make-fetch-happen "^9.1.0" + make-fetch-happen "^10.0.3" nopt "^5.0.0" npmlog "^6.0.0" rimraf "^3.0.2" @@ -4903,10 +4925,10 @@ node-gyp@^8.4.1: tar "^6.1.2" which "^2.0.2" -nodemailer@6.7.5: - version "6.7.5" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.5.tgz#b30b1566f5fa2249f7bd49ced4c58bec6b25915e" - integrity sha512-6VtMpwhsrixq1HDYSBBHvW0GwiWawE75dS3oal48VqRhUvKJNnKnJo2RI/bCVQubj1vgrgscMNW4DHaD6xtMCg== +nodemailer@6.7.6: + version "6.7.6" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.6.tgz#d3de8f644eaa0dad784d1be1375c596de492f3fc" + integrity sha512-/6KF/umU7r7X21Y648/yiRLrgkfz0dmpyuo4BfgYWIpnT/jCbkPTvegMfxCsDAu+O810p2L1BGXieMTPp3nJVA== nofilter@^2.0.3: version "2.0.3" @@ -5221,16 +5243,23 @@ parse5-htmlparser2-tree-adapter@^6.0.0: dependencies: parse5 "^6.0.1" -parse5@6.0.1, parse5@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parse5@7.0.0, parse5@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.0.0.tgz#51f74a5257f5fcc536389e8c2d0b3802e1bfa91a" + integrity sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g== + dependencies: + entities "^4.3.0" parse5@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== +parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + parseurl@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -5638,10 +5667,10 @@ punycode@2.1.1, punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -pureimage@0.3.8: - version "0.3.8" - resolved "https://registry.yarnpkg.com/pureimage/-/pureimage-0.3.8.tgz#b9c2a127f3182ab94fb4520e83f4fbcbdd9b38f1" - integrity sha512-+CuR0HM0VmBfKKQTM56myBonDZAhZkS6ymJ8W5oYYDXG7y7X34B/dEH3UesbJI497Vc2OkA+g8T1/Xj/FTyQ8A== +pureimage@0.3.14: + version "0.3.14" + resolved "https://registry.yarnpkg.com/pureimage/-/pureimage-0.3.14.tgz#e5fde69c7999d5114667926bda620ba462f72823" + integrity sha512-MoXNFWnJaaxMCqfB97Gyw73rI4MEY075VW/WJ+Z+F/ZgQP7HH8kdcIf8Meif15sdCXhTFlMTSHQxSIrSWkQILw== dependencies: jpeg-js "^0.4.1" opentype.js "^0.4.3" @@ -5733,14 +5762,14 @@ rdf-canonize@^3.0.0: dependencies: setimmediate "^1.0.5" -re2@1.17.4: - version "1.17.4" - resolved "https://registry.yarnpkg.com/re2/-/re2-1.17.4.tgz#7bf29290bdde963014e77bd2c2e799a6d788386e" - integrity sha512-xyZ4h5PqE8I9tAxTh3G0UttcK5ufrcUxReFjGzfX61vtanNbS1XZHjnwRSyPcLgChI4KLxVgOT/ioZXnUAdoTA== +re2@1.17.7: + version "1.17.7" + resolved "https://registry.yarnpkg.com/re2/-/re2-1.17.7.tgz#e14cab85a177a5534c7215c322d1b043c55aa1e9" + integrity sha512-X8GSuiBoVWwcjuppqSjsIkRxNUKDdjhkO9SBekQbZ2ksqWUReCy7DQPWOVpoTnpdtdz5PIpTTxTFzvJv5UMfjA== dependencies: - install-artifact-from-github "^1.3.0" - nan "^2.15.0" - node-gyp "^8.4.1" + install-artifact-from-github "^1.3.1" + nan "^2.16.0" + node-gyp "^9.0.0" readable-stream@1.1.x: version "1.1.14" @@ -5956,6 +5985,14 @@ rndstr@1.0.0: rangestr "0.0.1" seedrandom "2.4.2" +rss-parser@3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/rss-parser/-/rss-parser-3.12.0.tgz#b8888699ea46304a74363fbd8144671b2997984c" + integrity sha512-aqD3E8iavcCdkhVxNDIdg1nkBI17jgqF+9OqPS1orwNaOgySdpvq6B+DoONLhzjzwV8mWg37sb60e4bmLK117A== + dependencies: + entities "^2.0.3" + xml2js "^0.4.19" + run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" @@ -6008,10 +6045,10 @@ sax@>=0.6.0, sax@^1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== dependencies: xmlchars "^2.2.0" @@ -6176,27 +6213,27 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -smart-buffer@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" - integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== -socks-proxy-agent@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" - integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== +socks-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6" + integrity sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww== dependencies: agent-base "^6.0.2" - debug "^4.3.1" - socks "^2.6.1" + debug "^4.3.3" + socks "^2.6.2" -socks@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e" - integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA== +socks@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" + integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== dependencies: ip "^1.1.5" - smart-buffer "^4.1.0" + smart-buffer "^4.2.0" source-map-js@^0.6.2: version "0.6.2" @@ -6242,10 +6279,10 @@ sshpk@^1.14.1: safer-buffer "^2.0.2" tweetnacl "~0.14.0" -ssri@^8.0.0, ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== +ssri@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057" + integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q== dependencies: minipass "^3.1.1" @@ -6469,10 +6506,10 @@ syslog-pro@1.0.0: dependencies: moment "^2.22.2" -systeminformation@5.11.16: - version "5.11.16" - resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.16.tgz#5f6fda2447fafe204bd2ab543475f1ffa8c14a85" - integrity sha512-/a1VfP9WELKLT330yhAHJ4lWCXRYynel1kMMHKc/qdzCgDt3BIcMlo+3tKcTiRHFefjV3fz4AvqMx7dGO/72zw== +systeminformation@5.11.22: + version "5.11.22" + resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.22.tgz#52eb78fd6bb48eef372f502b494ff59aacf82c02" + integrity sha512-sBZJ/WBCf2vDLeMZaEyVuo+aXylOSmNHHB2cX0jHULFxSBLXHX+QUHYrCvmz+YiflKY3bsahVWX7vwuz1p1QZA== tapable@^2.2.0: version "2.2.0" @@ -6521,7 +6558,7 @@ tar-stream@^2.1.4, tar-stream@^2.2.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^6.0.2, tar@^6.1.2: +tar@^6.1.11, tar@^6.1.2: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -6630,10 +6667,10 @@ trace-redirect@1.0.6: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= -ts-loader@9.3.0: - version "9.3.0" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.3.0.tgz#980f4dbfb60e517179e15e10ed98e454b132159f" - integrity sha512-2kLLAdAD+FCKijvGKi9sS0OzoqxLCF3CxHpok7rVgCZ5UldRzH0TkbwG9XECKjBzHsAewntC5oDaI/FwKzEUog== +ts-loader@9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.3.1.tgz#fe25cca56e3e71c1087fe48dc67f4df8c59b22d4" + integrity sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw== dependencies: chalk "^4.1.0" enhanced-resolve "^5.0.0" @@ -6659,10 +6696,10 @@ ts-node@10.8.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsc-alias@1.6.9: - version "1.6.9" - resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.6.9.tgz#d04d95124b95ad8eea55e52d45cf65a744c26baa" - integrity sha512-5lv5uAHn0cgxY1XfpXIdquUSz2xXq3ryQyNtxC6DYH7YT5rt/W+9Gsft2uyLFTh+ozk4qU8iCSP3VemjT69xlQ== +tsc-alias@1.6.11: + version "1.6.11" + resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.6.11.tgz#d6d83f030ad11f48e4ead8ec5729929e5e60519b" + integrity sha512-mXEM21WriTJMQyo07B4Kc2nNFFk/1qOjU+jZ0ymXOyLz/A8J+dIBkimqZrh3s/x1qLGoJ1cNZQxa8GGoWOGX1Q== dependencies: chokidar "^3.5.3" commander "^9.0.0" @@ -6783,10 +6820,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typeorm@0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.6.tgz#65203443a1b684bb746785913fe2b0877aa991c0" - integrity sha512-DRqgfqcelMiGgWSMbBmVoJNFN2nPNA3EeY2gC324ndr2DZoGRTb9ILtp2oGVGnlA+cu5zgQ6it5oqKFNkte7Aw== +typeorm@0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.7.tgz#5776ed5058f0acb75d64723b39ff458d21de64c1" + integrity sha512-MsPJeP6Zuwfe64c++l80+VRqpGEGxf0CkztIEnehQ+CMmQPSHjOnFbFxwBuZ2jiLqZTjLk2ZqQdVF0RmvxNF3Q== dependencies: "@sqltools/formatter" "^1.2.2" app-root-path "^3.0.0" @@ -6806,15 +6843,10 @@ typeorm@0.3.6: xml2js "^0.4.23" yargs "^17.3.1" -typescript@4.7.3: - version "4.7.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" - integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== - -ulid@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/ulid/-/ulid-2.3.0.tgz#93063522771a9774121a84d126ecd3eb9804071f" - integrity sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw== +typescript@^4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== unbox-primitive@^1.0.1: version "1.0.1" @@ -7012,10 +7044,10 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== -whatwg-url@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-10.0.0.tgz#37264f720b575b4a311bd4094ed8c760caaa05da" - integrity sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w== +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== dependencies: tr46 "^3.0.0" webidl-conversions "^7.0.0" @@ -7115,16 +7147,11 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@8.8.0: +ws@8.8.0, ws@^8.8.0: version "8.8.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769" integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ== -ws@^8.2.3: - version "8.4.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" - integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== - xev@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/xev/-/xev-3.0.2.tgz#3f4080bd8bed0d3479c674050e3696da98d22a4d" @@ -7150,7 +7177,7 @@ xml2js@0.4.19: sax ">=0.6.0" xmlbuilder "~9.0.1" -xml2js@^0.4.23: +xml2js@^0.4.19, xml2js@^0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== diff --git a/packages/client/package.json b/packages/client/package.json index f1ab23a55..cbc9d8d34 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -3,7 +3,7 @@ "scripts": { "watch": "vite build --watch --mode development", "build": "vite build", - "lint": "eslint --quiet \"src/**/*.{ts,vue}\"" + "lint": "eslint --quiet src --ext .ts,.vue" }, "resolutions": { "chokidar": "^3.3.1", @@ -15,7 +15,7 @@ "@rollup/plugin-alias": "3.1.9", "@rollup/plugin-json": "4.1.0", "@syuilo/aiscript": "0.11.1", - "@vitejs/plugin-vue": "2.3.3", + "@vitejs/plugin-vue": "^3.0.0", "@vue/compiler-sfc": "3.2.37", "abort-controller": "3.0.0", "autobind-decorator": "2.4.0", @@ -35,7 +35,7 @@ "escape-regexp": "0.0.1", "eventemitter3": "4.0.7", "feed": "4.2.2", - "idb-keyval": "6.1.0", + "idb-keyval": "6.2.0", "insert-text-at-cursor": "0.3.0", "json5": "2.2.1", "katex": "0.15.6", @@ -45,36 +45,34 @@ "mocha": "10.0.0", "ms": "2.1.3", "nested-property": "4.0.0", - "photoswipe": "5.2.7", + "photoswipe": "5.2.8", "prismjs": "1.28.0", "private-ip": "2.3.3", "promise-limit": "2.7.0", "pug": "3.0.2", "punycode": "2.1.1", "qrcode": "1.5.0", - "querystring": "0.2.1", - "random-seed": "0.3.0", "reflect-metadata": "0.1.13", "rndstr": "1.0.0", - "rollup": "2.75.6", + "rollup": "2.75.7", "s-age": "1.1.2", - "sass": "1.52.3", + "sass": "1.53.0", "seedrandom": "3.0.5", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", - "three": "0.141.0", + "three": "0.142.0", "throttle-debounce": "5.0.0", "tinycolor2": "1.4.2", - "tsc-alias": "1.6.9", + "tsc-alias": "1.6.11", "tsconfig-paths": "4.0.0", "twemoji-parser": "14.0.0", - "typescript": "4.7.3", + "typescript": "4.7.4", "uuid": "8.3.2", "v-debounce": "0.1.2", "vanilla-tilt": "1.7.2", - "vite": "2.9.10", + "vite": "3.0.0", "vue": "3.2.37", "vue-prism-editor": "2.0.0-alpha.2", "vuedraggable": "4.0.1", @@ -93,20 +91,19 @@ "@types/oauth": "0.9.1", "@types/punycode": "2.1.0", "@types/qrcode": "1.4.2", - "@types/random-seed": "0.3.3", "@types/seedrandom": "3.0.2", "@types/throttle-debounce": "5.0.0", "@types/tinycolor2": "1.4.3", "@types/uuid": "8.3.4", "@types/websocket": "1.0.5", "@types/ws": "8.5.3", - "@typescript-eslint/eslint-plugin": "5.27.1", - "@typescript-eslint/parser": "5.27.1", + "@typescript-eslint/eslint-plugin": "^5.30.0", + "@typescript-eslint/parser": "^5.30.0", "cross-env": "7.0.3", - "cypress": "10.0.3", - "eslint": "8.17.0", - "eslint-plugin-import": "2.26.0", - "eslint-plugin-vue": "9.1.0", + "cypress": "10.3.0", + "eslint": "^8.20.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-vue": "^9.1.1", "start-server-and-test": "1.14.0" } } diff --git a/packages/client/src/components/abuse-report-window.vue b/packages/client/src/components/abuse-report-window.vue index 511434962..82960fa97 100644 --- a/packages/client/src/components/abuse-report-window.vue +++ b/packages/client/src/components/abuse-report-window.vue @@ -1,5 +1,5 @@ diff --git a/packages/client/src/components/ui/modal-window.vue b/packages/client/src/components/ui/modal-window.vue index bf9be971f..b7faea736 100644 --- a/packages/client/src/components/ui/modal-window.vue +++ b/packages/client/src/components/ui/modal-window.vue @@ -105,7 +105,6 @@ defineExpose({ background: var(--windowHeader); -webkit-backdrop-filter: var(--blur, blur(15px)); backdrop-filter: var(--blur, blur(15px)); - box-shadow: 0px 1px var(--divider); > button { height: $height; diff --git a/packages/client/src/components/ui/modal.vue b/packages/client/src/components/ui/modal.vue index d6a29ec4b..1abd41a51 100644 --- a/packages/client/src/components/ui/modal.vue +++ b/packages/client/src/components/ui/modal.vue @@ -10,7 +10,7 @@ + + diff --git a/packages/client/src/directives/get-size.ts b/packages/client/src/directives/get-size.ts index 2c4e9c188..76b54ea4b 100644 --- a/packages/client/src/directives/get-size.ts +++ b/packages/client/src/directives/get-size.ts @@ -34,7 +34,6 @@ function calc(src: Element) { export default { mounted(src, binding, vn) { - const resize = new ResizeObserver((entries, observer) => { calc(src); }); diff --git a/packages/client/src/init.ts b/packages/client/src/init.ts index 98f69c701..d3db31853 100644 --- a/packages/client/src/init.ts +++ b/packages/client/src/init.ts @@ -24,7 +24,7 @@ import { version, ui, lang, host } from '@/config'; import { applyTheme } from '@/scripts/theme'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode'; import { i18n } from '@/i18n'; -import { confirm, alert, post, popup, toast } from '@/os'; +import { confirm, alert, post, popup } from '@/os'; import { stream } from '@/stream'; import * as sound from '@/scripts/sound'; import { $i, refreshAccount, login, updateAccount, signout } from '@/account'; @@ -39,401 +39,391 @@ import { reactionPicker } from '@/scripts/reaction-picker'; import { getUrlWithoutLoginId } from '@/scripts/login-id'; import { getAccountFromId } from '@/scripts/get-account-from-id'; -console.info(`Misskey v${version}`); +(async () => { + console.info(`Misskey v${version}`); -if (_DEV_) { - console.warn('Development mode!!!'); + if (_DEV_) { + console.warn('Development mode!!!'); - console.info(`vue ${vueVersion}`); + console.info(`vue ${vueVersion}`); - (window as any).$i = $i; - (window as any).$store = defaultStore; + (window as any).$i = $i; + (window as any).$store = defaultStore; - window.addEventListener('error', event => { - console.error(event); - /* - alert({ - type: 'error', - title: 'DEV: Unhandled error', - text: event.message + window.addEventListener('error', event => { + console.error(event); + /* + alert({ + type: 'error', + title: 'DEV: Unhandled error', + text: event.message + }); + */ }); - */ + + window.addEventListener('unhandledrejection', event => { + console.error(event); + /* + alert({ + type: 'error', + title: 'DEV: Unhandled promise rejection', + text: event.reason + }); + */ + }); + } + + // タッチデバイスでCSSの:hoverを機能させる + document.addEventListener('touchend', () => {}, { passive: true }); + + // 一斉リロード + reloadChannel.addEventListener('message', path => { + if (path !== null) location.href = path; + else location.reload(); }); - window.addEventListener('unhandledrejection', event => { - console.error(event); - /* - alert({ - type: 'error', - title: 'DEV: Unhandled promise rejection', - text: event.reason - }); - */ - }); -} - -// タッチデバイスでCSSの:hoverを機能させる -document.addEventListener('touchend', () => {}, { passive: true }); - -// 一斉リロード -reloadChannel.addEventListener('message', path => { - if (path !== null) location.href = path; - else location.reload(); -}); - -//#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ -// TODO: いつの日にか消したい -const vh = window.innerHeight * 0.01; -document.documentElement.style.setProperty('--vh', `${vh}px`); -window.addEventListener('resize', () => { + //#region SEE: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ + // TODO: いつの日にか消したい const vh = window.innerHeight * 0.01; document.documentElement.style.setProperty('--vh', `${vh}px`); -}); -//#endregion + window.addEventListener('resize', () => { + const vh = window.innerHeight * 0.01; + document.documentElement.style.setProperty('--vh', `${vh}px`); + }); + //#endregion -// If mobile, insert the viewport meta tag -if (['smartphone', 'tablet'].includes(deviceKind)) { - const viewport = document.getElementsByName('viewport').item(0); - viewport.setAttribute('content', - `${viewport.getAttribute('content')}, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover`); -} - -//#region Set lang attr -const html = document.documentElement; -html.setAttribute('lang', lang); -//#endregion - -//#region loginId -const params = new URLSearchParams(location.search); -const loginId = params.get('loginId'); - -if (loginId) { - const target = getUrlWithoutLoginId(location.href); - - if (!$i || $i.id !== loginId) { - const account = await getAccountFromId(loginId); - if (account) { - await login(account.token, target); - } + // If mobile, insert the viewport meta tag + if (['smartphone', 'tablet'].includes(deviceKind)) { + const viewport = document.getElementsByName('viewport').item(0); + viewport.setAttribute('content', + `${viewport.getAttribute('content')}, minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover`); } - history.replaceState({ misskey: 'loginId' }, '', target); -} + //#region Set lang attr + const html = document.documentElement; + html.setAttribute('lang', lang); + //#endregion -//#endregion + //#region loginId + const params = new URLSearchParams(location.search); + const loginId = params.get('loginId'); -//#region Fetch user -if ($i && $i.token) { - if (_DEV_) { - console.log('account cache found. refreshing...'); - } + if (loginId) { + const target = getUrlWithoutLoginId(location.href); - refreshAccount(); -} else { - if (_DEV_) { - console.log('no account cache found.'); - } - - // 連携ログインの場合用にCookieを参照する - const i = (document.cookie.match(/igi=(\w+)/) || [null, null])[1]; - - if (i != null && i !== 'null') { - if (_DEV_) { - console.log('signing...'); - } - - try { - document.body.innerHTML = '
Please wait...
'; - await login(i); - } catch (err) { - // Render the error screen - // TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな) - document.body.innerHTML = '
Oops!
'; - } - } else { - if (_DEV_) { - console.log('not signed in'); - } - } -} -//#endregion - -const fetchInstanceMetaPromise = fetchInstance(); - -fetchInstanceMetaPromise.then(() => { - localStorage.setItem('v', instance.version); - - // Init service worker - initializeSw(); -}); - -const app = createApp( - window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) : - !$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) : - ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) : - ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) : - defineAsyncComponent(() => import('@/ui/universal.vue')), -); - -if (_DEV_) { - app.config.performance = true; -} - -app.config.globalProperties = { - $i, - $store: defaultStore, - $instance: instance, - $t: i18n.t, - $ts: i18n.ts, -}; - -widgets(app); -directives(app); -components(app); - -const splash = document.getElementById('splash'); -// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す)) -if (splash) splash.addEventListener('transitionend', () => { - splash.remove(); -}); - -// https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210 -// なぜかinit.tsの内容が2回実行されることがあるため、mountするdivを1つに制限する -const rootEl = (() => { - const MISSKEY_MOUNT_DIV_ID = 'misskey_app'; - - const currentEl = document.getElementById(MISSKEY_MOUNT_DIV_ID); - - if (currentEl) { - console.warn('multiple import detected'); - return currentEl; - } - - const rootEl = document.createElement('div'); - rootEl.id = MISSKEY_MOUNT_DIV_ID; - document.body.appendChild(rootEl); - return rootEl; -})(); - -app.mount(rootEl); - -// boot.jsのやつを解除 -window.onerror = null; -window.onunhandledrejection = null; - -reactionPicker.init(); - -if (splash) { - splash.style.opacity = '0'; - splash.style.pointerEvents = 'none'; -} - -// クライアントが更新されたか? -const lastVersion = localStorage.getItem('lastVersion'); -if (lastVersion !== version) { - localStorage.setItem('lastVersion', version); - - // テーマリビルドするため - localStorage.removeItem('theme'); - - try { // 変なバージョン文字列来るとcompareVersionsでエラーになるため - if (lastVersion != null && compareVersions(version, lastVersion) === 1) { - // ログインしてる場合だけ - if ($i) { - popup(defineAsyncComponent(() => import('@/components/updated.vue')), {}, {}, 'closed'); + if (!$i || $i.id !== loginId) { + const account = await getAccountFromId(loginId); + if (account) { + await login(account.token, target); } } - } catch (err) { + + history.replaceState({ misskey: 'loginId' }, '', target); } -} -// NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため) -watch(defaultStore.reactiveState.darkMode, (darkMode) => { - applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme')); -}, { immediate: localStorage.theme == null }); + //#endregion -const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme')); -const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme')); + //#region Fetch user + if ($i && $i.token) { + if (_DEV_) { + console.log('account cache found. refreshing...'); + } -watch(darkTheme, (theme) => { - if (defaultStore.state.darkMode) { - applyTheme(theme); - } -}); - -watch(lightTheme, (theme) => { - if (!defaultStore.state.darkMode) { - applyTheme(theme); - } -}); - -//#region Sync dark mode -if (ColdDeviceStorage.get('syncDeviceDarkMode')) { - defaultStore.set('darkMode', isDeviceDarkmode()); -} - -window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => { - if (ColdDeviceStorage.get('syncDeviceDarkMode')) { - defaultStore.set('darkMode', mql.matches); - } -}); -//#endregion - -fetchInstanceMetaPromise.then(() => { - if (defaultStore.state.themeInitial) { - if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme)); - if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme)); - defaultStore.set('themeInitial', false); - } -}); - -watch(defaultStore.reactiveState.useBlurEffectForModal, v => { - document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none'); -}, { immediate: true }); - -watch(defaultStore.reactiveState.useBlurEffect, v => { - if (v) { - document.documentElement.style.removeProperty('--blur'); + refreshAccount(); } else { - document.documentElement.style.setProperty('--blur', 'none'); - } -}, { immediate: true }); + if (_DEV_) { + console.log('no account cache found.'); + } -let reloadDialogShowing = false; -stream.on('_disconnected_', async () => { - if (defaultStore.state.serverDisconnectedBehavior === 'reload') { - location.reload(); - } else if (defaultStore.state.serverDisconnectedBehavior === 'dialog') { - if (reloadDialogShowing) return; - reloadDialogShowing = true; - const { canceled } = await confirm({ - type: 'warning', - title: i18n.ts.disconnectedFromServer, - text: i18n.ts.reloadConfirm, - }); - reloadDialogShowing = false; - if (!canceled) { + // 連携ログインの場合用にCookieを参照する + const i = (document.cookie.match(/igi=(\w+)/) || [null, null])[1]; + + if (i != null && i !== 'null') { + if (_DEV_) { + console.log('signing...'); + } + + try { + document.body.innerHTML = '
Please wait...
'; + await login(i); + } catch (err) { + // Render the error screen + // TODO: ちゃんとしたコンポーネントをレンダリングする(v10とかのトラブルシューティングゲーム付きのやつみたいな) + document.body.innerHTML = '
Oops!
'; + } + } else { + if (_DEV_) { + console.log('not signed in'); + } + } + } + //#endregion + + const fetchInstanceMetaPromise = fetchInstance(); + + fetchInstanceMetaPromise.then(() => { + localStorage.setItem('v', instance.version); + + // Init service worker + initializeSw(); + }); + + const app = createApp( + window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) : + !$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) : + ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) : + ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) : + defineAsyncComponent(() => import('@/ui/universal.vue')), + ); + + if (_DEV_) { + app.config.performance = true; + } + + app.config.globalProperties = { + $i, + $store: defaultStore, + $instance: instance, + $t: i18n.t, + $ts: i18n.ts, + }; + + widgets(app); + directives(app); + components(app); + + const splash = document.getElementById('splash'); + // 念のためnullチェック(HTMLが古い場合があるため(そのうち消す)) + if (splash) splash.addEventListener('transitionend', () => { + splash.remove(); + }); + + // https://github.com/misskey-dev/misskey/pull/8575#issuecomment-1114239210 + // なぜかinit.tsの内容が2回実行されることがあるため、mountするdivを1つに制限する + const rootEl = (() => { + const MISSKEY_MOUNT_DIV_ID = 'misskey_app'; + + const currentEl = document.getElementById(MISSKEY_MOUNT_DIV_ID); + + if (currentEl) { + console.warn('multiple import detected'); + return currentEl; + } + + const rootEl = document.createElement('div'); + rootEl.id = MISSKEY_MOUNT_DIV_ID; + document.body.appendChild(rootEl); + return rootEl; + })(); + + app.mount(rootEl); + + // boot.jsのやつを解除 + window.onerror = null; + window.onunhandledrejection = null; + + reactionPicker.init(); + + if (splash) { + splash.style.opacity = '0'; + splash.style.pointerEvents = 'none'; + } + + // クライアントが更新されたか? + const lastVersion = localStorage.getItem('lastVersion'); + if (lastVersion !== version) { + localStorage.setItem('lastVersion', version); + + // テーマリビルドするため + localStorage.removeItem('theme'); + + try { // 変なバージョン文字列来るとcompareVersionsでエラーになるため + if (lastVersion != null && compareVersions(version, lastVersion) === 1) { + // ログインしてる場合だけ + if ($i) { + popup(defineAsyncComponent(() => import('@/components/updated.vue')), {}, {}, 'closed'); + } + } + } catch (err) { + } + } + + // NOTE: この処理は必ず↑のクライアント更新時処理より後に来ること(テーマ再構築のため) + watch(defaultStore.reactiveState.darkMode, (darkMode) => { + applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme')); + }, { immediate: localStorage.theme == null }); + + const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme')); + const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme')); + + watch(darkTheme, (theme) => { + if (defaultStore.state.darkMode) { + applyTheme(theme); + } + }); + + watch(lightTheme, (theme) => { + if (!defaultStore.state.darkMode) { + applyTheme(theme); + } + }); + + //#region Sync dark mode + if (ColdDeviceStorage.get('syncDeviceDarkMode')) { + defaultStore.set('darkMode', isDeviceDarkmode()); + } + + window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => { + if (ColdDeviceStorage.get('syncDeviceDarkMode')) { + defaultStore.set('darkMode', mql.matches); + } + }); + //#endregion + + fetchInstanceMetaPromise.then(() => { + if (defaultStore.state.themeInitial) { + if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme)); + if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme)); + defaultStore.set('themeInitial', false); + } + }); + + watch(defaultStore.reactiveState.useBlurEffectForModal, v => { + document.documentElement.style.setProperty('--modalBgFilter', v ? 'blur(4px)' : 'none'); + }, { immediate: true }); + + watch(defaultStore.reactiveState.useBlurEffect, v => { + if (v) { + document.documentElement.style.removeProperty('--blur'); + } else { + document.documentElement.style.setProperty('--blur', 'none'); + } + }, { immediate: true }); + + let reloadDialogShowing = false; + stream.on('_disconnected_', async () => { + if (defaultStore.state.serverDisconnectedBehavior === 'reload') { location.reload(); + } else if (defaultStore.state.serverDisconnectedBehavior === 'dialog') { + if (reloadDialogShowing) return; + reloadDialogShowing = true; + const { canceled } = await confirm({ + type: 'warning', + title: i18n.ts.disconnectedFromServer, + text: i18n.ts.reloadConfirm, + }); + reloadDialogShowing = false; + if (!canceled) { + location.reload(); + } } - } -}); - -stream.on('emojiAdded', emojiData => { - // TODO - //store.commit('instance/set', ); -}); - -for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) { - import('./plugin').then(({ install }) => { - install(plugin); }); -} -const hotkeys = { - 'd': (): void => { - defaultStore.set('darkMode', !defaultStore.state.darkMode); - }, - 's': search, -}; + stream.on('emojiAdded', emojiData => { + // TODO + //store.commit('instance/set', ); + }); -if ($i) { - // only add post shortcuts if logged in - hotkeys['p|n'] = post; - - if ($i.isDeleted) { - alert({ - type: 'warning', - text: i18n.ts.accountDeletionInProgress, + for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) { + import('./plugin').then(({ install }) => { + install(plugin); }); } - const lastUsed = localStorage.getItem('lastUsed'); - if (lastUsed) { - const lastUsedDate = parseInt(lastUsed, 10); - // 二時間以上前なら - if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) { - toast(i18n.t('welcomeBackWithName', { - name: $i.name || $i.username, - })); - } - } - localStorage.setItem('lastUsed', Date.now().toString()); + const hotkeys = { + 'd': (): void => { + defaultStore.set('darkMode', !defaultStore.state.darkMode); + }, + 's': search, + }; - if ('Notification' in window) { - // 許可を得ていなかったらリクエスト - if (Notification.permission === 'default') { - Notification.requestPermission(); + if ($i) { + // only add post shortcuts if logged in + hotkeys['p|n'] = post; + + if ($i.isDeleted) { + alert({ + type: 'warning', + text: i18n.ts.accountDeletionInProgress, + }); } + + if ('Notification' in window) { + // 許可を得ていなかったらリクエスト + if (Notification.permission === 'default') { + Notification.requestPermission(); + } + } + + const main = markRaw(stream.useChannel('main', null, 'System')); + + // 自分の情報が更新されたとき + main.on('meUpdated', i => { + updateAccount(i); + }); + + main.on('readAllNotifications', () => { + updateAccount({ hasUnreadNotification: false }); + }); + + main.on('unreadNotification', () => { + updateAccount({ hasUnreadNotification: true }); + }); + + main.on('unreadMention', () => { + updateAccount({ hasUnreadMentions: true }); + }); + + main.on('readAllUnreadMentions', () => { + updateAccount({ hasUnreadMentions: false }); + }); + + main.on('unreadSpecifiedNote', () => { + updateAccount({ hasUnreadSpecifiedNotes: true }); + }); + + main.on('readAllUnreadSpecifiedNotes', () => { + updateAccount({ hasUnreadSpecifiedNotes: false }); + }); + + main.on('readAllMessagingMessages', () => { + updateAccount({ hasUnreadMessagingMessage: false }); + }); + + main.on('unreadMessagingMessage', () => { + updateAccount({ hasUnreadMessagingMessage: true }); + sound.play('chatBg'); + }); + + main.on('readAllAntennas', () => { + updateAccount({ hasUnreadAntenna: false }); + }); + + main.on('unreadAntenna', () => { + updateAccount({ hasUnreadAntenna: true }); + sound.play('antenna'); + }); + + main.on('readAllAnnouncements', () => { + updateAccount({ hasUnreadAnnouncement: false }); + }); + + main.on('readAllChannels', () => { + updateAccount({ hasUnreadChannel: false }); + }); + + main.on('unreadChannel', () => { + updateAccount({ hasUnreadChannel: true }); + sound.play('channel'); + }); + + // トークンが再生成されたとき + // このままではMisskeyが利用できないので強制的にサインアウトさせる + main.on('myTokenRegenerated', () => { + signout(); + }); } - const main = markRaw(stream.useChannel('main', null, 'System')); - - // 自分の情報が更新されたとき - main.on('meUpdated', i => { - updateAccount(i); - }); - - main.on('readAllNotifications', () => { - updateAccount({ hasUnreadNotification: false }); - }); - - main.on('unreadNotification', () => { - updateAccount({ hasUnreadNotification: true }); - }); - - main.on('unreadMention', () => { - updateAccount({ hasUnreadMentions: true }); - }); - - main.on('readAllUnreadMentions', () => { - updateAccount({ hasUnreadMentions: false }); - }); - - main.on('unreadSpecifiedNote', () => { - updateAccount({ hasUnreadSpecifiedNotes: true }); - }); - - main.on('readAllUnreadSpecifiedNotes', () => { - updateAccount({ hasUnreadSpecifiedNotes: false }); - }); - - main.on('readAllMessagingMessages', () => { - updateAccount({ hasUnreadMessagingMessage: false }); - }); - - main.on('unreadMessagingMessage', () => { - updateAccount({ hasUnreadMessagingMessage: true }); - sound.play('chatBg'); - }); - - main.on('readAllAntennas', () => { - updateAccount({ hasUnreadAntenna: false }); - }); - - main.on('unreadAntenna', () => { - updateAccount({ hasUnreadAntenna: true }); - sound.play('antenna'); - }); - - main.on('readAllAnnouncements', () => { - updateAccount({ hasUnreadAnnouncement: false }); - }); - - main.on('readAllChannels', () => { - updateAccount({ hasUnreadChannel: false }); - }); - - main.on('unreadChannel', () => { - updateAccount({ hasUnreadChannel: true }); - sound.play('channel'); - }); - - // トークンが再生成されたとき - // このままではMisskeyが利用できないので強制的にサインアウトさせる - main.on('myTokenRegenerated', () => { - signout(); - }); -} - -// shortcut -document.addEventListener('keydown', makeHotkey(hotkeys)); + // shortcut + document.addEventListener('keydown', makeHotkey(hotkeys)); +})(); diff --git a/packages/client/src/menu.ts b/packages/client/src/menu.ts index 5e281f4ea..fa5d26b3a 100644 --- a/packages/client/src/menu.ts +++ b/packages/client/src/menu.ts @@ -35,11 +35,6 @@ export const menuDef = reactive({ indicated: computed(() => $i != null && $i.hasPendingReceivedFollowRequest), to: '/my/follow-requests', }, - featured: { - title: 'featured', - icon: 'fas fa-fire-alt', - to: '/featured', - }, explore: { title: 'explore', icon: 'fas fa-hashtag', @@ -196,4 +191,11 @@ export const menuDef = reactive({ }], ev.currentTarget ?? ev.target); }, }, + reload: { + title: 'reload', + icon: 'fas fa-refresh', + action: (ev) => { + location.reload(); + }, + }, }); diff --git a/packages/client/src/nirax.ts b/packages/client/src/nirax.ts index 19c4464ea..4efa0345a 100644 --- a/packages/client/src/nirax.ts +++ b/packages/client/src/nirax.ts @@ -3,6 +3,7 @@ import { EventEmitter } from 'eventemitter3'; import { Ref, Component, ref, shallowRef, ShallowRef } from 'vue'; import { pleaseLogin } from '@/scripts/please-login'; +import { safeURIDecode } from '@/scripts/safe-uri-decode'; type RouteDef = { path: string; @@ -61,6 +62,7 @@ export class Router extends EventEmitter<{ props: Map | null; key: string; }) => void; + same: () => void; }> { private routes: RouteDef[]; private currentPath: string; @@ -115,7 +117,7 @@ export class Router extends EventEmitter<{ } if (p.wildcard) { if (parts.length !== 0) { - props.set(p.name, parts.join('/')); + props.set(p.name, safeURIDecode(parts.join('/'))); parts = []; } break pathMatchLoop; @@ -123,10 +125,12 @@ export class Router extends EventEmitter<{ if (p.startsWith) { if (parts[0] == null || !parts[0].startsWith(p.startsWith)) continue forEachRouteLoop; - props.set(p.name, parts[0].substring(p.startsWith.length)); + props.set(p.name, safeURIDecode(parts[0].substring(p.startsWith.length))); parts.shift(); } else { - props.set(p.name, parts[0]); + if (parts[0]) { + props.set(p.name, safeURIDecode(parts[0])); + } parts.shift(); } } @@ -136,7 +140,7 @@ export class Router extends EventEmitter<{ if (parts.length !== 0) continue forEachRouteLoop; if (route.hash != null && hash != null) { - props.set(route.hash, hash); + props.set(route.hash, safeURIDecode(hash)); } if (route.query != null && queryString != null) { @@ -146,7 +150,7 @@ export class Router extends EventEmitter<{ for (const q in route.query) { const as = route.query[q]; if (queryObject[q]) { - props.set(as, queryObject[q]); + props.set(as, safeURIDecode(queryObject[q])); } } } @@ -210,11 +214,15 @@ export class Router extends EventEmitter<{ } public push(path: string) { + const beforePath = this.currentPath; + if (path === beforePath) { + this.emit('same'); + return; + } if (this.navHook) { const cancel = this.navHook(path); if (cancel) return; } - const beforePath = this.currentPath; this.navigate(path, null); this.emit('push', { beforePath, diff --git a/packages/client/src/os.ts b/packages/client/src/os.ts index 00dae867d..64fb9b0ea 100644 --- a/packages/client/src/os.ts +++ b/packages/client/src/os.ts @@ -198,12 +198,6 @@ export function modalPageWindow(path: string) { }, {}, 'closed'); } -export function toast(message: string) { - popup(defineAsyncComponent(() => import('@/components/toast.vue')), { - message, - }, {}, 'closed'); -} - export function alert(props: { type?: 'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question'; title?: string | null; diff --git a/packages/client/src/pages/about-misskey.vue b/packages/client/src/pages/about-misskey.vue index ba85860cd..fd7b5f936 100644 --- a/packages/client/src/pages/about-misskey.vue +++ b/packages/client/src/pages/about-misskey.vue @@ -204,7 +204,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.aboutMisskey, icon: null, - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/about.vue b/packages/client/src/pages/about.vue index f76799fff..280e714fa 100644 --- a/packages/client/src/pages/about.vue +++ b/packages/client/src/pages/about.vue @@ -121,7 +121,6 @@ const headerTabs = $computed(() => [{ definePageMetadata(computed(() => ({ title: i18n.ts.instanceInfo, icon: 'fas fa-info-circle', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/admin-file.vue b/packages/client/src/pages/admin-file.vue index 402e9502d..7bfbed35f 100644 --- a/packages/client/src/pages/admin-file.vue +++ b/packages/client/src/pages/admin-file.vue @@ -117,7 +117,6 @@ const headerTabs = $computed(() => [{ definePageMetadata(computed(() => ({ title: file ? i18n.ts.file + ': ' + file.name : i18n.ts.file, icon: 'fas fa-file', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/admin/_header_.vue b/packages/client/src/pages/admin/_header_.vue index 1883b4abe..aea2663c3 100644 --- a/packages/client/src/pages/admin/_header_.vue +++ b/packages/client/src/pages/admin/_header_.vue @@ -28,7 +28,7 @@ diff --git a/packages/client/src/pages/admin/ads.vue b/packages/client/src/pages/admin/ads.vue deleted file mode 100644 index 05557469e..000000000 --- a/packages/client/src/pages/admin/ads.vue +++ /dev/null @@ -1,133 +0,0 @@ - - - - - diff --git a/packages/client/src/pages/admin/announcements.vue b/packages/client/src/pages/admin/announcements.vue index 025897d09..5107c2f30 100644 --- a/packages/client/src/pages/admin/announcements.vue +++ b/packages/client/src/pages/admin/announcements.vue @@ -102,7 +102,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.announcements, icon: 'fas fa-broadcast-tower', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/admin/bot-protection.vue b/packages/client/src/pages/admin/bot-protection.vue index d2e7919b4..d316f973b 100644 --- a/packages/client/src/pages/admin/bot-protection.vue +++ b/packages/client/src/pages/admin/bot-protection.vue @@ -61,27 +61,22 @@ let hcaptchaSecretKey: string | null = $ref(null); let recaptchaSiteKey: string | null = $ref(null); let recaptchaSecretKey: string | null = $ref(null); -const enableHcaptcha = $computed(() => provider === 'hcaptcha'); -const enableRecaptcha = $computed(() => provider === 'recaptcha'); - async function init() { const meta = await os.api('admin/meta'); - enableHcaptcha = meta.enableHcaptcha; hcaptchaSiteKey = meta.hcaptchaSiteKey; hcaptchaSecretKey = meta.hcaptchaSecretKey; - enableRecaptcha = meta.enableRecaptcha; recaptchaSiteKey = meta.recaptchaSiteKey; recaptchaSecretKey = meta.recaptchaSecretKey; - provider = enableHcaptcha ? 'hcaptcha' : enableRecaptcha ? 'recaptcha' : null; + provider = meta.enableHcaptcha ? 'hcaptcha' : meta.enableRecaptcha ? 'recaptcha' : null; } function save() { os.apiWithDialog('admin/update-meta', { - enableHcaptcha, + enableHcaptcha: provider === 'hcaptcha', hcaptchaSiteKey, hcaptchaSecretKey, - enableRecaptcha, + enableRecaptcha: provider === 'recaptcha', recaptchaSiteKey, recaptchaSecretKey, }).then(() => { diff --git a/packages/client/src/pages/admin/database.vue b/packages/client/src/pages/admin/database.vue index b9c5f9e39..ca8718ef6 100644 --- a/packages/client/src/pages/admin/database.vue +++ b/packages/client/src/pages/admin/database.vue @@ -29,6 +29,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.database, icon: 'fas fa-database', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/admin/email-settings.vue b/packages/client/src/pages/admin/email-settings.vue index c0ff94fad..46cfd3db7 100644 --- a/packages/client/src/pages/admin/email-settings.vue +++ b/packages/client/src/pages/admin/email-settings.vue @@ -122,6 +122,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.emailServer, icon: 'fas fa-envelope', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/admin/emojis.vue b/packages/client/src/pages/admin/emojis.vue index 868472ac9..5ed2b1478 100644 --- a/packages/client/src/pages/admin/emojis.vue +++ b/packages/client/src/pages/admin/emojis.vue @@ -1,7 +1,7 @@ @@ -38,7 +38,6 @@ const pagingComponent = ref>(); definePageMetadata({ title: i18n.ts.favorites, icon: 'fas fa-star', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/featured.vue b/packages/client/src/pages/featured.vue deleted file mode 100644 index 4e3f67c76..000000000 --- a/packages/client/src/pages/featured.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/packages/client/src/pages/follow-requests.vue b/packages/client/src/pages/follow-requests.vue index e6f9a9a5d..f21c68c4c 100644 --- a/packages/client/src/pages/follow-requests.vue +++ b/packages/client/src/pages/follow-requests.vue @@ -65,7 +65,6 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => ({ title: i18n.ts.followRequests, icon: 'fas fa-user-clock', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/gallery/edit.vue b/packages/client/src/pages/gallery/edit.vue index 1de8328fe..f8a5d54f7 100644 --- a/packages/client/src/pages/gallery/edit.vue +++ b/packages/client/src/pages/gallery/edit.vue @@ -116,11 +116,9 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => props.postId ? { title: i18n.ts.edit, icon: 'fas fa-pencil-alt', - bg: 'var(--bg)', } : { title: i18n.ts.postToGallery, icon: 'fas fa-pencil-alt', - bg: 'var(--bg)', })); diff --git a/packages/client/src/pages/gallery/index.vue b/packages/client/src/pages/gallery/index.vue index 1eb6ce22f..6b406af74 100644 --- a/packages/client/src/pages/gallery/index.vue +++ b/packages/client/src/pages/gallery/index.vue @@ -122,7 +122,6 @@ const headerTabs = $computed(() => [{ definePageMetadata({ title: i18n.ts.gallery, icon: 'fas fa-icons', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/gallery/post.vue b/packages/client/src/pages/gallery/post.vue index 6651c3e28..e87a541e9 100644 --- a/packages/client/src/pages/gallery/post.vue +++ b/packages/client/src/pages/gallery/post.vue @@ -74,8 +74,8 @@ const props = defineProps<{ postId: string; }>(); -const post = $ref(null); -const error = $ref(null); +let post = $ref(null); +let error = $ref(null); const otherPostsPagination = { endpoint: 'users/gallery/posts' as const, limit: 6, @@ -149,7 +149,6 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => post ? { title: post.title, avatar: post.user, - bg: 'var(--bg)', } : null)); diff --git a/packages/client/src/pages/instance-info.vue b/packages/client/src/pages/instance-info.vue index 83f3354df..b97ebb3e3 100644 --- a/packages/client/src/pages/instance-info.vue +++ b/packages/client/src/pages/instance-info.vue @@ -215,7 +215,6 @@ const headerTabs = $computed(() => [{ definePageMetadata({ title: props.host, icon: 'fas fa-server', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/messaging/index.vue b/packages/client/src/pages/messaging/index.vue index bf9ac056c..7df4c846f 100644 --- a/packages/client/src/pages/messaging/index.vue +++ b/packages/client/src/pages/messaging/index.vue @@ -159,7 +159,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.messaging, icon: 'fas fa-comments', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/my-antennas/create.vue b/packages/client/src/pages/my-antennas/create.vue index e792834a8..dc10bece8 100644 --- a/packages/client/src/pages/my-antennas/create.vue +++ b/packages/client/src/pages/my-antennas/create.vue @@ -38,7 +38,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.manageAntennas, icon: 'fas fa-satellite', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/my-antennas/editor.vue b/packages/client/src/pages/my-antennas/editor.vue index 6f3c4afbf..9470257c6 100644 --- a/packages/client/src/pages/my-antennas/editor.vue +++ b/packages/client/src/pages/my-antennas/editor.vue @@ -46,6 +46,7 @@ diff --git a/packages/client/src/pages/my-clips/index.vue b/packages/client/src/pages/my-clips/index.vue index 6434b0c00..ac5a3578f 100644 --- a/packages/client/src/pages/my-clips/index.vue +++ b/packages/client/src/pages/my-clips/index.vue @@ -69,7 +69,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.clip, icon: 'fas fa-paperclip', - bg: 'var(--bg)', action: { icon: 'fas fa-plus', handler: create, diff --git a/packages/client/src/pages/my-lists/index.vue b/packages/client/src/pages/my-lists/index.vue index 411826a95..03b638151 100644 --- a/packages/client/src/pages/my-lists/index.vue +++ b/packages/client/src/pages/my-lists/index.vue @@ -46,7 +46,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.manageLists, icon: 'fas fa-list-ul', - bg: 'var(--bg)', action: { icon: 'fas fa-plus', handler: create, diff --git a/packages/client/src/pages/my-lists/list.vue b/packages/client/src/pages/my-lists/list.vue index 6e76c4a7d..892878ae8 100644 --- a/packages/client/src/pages/my-lists/list.vue +++ b/packages/client/src/pages/my-lists/list.vue @@ -41,6 +41,7 @@ import MkButton from '@/components/ui/button.vue'; import * as os from '@/os'; import { mainRouter } from '@/router'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { i18n } from '@/i18n'; const props = defineProps<{ listId: string; @@ -120,7 +121,6 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => list ? { title: list.name, icon: 'fas fa-list-ul', - bg: 'var(--bg)', } : null)); diff --git a/packages/client/src/pages/not-found.vue b/packages/client/src/pages/not-found.vue index 955fbbccf..a819cce96 100644 --- a/packages/client/src/pages/not-found.vue +++ b/packages/client/src/pages/not-found.vue @@ -18,6 +18,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.notFound, icon: 'fas fa-exclamation-triangle', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/note.vue b/packages/client/src/pages/note.vue index 852b82157..7c936cc62 100644 --- a/packages/client/src/pages/note.vue +++ b/packages/client/src/pages/note.vue @@ -132,7 +132,6 @@ definePageMetadata(computed(() => note ? { title: i18n.t('noteOf', { user: note.user.name }), text: note.text, }, - bg: 'var(--bg)', } : null)); diff --git a/packages/client/src/pages/notifications.vue b/packages/client/src/pages/notifications.vue index 52cb298fa..1ab5d0ecf 100644 --- a/packages/client/src/pages/notifications.vue +++ b/packages/client/src/pages/notifications.vue @@ -62,7 +62,6 @@ const headerTabs = $computed(() => [{ definePageMetadata(computed(() => ({ title: i18n.ts.notifications, icon: 'fas fa-bell', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/page-editor/els/page-editor.el.radio-button.vue b/packages/client/src/pages/page-editor/els/page-editor.el.radio-button.vue index 183e60a69..4b28f120a 100644 --- a/packages/client/src/pages/page-editor/els/page-editor.el.radio-button.vue +++ b/packages/client/src/pages/page-editor/els/page-editor.el.radio-button.vue @@ -32,7 +32,7 @@ const props = withDefaults(defineProps<{ let values: string = $ref(props.value.values.join('\n')); watch(values, () => { - props.value.values = values.split('\n') + props.value.values = values.split('\n'); }, { deep: true }); diff --git a/packages/client/src/pages/page-editor/page-editor.vue b/packages/client/src/pages/page-editor/page-editor.vue index c38286c1d..95f23cb89 100644 --- a/packages/client/src/pages/page-editor/page-editor.vue +++ b/packages/client/src/pages/page-editor/page-editor.vue @@ -1,6 +1,6 @@ diff --git a/packages/client/src/pages/page.vue b/packages/client/src/pages/page.vue index c60b7069e..a93dd8fa9 100644 --- a/packages/client/src/pages/page.vue +++ b/packages/client/src/pages/page.vue @@ -47,7 +47,6 @@
{{ $ts.createdAt }}:
{{ $ts.updatedAt }}:
- diff --git a/packages/client/src/pages/pages.vue b/packages/client/src/pages/pages.vue index 16aeae2f5..62c675e41 100644 --- a/packages/client/src/pages/pages.vue +++ b/packages/client/src/pages/pages.vue @@ -77,7 +77,6 @@ const headerTabs = $computed(() => [{ definePageMetadata(computed(() => ({ title: i18n.ts.pages, icon: 'fas fa-sticky-note', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/preview.vue b/packages/client/src/pages/preview.vue index cba7589a3..8f211081d 100644 --- a/packages/client/src/pages/preview.vue +++ b/packages/client/src/pages/preview.vue @@ -17,7 +17,6 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => ({ title: i18n.ts.preview, icon: 'fas fa-eye', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/reset-password.vue b/packages/client/src/pages/reset-password.vue index 39a1191ca..10c41f2d2 100644 --- a/packages/client/src/pages/reset-password.vue +++ b/packages/client/src/pages/reset-password.vue @@ -51,7 +51,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.resetPassword, icon: 'fas fa-lock', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/search.vue b/packages/client/src/pages/search.vue index 25fef7af5..404b9e3db 100644 --- a/packages/client/src/pages/search.vue +++ b/packages/client/src/pages/search.vue @@ -34,6 +34,5 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => ({ title: i18n.t('searchWith', { q: props.query }), icon: 'fas fa-search', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/settings/2fa.vue b/packages/client/src/pages/settings/2fa.vue index fb3a7a17f..d72d3e206 100644 --- a/packages/client/src/pages/settings/2fa.vue +++ b/packages/client/src/pages/settings/2fa.vue @@ -55,7 +55,7 @@
  • {{ i18n.ts._2fa.step2 }}

    {{ $ts._2fa.step2Url }}
    {{ twoFactorData.url }}

  • {{ i18n.ts._2fa.step3 }}
    - + {{ i18n.ts.done }}
  • diff --git a/packages/client/src/pages/settings/accounts.vue b/packages/client/src/pages/settings/accounts.vue index 47b816243..d1e71c454 100644 --- a/packages/client/src/pages/settings/accounts.vue +++ b/packages/client/src/pages/settings/accounts.vue @@ -109,7 +109,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.accounts, icon: 'fas fa-users', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/api.vue b/packages/client/src/pages/settings/api.vue index d94862712..b8a2dedb5 100644 --- a/packages/client/src/pages/settings/api.vue +++ b/packages/client/src/pages/settings/api.vue @@ -42,6 +42,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: 'API', icon: 'fas fa-key', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/apps.vue b/packages/client/src/pages/settings/apps.vue index 673e91fe6..10ecbc795 100644 --- a/packages/client/src/pages/settings/apps.vue +++ b/packages/client/src/pages/settings/apps.vue @@ -67,7 +67,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.installedApps, icon: 'fas fa-plug', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/custom-css.vue b/packages/client/src/pages/settings/custom-css.vue index 3e032be25..d5000d397 100644 --- a/packages/client/src/pages/settings/custom-css.vue +++ b/packages/client/src/pages/settings/custom-css.vue @@ -42,6 +42,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.customCss, icon: 'fas fa-code', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/deck.vue b/packages/client/src/pages/settings/deck.vue index 295357377..b1cf8a8cc 100644 --- a/packages/client/src/pages/settings/deck.vue +++ b/packages/client/src/pages/settings/deck.vue @@ -73,6 +73,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.deck, icon: 'fas fa-columns', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/delete-account.vue b/packages/client/src/pages/settings/delete-account.vue index a587c3299..3c4ea716c 100644 --- a/packages/client/src/pages/settings/delete-account.vue +++ b/packages/client/src/pages/settings/delete-account.vue @@ -48,6 +48,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts._accountDelete.accountDelete, icon: 'fas fa-exclamation-triangle', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/drive.vue b/packages/client/src/pages/settings/drive.vue index 73c0384f1..cec2dc4d5 100644 --- a/packages/client/src/pages/settings/drive.vue +++ b/packages/client/src/pages/settings/drive.vue @@ -101,7 +101,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.drive, icon: 'fas fa-cloud', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/email.vue b/packages/client/src/pages/settings/email.vue index 8b67ff34d..e575af6d6 100644 --- a/packages/client/src/pages/settings/email.vue +++ b/packages/client/src/pages/settings/email.vue @@ -107,6 +107,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.email, icon: 'fas fa-envelope', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/general.vue b/packages/client/src/pages/settings/general.vue index e7339af14..74fa0bc92 100644 --- a/packages/client/src/pages/settings/general.vue +++ b/packages/client/src/pages/settings/general.vue @@ -186,6 +186,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.general, icon: 'fas fa-cogs', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/import-export.vue b/packages/client/src/pages/settings/import-export.vue index 49d8a80b3..d48dab9f8 100644 --- a/packages/client/src/pages/settings/import-export.vue +++ b/packages/client/src/pages/settings/import-export.vue @@ -155,7 +155,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.importAndExport, icon: 'fas fa-boxes', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/index.vue b/packages/client/src/pages/settings/index.vue index 011962c2e..bdd7e05aa 100644 --- a/packages/client/src/pages/settings/index.vue +++ b/packages/client/src/pages/settings/index.vue @@ -41,7 +41,6 @@ const props = withDefaults(defineProps<{ const indexInfo = { title: i18n.ts.settings, icon: 'fas fa-cog', - bg: 'var(--bg)', hideHeader: true, }; const INFO = ref(indexInfo); diff --git a/packages/client/src/pages/settings/integration.vue b/packages/client/src/pages/settings/integration.vue index 7de151040..ccb02e08a 100644 --- a/packages/client/src/pages/settings/integration.vue +++ b/packages/client/src/pages/settings/integration.vue @@ -95,6 +95,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.integration, icon: 'fas fa-share-alt', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/menu.vue b/packages/client/src/pages/settings/menu.vue index 1b4d8799c..076654c10 100644 --- a/packages/client/src/pages/settings/menu.vue +++ b/packages/client/src/pages/settings/menu.vue @@ -83,6 +83,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.menu, icon: 'fas fa-list-ul', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/mute-block.vue b/packages/client/src/pages/settings/mute-block.vue index d8cb28662..397a0c815 100644 --- a/packages/client/src/pages/settings/mute-block.vue +++ b/packages/client/src/pages/settings/mute-block.vue @@ -57,6 +57,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.muteAndBlock, icon: 'fas fa-ban', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/notifications.vue b/packages/client/src/pages/settings/notifications.vue index 494a3eebe..d2a363965 100644 --- a/packages/client/src/pages/settings/notifications.vue +++ b/packages/client/src/pages/settings/notifications.vue @@ -56,6 +56,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.notifications, icon: 'fas fa-bell', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/other.vue b/packages/client/src/pages/settings/other.vue index 283d87a06..52ef4d401 100644 --- a/packages/client/src/pages/settings/other.vue +++ b/packages/client/src/pages/settings/other.vue @@ -41,6 +41,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.other, icon: 'fas fa-ellipsis-h', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/plugin.install.vue b/packages/client/src/pages/settings/plugin.install.vue index 7ff55e9d8..a4cab4b7a 100644 --- a/packages/client/src/pages/settings/plugin.install.vue +++ b/packages/client/src/pages/settings/plugin.install.vue @@ -120,6 +120,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts._plugin.install, icon: 'fas fa-download', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/plugin.vue b/packages/client/src/pages/settings/plugin.vue index 75cf42bb8..8e773b799 100644 --- a/packages/client/src/pages/settings/plugin.vue +++ b/packages/client/src/pages/settings/plugin.vue @@ -90,7 +90,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.plugins, icon: 'fas fa-plug', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/privacy.vue b/packages/client/src/pages/settings/privacy.vue index 4d509efe2..be9e34cdf 100644 --- a/packages/client/src/pages/settings/privacy.vue +++ b/packages/client/src/pages/settings/privacy.vue @@ -96,6 +96,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.privacy, icon: 'fas fa-lock-open', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/profile.vue b/packages/client/src/pages/settings/profile.vue index b662de9e3..6b60148df 100644 --- a/packages/client/src/pages/settings/profile.vue +++ b/packages/client/src/pages/settings/profile.vue @@ -183,7 +183,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.profile, icon: 'fas fa-user', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index d0fdf835c..382e1b081 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -131,7 +131,6 @@ definePageMetadata({ icon: 'fas fa-eye', handler: preview, }, - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/security.vue b/packages/client/src/pages/settings/security.vue index 57880ef3d..eb3efa9af 100644 --- a/packages/client/src/pages/settings/security.vue +++ b/packages/client/src/pages/settings/security.vue @@ -104,7 +104,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.security, icon: 'fas fa-lock', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/sounds.vue b/packages/client/src/pages/settings/sounds.vue index bb23257d7..f29c9eb04 100644 --- a/packages/client/src/pages/settings/sounds.vue +++ b/packages/client/src/pages/settings/sounds.vue @@ -131,6 +131,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.sounds, icon: 'fas fa-music', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/theme.install.vue b/packages/client/src/pages/settings/theme.install.vue index 6a863ed9e..2994d8fb1 100644 --- a/packages/client/src/pages/settings/theme.install.vue +++ b/packages/client/src/pages/settings/theme.install.vue @@ -76,6 +76,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts._theme.install, icon: 'fas fa-download', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/theme.manage.vue b/packages/client/src/pages/settings/theme.manage.vue index 68cbf3c35..9d28b4a31 100644 --- a/packages/client/src/pages/settings/theme.manage.vue +++ b/packages/client/src/pages/settings/theme.manage.vue @@ -74,6 +74,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts._theme.manage, icon: 'fas fa-folder-open', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/theme.vue b/packages/client/src/pages/settings/theme.vue index d4c23e07b..6e7a5ff3a 100644 --- a/packages/client/src/pages/settings/theme.vue +++ b/packages/client/src/pages/settings/theme.vue @@ -152,7 +152,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.theme, icon: 'fas fa-palette', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/webhook.edit.vue b/packages/client/src/pages/settings/webhook.edit.vue index d3cf5d7b7..618250958 100644 --- a/packages/client/src/pages/settings/webhook.edit.vue +++ b/packages/client/src/pages/settings/webhook.edit.vue @@ -86,6 +86,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: 'Edit webhook', icon: 'fas fa-bolt', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/webhook.new.vue b/packages/client/src/pages/settings/webhook.new.vue index 508c0d78b..fa96c5fa4 100644 --- a/packages/client/src/pages/settings/webhook.new.vue +++ b/packages/client/src/pages/settings/webhook.new.vue @@ -78,6 +78,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: 'Create new webhook', icon: 'fas fa-bolt', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/webhook.vue b/packages/client/src/pages/settings/webhook.vue index 50739e2fd..ef9b9b56f 100644 --- a/packages/client/src/pages/settings/webhook.vue +++ b/packages/client/src/pages/settings/webhook.vue @@ -49,6 +49,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: 'Webhook', icon: 'fas fa-bolt', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/settings/word-mute.vue b/packages/client/src/pages/settings/word-mute.vue index c6af0e766..5fee7cd35 100644 --- a/packages/client/src/pages/settings/word-mute.vue +++ b/packages/client/src/pages/settings/word-mute.vue @@ -124,6 +124,5 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.wordMute, icon: 'fas fa-comment-slash', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/tag.vue b/packages/client/src/pages/tag.vue index d63864ed5..406eb1c98 100644 --- a/packages/client/src/pages/tag.vue +++ b/packages/client/src/pages/tag.vue @@ -28,6 +28,5 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => ({ title: props.tag, icon: 'fas fa-hashtag', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/theme-editor.vue b/packages/client/src/pages/theme-editor.vue index 352554353..44b5a05f2 100644 --- a/packages/client/src/pages/theme-editor.vue +++ b/packages/client/src/pages/theme-editor.vue @@ -78,6 +78,7 @@ import FormButton from '@/components/ui/button.vue'; import FormTextarea from '@/components/form/textarea.vue'; import FormFolder from '@/components/form/folder.vue'; +import { $i } from '@/account'; import { Theme, applyTheme } from '@/scripts/theme'; import lightTheme from '@/themes/_light.json5'; import darkTheme from '@/themes/_dark.json5'; @@ -118,7 +119,7 @@ const fgColors = [ { color: 'pink', forLight: '#84667d', forDark: '#e4d1e0', forPreview: '#b12390' }, ]; -const theme = $ref>({ +let theme = $ref>({ base: 'light', props: lightTheme.props, }); @@ -224,7 +225,6 @@ const headerTabs = $computed(() => []); definePageMetadata({ title: i18n.ts.themeEditor, icon: 'fas fa-palette', - bg: 'var(--bg)', }); diff --git a/packages/client/src/pages/timeline.vue b/packages/client/src/pages/timeline.vue index 004c29c56..40eb85ff4 100644 --- a/packages/client/src/pages/timeline.vue +++ b/packages/client/src/pages/timeline.vue @@ -151,7 +151,6 @@ const headerTabs = $computed(() => [{ definePageMetadata(computed(() => ({ title: i18n.ts.timeline, icon: src === 'local' ? 'fas fa-comments' : src === 'social' ? 'fas fa-share-alt' : src === 'global' ? 'fas fa-globe' : 'fas fa-home', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/user-info.vue b/packages/client/src/pages/user-info.vue index 76b772ece..f9b5cb629 100644 --- a/packages/client/src/pages/user-info.vue +++ b/packages/client/src/pages/user-info.vue @@ -301,7 +301,6 @@ const headerTabs = $computed(() => [{ definePageMetadata(computed(() => ({ title: user ? acct(user) : i18n.ts.userInfo, icon: 'fas fa-info-circle', - bg: 'var(--bg)', }))); diff --git a/packages/client/src/pages/user-list-timeline.vue b/packages/client/src/pages/user-list-timeline.vue index 07d5a166e..593db1dea 100644 --- a/packages/client/src/pages/user-list-timeline.vue +++ b/packages/client/src/pages/user-list-timeline.vue @@ -79,7 +79,6 @@ const headerTabs = $computed(() => []); definePageMetadata(computed(() => list ? { title: list.name, icon: 'fas fa-list-ul', - bg: 'var(--bg)', } : null)); diff --git a/packages/client/src/pages/user/followers.vue b/packages/client/src/pages/user/followers.vue new file mode 100644 index 000000000..b61b48329 --- /dev/null +++ b/packages/client/src/pages/user/followers.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/packages/client/src/pages/user/following.vue b/packages/client/src/pages/user/following.vue new file mode 100644 index 000000000..a23977b42 --- /dev/null +++ b/packages/client/src/pages/user/following.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/packages/client/src/pages/user/home.vue b/packages/client/src/pages/user/home.vue new file mode 100644 index 000000000..f7c25f077 --- /dev/null +++ b/packages/client/src/pages/user/home.vue @@ -0,0 +1,478 @@ + + + + + diff --git a/packages/client/src/pages/user/index.vue b/packages/client/src/pages/user/index.vue index 7b2e2cde1..55719d324 100644 --- a/packages/client/src/pages/user/index.vue +++ b/packages/client/src/pages/user/index.vue @@ -1,125 +1,16 @@ - + + diff --git a/packages/client/src/pages/welcome.entrance.b.vue b/packages/client/src/pages/welcome.entrance.b.vue deleted file mode 100644 index 053087fda..000000000 --- a/packages/client/src/pages/welcome.entrance.b.vue +++ /dev/null @@ -1,236 +0,0 @@ - - - - - diff --git a/packages/client/src/pages/welcome.entrance.c.vue b/packages/client/src/pages/welcome.entrance.c.vue deleted file mode 100644 index 6bf487e16..000000000 --- a/packages/client/src/pages/welcome.entrance.c.vue +++ /dev/null @@ -1,305 +0,0 @@ - - - - - diff --git a/packages/client/src/pages/welcome.setup.vue b/packages/client/src/pages/welcome.setup.vue index 1a2f46028..4892ab6ea 100644 --- a/packages/client/src/pages/welcome.setup.vue +++ b/packages/client/src/pages/welcome.setup.vue @@ -3,7 +3,7 @@

    Welcome to Misskey!

    {{ $ts.intro }}

    - + diff --git a/packages/client/src/plugin.ts b/packages/client/src/plugin.ts index ca7b4b73d..de1c95567 100644 --- a/packages/client/src/plugin.ts +++ b/packages/client/src/plugin.ts @@ -38,7 +38,7 @@ export function install(plugin) { function createPluginEnv(opts) { const config = new Map(); for (const [k, v] of Object.entries(opts.plugin.config || {})) { - config.set(k, jsToVal(opts.plugin.configData.hasOwnProperty(k) ? opts.plugin.configData[k] : v.default)); + config.set(k, jsToVal(typeof opts.plugin.configData[k] !== 'undefined' ? opts.plugin.configData[k] : v.default)); } return { diff --git a/packages/client/src/router.ts b/packages/client/src/router.ts index bcb6cd7e8..7ce338bd0 100644 --- a/packages/client/src/router.ts +++ b/packages/client/src/router.ts @@ -12,15 +12,21 @@ const page = (loader: AsyncComponentLoader) => defineAsyncComponent({ }); export const routes = [{ - name: 'user', - path: '/@:acct/:page?', - component: page(() => import('./pages/user/index.vue')), -}, { path: '/@:initUser/pages/:initPageName/view-source', component: page(() => import('./pages/page-editor/page-editor.vue')), }, { path: '/@:username/pages/:pageName', component: page(() => import('./pages/page.vue')), +}, { + path: '/@:acct/following', + component: page(() => import('./pages/user/following.vue')), +}, { + path: '/@:acct/followers', + component: page(() => import('./pages/user/followers.vue')), +}, { + name: 'user', + path: '/@:acct/:page?', + component: page(() => import('./pages/user/index.vue')), }, { name: 'note', path: '/notes/:noteId', @@ -55,9 +61,6 @@ export const routes = [{ }, { path: '/about-misskey', component: page(() => import('./pages/about-misskey.vue')), -}, { - path: '/featured', - component: page(() => import('./pages/featured.vue')), }, { path: '/theme-editor', component: page(() => import('./pages/theme-editor.vue')), @@ -267,6 +270,10 @@ mainRouter.addListener('push', ctx => { } }); +mainRouter.addListener('same', () => { + window.scroll({ top: 0, behavior: 'smooth' }); +}); + window.addEventListener('popstate', (event) => { mainRouter.change(location.pathname + location.search + location.hash, event.state?.key); const scrollPos = scrollPosStore.get(event.state?.key) ?? 0; diff --git a/packages/client/src/scripts/array.ts b/packages/client/src/scripts/array.ts index 29d027de1..26c6195d6 100644 --- a/packages/client/src/scripts/array.ts +++ b/packages/client/src/scripts/array.ts @@ -98,7 +98,7 @@ export function groupOn(f: (x: T) => S, xs: T[]): T[][] { export function groupByX(collections: T[], keySelector: (x: T) => string) { return collections.reduce((obj: Record, item: T) => { const key = keySelector(item); - if (!obj.hasOwnProperty(key)) { + if (typeof obj[key] === 'undefined') { obj[key] = []; } diff --git a/packages/client/src/scripts/autocomplete.ts b/packages/client/src/scripts/autocomplete.ts index 8d9bdee8f..3ef622417 100644 --- a/packages/client/src/scripts/autocomplete.ts +++ b/packages/client/src/scripts/autocomplete.ts @@ -8,7 +8,7 @@ export class Autocomplete { x: Ref; y: Ref; q: Ref; - close: Function; + close: () => void; } | null; private textarea: HTMLInputElement | HTMLTextAreaElement; private currentType: string; diff --git a/packages/client/src/scripts/emojilist.ts b/packages/client/src/scripts/emojilist.ts index 4196170d2..f9afcda12 100644 --- a/packages/client/src/scripts/emojilist.ts +++ b/packages/client/src/scripts/emojilist.ts @@ -8,4 +8,6 @@ export type UnicodeEmojiDef = { } // initial converted from https://github.com/muan/emojilib/commit/242fe68be86ed6536843b83f7e32f376468b38fb -export const emojilist = (await import('../emojilist.json')).default as UnicodeEmojiDef[]; +import _emojilist from '../emojilist.json'; + +export const emojilist = _emojilist as UnicodeEmojiDef[]; diff --git a/packages/client/src/scripts/gen-search-query.ts b/packages/client/src/scripts/gen-search-query.ts index 57a06c280..b413cbbab 100644 --- a/packages/client/src/scripts/gen-search-query.ts +++ b/packages/client/src/scripts/gen-search-query.ts @@ -21,7 +21,6 @@ export async function genSearchQuery(v: any, q: string) { } } } - } return { query: q.split(' ').filter(x => !x.startsWith('/') && !x.startsWith('@')).join(' '), diff --git a/packages/client/src/scripts/hotkey.ts b/packages/client/src/scripts/hotkey.ts index fd9c74f6c..bd8c3b6ca 100644 --- a/packages/client/src/scripts/hotkey.ts +++ b/packages/client/src/scripts/hotkey.ts @@ -1,6 +1,8 @@ import keyCode from './keycode'; -type Keymap = Record; +type Callback = (ev: KeyboardEvent) => void; + +type Keymap = Record; type Pattern = { which: string[]; @@ -11,14 +13,14 @@ type Pattern = { type Action = { patterns: Pattern[]; - callback: Function; + callback: Callback; allowRepeat: boolean; }; const parseKeymap = (keymap: Keymap) => Object.entries(keymap).map(([patterns, callback]): Action => { const result = { patterns: [], - callback: callback, + callback, allowRepeat: true } as Action; diff --git a/packages/client/src/scripts/hpml/evaluator.ts b/packages/client/src/scripts/hpml/evaluator.ts index 8106687b6..10023edff 100644 --- a/packages/client/src/scripts/hpml/evaluator.ts +++ b/packages/client/src/scripts/hpml/evaluator.ts @@ -159,7 +159,6 @@ export class Hpml { @autobind private evaluate(expr: Expr, scope: HpmlScope): any { - if (isLiteralValue(expr)) { if (expr.type === null) { return null; diff --git a/packages/client/src/scripts/hpml/index.ts b/packages/client/src/scripts/hpml/index.ts index ac81eac2d..7cf88d596 100644 --- a/packages/client/src/scripts/hpml/index.ts +++ b/packages/client/src/scripts/hpml/index.ts @@ -14,13 +14,13 @@ export type Fn = { export type Type = 'string' | 'number' | 'boolean' | 'stringArray' | null; export const literalDefs: Record = { - text: { out: 'string', category: 'value', icon: 'fas fa-quote-right', }, - multiLineText: { out: 'string', category: 'value', icon: 'fas fa-align-left', }, - textList: { out: 'stringArray', category: 'value', icon: 'fas fa-list', }, - number: { out: 'number', category: 'value', icon: 'fas fa-sort-numeric-up', }, - ref: { out: null, category: 'value', icon: 'fas fa-magic', }, - aiScriptVar: { out: null, category: 'value', icon: 'fas fa-magic', }, - fn: { out: 'function', category: 'value', icon: 'fas fa-square-root-alt', }, + text: { out: 'string', category: 'value', icon: 'fas fa-quote-right', }, + multiLineText: { out: 'string', category: 'value', icon: 'fas fa-align-left', }, + textList: { out: 'stringArray', category: 'value', icon: 'fas fa-list', }, + number: { out: 'number', category: 'value', icon: 'fas fa-sort-numeric-up', }, + ref: { out: null, category: 'value', icon: 'fas fa-magic', }, + aiScriptVar: { out: null, category: 'value', icon: 'fas fa-magic', }, + fn: { out: 'function', category: 'value', icon: 'fas fa-square-root-alt', }, }; export const blockDefs = [ diff --git a/packages/client/src/scripts/hpml/lib.ts b/packages/client/src/scripts/hpml/lib.ts index 01a44ffcd..cab467a92 100644 --- a/packages/client/src/scripts/hpml/lib.ts +++ b/packages/client/src/scripts/hpml/lib.ts @@ -125,55 +125,56 @@ export function initAiLib(hpml: Hpml) { } }); */ - }) + }), }; } export const funcDefs: Record = { - if: { in: ['boolean', 0, 0], out: 0, category: 'flow', icon: 'fas fa-share-alt', }, - for: { in: ['number', 'function'], out: null, category: 'flow', icon: 'fas fa-recycle', }, - not: { in: ['boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag', }, - or: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag', }, - and: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag', }, - add: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-plus', }, - subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-minus', }, - multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-times', }, - divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide', }, - mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide', }, - round: { in: ['number'], out: 'number', category: 'operation', icon: 'fas fa-calculator', }, - eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-equals', }, - notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-not-equal', }, - gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than', }, - lt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than', }, - gtEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than-equal', }, - ltEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than-equal', }, - strLen: { in: ['string'], out: 'number', category: 'text', icon: 'fas fa-quote-right', }, - strPick: { in: ['string', 'number'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, - strReplace: { in: ['string', 'string', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, - strReverse: { in: ['string'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, - join: { in: ['stringArray', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, - stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: 'fas fa-exchange-alt', }, - numberToString: { in: ['number'], out: 'string', category: 'convert', icon: 'fas fa-exchange-alt', }, - splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: 'fas fa-exchange-alt', }, - pick: { in: [null, 'number'], out: null, category: 'list', icon: 'fas fa-indent', }, - listLen: { in: [null], out: 'number', category: 'list', icon: 'fas fa-indent', }, - rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice', }, - dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice', }, - seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice', }, - random: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice', }, - dailyRandom: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice', }, - seedRandom: { in: [null, 'number'], out: 'boolean', category: 'random', icon: 'fas fa-dice', }, - randomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice', }, - dailyRandomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice', }, - seedRandomPick: { in: [null, 0], out: 0, category: 'random', icon: 'fas fa-dice', }, - DRPWPM: { in: ['stringArray'], out: 'string', category: 'random', icon: 'fas fa-dice', }, // dailyRandomPickWithProbabilityMapping + if: { in: ['boolean', 0, 0], out: 0, category: 'flow', icon: 'fas fa-share-alt' }, + for: { in: ['number', 'function'], out: null, category: 'flow', icon: 'fas fa-recycle' }, + not: { in: ['boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag' }, + or: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag' }, + and: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag' }, + add: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-plus' }, + subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-minus' }, + multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-times' }, + divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide' }, + mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide' }, + round: { in: ['number'], out: 'number', category: 'operation', icon: 'fas fa-calculator' }, + eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-equals' }, + notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-not-equal' }, + gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than' }, + lt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than' }, + gtEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than-equal' }, + ltEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than-equal' }, + strLen: { in: ['string'], out: 'number', category: 'text', icon: 'fas fa-quote-right' }, + strPick: { in: ['string', 'number'], out: 'string', category: 'text', icon: 'fas fa-quote-right' }, + strReplace: { in: ['string', 'string', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right' }, + strReverse: { in: ['string'], out: 'string', category: 'text', icon: 'fas fa-quote-right' }, + join: { in: ['stringArray', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right' }, + stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: 'fas fa-exchange-alt' }, + numberToString: { in: ['number'], out: 'string', category: 'convert', icon: 'fas fa-exchange-alt' }, + splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: 'fas fa-exchange-alt' }, + pick: { in: [null, 'number'], out: null, category: 'list', icon: 'fas fa-indent' }, + listLen: { in: [null], out: 'number', category: 'list', icon: 'fas fa-indent' }, + rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice' }, + dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice' }, + seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice' }, + random: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice' }, + dailyRandom: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice' }, + seedRandom: { in: [null, 'number'], out: 'boolean', category: 'random', icon: 'fas fa-dice' }, + randomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice' }, + dailyRandomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice' }, + seedRandomPick: { in: [null, 0], out: 0, category: 'random', icon: 'fas fa-dice' }, + DRPWPM: { in: ['stringArray'], out: 'string', category: 'random', icon: 'fas fa-dice' }, // dailyRandomPickWithProbabilityMapping }; export function initHpmlLib(expr: Expr, scope: HpmlScope, randomSeed: string, visitor?: any) { - const date = new Date(); const day = `${visitor ? visitor.id : ''} ${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`; + // SHOULD be fine to ignore since it's intended + function shape isn't defined + // eslint-disable-next-line @typescript-eslint/ban-types const funcs: Record = { not: (a: boolean) => !a, or: (a: boolean, b: boolean) => a || b, @@ -189,7 +190,7 @@ export function initHpmlLib(expr: Expr, scope: HpmlScope, randomSeed: string, vi const result: any[] = []; for (let i = 0; i < times; i++) { result.push(fn.exec({ - [fn.slots[0]]: i + 1 + [fn.slots[0]]: i + 1, })); } return result; diff --git a/packages/client/src/scripts/idb-proxy.ts b/packages/client/src/scripts/idb-proxy.ts index d462a0d7c..77bb84463 100644 --- a/packages/client/src/scripts/idb-proxy.ts +++ b/packages/client/src/scripts/idb-proxy.ts @@ -11,16 +11,15 @@ const fallbackName = (key: string) => `idbfallback::${key}`; let idbAvailable = typeof window !== 'undefined' ? !!window.indexedDB : true; if (idbAvailable) { - try { - await iset('idb-test', 'test'); - } catch (err) { + iset('idb-test', 'test').catch(err => { console.error('idb error', err); + console.error('indexedDB is unavailable. It will use localStorage.'); idbAvailable = false; - } + }); +} else { + console.error('indexedDB is unavailable. It will use localStorage.'); } -if (!idbAvailable) console.error('indexedDB is unavailable. It will use localStorage.'); - export async function get(key: string) { if (idbAvailable) return iget(key); return JSON.parse(localStorage.getItem(fallbackName(key))); diff --git a/packages/client/src/scripts/safe-uri-decode.ts b/packages/client/src/scripts/safe-uri-decode.ts new file mode 100644 index 000000000..301b56d7f --- /dev/null +++ b/packages/client/src/scripts/safe-uri-decode.ts @@ -0,0 +1,7 @@ +export function safeURIDecode(str: string): string { + try { + return decodeURIComponent(str); + } catch { + return str; + } +} diff --git a/packages/client/src/scripts/url.ts b/packages/client/src/scripts/url.ts index 542b00e0f..86735de9f 100644 --- a/packages/client/src/scripts/url.ts +++ b/packages/client/src/scripts/url.ts @@ -1,4 +1,4 @@ -export function query(obj: {}): string { +export function query(obj: Record): string { const params = Object.entries(obj) .filter(([, v]) => Array.isArray(v) ? v.length : v !== undefined) .reduce((a, [k, v]) => (a[k] = v, a), {} as Record); diff --git a/packages/client/src/scripts/use-interval.ts b/packages/client/src/scripts/use-interval.ts index eb6e44338..201ba417e 100644 --- a/packages/client/src/scripts/use-interval.ts +++ b/packages/client/src/scripts/use-interval.ts @@ -4,6 +4,8 @@ export function useInterval(fn: () => void, interval: number, options: { immediate: boolean; afterMounted: boolean; }): void { + if (Number.isNaN(interval)) return; + let intervalId: number | null = null; if (options.afterMounted) { diff --git a/packages/client/src/scripts/use-tooltip.ts b/packages/client/src/scripts/use-tooltip.ts index bc8f27a03..1f6e0fb6c 100644 --- a/packages/client/src/scripts/use-tooltip.ts +++ b/packages/client/src/scripts/use-tooltip.ts @@ -3,6 +3,7 @@ import { Ref, ref, watch, onUnmounted } from 'vue'; export function useTooltip( elRef: Ref, onShow: (showing: Ref) => void, + delay = 300, ): void { let isHovering = false; @@ -40,7 +41,7 @@ export function useTooltip( if (isHovering) return; if (shouldIgnoreMouseover) return; isHovering = true; - timeoutId = window.setTimeout(open, 300); + timeoutId = window.setTimeout(open, delay); }; const onMouseleave = () => { @@ -54,7 +55,7 @@ export function useTooltip( shouldIgnoreMouseover = true; if (isHovering) return; isHovering = true; - timeoutId = window.setTimeout(open, 300); + timeoutId = window.setTimeout(open, delay); }; const onTouchend = () => { diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts index 31aab5c79..6095e6f22 100644 --- a/packages/client/src/store.ts +++ b/packages/client/src/store.ts @@ -59,10 +59,6 @@ export const defaultStore = markRaw(new Storage('base', { where: 'account', default: [], }, - mutedAds: { - where: 'account', - default: [] as string[], - }, menu: { where: 'deviceAccount', @@ -72,7 +68,6 @@ export const defaultStore = markRaw(new Storage('base', { 'drive', 'followRequests', '-', - 'featured', 'explore', 'announcements', 'search', diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index 94b5dd8cb..76b395e7b 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -39,14 +39,6 @@ html { scrollbar-color: var(--scrollbarHandle) inherit; scrollbar-width: thin; - &:hover { - scrollbar-color: var(--scrollbarHandleHover) inherit; - } - - &:active { - scrollbar-color: var(--accent) inherit; - } - &::-webkit-scrollbar { width: 6px; height: 6px; @@ -379,6 +371,20 @@ hr { background: var(--acrylicPanel); -webkit-backdrop-filter: var(--blur, blur(15px)); backdrop-filter: var(--blur, blur(15px)); + + @supports not (backdrop-filter: var(--blur, blur(15px))) { + &:after { + content: ""; + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + z-index: -1; + background: var(--bg); + opacity: .75; + } + } } ._formBlock { diff --git a/packages/client/src/ui/classic.vue b/packages/client/src/ui/classic.vue index 412b6db34..70db7ed12 100644 --- a/packages/client/src/ui/classic.vue +++ b/packages/client/src/ui/classic.vue @@ -60,8 +60,8 @@ const DESKTOP_THRESHOLD = 1100; let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD); let pageMetadata = $ref>(); -const widgetsShowing = $ref(false); -const fullView = $ref(false); +let widgetsShowing = $ref(false); +let fullView = $ref(false); let globalHeaderHeight = $ref(0); const wallpaper = localStorage.getItem('wallpaper') != null; const showMenuOnTop = $computed(() => defaultStore.state.menuDisplay === 'top'); diff --git a/packages/client/src/ui/classic.widgets.vue b/packages/client/src/ui/classic.widgets.vue index 6f9d18bde..845ccab36 100644 --- a/packages/client/src/ui/classic.widgets.vue +++ b/packages/client/src/ui/classic.widgets.vue @@ -1,7 +1,6 @@