Compare commits

...

24 Commits

Author SHA1 Message Date
d55f3720f2 merge unconflict
Some checks failed
Build DevBuild / Build (push) Has been cancelled
test / test (push) Has been cancelled
2025-11-18 22:54:48 +01:00
Cobblestone
eec4771646 too late now 2025-11-13 22:40:11 -05:00
Cobblestone
f1d9f26c79 finish adding latex support to more markdown 2025-11-13 22:36:38 -05:00
Cobblestone
03449a8985 Merge branch 'main' of https://github.com/Nexulien/Nexulien 2025-11-13 19:56:11 -05:00
Zoid
2d01bbb279 Merge branch 'Vendicated:main' into main 2025-11-12 16:34:40 -05:00
Vendicated
efe6f5c697 bump to v1.13.6 2025-11-12 22:16:13 +01:00
Vendicated
b3c070bca2 ViewIcons: fix viewing icon in dm header 2025-11-12 22:08:18 +01:00
Vendicated
e90b31e717 fix chat bar buttons not showing 2025-11-12 22:05:20 +01:00
Vendicated
ed1baadac3 LastFMRichPresence: linkify track/artist/album & make api key optional 2025-11-12 16:56:27 +01:00
Vendicated
00ae603884 VoiceMessages: fix crash when uploading invalid audio files 2025-11-12 16:16:33 +01:00
Jaegerwald
fd34978e1a tone indicators: /nh not hateful 2025-11-11 09:47:09 +01:00
Jaegerwald
08146aada4 Merge branch 'Vendicated:main' into main 2025-11-05 18:38:47 +01:00
thororen
c9ebece84d FakeProfileThemes: Fix broken ProfileModal find (#3766) 2025-11-05 13:29:37 -03:00
thororen
6bbc4783cd Experiments: Fix Link Embeds (#3763) 2025-11-04 15:18:30 -03:00
Zoid
e30c335c9a Merge branch 'Vendicated:main' into main 2025-11-04 09:39:28 -05:00
Vendicated
7c708acf0b bump to v1.13.5 2025-11-02 18:35:01 +01:00
thororen
44a75e4e94 fix Decor & NoTrack (#3752)
Co-authored-by: Vendicated <vendicated@riseup.net>
2025-11-02 17:28:53 +00:00
Vendicated
3992f971d0 fix missing Toolbox 2025-11-02 18:21:54 +01:00
hich4t
b6d727607f CustomRPC: add detail/state and image URL fields (#3758)
Co-authored-by: Vendicated <vendicated@riseup.net>
2025-11-02 17:24:16 +01:00
Vendicated
cf8db5df6f Merge remote-tracking branch 'origin/main' into dev 2025-11-02 17:04:37 +01:00
Andrew
0f258731db ReplaceGoogleSearch: add option to replace engine with single option (#3737)
Co-authored-by: Vendicated <vendicated@riseup.net>
2025-10-28 17:46:07 +00:00
boop-the-dog
6e5a55a961 Merge branch 'main' of https://github.com/Nexulien/Nexulien 2025-10-18 13:53:49 -04:00
boop-the-dog
79b5c43213 Merge branch 'main' of https://github.com/Nexulien/Nexulien 2025-10-10 12:08:05 -04:00
boop-the-dog
55496b9017 a 2025-10-10 12:08:01 -04:00
20 changed files with 394 additions and 183 deletions

View File

@@ -1,7 +1,7 @@
{ {
"name": "not-nexulien", "name": "not-nexulien",
"private": "true", "private": "true",
"version": "1.13.4", "version": "1.13.6",
"description": "the best (worst) discord client mod, now with custom badges and plugins whenever i feel like it", "description": "the best (worst) discord client mod, now with custom badges and plugins whenever i feel like it",
"homepage": "https://git.defautluser0.xyz/not-nexulien/Not-Nexulien", "homepage": "https://git.defautluser0.xyz/not-nexulien/Not-Nexulien",
"bugs": { "bugs": {
@@ -42,6 +42,7 @@
"floyd-steinberg": "^1.0.6", "floyd-steinberg": "^1.0.6",
"gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3", "gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3",
"jimp": "^1.6.0", "jimp": "^1.6.0",
"katex": "^0.16.22",
"monaco-editor": "^0.52.2", "monaco-editor": "^0.52.2",
"nanoid": "^5.1.5", "nanoid": "^5.1.5",
"virtual-merge": "^1.0.1" "virtual-merge": "^1.0.1"
@@ -81,7 +82,7 @@
"typescript-transform-paths": "^3.5.5", "typescript-transform-paths": "^3.5.5",
"zip-local": "^0.3.5" "zip-local": "^0.3.5"
}, },
"packageManager": "pnpm@10.4.1", "packageManager": "pnpm@10.8.0",
"pnpm": { "pnpm": {
"patchedDependencies": { "patchedDependencies": {
"eslint@9.20.1": "patches/eslint@9.20.1.patch", "eslint@9.20.1": "patches/eslint@9.20.1.patch",

View File

@@ -3,8 +3,10 @@ import { ActivityFlags, ActivityStatusDisplayType, ActivityType } from "../../en
export interface ActivityAssets { export interface ActivityAssets {
large_image?: string; large_image?: string;
large_text?: string; large_text?: string;
large_url?: string;
small_image?: string; small_image?: string;
small_text?: string; small_text?: string;
small_url?: string;
} }
export interface ActivityButton { export interface ActivityButton {

217
pnpm-lock.yaml generated
View File

@@ -37,6 +37,9 @@ importers:
jimp: jimp:
specifier: ^1.6.0 specifier: ^1.6.0
version: 1.6.0 version: 1.6.0
katex:
specifier: ^0.16.22
version: 0.16.22
monaco-editor: monaco-editor:
specifier: ^0.52.2 specifier: ^0.52.2
version: 0.52.2 version: 0.52.2
@@ -85,7 +88,7 @@ importers:
version: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) version: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
eslint-import-resolver-alias: eslint-import-resolver-alias:
specifier: ^1.1.2 specifier: ^1.1.2
version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))) version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)))
eslint-plugin-path-alias: eslint-plugin-path-alias:
specifier: 2.1.0 specifier: 2.1.0
version: 2.1.0(patch_hash=87545cb13985b338c8fa2ea7b0a3c75c57ad7fbc81c56b38d6c9438329957727)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) version: 2.1.0(patch_hash=87545cb13985b338c8fa2ea7b0a3c75c57ad7fbc81c56b38d6c9438329957727)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
@@ -100,7 +103,7 @@ importers:
version: 12.1.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) version: 12.1.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
eslint-plugin-unused-imports: eslint-plugin-unused-imports:
specifier: ^4.1.4 specifier: ^4.1.4
version: 4.1.4(@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) version: 4.1.4(@typescript-eslint/eslint-plugin@8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
highlight.js: highlight.js:
specifier: 11.11.1 specifier: 11.11.1
version: 11.11.1 version: 11.11.1
@@ -139,7 +142,7 @@ importers:
version: 5.8.2 version: 5.8.2
typescript-eslint: typescript-eslint:
specifier: ^8.28.0 specifier: ^8.28.0
version: 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) version: 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
typescript-transform-paths: typescript-transform-paths:
specifier: ^3.5.5 specifier: ^3.5.5
version: 3.5.5(typescript@5.8.2) version: 3.5.5(typescript@5.8.2)
@@ -385,6 +388,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@eslint-community/eslint-utils@4.4.1':
resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
'@eslint-community/eslint-utils@4.5.1': '@eslint-community/eslint-utils@4.5.1':
resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -676,51 +685,76 @@ packages:
'@types/yazl@2.4.6': '@types/yazl@2.4.6':
resolution: {integrity: sha512-/ifFjQtcKaoZOjl5NNCQRR0fAKafB3Foxd7J/WvFPTMea46zekapcR30uzkwIkKAAuq5T6d0dkwz754RFH27hg==} resolution: {integrity: sha512-/ifFjQtcKaoZOjl5NNCQRR0fAKafB3Foxd7J/WvFPTMea46zekapcR30uzkwIkKAAuq5T6d0dkwz754RFH27hg==}
'@typescript-eslint/eslint-plugin@8.28.0': '@typescript-eslint/eslint-plugin@8.29.0':
resolution: {integrity: sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==} resolution: {integrity: sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/parser@8.28.0': '@typescript-eslint/parser@8.29.0':
resolution: {integrity: sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==} resolution: {integrity: sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/scope-manager@8.28.0': '@typescript-eslint/scope-manager@8.24.1':
resolution: {integrity: sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==} resolution: {integrity: sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/type-utils@8.28.0': '@typescript-eslint/scope-manager@8.29.0':
resolution: {integrity: sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==} resolution: {integrity: sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/type-utils@8.29.0':
resolution: {integrity: sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/types@8.28.0': '@typescript-eslint/types@8.24.1':
resolution: {integrity: sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==} resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.28.0': '@typescript-eslint/types@8.29.0':
resolution: {integrity: sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==} resolution: {integrity: sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.24.1':
resolution: {integrity: sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/typescript-estree@8.29.0':
resolution: {integrity: sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/utils@8.28.0': '@typescript-eslint/utils@8.24.1':
resolution: {integrity: sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==} resolution: {integrity: sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.8.0'
'@typescript-eslint/utils@8.29.0':
resolution: {integrity: sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0' typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/visitor-keys@8.28.0': '@typescript-eslint/visitor-keys@8.24.1':
resolution: {integrity: sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==} resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.29.0':
resolution: {integrity: sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@vap/core@0.0.12': '@vap/core@0.0.12':
@@ -992,6 +1026,10 @@ packages:
commander@2.20.3: commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
commander@8.3.0:
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
engines: {node: '>= 12'}
component-emitter@1.3.1: component-emitter@1.3.1:
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
@@ -1862,6 +1900,10 @@ packages:
jszip@2.7.0: jszip@2.7.0:
resolution: {integrity: sha512-JIsRKRVC3gTRo2vM4Wy9WBC3TRcfnIZU8k65Phi3izkvPH975FowRYtKGT6PxevA0XnJ/yO8b0QwV0ydVyQwfw==} resolution: {integrity: sha512-JIsRKRVC3gTRo2vM4Wy9WBC3TRcfnIZU8k65Phi3izkvPH975FowRYtKGT6PxevA0XnJ/yO8b0QwV0ydVyQwfw==}
katex@0.16.22:
resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==}
hasBin: true
keyv@4.5.4: keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -2218,7 +2260,6 @@ packages:
engines: {node: '>=0.6.0', teleport: '>=0.2.0'} engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
deprecated: |- deprecated: |-
You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.
(For a CapTP with native promises, see @endo/eventual-send and @endo/captp) (For a CapTP with native promises, see @endo/eventual-send and @endo/captp)
queue-microtask@1.2.3: queue-microtask@1.2.3:
@@ -2606,8 +2647,8 @@ packages:
typed-query-selector@2.12.0: typed-query-selector@2.12.0:
resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==}
typescript-eslint@8.28.0: typescript-eslint@8.29.0:
resolution: {integrity: sha512-jfZtxJoHm59bvoCMYCe2BM0/baMswRhMmYhy+w6VfcyHrjxZ0OJe0tGasydCpIpA+A/WIJhTyZfb3EtwNC/kHQ==} resolution: {integrity: sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
@@ -2863,6 +2904,11 @@ snapshots:
'@esbuild/win32-x64@0.25.1': '@esbuild/win32-x64@0.25.1':
optional: true optional: true
'@eslint-community/eslint-utils@4.4.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))':
dependencies:
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
eslint-visitor-keys: 3.4.3
'@eslint-community/eslint-utils@4.5.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))': '@eslint-community/eslint-utils@4.5.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))':
dependencies: dependencies:
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
@@ -3168,7 +3214,7 @@ snapshots:
'@stylistic/eslint-plugin@4.2.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': '@stylistic/eslint-plugin@4.2.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)':
dependencies: dependencies:
'@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
eslint-visitor-keys: 4.2.0 eslint-visitor-keys: 4.2.0
espree: 10.3.0 espree: 10.3.0
@@ -3248,14 +3294,14 @@ snapshots:
dependencies: dependencies:
'@types/node': 22.13.13 '@types/node': 22.13.13
'@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': '@typescript-eslint/eslint-plugin@8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/parser': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
'@typescript-eslint/scope-manager': 8.28.0 '@typescript-eslint/scope-manager': 8.29.0
'@typescript-eslint/type-utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/type-utils': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
'@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/utils': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
'@typescript-eslint/visitor-keys': 8.28.0 '@typescript-eslint/visitor-keys': 8.29.0
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
graphemer: 1.4.0 graphemer: 1.4.0
ignore: 5.3.2 ignore: 5.3.2
@@ -3265,27 +3311,32 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': '@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.28.0 '@typescript-eslint/scope-manager': 8.29.0
'@typescript-eslint/types': 8.28.0 '@typescript-eslint/types': 8.29.0
'@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2)
'@typescript-eslint/visitor-keys': 8.28.0 '@typescript-eslint/visitor-keys': 8.29.0
debug: 4.4.0 debug: 4.4.0
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
typescript: 5.8.2 typescript: 5.8.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/scope-manager@8.28.0': '@typescript-eslint/scope-manager@8.24.1':
dependencies: dependencies:
'@typescript-eslint/types': 8.28.0 '@typescript-eslint/types': 8.24.1
'@typescript-eslint/visitor-keys': 8.28.0 '@typescript-eslint/visitor-keys': 8.24.1
'@typescript-eslint/type-utils@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': '@typescript-eslint/scope-manager@8.29.0':
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) '@typescript-eslint/types': 8.29.0
'@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/visitor-keys': 8.29.0
'@typescript-eslint/type-utils@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)':
dependencies:
'@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2)
'@typescript-eslint/utils': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
debug: 4.4.0 debug: 4.4.0
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
ts-api-utils: 2.1.0(typescript@5.8.2) ts-api-utils: 2.1.0(typescript@5.8.2)
@@ -3293,12 +3344,14 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/types@8.28.0': {} '@typescript-eslint/types@8.24.1': {}
'@typescript-eslint/typescript-estree@8.28.0(typescript@5.8.2)': '@typescript-eslint/types@8.29.0': {}
'@typescript-eslint/typescript-estree@8.24.1(typescript@5.8.2)':
dependencies: dependencies:
'@typescript-eslint/types': 8.28.0 '@typescript-eslint/types': 8.24.1
'@typescript-eslint/visitor-keys': 8.28.0 '@typescript-eslint/visitor-keys': 8.24.1
debug: 4.4.0 debug: 4.4.0
fast-glob: 3.3.3 fast-glob: 3.3.3
is-glob: 4.0.3 is-glob: 4.0.3
@@ -3309,20 +3362,50 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)': '@typescript-eslint/typescript-estree@8.29.0(typescript@5.8.2)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.5.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) '@typescript-eslint/types': 8.29.0
'@typescript-eslint/scope-manager': 8.28.0 '@typescript-eslint/visitor-keys': 8.29.0
'@typescript-eslint/types': 8.28.0 debug: 4.4.0
'@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) fast-glob: 3.3.3
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.7.1
ts-api-utils: 2.1.0(typescript@5.8.2)
typescript: 5.8.2
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.24.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)':
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
'@typescript-eslint/scope-manager': 8.24.1
'@typescript-eslint/types': 8.24.1
'@typescript-eslint/typescript-estree': 8.24.1(typescript@5.8.2)
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
typescript: 5.8.2 typescript: 5.8.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/visitor-keys@8.28.0': '@typescript-eslint/utils@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)':
dependencies: dependencies:
'@typescript-eslint/types': 8.28.0 '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
'@typescript-eslint/scope-manager': 8.29.0
'@typescript-eslint/types': 8.29.0
'@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.2)
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
typescript: 5.8.2
transitivePeerDependencies:
- supports-color
'@typescript-eslint/visitor-keys@8.24.1':
dependencies:
'@typescript-eslint/types': 8.24.1
eslint-visitor-keys: 4.2.0
'@typescript-eslint/visitor-keys@8.29.0':
dependencies:
'@typescript-eslint/types': 8.29.0
eslint-visitor-keys: 4.2.0 eslint-visitor-keys: 4.2.0
'@vap/core@0.0.12': '@vap/core@0.0.12':
@@ -3625,6 +3708,8 @@ snapshots:
commander@2.20.3: {} commander@2.20.3: {}
commander@8.3.0: {}
component-emitter@1.3.1: {} component-emitter@1.3.1: {}
concat-map@0.0.1: {} concat-map@0.0.1: {}
@@ -3899,9 +3984,9 @@ snapshots:
optionalDependencies: optionalDependencies:
source-map: 0.6.1 source-map: 0.6.1
eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))): eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))):
dependencies: dependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
eslint-import-resolver-node@0.3.9: eslint-import-resolver-node@0.3.9:
dependencies: dependencies:
@@ -3911,17 +3996,17 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): eslint-module-utils@2.12.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)):
dependencies: dependencies:
debug: 3.2.7 debug: 3.2.7
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/parser': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)):
dependencies: dependencies:
'@rtsao/scc': 1.1.0 '@rtsao/scc': 1.1.0
array-includes: 3.1.8 array-includes: 3.1.8
@@ -3932,7 +4017,7 @@ snapshots:
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)) eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))
hasown: 2.0.2 hasown: 2.0.2
is-core-module: 2.16.1 is-core-module: 2.16.1
is-glob: 4.0.3 is-glob: 4.0.3
@@ -3944,7 +4029,7 @@ snapshots:
string.prototype.trimend: 1.0.9 string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0 tsconfig-paths: 3.15.0
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/parser': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
transitivePeerDependencies: transitivePeerDependencies:
- eslint-import-resolver-typescript - eslint-import-resolver-typescript
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
@@ -3989,11 +4074,11 @@ snapshots:
dependencies: dependencies:
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)): eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)):
dependencies: dependencies:
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
optionalDependencies: optionalDependencies:
'@typescript-eslint/eslint-plugin': 8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/eslint-plugin': 8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
eslint-scope@8.3.0: eslint-scope@8.3.0:
dependencies: dependencies:
@@ -4665,6 +4750,10 @@ snapshots:
dependencies: dependencies:
pako: 1.0.11 pako: 1.0.11
katex@0.16.22:
dependencies:
commander: 8.3.0
keyv@4.5.4: keyv@4.5.4:
dependencies: dependencies:
json-buffer: 3.0.1 json-buffer: 3.0.1
@@ -5546,11 +5635,11 @@ snapshots:
typed-query-selector@2.12.0: {} typed-query-selector@2.12.0: {}
typescript-eslint@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2): typescript-eslint@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2):
dependencies: dependencies:
'@typescript-eslint/eslint-plugin': 8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/eslint-plugin': 8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2))(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
'@typescript-eslint/parser': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/parser': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
'@typescript-eslint/utils': 8.28.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2) '@typescript-eslint/utils': 8.29.0(eslint@9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215))(typescript@5.8.2)
eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215) eslint: 9.20.1(patch_hash=4f22e92770bf528b2448fbec0984b9c0761dd588ed0e83dcc41edfc9af711215)
typescript: 5.8.2 typescript: 5.8.2
transitivePeerDependencies: transitivePeerDependencies:

