Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
thororen1234 2026-07-02 13:34:40 -04:00
commit bf376f9bbd
No known key found for this signature in database
15 changed files with 1117 additions and 1908 deletions

View file

@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6

View file

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
fetch-depth: 0
@ -79,7 +79,8 @@ jobs:
- name: Create sources zip
if: steps.check.outputs.release == 'true'
run: zip -r dist/extension-sources.zip . -x "node_modules/*" -x "dist/*" -x
run:
zip -r dist/extension-sources.zip . -x "node_modules/*" -x "dist/*" -x
".git/*"
- name: Publish extension

View file

@ -12,7 +12,8 @@ on:
default: both
webhook_url:
type: string
description: "Webhook URL that the report will be posted to. This will be
description:
"Webhook URL that the report will be posted to. This will be
visible for everyone, so DO NOT pass sensitive webhooks like
discord webhook. This is meant to be used by Equibot."
required: false
@ -29,11 +30,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
ref: ${{ github.event_name == 'schedule' && 'dev' || github.ref }}
- uses: pnpm/action-setup@v6 # Install pnpm using packageManager key in package.json
- uses: pnpm/action-setup@v6
- name: Use Node.js 24
uses: actions/setup-node@v6

View file

@ -15,8 +15,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6 # Install pnpm using packageManager key in package.json
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
- name: Use Node.js 24
uses: actions/setup-node@v6

2
.npmrc
View file

@ -1,2 +0,0 @@
strict-peer-dependencies=false
package-manager-strict=false

View file

@ -52,13 +52,13 @@
"@types/tinycolor2": "^1.4.6",
"@vap/core": "0.0.12",
"@vap/shiki": "0.10.5",
"fflate": "^0.8.2",
"fflate": "^0.8.3",
"gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3",
"gifuct-js": "^2.1.2",
"idb": "8.0.3",
"jsqr": "1.4.0",
"monaco-editor": "^0.55.1",
"nanoid": "^5.1.6",
"nanoid": "^5.1.16",
"native-file-system-adapter": "^3.0.1",
"usercss-meta": "^0.12.0",
"virtual-merge": "^1.0.1",
@ -67,16 +67,16 @@
"devDependencies": {
"@electron/asar": "^4.2.0",
"@stylistic/eslint-plugin": "^5.10.0",
"@types/chrome": "^0.1.40",
"@types/chrome": "^0.2.0",
"@types/lodash": "^4.17.24",
"@types/node": "^25.6.0",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@types/node": "^26.0.1",
"@types/react": "19.1.0",
"@types/react-dom": "19.1.0",
"@types/yazl": "^3.3.1",
"@vencord/discord-types": "link:packages/discord-types",
"diff": "^9.0.0",
"esbuild": "^0.28.0",
"eslint": "10.2.0",
"esbuild": "^0.28.1",
"eslint": "10.6.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-simple-header": "^1.2.1",
@ -86,22 +86,22 @@
"html-minifier-terser": "^7.2.0",
"moment": "^2.22.2",
"p-limit": "^7.3.0",
"puppeteer-core": "^24.41.0",
"puppeteer-core": "^25.2.1",
"standalone-electron-types": "^41.2.1",
"stylelint": "^17.8.0",
"stylelint": "^17.14.0",
"stylelint-config-standard": "^40.0.0",
"svgo": "^4.0.1",
"ts-patch": "^3.3.0",
"ts-pattern": "^5.9.0",
"tsx": "^4.21.0",
"type-fest": "^5.5.0",
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.2",
"tsx": "^4.22.4",
"type-fest": "^5.7.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.62.1",
"typescript-transform-paths": "^3.5.6",
"zip-local": "^0.3.5"
},
"packageManager": "pnpm@11.8.0",
"packageManager": "pnpm@11.9.0",
"engines": {
"node": ">=18"
"node": ">=22"
}
}

View file

