Add Premid Plugin + RoleMembersViewer

This commit is contained in:
thororen1234 2025-02-08 15:14:28 -05:00
parent d793f37b39
commit f3f7696dca
6 changed files with 747 additions and 31 deletions

View file

@ -51,6 +51,7 @@
"idb": "8.0.0", "idb": "8.0.0",
"monaco-editor": "^0.52.2", "monaco-editor": "^0.52.2",
"nanoid": "^5.0.9", "nanoid": "^5.0.9",
"socket.io": "^4.8.1",
"usercss-meta": "^0.12.0", "usercss-meta": "^0.12.0",
"openai": "^4.30.0", "openai": "^4.30.0",
"virtual-merge": "^1.0.1" "virtual-merge": "^1.0.1"
@ -122,4 +123,4 @@
"node": ">=18", "node": ">=18",
"pnpm": ">=9" "pnpm": ">=9"
} }
} }

177
pnpm-lock.yaml generated
View file

@ -64,6 +64,9 @@ importers:
openai: openai:
specifier: ^4.30.0 specifier: ^4.30.0
version: 4.52.7 version: 4.52.7
socket.io:
specifier: ^4.8.1
version: 4.8.1
usercss-meta: usercss-meta:
specifier: ^0.12.0 specifier: ^0.12.0
version: 0.12.0 version: 0.12.0
@ -667,6 +670,9 @@ packages:
'@sapphi-red/web-noise-suppressor@0.3.5': '@sapphi-red/web-noise-suppressor@0.3.5':
resolution: {integrity: sha512-jh3+V9yM+zxLriQexoGm0GatoPaJWjs6ypFIbFYwQp+AoUb55eUXrjKtKQyuC5zShzzeAQUl0M5JzqB7SSrsRA==} resolution: {integrity: sha512-jh3+V9yM+zxLriQexoGm0GatoPaJWjs6ypFIbFYwQp+AoUb55eUXrjKtKQyuC5zShzzeAQUl0M5JzqB7SSrsRA==}
'@socket.io/component-emitter@3.1.2':
resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
'@stylistic/eslint-plugin@2.12.1': '@stylistic/eslint-plugin@2.12.1':
resolution: {integrity: sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==} resolution: {integrity: sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -679,6 +685,9 @@ packages:
'@types/chrome@0.0.287': '@types/chrome@0.0.287':
resolution: {integrity: sha512-wWhBNPNXZHwycHKNYnexUcpSbrihVZu++0rdp6GEk5ZgAglenLx+RwdEouh6FrHS0XQiOxSd62yaujM1OoQlZQ==} resolution: {integrity: sha512-wWhBNPNXZHwycHKNYnexUcpSbrihVZu++0rdp6GEk5ZgAglenLx+RwdEouh6FrHS0XQiOxSd62yaujM1OoQlZQ==}
'@types/cors@2.8.17':
resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==}
'@types/diff@6.0.0': '@types/diff@6.0.0':
resolution: {integrity: sha512-dhVCYGv3ZSbzmQaBSagrv1WJ6rXCdkyTcDyoNu1MD8JohI7pR7k8wdZEm+mvdxRKXyHVwckFzWU1vJc+Z29MlA==} resolution: {integrity: sha512-dhVCYGv3ZSbzmQaBSagrv1WJ6rXCdkyTcDyoNu1MD8JohI7pR7k8wdZEm+mvdxRKXyHVwckFzWU1vJc+Z29MlA==}
@ -819,6 +828,10 @@ packages:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'} engines: {node: '>=6.5'}
accepts@1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
acorn-jsx@5.3.2: acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies: peerDependencies:
@ -891,10 +904,6 @@ packages:
resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
array.prototype.flatmap@1.3.2:
resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
engines: {node: '>= 0.4'}
array.prototype.flatmap@1.3.3: array.prototype.flatmap@1.3.3:
resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -956,6 +965,10 @@ packages:
base64-js@1.5.1: base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
base64id@2.0.0:
resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
engines: {node: ^4.5.0 || >= 5.9}
basic-ftp@5.0.5: basic-ftp@5.0.5:
resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
@ -1057,6 +1070,14 @@ packages:
concat-map@0.0.1: concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
cookie@0.7.2:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'}
cors@2.8.5:
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
engines: {node: '>= 0.10'}
cosmiconfig@9.0.0: cosmiconfig@9.0.0:
resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==}
engines: {node: '>=14'} engines: {node: '>=14'}
@ -1193,6 +1214,14 @@ packages:
end-of-stream@1.4.4: end-of-stream@1.4.4:
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
engine.io-parser@5.2.3:
resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==}
engines: {node: '>=10.0.0'}
engine.io@6.6.4:
resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==}
engines: {node: '>=10.2.0'}
entities@4.5.0: entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@ -2157,6 +2186,10 @@ packages:
natural-compare@1.4.0: natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
negotiator@0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
netmask@2.0.2: netmask@2.0.2:
resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
engines: {node: '>= 0.4.0'} engines: {node: '>= 0.4.0'}
@ -2217,10 +2250,6 @@ packages:
resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
object.values@1.2.0:
resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==}
engines: {node: '>= 0.4'}
object.values@1.2.1: object.values@1.2.1:
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -2514,6 +2543,17 @@ packages:
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
socket.io-adapter@2.5.5:
resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==}
socket.io-parser@4.2.4:
resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==}
engines: {node: '>=10.0.0'}
socket.io@4.8.1:
resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==}
engines: {node: '>=10.2.0'}
socks-proxy-agent@8.0.5: socks-proxy-agent@8.0.5:
resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
@ -2780,6 +2820,10 @@ packages:
util-deprecate@1.0.2: util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
virtual-merge@1.0.1: virtual-merge@1.0.1:
resolution: {integrity: sha512-h7rzV6n5fZJbDu2lP4iu+IOtsZ00uqECFUxFePK1uY0pz/S5B7FNDJpmdDVfyGL7poyJECEHfTaIpJaknNkU0Q==} resolution: {integrity: sha512-h7rzV6n5fZJbDu2lP4iu+IOtsZ00uqECFUxFePK1uY0pz/S5B7FNDJpmdDVfyGL7poyJECEHfTaIpJaknNkU0Q==}
@ -2855,6 +2899,18 @@ packages:
resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
ws@8.17.1:
resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
ws@8.18.0: ws@8.18.0:
resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
@ -3214,6 +3270,8 @@ snapshots:
'@sapphi-red/web-noise-suppressor@0.3.5': {} '@sapphi-red/web-noise-suppressor@0.3.5': {}
'@socket.io/component-emitter@3.1.2': {}
'@stylistic/eslint-plugin@2.12.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2)': '@stylistic/eslint-plugin@2.12.1(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2)':
dependencies: dependencies:
'@typescript-eslint/utils': 8.19.0(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2) '@typescript-eslint/utils': 8.19.0(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2)
@ -3233,6 +3291,10 @@ snapshots:
'@types/filesystem': 0.0.36 '@types/filesystem': 0.0.36
'@types/har-format': 1.2.15 '@types/har-format': 1.2.15
'@types/cors@2.8.17':
dependencies:
'@types/node': 22.10.5
'@types/diff@6.0.0': {} '@types/diff@6.0.0': {}
'@types/estree@1.0.6': {} '@types/estree@1.0.6': {}
@ -3344,7 +3406,7 @@ snapshots:
'@typescript-eslint/types': 8.19.0 '@typescript-eslint/types': 8.19.0
'@typescript-eslint/typescript-estree': 8.19.0(typescript@5.7.2) '@typescript-eslint/typescript-estree': 8.19.0(typescript@5.7.2)
'@typescript-eslint/visitor-keys': 8.19.0 '@typescript-eslint/visitor-keys': 8.19.0
debug: 4.3.6 debug: 4.4.0
eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4)
typescript: 5.7.2 typescript: 5.7.2
transitivePeerDependencies: transitivePeerDependencies:
@ -3359,7 +3421,7 @@ snapshots:
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 8.19.0(typescript@5.7.2) '@typescript-eslint/typescript-estree': 8.19.0(typescript@5.7.2)
'@typescript-eslint/utils': 8.19.0(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2) '@typescript-eslint/utils': 8.19.0(eslint@9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4))(typescript@5.7.2)
debug: 4.3.6 debug: 4.4.0
eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4)
ts-api-utils: 1.3.0(typescript@5.7.2) ts-api-utils: 1.3.0(typescript@5.7.2)
typescript: 5.7.2 typescript: 5.7.2
@ -3372,7 +3434,7 @@ snapshots:
dependencies: dependencies:
'@typescript-eslint/types': 8.19.0 '@typescript-eslint/types': 8.19.0
'@typescript-eslint/visitor-keys': 8.19.0 '@typescript-eslint/visitor-keys': 8.19.0
debug: 4.3.6 debug: 4.4.0
fast-glob: 3.3.2 fast-glob: 3.3.2
is-glob: 4.0.3 is-glob: 4.0.3
minimatch: 9.0.5 minimatch: 9.0.5
@ -3412,6 +3474,11 @@ snapshots:
dependencies: dependencies:
event-target-shim: 5.0.1 event-target-shim: 5.0.1
accepts@1.3.8:
dependencies:
mime-types: 2.1.35
negotiator: 0.6.3
acorn-jsx@5.3.2(acorn@8.14.0): acorn-jsx@5.3.2(acorn@8.14.0):
dependencies: dependencies:
acorn: 8.14.0 acorn: 8.14.0
@ -3484,9 +3551,9 @@ snapshots:
array.prototype.findlastindex@1.2.5: array.prototype.findlastindex@1.2.5:
dependencies: dependencies:
call-bind: 1.0.7 call-bind: 1.0.8
define-properties: 1.2.1 define-properties: 1.2.1
es-abstract: 1.23.3 es-abstract: 1.23.9
es-errors: 1.3.0 es-errors: 1.3.0
es-object-atoms: 1.0.0 es-object-atoms: 1.0.0
es-shim-unscopables: 1.0.2 es-shim-unscopables: 1.0.2
@ -3498,13 +3565,6 @@ snapshots:
es-abstract: 1.23.3 es-abstract: 1.23.3
es-shim-unscopables: 1.0.2 es-shim-unscopables: 1.0.2
array.prototype.flatmap@1.3.2:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-abstract: 1.23.3
es-shim-unscopables: 1.0.2
array.prototype.flatmap@1.3.3: array.prototype.flatmap@1.3.3:
dependencies: dependencies:
call-bind: 1.0.8 call-bind: 1.0.8
@ -3586,6 +3646,8 @@ snapshots:
base64-js@1.5.1: {} base64-js@1.5.1: {}
base64id@2.0.0: {}
basic-ftp@5.0.5: {} basic-ftp@5.0.5: {}
brace-expansion@1.1.11: brace-expansion@1.1.11:
@ -3695,6 +3757,13 @@ snapshots:
concat-map@0.0.1: {} concat-map@0.0.1: {}
cookie@0.7.2: {}
cors@2.8.5:
dependencies:
object-assign: 4.1.1
vary: 1.1.2
cosmiconfig@9.0.0(typescript@5.7.2): cosmiconfig@9.0.0(typescript@5.7.2):
dependencies: dependencies:
env-paths: 2.2.1 env-paths: 2.2.1
@ -3829,6 +3898,24 @@ snapshots:
dependencies: dependencies:
once: 1.4.0 once: 1.4.0
engine.io-parser@5.2.3: {}
engine.io@6.6.4:
dependencies:
'@types/cors': 2.8.17
'@types/node': 22.10.5
accepts: 1.3.8
base64id: 2.0.0
cookie: 0.7.2
cors: 2.8.5
debug: 4.3.6
engine.io-parser: 5.2.3
ws: 8.17.1
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
entities@4.5.0: {} entities@4.5.0: {}
env-paths@2.2.1: {} env-paths@2.2.1: {}
@ -4178,7 +4265,7 @@ snapshots:
array-includes: 3.1.8 array-includes: 3.1.8
array.prototype.findlastindex: 1.2.5 array.prototype.findlastindex: 1.2.5
array.prototype.flat: 1.3.2 array.prototype.flat: 1.3.2
array.prototype.flatmap: 1.3.2 array.prototype.flatmap: 1.3.3
debug: 3.2.7 debug: 3.2.7
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4) eslint: 9.17.0(patch_hash=xm46kqcmdgzlmm4aifkfpxaho4)
@ -4190,7 +4277,7 @@ snapshots:
minimatch: 3.1.2 minimatch: 3.1.2
object.fromentries: 2.0.8 object.fromentries: 2.0.8
object.groupby: 1.0.3 object.groupby: 1.0.3
object.values: 1.2.0 object.values: 1.2.1
semver: 6.3.1 semver: 6.3.1
tsconfig-paths: 3.15.0 tsconfig-paths: 3.15.0
optionalDependencies: optionalDependencies:
@ -4954,6 +5041,8 @@ snapshots:
natural-compare@1.4.0: {} natural-compare@1.4.0: {}
negotiator@0.6.3: {}
netmask@2.0.2: {} netmask@2.0.2: {}
no-case@3.0.4: no-case@3.0.4:
@ -5008,15 +5097,9 @@ snapshots:
object.groupby@1.0.3: object.groupby@1.0.3:
dependencies: dependencies:
call-bind: 1.0.7 call-bind: 1.0.8
define-properties: 1.2.1 define-properties: 1.2.1
es-abstract: 1.23.3 es-abstract: 1.23.9
object.values@1.2.0:
dependencies:
call-bind: 1.0.7
define-properties: 1.2.1
es-object-atoms: 1.0.0
object.values@1.2.1: object.values@1.2.1:
dependencies: dependencies:
@ -5376,6 +5459,36 @@ snapshots:
smart-buffer@4.2.0: {} smart-buffer@4.2.0: {}
socket.io-adapter@2.5.5:
dependencies:
debug: 4.3.6
ws: 8.17.1
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
socket.io-parser@4.2.4:
dependencies:
'@socket.io/component-emitter': 3.1.2
debug: 4.3.6
transitivePeerDependencies:
- supports-color
socket.io@4.8.1:
dependencies:
accepts: 1.3.8
base64id: 2.0.0
cors: 2.8.5
debug: 4.3.6
engine.io: 6.6.4
socket.io-adapter: 2.5.5
socket.io-parser: 4.2.4
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
socks-proxy-agent@8.0.5: socks-proxy-agent@8.0.5:
dependencies: dependencies:
agent-base: 7.1.3 agent-base: 7.1.3
@ -5766,6 +5879,8 @@ snapshots:
util-deprecate@1.0.2: {} util-deprecate@1.0.2: {}
vary@1.1.2: {}
virtual-merge@1.0.1: {} virtual-merge@1.0.1: {}
vscode-oniguruma@1.7.0: {} vscode-oniguruma@1.7.0: {}
@ -5866,6 +5981,8 @@ snapshots:
imurmurhash: 0.1.4 imurmurhash: 0.1.4
signal-exit: 4.1.0 signal-exit: 4.1.0
ws@8.17.1: {}
ws@8.18.0: {} ws@8.18.0: {}
y18n@5.0.8: {} y18n@5.0.8: {}