View File

@@ -84,12 +84,14 @@ export function _injectButtons(buttons: ReactNode[], props: ChatBarProps) {
if (props.disabled) return; if (props.disabled) return;
for (const [key, Button] of buttonFactories) { for (const [key, Button] of buttonFactories) {
buttons.push( buttons.unshift(
<ErrorBoundary noop key={key} onError={e => logger.error(`Failed to render ${key}`, e.error)}> <ErrorBoundary noop key={key} onError={e => logger.error(`Failed to render ${key}`, e.error)}>
<Button {...props} isMainChat={props.type.analyticsName === "normal"} /> <Button {...props} isMainChat={props.type.analyticsName === "normal"} />
</ErrorBoundary> </ErrorBoundary>
); );
} }
return buttons;
} }
export const addChatBarButton = (id: string, button: ChatBarButtonFactory) => buttonFactories.set(id, button); export const addChatBarButton = (id: string, button: ChatBarButtonFactory) => buttonFactories.set(id, button);

View File

@@ -16,8 +16,8 @@ export default definePlugin({
{ {
find: '"sticker")', find: '"sticker")',
replacement: { replacement: {
match: /return\(\i\.\i\|\|(?=\(.+?(\i)\.push)/, match: /(?<=className:.{0,20}\.buttons.{0,50}children:)(\i)/,
replace: "$&(Vencord.Api.ChatButtons._injectButtons($1,arguments[0]),false)||" replace: "Vencord.Api.ChatButtons._injectButtons($1,arguments[0])"
} }
} }
] ]

View File

@@ -49,7 +49,7 @@ export default definePlugin({
}, },
}, },
{ {
find: ".METRICS", find: ".METRICS_V2",
replacement: [ replacement: [
{ {
match: /this\._intervalId=/, match: /this\._intervalId=/,

View File

@@ -62,7 +62,7 @@ function getBrailleCharacter(image: any, xOff: number, yOff: number) {
]; ];
// i hate javascript // i hate javascript
return brailleMap.get(JSON.stringify(thing)); return brailleMap.get(JSON.stringify(thing))!;
} }
@@ -133,7 +133,7 @@ export default definePlugin({
const invertParam = opts.find(o => o.name === "invert"); const invertParam = opts.find(o => o.name === "invert");
let image = imageData.greyscale(); let image = imageData.greyscale();
let s = "```\n"; let s = "";
if (opts.find(o => o.name === "width")) { if (opts.find(o => o.name === "width")) {
image.resize({ w: parseInt(opts.find(o => o.name === "width")!.value) }); image.resize({ w: parseInt(opts.find(o => o.name === "width")!.value) });
@@ -160,11 +160,13 @@ export default definePlugin({
for (let j = 0; j < image.width / 2; j++) { for (let j = 0; j < image.width / 2; j++) {
s += getBrailleCharacter(image, j, i); s += getBrailleCharacter(image, j, i);
} }
s = s.replaceAll(/\u2800+$/g, "");
s += "\n"; s += "\n";
} }
sendBotMessage(ctx.channel.id, { sendBotMessage(ctx.channel.id, {
content: s + "\n```" content: `\`\`\`\n${s}\n\`\`\``
}); });
} }
} }

View File

@@ -73,6 +73,11 @@ function isNumberValid(value: number) {
return true; return true;
} }
function isUrlValid(value: string) {
if (value && !/^https?:\/\/.+/.test(value)) return "Must be a valid URL.";
return true;
}
function isImageKeyValid(value: string) { function isImageKeyValid(value: string) {
if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//.test(value)) return "Don't use a Discord link. Use an Imgur image link instead."; if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//.test(value)) return "Don't use a Discord link. Use an Imgur image link instead.";
if (/https?:\/\/(?!i\.)?imgur\.com\//.test(value)) return "Imgur link must be a direct link to the image (e.g. https://i.imgur.com/...). Right click the image and click 'Copy image address'"; if (/https?:\/\/(?!i\.)?imgur\.com\//.test(value)) return "Imgur link must be a direct link to the image (e.g. https://i.imgur.com/...). Right click the image and click 'Copy image address'";
@@ -180,8 +185,15 @@ export function RPCSettings() {
{ settingsKey: "appName", label: "Application Name", isValid: makeValidator(128, true) }, { settingsKey: "appName", label: "Application Name", isValid: makeValidator(128, true) },
]} /> ]} />
<SingleSetting settingsKey="details" label="Detail (line 1)" isValid={maxLength128} /> <PairSetting data={[
<SingleSetting settingsKey="state" label="State (line 2)" isValid={maxLength128} /> { settingsKey: "details", label: "Detail (line 1)", isValid: maxLength128 },
{ settingsKey: "detailsURL", label: "Detail URL", isValid: isUrlValid },
]} />
<PairSetting data={[
{ settingsKey: "state", label: "State (line 2)", isValid: maxLength128 },
{ settingsKey: "stateURL", label: "State URL", isValid: isUrlValid },
]} />
<SingleSetting <SingleSetting
settingsKey="streamLink" settingsKey="streamLink"
@@ -195,13 +207,15 @@ export function RPCSettings() {
settingsKey: "partySize", settingsKey: "partySize",
label: "Party Size", label: "Party Size",
transform: parseNumber, transform: parseNumber,
isValid: isNumberValid isValid: isNumberValid,
disabled: s.type !== ActivityType.PLAYING,
}, },
{ {
settingsKey: "partyMaxSize", settingsKey: "partyMaxSize",
label: "Maximum Party Size", label: "Maximum Party Size",
transform: parseNumber, transform: parseNumber,
isValid: isNumberValid isValid: isNumberValid,
disabled: s.type !== ActivityType.PLAYING,
}, },
]} /> ]} />
@@ -211,21 +225,23 @@ export function RPCSettings() {
{ settingsKey: "imageBig", label: "Large Image URL/Key", isValid: isImageKeyValid }, { settingsKey: "imageBig", label: "Large Image URL/Key", isValid: isImageKeyValid },
{ settingsKey: "imageBigTooltip", label: "Large Image Text", isValid: maxLength128 }, { settingsKey: "imageBigTooltip", label: "Large Image Text", isValid: maxLength128 },
]} /> ]} />
<SingleSetting settingsKey="imageBigURL" label="Large Image clickable URL" isValid={isUrlValid} />
<PairSetting data={[ <PairSetting data={[
{ settingsKey: "imageSmall", label: "Small Image URL/Key", isValid: isImageKeyValid }, { settingsKey: "imageSmall", label: "Small Image URL/Key", isValid: isImageKeyValid },
{ settingsKey: "imageSmallTooltip", label: "Small Image Text", isValid: maxLength128 }, { settingsKey: "imageSmallTooltip", label: "Small Image Text", isValid: maxLength128 },
]} /> ]} />
<SingleSetting settingsKey="imageSmallURL" label="Small Image clickable URL" isValid={isUrlValid} />
<Divider /> <Divider />
<PairSetting data={[ <PairSetting data={[
{ settingsKey: "buttonOneText", label: "Button1 Text", isValid: makeValidator(31) }, { settingsKey: "buttonOneText", label: "Button1 Text", isValid: makeValidator(31) },
{ settingsKey: "buttonOneURL", label: "Button1 URL" }, { settingsKey: "buttonOneURL", label: "Button1 URL", isValid: isUrlValid },
]} /> ]} />
<PairSetting data={[ <PairSetting data={[
{ settingsKey: "buttonTwoText", label: "Button2 Text", isValid: makeValidator(31) }, { settingsKey: "buttonTwoText", label: "Button2 Text", isValid: makeValidator(31) },
{ settingsKey: "buttonTwoURL", label: "Button2 URL" }, { settingsKey: "buttonTwoURL", label: "Button2 URL", isValid: isUrlValid },
]} /> ]} />
<Divider /> <Divider />