@ -13,10 +13,10 @@
"directory": "packages/discord-types"
},
"dependencies": {
"moment": "^2.22.2",
"type-fest": "^4.41.0"
"moment": "2.22.2",
"type-fest": "^5.7.0"
},
"peerDependencies": {
"@types/react": "^19.0.10"
"@types/react": "19.1.0"
}
}

View file

@ -1,7 +1,7 @@
{
"name": "@equicord/types",
"private": false,
"version": "1.14.2",
"version": "1.14.15",
"description": "",
"types": "index.d.ts",
"scripts": {
@ -10,23 +10,23 @@
},
"keywords": [],
"author": "Equicord & Vencord Contributors",
"license": "GPL-3.0",
"license": "GPL-3.0-or-later",
"devDependencies": {
"@types/fs-extra": "^11.0.4",
"fs-extra": "^11.3.0",
"tsx": "^4.19.2"
"fs-extra": "^11.3.6",
"tsx": "^4.22.4"
},
"dependencies": {
"@types/lodash": "4.17.15",
"@types/node": "^22.13.4",
"@vencord/discord-types": "^1.0.0",
"@types/lodash": "4.17.19",
"@types/node": "^26.0.1",
"@vencord/discord-types": "^1.0.1",
"highlight.js": "11.11.1",
"moment": "^2.22.2",
"ts-pattern": "^5.6.0",
"type-fest": "^4.35.0"
"type-fest": "^5.7.0"
},
"peerDependencies": {
"@types/react": "^19.0.10",
"@types/react-dom": "19.0.4"
}
}
}