View file

@ -0,0 +1,327 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2023 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { definePluginSettings } from "@api/Settings";
import { Link } from "@components/Link";
import { Devs } from "@utils/constants";
import { Logger } from "@utils/Logger";
import definePlugin, { OptionType, PluginNative } from "@utils/types";
import { findByCodeLazy } from "@webpack";
import { ApplicationAssetUtils, FluxDispatcher, Forms, Toasts } from "@webpack/common";
interface ActivityAssets {
large_image: string;
large_text?: string | null;
small_image: string;
small_text: string;
}
type ActivityButton = {
label: string;
url: string;
};
export interface Activity {
state: string;
details?: string;
timestamps?: {
start?: number;
end?: number;
};
assets: ActivityAssets;
buttons?: Array<string>;
name: string;
application_id: string;
metadata?: {
button_urls?: Array<string>;
};
type: number;
flags: number;
}
interface PremidActivity {
state: string;
details?: string;
startTimestamp?: number;
endTimestamp?: number;
largeImageKey: string;
largeImageText: string;
smallImageKey: string;
smallImageText: string;
buttons?: ActivityButton[];
name?: string;
application_id: string;
type: number;
flags: number;
}
interface PresenceData {
// Only relevant types - https://github.com/PreMiD/PreMiD/blob/main/%40types/PreMiD/PresenceData.d.ts
clientId: string;
presenceData: PremidActivity;
}
const enum ActivityType {
PLAYING = 0,
LISTENING = 2,
WATCHING = 3,
COMPETING = 5
}
const enum ActivityFlag {
INSTANCE = 1 << 0
}
interface PublicApp {
id: string;
name: string;
icon: string;
statusType: ActivityType | undefined;
flags: number;
}
const logger = new Logger("Vencord-PreMiD", "#8fd0ff");
const fetchApplicationsRPC = findByCodeLazy('"Invalid Origin"', ".application");
const apps: any = {};
async function getApp(applicationId: string): Promise<PublicApp> {
if (apps[applicationId]) return apps[applicationId];
const socket: any = {};
debugLog(`Looking up ${applicationId}`);
await fetchApplicationsRPC(socket, applicationId);
logger.debug(socket);
debugLog(`Lookup finished for ${socket.application.name}`);
const activityType = await determineStatusType(socket.application);
debugLog(`Activity type for ${socket.application.name}: ${activityType}`);
socket.application.statusType = settings.store.detectCategory ? activityType : ActivityType.PLAYING || ActivityType.PLAYING;
apps[applicationId] = socket.application;
return socket.application;
}
const assetCache: Map<string, string> = new Map();
// memoized because this method isnt cached
async function getAppAsset(applicationId: string, key: string): Promise<string> {
if (assetCache.has(applicationId + key)) {
return assetCache.get(applicationId + key)!;
}
const result = (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0];
assetCache.set(applicationId + key, result);
return result;
}
function setActivity(activity: Activity | undefined) {
FluxDispatcher.dispatch({
type: "LOCAL_ACTIVITY_UPDATE",
activity,
socketId: "PreMiD",
});
}
const settings = definePluginSettings({
enableSet: {
description: "Should the plugin set presences?",
type: OptionType.BOOLEAN,
default: true,
onChange: (value: boolean) => {
if (!value) preMid.clearActivity();
},
},
showButtons: {
description: "Show buttons",
type: OptionType.BOOLEAN,
default: true,
},
detectCategory: {
description: "Set your Activity Type based on presence category",
type: OptionType.BOOLEAN,
default: true,
},
hideViewChannel: {
description: "YouTube: Hide view channel button",
type: OptionType.BOOLEAN,
default: false,
}
});
const Native = VencordNative.pluginHelpers.PreMiD as PluginNative<typeof import("./native")>;
const preMid = definePlugin({
name: "PreMiD",
tags: ["presence", "premid", "rpc", "watching"],
description: "A PreMiD app replacement. Supports watching/listening status. Requires extra setup (see settings)",
authors: [Devs.Nyako],
toolboxActions: {
"Toggle presence sharing": () => {
settings.store.enableSet = !settings.store.enableSet;
showToast(`Presence sharing is now ${settings.store.enableSet ? "enabled" : "disabled"}`);
preMid.clearActivity();
},
},
settingsAboutComponent: () => (
<>
<Forms.FormTitle tag="h3">How to use this plugin</Forms.FormTitle>
<Forms.FormText>
Install the <Link href="https://premid.app/downloads#ext-downloads">PreMiD browser extension</Link>. (recommended version: 2.5.2 OR 2.6.11+)
</Forms.FormText>
<Forms.FormText tag="h4">
This will not work with anything that has differing behavior (such as PreWrap)
</Forms.FormText>
<Forms.FormText>
That's all you need, if you followed the instructions in this plugin's README you should be good. This plugin replicates their electron tray process so no need to use allat.
</Forms.FormText>
</>
),
settings,
logger,
start() {
Native.init();
},
stop() {
this.clearActivity();
Native.disconnect();
},
clearActivity() {
FluxDispatcher.dispatch({
type: "LOCAL_ACTIVITY_UPDATE",
activity: null,
socketId: "PreMiD",
});
},
showToast,
async receiveActivity(data: PresenceData) {
logger.debug("Received activity", data);
if (!settings.store.enableSet) {
this.clearActivity();
return;
}
try {
const id = data.clientId;
if (!id) return;
const appInfo = await getApp(id);
const presence = { ...data.presenceData };
if (appInfo.name === "PreMiD") return;
logger.debug(`Setting activity of ${appInfo.name} "${presence.details}"`);
const { details, state, largeImageKey, smallImageKey, smallImageText } = presence;
const activity: Activity = {
application_id: id,
name: appInfo.name,
details: details ?? "",
state: state ?? "",
type: appInfo.statusType || ActivityType.PLAYING,
flags: ActivityFlag.INSTANCE,
assets: {
large_image: await getAppAsset(id, largeImageKey ?? "oops"),
small_image: await getAppAsset(id, smallImageKey ?? "oops"),
small_text: smallImageText || "hello there :3",
},
buttons: presence.buttons?.map((b: { label: any; }) => b.label),
metadata: {
button_urls: presence.buttons?.map((b: { url: any; }) => b.url)
},
timestamps: {
start: presence.startTimestamp,
end: presence.endTimestamp
}
};
if (activity.type === ActivityType.PLAYING) {
activity.assets = {
large_image: await getAppAsset(id, largeImageKey ?? "guh"),
large_text: "vc-premid",
small_image: await getAppAsset(id, smallImageKey ?? "guhh"),
small_text: smallImageText || "hello there :3",
};
}
if (settings.store.showButtons && activity.buttons) {
if (appInfo.name === "YouTube" && settings.store.hideViewChannel) {
activity.buttons?.pop();
if (activity.metadata && activity.metadata && activity.metadata.button_urls) {
activity.metadata.button_urls = [activity.metadata.button_urls[0]];
}
}
}
for (const k in activity) {
if (k === "type") continue; // without type, the presence is considered invalid.
const v = activity[k];
if (!v || v.length === 0)
delete activity[k];
}
setActivity(activity);
} catch (err) {
logger.error(err);
}
}
});
async function determineStatusType(info: PublicApp): Promise<ActivityType | undefined> {
let firstCharacter = info.name.charAt(0);
if (firstCharacter.match(/[a-zA-Z]/)) {
firstCharacter = firstCharacter;
} else if (firstCharacter.match(/[0-9]/)) {
firstCharacter = "0-9";
} else {
firstCharacter = "%23"; // #
}
const res = await fetch(`https://raw.githubusercontent.com/PreMiD/Presences/main/websites/${firstCharacter}/${info.name}/metadata.json`);
if (!res.ok) return ActivityType.PLAYING;
try {
const metadata = await res.json();
switch (metadata.category) {
case "socials":
if (metadata.tags.includes("video")) {
return ActivityType.WATCHING;
}
break;
case "anime":
if (metadata.tags.some((tag: string) => ["video", "media", "streaming"].includes(tag))) {
return ActivityType.WATCHING;
}
break;
case "music":
return ActivityType.LISTENING;
case "videos":
return ActivityType.WATCHING;
}
} catch (e) {
logger.error(e);
return ActivityType.PLAYING;
}
return ActivityType.PLAYING;
}
function debugLog(msg: string) {
if (IS_DEV) console.log(msg);
}
function showToast(msg: string) {
Toasts.show({
message: msg,
type: Toasts.Type.SUCCESS,
id: Toasts.genId(),
options: {
duration: 5000,
position: Toasts.Position.TOP
}
});
}
export default preMid;