View File

@@ -60,15 +60,19 @@ export const settings = definePluginSettings({
appID?: string; appID?: string;
appName?: string; appName?: string;
details?: string; details?: string;
detailsURL?: string;
state?: string; state?: string;
stateURL?: string;
type?: ActivityType; type?: ActivityType;
streamLink?: string; streamLink?: string;
timestampMode?: TimestampMode; timestampMode?: TimestampMode;
startTime?: number; startTime?: number;
endTime?: number; endTime?: number;
imageBig?: string; imageBig?: string;
imageBigURL?: string;
imageBigTooltip?: string; imageBigTooltip?: string;
imageSmall?: string; imageSmall?: string;
imageSmallURL?: string;
imageSmallTooltip?: string; imageSmallTooltip?: string;
buttonOneText?: string; buttonOneText?: string;
buttonOneURL?: string; buttonOneURL?: string;
@@ -83,14 +87,18 @@ async function createActivity(): Promise<Activity | undefined> {
appID, appID,
appName, appName,
details, details,
detailsURL,
state, state,
stateURL,
type, type,
streamLink, streamLink,
startTime, startTime,
endTime, endTime,
imageBig, imageBig,
imageBigURL,
imageBigTooltip, imageBigTooltip,
imageSmall, imageSmall,
imageSmallURL,
imageSmallTooltip, imageSmallTooltip,
buttonOneText, buttonOneText,
buttonOneURL, buttonOneURL,
@@ -137,6 +145,14 @@ async function createActivity(): Promise<Activity | undefined> {
break; break;
} }
if (detailsURL) {
activity.details_url = detailsURL;
}
if (stateURL) {
activity.state_url = stateURL;
}
if (buttonOneText) { if (buttonOneText) {
activity.buttons = [ activity.buttons = [
buttonOneText, buttonOneText,
@@ -154,7 +170,8 @@ async function createActivity(): Promise<Activity | undefined> {
if (imageBig) { if (imageBig) {
activity.assets = { activity.assets = {
large_image: await getApplicationAsset(imageBig), large_image: await getApplicationAsset(imageBig),
large_text: imageBigTooltip || undefined large_text: imageBigTooltip || undefined,
large_url: imageBigURL || undefined
}; };
} }
@@ -162,7 +179,8 @@ async function createActivity(): Promise<Activity | undefined> {
activity.assets = { activity.assets = {
...activity.assets, ...activity.assets,
small_image: await getApplicationAsset(imageSmall), small_image: await getApplicationAsset(imageSmall),
small_text: imageSmallTooltip || undefined small_text: imageSmallTooltip || undefined,
small_url: imageSmallURL || undefined
}; };
} }

View File

@@ -70,7 +70,7 @@ export default definePlugin({
replacement: [ replacement: [
// Add Decor avatar decoration hook to avatar decoration hook // Add Decor avatar decoration hook to avatar decoration hook
{ {
match: /(?<=TryItOut:\i,guildId:\i}\),)(?<=user:(\i).+?)/, match: /(?<=\.avatarDecoration,guildId:\i\}\)\),)(?<=user:(\i).+?)/,
replace: "vcDecorAvatarDecoration=$self.useUserDecorAvatarDecoration($1)," replace: "vcDecorAvatarDecoration=$self.useUserDecorAvatarDecoration($1),"
}, },
// Use added hook // Use added hook

View File

@@ -104,18 +104,9 @@ export default definePlugin({
replace: "false", replace: "false",
} }
}, },
// Enable option to always record clips even if you are not streaming
{
find: "isDecoupledGameClippingEnabled(){",
replacement: {
match: /\i\.isStaff\(\)/,
replace: "true"
}
},
// Enable experiment embed on sent experiment links // Enable experiment embed on sent experiment links
{ {
find: "dev://experiment/", find: ".experimentOverride,children:",
replacement: [ replacement: [
{ {
match: /\i\.isStaff\(\)/, match: /\i\.isStaff\(\)/,
@@ -123,7 +114,7 @@ export default definePlugin({
}, },
// Fix some tricky experiments name causing a client crash // Fix some tricky experiments name causing a client crash
{ {
match: /.getExperimentBucketName.+?if\(null==(\i)\|\|null==\i(?=\)return null;)/, match: /\.isStaffPersonal\(\).+?if\(null==(\i)\|\|null==\i(?=\)return null;)/,
replace: "$&||({})[$1]!=null" replace: "$&||({})[$1]!=null"
} }
] ]

View File

@@ -95,10 +95,10 @@ interface ProfileModalProps {
canUsePremiumCustomization: boolean; canUsePremiumCustomization: boolean;
hideExampleButton: boolean; hideExampleButton: boolean;
hideFakeActivity: boolean; hideFakeActivity: boolean;
isTryItOutFlow: boolean; isTryItOut: boolean;
} }
const ProfileModal = findComponentByCodeLazy<ProfileModalProps>("isTryItOutFlow:", "pendingThemeColors:", "pendingAvatarDecoration:", "EDIT_PROFILE_BANNER"); const ProfileModal = findComponentByCodeLazy<ProfileModalProps>("isTryItOut:", "pendingThemeColors:", "pendingAvatarDecoration:", "EDIT_PROFILE_BANNER");
function SettingsAboutComponentWrapper() { function SettingsAboutComponentWrapper() {
const [, , userProfileLoading] = useAwaiter(() => fetchUserProfile(UserStore.getCurrentUser().id)); const [, , userProfileLoading] = useAwaiter(() => fetchUserProfile(UserStore.getCurrentUser().id));
@@ -188,7 +188,7 @@ function SettingsAboutComponent() {
canUsePremiumCustomization={true} canUsePremiumCustomization={true}
hideExampleButton={true} hideExampleButton={true}
hideFakeActivity={true} hideFakeActivity={true}
isTryItOutFlow={true} isTryItOut={true}
/> />
</div> </div>
</Forms.FormText> </Forms.FormText>

View File

@@ -17,14 +17,12 @@
*/ */
import { definePluginSettings } from "@api/Settings"; import { definePluginSettings } from "@api/Settings";
import { Link } from "@components/Link";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger"; import { Logger } from "@utils/Logger";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { Activity, ActivityAssets, ActivityButton } from "@vencord/discord-types"; import { Activity, ActivityAssets, ActivityButton } from "@vencord/discord-types";
import { ActivityFlags, ActivityStatusDisplayType, ActivityType } from "@vencord/discord-types/enums"; import { ActivityFlags, ActivityStatusDisplayType, ActivityType } from "@vencord/discord-types/enums";
import { findByPropsLazy } from "@webpack"; import { ApplicationAssetUtils, FluxDispatcher, PresenceStore } from "@webpack/common";
import { ApplicationAssetUtils, FluxDispatcher, Forms } from "@webpack/common";
interface TrackData { interface TrackData {
name: string; name: string;
@@ -43,15 +41,15 @@ const enum NameFormat {
AlbumName = "album" AlbumName = "album"
} }
const applicationId = "1108588077900898414"; // Last.fm API keys are essentially public information and have no access to your account, so including one here is fine.
const placeholderId = "2a96cbd8b46e442fc41c2b86b821562f"; const API_KEY = "790c37d90400163a5a5fe00d6ca32ef0";
const DISCORD_APP_ID = "1108588077900898414";
const LASTFM_PLACEHOLDER_IMAGE_HASH = "2a96cbd8b46e442fc41c2b86b821562f";
const logger = new Logger("LastFMRichPresence"); const logger = new Logger("LastFMRichPresence");
const PresenceStore = findByPropsLazy("getLocalPresence");
async function getApplicationAsset(key: string): Promise<string> { async function getApplicationAsset(key: string): Promise<string> {
return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0]; return (await ApplicationAssetUtils.fetchAssetIds(DISCORD_APP_ID, [key]))[0];
} }
function setActivity(activity: Activity | null) { function setActivity(activity: Activity | null) {
@@ -64,25 +62,21 @@ function setActivity(activity: Activity | null) {
const settings = definePluginSettings({ const settings = definePluginSettings({
username: { username: {
description: "last.fm username", description: "Last.fm username",
type: OptionType.STRING,
},
apiKey: {
description: "last.fm api key",
type: OptionType.STRING, type: OptionType.STRING,
}, },
shareUsername: { shareUsername: {
description: "show link to last.fm profile", description: "Show link to Last.fm profile",
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
default: false, default: false,
}, },
shareSong: { clickableLinks: {
description: "show link to song on last.fm", description: "Make track, artist and album names clickable links",
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
default: true, default: true,
}, },
hideWithSpotify: { hideWithSpotify: {
description: "hide last.fm presence if spotify is running", description: "Hide Last.fm presence if spotify is running",
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
default: true, default: true,
}, },
@@ -92,7 +86,7 @@ const settings = definePluginSettings({
default: false, default: false,
}, },
statusName: { statusName: {
description: "custom status text", description: "Custom status text",
type: OptionType.STRING, type: OptionType.STRING,
default: "some music", default: "some music",
}, },
@@ -102,12 +96,12 @@ const settings = definePluginSettings({
options: [ options: [
{ {
label: "Don't show (shows generic listening message)", label: "Don't show (shows generic listening message)",
value: "off", value: "off"
default: true
}, },
{ {
label: "Show artist name", label: "Show artist name",
value: "artist" value: "artist",
default: true
}, },
{ {
label: "Show track name", label: "Show track name",
@@ -147,7 +141,7 @@ const settings = definePluginSettings({
], ],
}, },
useListeningStatus: { useListeningStatus: {
description: 'show "Listening to" status instead of "Playing"', description: 'Show "Listening to" status instead of "Playing"',
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
default: false, default: false,
}, },
@@ -167,10 +161,14 @@ const settings = definePluginSettings({
], ],
}, },
showLastFmLogo: { showLastFmLogo: {
description: "show the Last.fm logo by the album cover", description: "Show the Last.fm logo by the album cover",
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
default: true, default: true,
} },
apiKey: {
description: "Custom Last.fm API key. You shouldn't need to set this",
type: OptionType.STRING,
},
}); });
export default definePlugin({ export default definePlugin({
@@ -178,22 +176,6 @@ export default definePlugin({
description: "Little plugin for Last.fm rich presence", description: "Little plugin for Last.fm rich presence",
authors: [Devs.dzshn, Devs.RuiNtD, Devs.blahajZip, Devs.archeruwu], authors: [Devs.dzshn, Devs.RuiNtD, Devs.blahajZip, Devs.archeruwu],
settingsAboutComponent: () => (
<>
<Forms.FormTitle tag="h3">How to get an API key</Forms.FormTitle>
<Forms.FormText>
An API key is required to fetch your current track. To get one, you can
visit <Link href="https://www.last.fm/api/account/create">this page</Link> and
fill in the following information: <br /> <br />
Application name: Discord Rich Presence <br />
Application description: (personal use) <br /> <br />
And copy the API key (not the shared secret!)
</Forms.FormText>
</>
),
settings, settings,
start() { start() {
@@ -206,13 +188,13 @@ export default definePlugin({
}, },
async fetchTrackData(): Promise<TrackData | null> { async fetchTrackData(): Promise<TrackData | null> {
if (!settings.store.username || !settings.store.apiKey) if (!settings.store.username)
return null; return null;
try { try {
const params = new URLSearchParams({ const params = new URLSearchParams({
method: "user.getrecenttracks", method: "user.getrecenttracks",
api_key: settings.store.apiKey, api_key: settings.store.apiKey || API_KEY,
user: settings.store.username, user: settings.store.username,
limit: "1", limit: "1",
format: "json" format: "json"
@@ -252,7 +234,7 @@ export default definePlugin({
}, },
getLargeImage(track: TrackData): string | undefined { getLargeImage(track: TrackData): string | undefined {
if (track.imageUrl && !track.imageUrl.includes(placeholderId)) if (track.imageUrl && !track.imageUrl.includes(LASTFM_PLACEHOLDER_IMAGE_HASH))
return track.imageUrl; return track.imageUrl;
if (settings.store.missingArt === "placeholder") if (settings.store.missingArt === "placeholder")
@@ -261,13 +243,13 @@ export default definePlugin({
async getActivity(): Promise<Activity | null> { async getActivity(): Promise<Activity | null> {
if (settings.store.hideWithActivity) { if (settings.store.hideWithActivity) {
if (PresenceStore.getActivities().some(a => a.application_id !== applicationId)) { if (PresenceStore.getActivities().some(a => a.application_id !== DISCORD_APP_ID)) {
return null; return null;
} }
} }
if (settings.store.hideWithSpotify) { if (settings.store.hideWithSpotify) {
if (PresenceStore.getActivities().some(a => a.type === ActivityType.LISTENING && a.application_id !== applicationId)) { if (PresenceStore.getActivities().some(a => a.type === ActivityType.LISTENING && a.application_id !== DISCORD_APP_ID)) {
// there is already music status because of Spotify or richerCider (probably more) // there is already music status because of Spotify or richerCider (probably more)
return null; return null;
} }
@@ -298,12 +280,6 @@ export default definePlugin({
url: `https://www.last.fm/user/${settings.store.username}`, url: `https://www.last.fm/user/${settings.store.username}`,
}); });
if (settings.store.shareSong)
buttons.push({
label: "View Song",
url: trackData.url,
});
const statusName = (() => { const statusName = (() => {
switch (settings.store.nameFormat) { switch (settings.store.nameFormat) {
case NameFormat.ArtistFirst: case NameFormat.ArtistFirst:
@@ -321,8 +297,8 @@ export default definePlugin({
} }
})(); })();
return { const activity: Activity = {
application_id: applicationId, application_id: DISCORD_APP_ID,
name: statusName, name: statusName,
details: trackData.name, details: trackData.name,
@@ -332,6 +308,7 @@ export default definePlugin({
"artist": ActivityStatusDisplayType.STATE, "artist": ActivityStatusDisplayType.STATE,
"track": ActivityStatusDisplayType.DETAILS "track": ActivityStatusDisplayType.DETAILS
}[settings.store.statusDisplayType], }[settings.store.statusDisplayType],
assets, assets,
buttons: buttons.length ? buttons.map(v => v.label) : undefined, buttons: buttons.length ? buttons.map(v => v.label) : undefined,
@@ -342,5 +319,16 @@ export default definePlugin({
type: settings.store.useListeningStatus ? ActivityType.LISTENING : ActivityType.PLAYING, type: settings.store.useListeningStatus ? ActivityType.LISTENING : ActivityType.PLAYING,
flags: ActivityFlags.INSTANCE, flags: ActivityFlags.INSTANCE,
}; };
if (settings.store.clickableLinks) {
activity.details_url = trackData.url;
activity.state_url = `https://www.last.fm/music/${encodeURIComponent(trackData.artist)}`;
if (trackData.album) {
activity.assets!.large_url = `https://www.last.fm/music/${encodeURIComponent(trackData.artist)}/${encodeURIComponent(trackData.album)}`;
}
}
return activity;
} }
}); });

View File

@@ -8,6 +8,7 @@ import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types"; import definePlugin, { OptionType } from "@utils/types";
import { React, useEffect, useRef } from "webpack/common/react"; import { React, useEffect, useRef } from "webpack/common/react";
import katex from 'katex';
const blockReact = (data, output, className, _) => { const blockReact = (data, output, className, _) => {
return ( return (
@@ -98,7 +99,7 @@ const ShadowDomComponent = ({ children, ...props }) => {
if (hostRef.current) { if (hostRef.current) {
try { try {
const shadowRoot = hostRef.current.shadowRoot || hostRef.current.attachShadow({ mode: "open" }); const shadowRoot = hostRef.current.shadowRoot || hostRef.current.attachShadow({ mode: "open" });
shadowRoot.innerHTML = DOMPurify.sanitize(children.__html, { ADD_TAGS: ["style", "link"], FORBID_TAGS: ["video", "audio"] }); shadowRoot.innerHTML = DOMPurify.sanitize(children.__html, { ADD_TAGS: ["style", "link", "svg", "math"], FORBID_TAGS: ["video", "audio"] });
} catch (e) { } catch (e) {
if (!(e instanceof DOMException && e.name === "NotSupportedError")) { if (!(e instanceof DOMException && e.name === "NotSupportedError")) {
console.error(e); console.error(e);
@@ -134,20 +135,67 @@ const HTMLReact = (data, _1, _2, _3) => {
); );
}; };
const LaTeXReact = (data, _1, _2, _3) => {
if (!settings.store.html) {
return blockReact(data, _1, "invalid-mm-effect", 0);
}
let trueContent = "";
for (const child of data.content) {
if (child.type === "text") {
trueContent += katex.renderToString(cleanBrokenLatex(child.content), { throwOnError: false, maxSize: 10, /* displayMode: _3 === 1 */ })
// TODO: Fix display mode rendering, this is for future Cobble
// if (_3 === 1) {
// console.log(cleanBrokenLatex(child.content))
// }
}
}
return (
// eslint-disable-next-line react/no-children-prop
// <ShadowDomComponent children={{ __html: trueContent }} />
<span dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(trueContent, { ADD_TAGS: ["svg", "math"], FORBID_TAGS: ["video", "audio"] }) }}></span>
);
};
/**
* Fixes broken LaTeX strings caused by Discord escaping
*
* @param brokenLatexString you'd never guess what this is
* @returns the cleaned LaTeX string
*/
function cleanBrokenLatex(brokenLatexString: string): string {
let cleaned = brokenLatexString
.replace(/\\([;{}])\|\\\1/g, '\\$1|\\$1')
.replace(/([;{}])\|\1/g, '\\$1|\\$1')
.replace(/\\\\/g, '\\\\\\\\');
return cleaned;
}
function escapeRegex(str: string): string { function escapeRegex(str: string): string {
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
} }
const createRule = (name, order, charList, type, animLength = 0) => { const createRule = (name, order, charList, type, animLength = 0) => {
const regex = new RegExp(`^${escapeRegex(charList[0])}([\\s\\S]+?)${escapeRegex(charList[1])}`); const regex = new RegExp(`^${escapeRegex(charList[0])}([\\s\\S]+?)${escapeRegex(charList[1])}`);
const reactFunction = let reactFunction: (data, output, className, animLength) => React.ReactNode;
type === "block" ? blockReact : switch (type) {
type === "character" ? characterReact : case "block":
type === "html" ? HTMLReact : reactFunction = blockReact;
type === "delay" ? delayReact : break;
() => { case "character":
reactFunction = characterReact;
break;
case "html":
reactFunction = HTMLReact;
break;
case "delay":
reactFunction = delayReact;
break;
case "latex":
reactFunction = LaTeXReact;
break;
default:
throw new Error(`Unsupported type: ${type}`); throw new Error(`Unsupported type: ${type}`);
}; }
const rule = { const rule = {
name: name, name: name,
order: order, order: order,
@@ -313,6 +361,8 @@ const rules = [
createRule("html", 24, ["[[[", "]]]"], "html"), createRule("html", 24, ["[[[", "]]]"], "html"),
createRule("slam", 24, [">>", "<<"], "delay", 250), createRule("slam", 24, [">>", "<<"], "delay", 250),
createRule("cursive", 24, ["&&", "&&"], "block"), createRule("cursive", 24, ["&&", "&&"], "block"),
// createRule("latex_display", 23, ["$$", "$$"], "latex", 1), TODO: for future Cobble
createRule("latex", 24, ["$", "$"], "latex", 0),
]; ];
const rulesByName = {}; const rulesByName = {};
@@ -336,7 +386,7 @@ const settings = definePluginSettings({
}, },
html: { html: {
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
description: "Whether to enable HTML effects. WARNING: This can be dangerous.", description: "Whether to enable HTML or LaTeX effects. WARNING: This can be dangerous.",
default: false, default: false,
} }
}); });
@@ -345,7 +395,7 @@ export default definePlugin({
name: "MoreMarkdown", name: "MoreMarkdown",
description: "More markdown capabilities for Nexulien", description: "More markdown capabilities for Nexulien",
nexulien: true, nexulien: true,
authors: [Devs.Zoid, Devs.Jaegerwald, Devs.SwitchedCube], authors: [Devs.Zoid, Devs.Jaegerwald, Devs.SwitchedCube, Devs.Cobble],
rulesByName: rulesByName, rulesByName: rulesByName,
settings, settings,
@@ -359,6 +409,12 @@ export default definePlugin({
}, },
], ],
start: () => { start: () => {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = "https://raw.githubusercontent.com/HoodieRocks/NexulienAssets/refs/heads/main/katex.min.css";
link.crossOrigin = "anonymous";
document.head.appendChild(link);
styles = document.createElement("style"); styles = document.createElement("style");
styles.id = "moreMarkdownStyles"; styles.id = "moreMarkdownStyles";
document.head.appendChild(styles); document.head.appendChild(styles);

View File

@@ -22,6 +22,11 @@ const DefaultEngines = {
Wikipedia: "https://wikipedia.org/w/index.php?search=", Wikipedia: "https://wikipedia.org/w/index.php?search=",
} as const; } as const;
const enum ReplacementEngineValue {
OFF = "off",
CUSTOM = "custom",
}
const settings = definePluginSettings({ const settings = definePluginSettings({
customEngineName: { customEngineName: {
description: "Name of the custom search engine", description: "Name of the custom search engine",
@@ -32,6 +37,15 @@ const settings = definePluginSettings({
description: "The URL of your Engine", description: "The URL of your Engine",
type: OptionType.STRING, type: OptionType.STRING,
placeholder: "https://google.com/search?q=" placeholder: "https://google.com/search?q="
},
replacementEngine: {
description: "Replace with a specific search engine instead of adding a menu",
type: OptionType.SELECT,
options: [
{ label: "Off", value: ReplacementEngineValue.OFF, default: true },
{ label: "Custom Engine", value: ReplacementEngineValue.CUSTOM },
...Object.keys(DefaultEngines).map(engine => ({ label: engine, value: engine }))
]
} }
}); });
@@ -40,13 +54,31 @@ function search(src: string, engine: string) {
} }
function makeSearchItem(src: string) { function makeSearchItem(src: string) {
let Engines = {}; const { customEngineName, customEngineURL, replacementEngine } = settings.store;
if (settings.store.customEngineName && settings.store.customEngineURL) { const hasCustomEngine = Boolean(customEngineName && customEngineURL);
Engines[settings.store.customEngineName] = settings.store.customEngineURL; const hasValidReplacementEngine = replacementEngine !== ReplacementEngineValue.OFF && !(replacementEngine === ReplacementEngineValue.CUSTOM && !hasCustomEngine);
const Engines = { ...DefaultEngines };
if (hasCustomEngine) {
Engines[customEngineName!] = customEngineURL;
} }
Engines = { ...Engines, ...DefaultEngines }; if (hasValidReplacementEngine) {
const name = replacementEngine === ReplacementEngineValue.CUSTOM && hasCustomEngine
? customEngineName
: replacementEngine;
return (
<Menu.MenuItem
label={`Search with ${name}`}
key="search-custom-engine"
id="vc-search-custom-engine"
action={() => search(src, Engines[name!])}
/>
);
}
return ( return (
<Menu.MenuItem <Menu.MenuItem
@@ -95,7 +127,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, _props)
export default definePlugin({ export default definePlugin({
name: "ReplaceGoogleSearch", name: "ReplaceGoogleSearch",
description: "Replaces the Google search with different Engines", description: "Replaces the Google search with different Engine(s)",
authors: [Devs.Moxxie, Devs.Ethan], authors: [Devs.Moxxie, Devs.Ethan],
settings, settings,

View File

@@ -107,7 +107,8 @@ export const toneIndicators = [
ti(["vu"], "very upset"), ti(["vu"], "very upset"),
ti(["w"], "warmth"), ti(["w"], "warmth"),
ti(["unin"], "unintentional"), ti(["unin"], "unintentional"),
ti(["unre"], "unrelated") ti(["unre"], "unrelated"),
ti(["nh"], "not hateful")
]; ];
const f = toneIndicators.reduce((ret, cur) => { const f = toneIndicators.reduce((ret, cur) => {
return { return {

View File

@@ -25,7 +25,7 @@ import { Devs } from "@utils/constants";
import definePlugin from "@utils/types"; import definePlugin from "@utils/types";
import { findComponentByCodeLazy } from "@webpack"; import { findComponentByCodeLazy } from "@webpack";
import { Menu, Popout, useRef, useState } from "@webpack/common"; import { Menu, Popout, useRef, useState } from "@webpack/common";
import type { ReactNode } from "react"; import type { PropsWithChildren, ReactNode } from "react";
const HeaderBarIcon = findComponentByCodeLazy(".HEADER_BAR_BADGE_TOP:", '.iconBadge,"top"'); const HeaderBarIcon = findComponentByCodeLazy(".HEADER_BAR_BADGE_TOP:", '.iconBadge,"top"');
@@ -131,16 +131,20 @@ export default definePlugin({
{ {
find: '?"BACK_FORWARD_NAVIGATION":', find: '?"BACK_FORWARD_NAVIGATION":',
replacement: { replacement: {
// TODO: (?:\.button) is for stable compat and should be removed soon:tm: match: /(?<=trailing:.{0,50})\i\.Fragment,\{(?=.+?className:(\i))/,
match: /focusSectionProps:"HELP".{0,20},className:(\i(?:\.button)?)\}\),/, replace: "$self.TrailingWrapper,{className:$1,"
replace: "$& $self.renderVencordPopoutButton($1),"
} }
} }
], ],
renderVencordPopoutButton: (buttonClass: string) => ( TrailingWrapper({ children, className }: PropsWithChildren<{ className: string; }>) {
return (
<>
{children}
<ErrorBoundary noop> <ErrorBoundary noop>
<VencordPopoutButton buttonClass={buttonClass} /> <VencordPopoutButton buttonClass={className} />
</ErrorBoundary> </ErrorBoundary>
) </>
);
},
}); });

View File

@@ -233,7 +233,7 @@ export default definePlugin({
}, },
// User Dms top large icon // User Dms top large icon
{ {
find: 'experimentLocation:"empty_messages"', find: ".EMPTY_GROUP_DM)",
replacement: { replacement: {
match: /(?<=SIZE_80,)(?=src:(.+?\))[,}])/, match: /(?<=SIZE_80,)(?=src:(.+?\))[,}])/,
replace: (_, avatarUrl) => `onClick:()=>$self.openAvatar(${avatarUrl}),` replace: (_, avatarUrl) => `onClick:()=>$self.openAvatar(${avatarUrl}),`

View File

@@ -21,6 +21,7 @@ import "./styles.css";
import { NavContextMenuPatchCallback } from "@api/ContextMenu"; import { NavContextMenuPatchCallback } from "@api/ContextMenu";
import { Microphone } from "@components/Icons"; import { Microphone } from "@components/Icons";
import { Link } from "@components/Link"; import { Link } from "@components/Link";
import { Paragraph } from "@components/Paragraph";
import { Devs } from "@utils/constants"; import { Devs } from "@utils/constants";
import { Margins } from "@utils/margins"; import { Margins } from "@utils/margins";
import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal"; import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal";
@@ -144,7 +145,7 @@ function Modal({ modalProps }: { modalProps: ModalProps; }) {
URL.revokeObjectURL(blobUrl); URL.revokeObjectURL(blobUrl);
}, [blobUrl]); }, [blobUrl]);
const [meta] = useAwaiter(async () => { const [meta, metaError] = useAwaiter(async () => {
if (!blob) return EMPTY_META; if (!blob) return EMPTY_META;
const audioContext = new AudioContext(); const audioContext = new AudioContext();
@@ -214,11 +215,15 @@ function Modal({ modalProps }: { modalProps: ModalProps; }) {
</div> </div>
<Forms.FormTitle>Preview</Forms.FormTitle> <Forms.FormTitle>Preview</Forms.FormTitle>
{metaError
? <Paragraph className={cl("error")}>Failed to parse selected audio file: {metaError.message}</Paragraph>
: (
<VoicePreview <VoicePreview
src={blobUrl} src={blobUrl}
waveform={meta.waveform} waveform={meta.waveform}
recording={isRecording} recording={isRecording}
/> />
)}
{isUnsupportedFormat && ( {isUnsupportedFormat && (
<Card className={`vc-warning-card ${Margins.top16}`}> <Card className={`vc-warning-card ${Margins.top16}`}>
@@ -236,7 +241,7 @@ function Modal({ modalProps }: { modalProps: ModalProps; }) {
<Button <Button
disabled={!blob} disabled={!blob}
onClick={() => { onClick={() => {
sendAudio(blob!, meta); sendAudio(blob!, meta ?? EMPTY_META);
modalProps.onClose(); modalProps.onClose();
showToast("Now sending voice message... Please be patient", Toasts.Type.MESSAGE); showToast("Now sending voice message... Please be patient", Toasts.Type.MESSAGE);
}} }}

View File

@@ -48,3 +48,7 @@
flex: 1; flex: 1;
text-align: center; text-align: center;
} }
.vc-vmsg-error {
color: var(--text-danger);
}