2504
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,25 +1,19 @@
packages:
- packages/*
allowBuilds:
esbuild: true
overrides:
"@eslint/plugin-kit@<0.3.4": ">=0.3.4"
patchedDependencies:
"@types/less@3.0.8": patches/@types__less@3.0.8.patch
peerDependencyRules:
ignoreMissing:
- eslint-plugin-import
- eslint
allowedDeprecatedVersions:
source-map-resolve: "*"
resolve-url: "*"
source-map-url: "*"
urix: "*"
q: "*"
strictPeerDependencies: false
allowBuilds:
esbuild: true
pmOnFail: warn
verifyDepsBeforeRun: prompt

View file

@ -17,7 +17,7 @@
*/
import { Logger } from "@utils/Logger";
import type { Channel, CloudUpload, CustomEmoji, Message } from "@vencord/discord-types";
import type { Channel, CustomEmoji, Message } from "@vencord/discord-types";
import { MessageStore } from "@webpack/common";
import type { Promisable } from "type-fest";
@ -30,37 +30,40 @@ export interface MessageObject {
tts: boolean;
}
export interface MessageReplyOptions {
messageReference: Message["messageReference"];
export interface SendMessageOptions {
messageReference?: Message["messageReference"];
allowedMentions?: {
parse: Array<string>;
users?: Array<string>;
roles?: Array<string>;
parse: string[];
repliedUser: boolean;
};
location: string;
stickerIds?: string[];
alsoForwardToChannelId?: string;
// If you end up using these, update their type
scheduledTimestamp?: unknown;
mediaMention?: unknown;
}
export interface MessageOptions {
stickers?: string[];
uploads?: CloudUpload[];
replyOptions: MessageReplyOptions;
export interface SendMessageProps {
hasStickers: boolean;
hasAttachments: boolean;
content: string;
channel: Channel;
type?: any;
openWarningPopout: (props: any) => any;
}
export type MessageSendListener = (channelId: string, messageObj: MessageObject, options: MessageOptions) => Promisable<void | { cancel: boolean; }>;
export type MessageSendListener = (channelId: string, messageObj: MessageObject, options: SendMessageOptions, props: SendMessageProps) => Promisable<void | { cancel: boolean; }>;
export type MessageEditListener = (channelId: string, messageId: string, messageObj: MessageObject) => Promisable<void | { cancel: boolean; }>;
const sendListeners = new Set<MessageSendListener>();
const editListeners = new Set<MessageEditListener>();
export async function _handlePreSend(channelId: string, messageObj: MessageObject, options: MessageOptions, replyOptions: MessageReplyOptions) {
options.replyOptions = replyOptions;
export async function _handlePreSend(channelId: string, messageObj: MessageObject, options: SendMessageOptions, props: SendMessageProps) {
for (const listener of sendListeners) {
try {
const result = await listener(channelId, messageObj, options);
const result = await listener(channelId, messageObj, options, props);
if (result?.cancel) {
return true;
}

View file

@ -49,7 +49,7 @@ async function calculateGitChanges() {
return data.commits.map((c: any) => ({
hash: c.sha,
author: c.author?.login ?? c.commit?.author?.name ?? "Ghost",
author: c.author?.login ?? c.commit?.author?.name ?? "Unknown Author",
message: c.commit.message.split("\n")[0]
}));
}

View file

@ -39,8 +39,8 @@ export default definePlugin({
replacement: {
// https://regex101.com/r/7iswuk/1
match: /let (\i)=\i\.\i\.parse\((\i),.+?\.getSendMessageOptions\(\{.+?\}\)?;(?=.+?(\i)\.flags=)(?<=\)\(({.+?})\)\.then.+?)/,
replace: (m, parsedMessage, channel, replyOptions, extra) => m +
`if(await Vencord.Api.MessageEvents._handlePreSend(${channel}.id,${parsedMessage},${extra},${replyOptions}))` +
replace: (m, parsedMessage, channel, options, props) => m +
`if(await Vencord.Api.MessageEvents._handlePreSend(${channel}.id,${parsedMessage},${options},${props}))` +
"return{shouldClear:false,shouldRefocus:true};"
}
},

View file

@ -827,7 +827,7 @@ export default definePlugin({
return;
}
this.preSend = addMessagePreSendListener(async (channelId, messageObj, extra) => {
this.preSend = addMessagePreSendListener(async (channelId, messageObj, options) => {
const { guildId } = this;
let hasBypass = false;
@ -836,7 +836,7 @@ export default definePlugin({
if (!s.enableStickerBypass)
break stickerBypass;
const sticker = StickersStore.getStickerById(extra.stickers?.[0]!);
const sticker = StickersStore.getStickerById(options.stickerIds?.[0]!);
if (!sticker)
break stickerBypass;
@ -882,7 +882,7 @@ export default definePlugin({
const linkText = s.hyperLinkText.replaceAll("{{NAME}}", sticker.name);
messageObj.content += `${getWordBoundary(messageObj.content, messageObj.content.length - 1)}${s.useStickerHyperLinks ? `[${linkText}](${url})` : url}`;
extra.stickers!.length = 0;
options.stickerIds!.length = 0;
}
}

View file

@ -18,201 +18,203 @@
* You should have received a copy of the GNU General Public License
* along with AdGuard's Block YouTube Ads. If not, see <http://www.gnu.org/licenses/>.
*/
(() => {
if (window.adguardInjected) return;
window.adguardInjected = true;
const hiddenCSS = [
"#__ffYoutube1",
"#__ffYoutube2",
"#__ffYoutube3",
"#__ffYoutube4",
"#feed-pyv-container",
"#feedmodule-PRO",
"#homepage-chrome-side-promo",
"#merch-shelf",
"#offer-module",
'#pla-shelf > ytd-pla-shelf-renderer[class="style-scope ytd-watch"]',
"#pla-shelf",
"#premium-yva",
"#promo-info",
"#promo-list",
"#promotion-shelf",
"#related > ytd-watch-next-secondary-results-renderer > #items > ytd-compact-promoted-video-renderer.ytd-watch-next-secondary-results-renderer",
"#search-pva",
"#shelf-pyv-container",
"#video-masthead",
"#watch-branded-actions",
"#watch-buy-urls",
"#watch-channel-brand-div",
"#watch7-branded-banner",
"#YtKevlarVisibilityIdentifier",
"#YtSparklesVisibilityIdentifier",
".carousel-offer-url-container",
".companion-ad-container",
".GoogleActiveViewElement",
'.list-view[style="margin: 7px 0pt;"]',
".promoted-sparkles-text-search-root-container",
".promoted-videos",
".searchView.list-view",
".sparkles-light-cta",
".watch-extra-info-column",
".watch-extra-info-right",
".ytd-carousel-ad-renderer",
".ytd-compact-promoted-video-renderer",
".ytd-companion-slot-renderer",
".ytd-merch-shelf-renderer",
".ytd-player-legacy-desktop-watch-ads-renderer",
".ytd-promoted-sparkles-text-search-renderer",
".ytd-promoted-video-renderer",
".ytd-search-pyv-renderer",
".ytd-video-masthead-ad-v3-renderer",
".ytp-ad-action-interstitial-background-container",
".ytp-ad-action-interstitial-slot",
".ytp-ad-image-overlay",
".ytp-ad-overlay-container",
".ytp-ad-progress",
".ytp-ad-progress-list",
'[class*="ytd-display-ad-"]',
'[layout*="display-ad-"]',
'a[href^="http://www.youtube.com/cthru?"]',
'a[href^="https://www.youtube.com/cthru?"]',
"ytd-action-companion-ad-renderer",
"ytd-banner-promo-renderer",
"ytd-compact-promoted-video-renderer",
"ytd-companion-slot-renderer",
"ytd-display-ad-renderer",
"ytd-promoted-sparkles-text-search-renderer",
"ytd-promoted-sparkles-web-renderer",
"ytd-search-pyv-renderer",
"ytd-single-option-survey-renderer",
"ytd-video-masthead-ad-advertiser-info-renderer",
"ytd-video-masthead-ad-v3-renderer",
"YTM-PROMOTED-VIDEO-RENDERER",
];
/**
* Adds CSS to the page
*/
const hideElements = () => {
const selectors = hiddenCSS;
if (!selectors) {
return;
}
const rule = selectors.join(", ") + " { display: none!important; }";
const style = document.createElement("style");
style.textContent = rule;
document.head.appendChild(style);
};
/**
* Calls the "callback" function on every DOM change, but not for the tracked events
* @param {Function} callback callback function
*/
const observeDomChanges = callback => {
const domMutationObserver = new MutationObserver(mutations => {
callback(mutations);
});
domMutationObserver.observe(document.documentElement, {
childList: true,
subtree: true,
});
};
/**
* This function is supposed to be called on every DOM change
*/
const hideDynamicAds = () => {
const elements = document.querySelectorAll("#contents > ytd-rich-item-renderer ytd-display-ad-renderer");
if (elements.length === 0) {
return;
}
elements.forEach(el => {
if (el.parentNode && el.parentNode.parentNode) {
const parent = el.parentNode.parentNode;
if (parent.localName === "ytd-rich-item-renderer") {
parent.style.display = "none";
}
const hiddenCSS = [
"#__ffYoutube1",
"#__ffYoutube2",
"#__ffYoutube3",
"#__ffYoutube4",
"#feed-pyv-container",
"#feedmodule-PRO",
"#homepage-chrome-side-promo",
"#merch-shelf",
"#offer-module",
'#pla-shelf > ytd-pla-shelf-renderer[class="style-scope ytd-watch"]',
"#pla-shelf",
"#premium-yva",
"#promo-info",
"#promo-list",
"#promotion-shelf",
"#related > ytd-watch-next-secondary-results-renderer > #items > ytd-compact-promoted-video-renderer.ytd-watch-next-secondary-results-renderer",
"#search-pva",
"#shelf-pyv-container",
"#video-masthead",
"#watch-branded-actions",
"#watch-buy-urls",
"#watch-channel-brand-div",
"#watch7-branded-banner",
"#YtKevlarVisibilityIdentifier",
"#YtSparklesVisibilityIdentifier",
".carousel-offer-url-container",
".companion-ad-container",
".GoogleActiveViewElement",
'.list-view[style="margin: 7px 0pt;"]',
".promoted-sparkles-text-search-root-container",
".promoted-videos",
".searchView.list-view",
".sparkles-light-cta",
".watch-extra-info-column",
".watch-extra-info-right",
".ytd-carousel-ad-renderer",
".ytd-compact-promoted-video-renderer",
".ytd-companion-slot-renderer",
".ytd-merch-shelf-renderer",
".ytd-player-legacy-desktop-watch-ads-renderer",
".ytd-promoted-sparkles-text-search-renderer",
".ytd-promoted-video-renderer",
".ytd-search-pyv-renderer",
".ytd-video-masthead-ad-v3-renderer",
".ytp-ad-action-interstitial-background-container",
".ytp-ad-action-interstitial-slot",
".ytp-ad-image-overlay",
".ytp-ad-overlay-container",
".ytp-ad-progress",
".ytp-ad-progress-list",
'[class*="ytd-display-ad-"]',
'[layout*="display-ad-"]',
'a[href^="http://www.youtube.com/cthru?"]',
'a[href^="https://www.youtube.com/cthru?"]',
"ytd-action-companion-ad-renderer",
"ytd-banner-promo-renderer",
"ytd-compact-promoted-video-renderer",
"ytd-companion-slot-renderer",
"ytd-display-ad-renderer",
"ytd-promoted-sparkles-text-search-renderer",
"ytd-promoted-sparkles-web-renderer",
"ytd-search-pyv-renderer",
"ytd-single-option-survey-renderer",
"ytd-video-masthead-ad-advertiser-info-renderer",
"ytd-video-masthead-ad-v3-renderer",
"YTM-PROMOTED-VIDEO-RENDERER",
];
/**
* Adds CSS to the page
*/
const hideElements = () => {
const selectors = hiddenCSS;
if (!selectors) {
return;
}
});
};
/**
* This function checks if the video ads are currently running
* and auto-clicks the skip button.
*/
const autoSkipAds = () => {
// If there's a video that plays the ad at this moment, scroll this ad
if (document.querySelector(".ad-showing")) {
const video = document.querySelector("video");
if (video && video.duration) {
video.currentTime = video.duration;
// Skip button should appear after that,
// now simply click it automatically
setTimeout(() => {
const skipBtn = document.querySelector("button.ytp-ad-skip-button");
if (skipBtn) {
skipBtn.click();
}
}, 100);
}
}
};
/**
* This function overrides a property on the specified object.
*
* @param {object} obj object to look for properties in
* @param {string} propertyName property to override
* @param {*} overrideValue value to set
*/
const overrideObject = (obj, propertyName, overrideValue) => {
if (!obj) {
return false;
}
let overriden = false;
for (const key in obj) {
if (obj.hasOwnProperty(key) && key === propertyName) {
obj[key] = overrideValue;
overriden = true;
} else if (obj.hasOwnProperty(key) && typeof obj[key] === "object") {
if (overrideObject(obj[key], propertyName, overrideValue)) {
overriden = true;
}
}
}
return overriden;
};
/**
* Overrides JSON.parse and Response.json functions.
* Examines these functions arguments, looks for properties with the specified name there
* and if it exists, changes it's value to what was specified.
*
* @param {string} propertyName name of the property
* @param {*} overrideValue new value for the property
*/
const jsonOverride = (propertyName, overrideValue) => {
const nativeJSONParse = JSON.parse;
JSON.parse = (...args) => {
const obj = nativeJSONParse.apply(this, args);
// Override it's props and return back to the caller
overrideObject(obj, propertyName, overrideValue);
return obj;
const rule = selectors.join(", ") + " { display: none!important; }";
const style = document.createElement("style");
style.textContent = rule;
document.head.appendChild(style);
};
// Override Response.prototype.json
Response.prototype.json = new Proxy(Response.prototype.json, {
async apply(...args) {
// Call the target function, get the original Promise
const result = await Reflect.apply(...args);
// Create a new one and override the JSON inside
overrideObject(result, propertyName, overrideValue);
return result;
},
});
};
// Removes ads metadata from YouTube XHR requests
jsonOverride("adPlacements", []);
jsonOverride("playerAds", []);
// Applies CSS that hides YouTube ad elements
hideElements();
// Some changes should be re-evaluated on every page change
hideDynamicAds();
autoSkipAds();
observeDomChanges(() => {
/**
* Calls the "callback" function on every DOM change, but not for the tracked events
* @param {Function} callback callback function
*/
const observeDomChanges = callback => {
const domMutationObserver = new MutationObserver(mutations => {
callback(mutations);
});
domMutationObserver.observe(document.documentElement, {
childList: true,
subtree: true,
});
};
/**
* This function is supposed to be called on every DOM change
*/
const hideDynamicAds = () => {
const elements = document.querySelectorAll("#contents > ytd-rich-item-renderer ytd-display-ad-renderer");
if (elements.length === 0) {
return;
}
elements.forEach(el => {
if (el.parentNode && el.parentNode.parentNode) {
const parent = el.parentNode.parentNode;
if (parent.localName === "ytd-rich-item-renderer") {
parent.style.display = "none";
}
}
});
};
/**
* This function checks if the video ads are currently running
* and auto-clicks the skip button.
*/
const autoSkipAds = () => {
// If there's a video that plays the ad at this moment, scroll this ad
if (document.querySelector(".ad-showing")) {
const video = document.querySelector("video");
if (video && video.duration) {
video.currentTime = video.duration;
// Skip button should appear after that,
// now simply click it automatically
setTimeout(() => {
const skipBtn = document.querySelector("button.ytp-ad-skip-button");
if (skipBtn) {
skipBtn.click();
}
}, 100);
}
}
};
/**
* This function overrides a property on the specified object.
*
* @param {object} obj object to look for properties in
* @param {string} propertyName property to override
* @param {*} overrideValue value to set
*/
const overrideObject = (obj, propertyName, overrideValue) => {
if (!obj) {
return false;
}
let overriden = false;
for (const key in obj) {
if (obj.hasOwnProperty(key) && key === propertyName) {
obj[key] = overrideValue;
overriden = true;
} else if (obj.hasOwnProperty(key) && typeof obj[key] === "object") {
if (overrideObject(obj[key], propertyName, overrideValue)) {
overriden = true;
}
}
}
return overriden;
};
/**
* Overrides JSON.parse and Response.json functions.
* Examines these functions arguments, looks for properties with the specified name there
* and if it exists, changes it's value to what was specified.
*
* @param {string} propertyName name of the property
* @param {*} overrideValue new value for the property
*/
const jsonOverride = (propertyName, overrideValue) => {
const nativeJSONParse = JSON.parse;
JSON.parse = (...args) => {
const obj = nativeJSONParse.apply(this, args);
// Override it's props and return back to the caller
overrideObject(obj, propertyName, overrideValue);
return obj;
};
// Override Response.prototype.json
Response.prototype.json = new Proxy(Response.prototype.json, {
async apply(...args) {
// Call the target function, get the original Promise
const result = await Reflect.apply(...args);
// Create a new one and override the JSON inside
overrideObject(result, propertyName, overrideValue);
return result;
},
});
};
// Removes ads metadata from YouTube XHR requests
jsonOverride("adPlacements", []);
jsonOverride("playerAds", []);
// Applies CSS that hides YouTube ad elements
hideElements();
// Some changes should be re-evaluated on every page change
hideDynamicAds();
autoSkipAds();
});
observeDomChanges(() => {
hideDynamicAds();
autoSkipAds();
});
})();