View file

@ -0,0 +1,116 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { BrowserWindow, dialog, WebContents } from "electron";
import { createServer, Server as HttpServer } from "http";
import { Server, Socket } from "socket.io";
let io: Server;
let httpServer: HttpServer;
let hasInit = false;
let webFrame: WebContents;
export function init() {
if (hasInit) return;
const windows = BrowserWindow.getAllWindows();
const discordUrls = ["https://discord.com", "https://ptb.discord.com", "https://canary.discord.com"];
for (const win of windows) {
const url = win.webContents.getURL();
if (discordUrls.some(prefix => url.startsWith(prefix))) {
webFrame = win.webContents;
}
}
httpServer = createServer();
io = new Server(httpServer, {
serveClient: false,
allowEIO3: true,
cors: { origin: "*" }
});
httpServer.listen(3020, () => {
console.log("[vc-premid] SocketIO starting on 3020");
logRenderer("SocketIO starting on 3020");
});
httpServer.on("error", onIOError);
io.on("connection", onConnect);
hasInit = true;
}
export function disconnect() {
if (!hasInit) return;
io.close();
httpServer.close();
hasInit = false;
}
async function onConnect(sio: Socket) {
try {
logRenderer("[vc-premid] PreMiD socket connected!");
// Get current user from plugin & send to extension
const {
username,
globalName,
id,
avatar,
discriminator,
flags,
premiumType
} = JSON.parse(await webFrame.executeJavaScript("JSON.stringify(window.Vencord.Webpack.Common.UserStore.getCurrentUser());"));
sio.emit("discordUser", { username, global_name: globalName, discriminator, id, avatar, bot: false, flags, premium_type: premiumType });
// Extension requests Premid version
sio.on("getVersion", () => {
logRenderer("Extension requested version");
sio.emit("receiveVersion", "221");
});
sio.on("setActivity", setActivity);
sio.on("clearActivity", clearActivity);
sio.on("selectLocalPresence", () => {
logRenderer("Selecting local presence is not supported");
dialog.showMessageBox({ message: "Selecting local presence is not supported right now!", title: "vc-premid: oops!" });
});
sio.once("disconnect", () => onIoDisconnect());
} catch (e) {
logError("Error in onConnect: ", e);
}
}
function logRenderer(message: string) {
if (webFrame) {
webFrame.executeJavaScript(`window.Vencord.Plugins.plugins.PreMiD.logger.info('${message}')`);
} else {
// just in case, dont worry about it pls
console.log(`[vc-premid (fallback)] ${message}`);
}
}
function logError(message: string, ...args: any[]) {
console.error(`${message}`, args);
}
function setActivity(activity: any) {
// hopefully this works
webFrame.executeJavaScript(`window.Vencord.Plugins.plugins.PreMiD.receiveActivity(${JSON.stringify(activity)})`).catch(console.error);
}
function clearActivity() {
webFrame.executeJavaScript("window.Vencord.Plugins.plugins.PreMiD.clearActivity()");
}
function onIOError(e: { message: string; code: string; }) {
if (e.message.includes("EADDRINUSE")) return; // dont care, probably 2+ clients open
logError("SocketIO error", e);
}
async function onIoDisconnect() {
console.log("[vc-premid] SocketIO disconnected");
logRenderer("SocketIO disconnected");
clearActivity();
}

View file

@ -0,0 +1,151 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2025 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { EquicordDevs } from "@utils/constants";
import definePlugin from "@utils/types";
import {
FluxDispatcher,
GuildMemberStore,
GuildStore,
Menu,
SelectedChannelStore,
SelectedGuildStore,
UserProfileActions,
UserStore
} from "@webpack/common";
import { JSX } from "react";
function fetchMembersWithRole(guildId: string, roleId: string) {
const guildMembers = GuildMemberStore.getMembers(guildId);
let membersInRole = 0;
guildMembers.forEach(member => {
if (member.roles.includes(roleId)) {
membersInRole++;
}
});
if (Object.keys(guildMembers).length < membersInRole) {
const chunk = 100;
const requestCount = Math.ceil(membersInRole / chunk);
for (let i = 0; i < requestCount; i++) {
FluxDispatcher.dispatch({
type: "GUILD_MEMBERS_REQUEST",
guildId,
userIds: [],
query: "",
limit: chunk,
withPresences: true,
notifyOnLimit: true
});
}
}
const updatedGuildMembers = GuildMemberStore.getMembers(guildId);
return Object.values(updatedGuildMembers)
.filter(m => m.roles.includes(roleId))
.map(m => ({
...m,
user: UserStore.getUser(m.userId)
}))
.sort((a, b) => a.user.username.localeCompare(b.user.username));
}
export default definePlugin({
name: "RoleMembersViewer",
description: "Shows members with a role when right clicking roles in user profiles or role mentions in messages",
authors: [EquicordDevs.okiso],
contextMenus: {
"dev-context"(children, { id }: { id: string; }) {
const guild = GuildStore.getGuild(SelectedGuildStore.getGuildId());
if (!guild) return;
const role = GuildStore.getRole(guild.id, id);
if (!role) return;
const guildId = guild.id;
const membersWithRole = fetchMembersWithRole(guildId, id);
const memberItems = membersWithRole.map(member => (
<Menu.MenuItem
key={member.userId}
id={`role-member-${member.userId}`}
label={member.user.username}
action={() => {
UserProfileActions.openUserProfileModal({
userId: member.userId,
guildId,
channelId: SelectedChannelStore.getChannelId()
});
}}
/>
));
children.push(
<Menu.MenuItem
id="role-members-viewer"
label={`View Members (${role.name}) - ${membersWithRole.length}`}
>
<Menu.MenuGroup>{memberItems}</Menu.MenuGroup>
</Menu.MenuItem>
);
},
"message"(children, { message }: { message: any; }) {
const guild = GuildStore.getGuild(SelectedGuildStore.getGuildId());
if (!guild) return;
const roleMentions = message.content.match(/<@&(\d+)>/g);
if (!roleMentions?.length) return;
// Extract unique role IDs from the mentions.
const roleIds = roleMentions.map(mention => mention.match(/<@&(\d+)>/)![1]);
const uniqueRoleIds = [...new Set(roleIds)];
const guildId = guild.id;
const roleMenuItems: JSX.Element[] = [];
for (const roleId of uniqueRoleIds as string[]) {
const role = GuildStore.getRole(guildId, roleId);
if (!role) continue;
const membersWithRole = fetchMembersWithRole(guildId, roleId);
const memberItems = membersWithRole.map(member => (
<Menu.MenuItem
key={member.userId}
id={`role-member-${member.userId}`}
label={member.user?.username ?? "Unknown User"}
action={() => {
UserProfileActions.openUserProfileModal({
userId: member.userId,
guildId,
channelId: SelectedChannelStore.getChannelId()
});
}}
/>
));
roleMenuItems.push(
<Menu.MenuItem
id={`role-members-viewer-${roleId}`}
label={`@${role.name} - ${membersWithRole.length}`}
>
<Menu.MenuGroup>{memberItems}</Menu.MenuGroup>
</Menu.MenuItem>
);
}
if (roleMenuItems.length > 0) {
children.push(
<Menu.MenuItem
id="role-members-viewer"
label={`View Role Members (${roleMenuItems.length} roles)`}
>
<Menu.MenuGroup>{roleMenuItems}</Menu.MenuGroup>
</Menu.MenuItem>
);
}
}
}
});

View file

@ -1000,6 +1000,10 @@ export const EquicordDevs = Object.freeze({
name: "mochie", name: "mochie",
id: 1043599230247374869n, id: 1043599230247374869n,
}, },
okiso: {
name: "okiso",
id: 274178934143451137n,
},
} satisfies Record<string, Dev>); } satisfies Record<string, Dev>);
// iife so #__PURE__ works correctly // iife so #__PURE__ works correctly