Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
feat(plugins): a bunch of plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
verticalsync committed Apr 18, 2024
1 parent d6340b0 commit be163bc
Show file tree
Hide file tree
Showing 9 changed files with 469 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ Visit [1_INSTALLING.md](/docs/1_INSTALLING.md)
- CopyEmojiAsFormattedString (by [happyendermangit](https://github.com/happyendermangit/) and [vishnyanetchereshnya](https://github.com/vishnyanetchereshnya)) (added from vishnyanetchereshnya's [pull request](https://github.com/Vendicated/Vencord/pull/2266))
- HolyNotes (by [Wolfie](https://github.com/WolfPlugs/VencordPlugins))
- CopyUserMention (by [Cortex](https://github.com/verysillycat))
- VoiceDownload (by [puv](https://github.com/puv)) (added from puv's [pull request](https://github.com/Vendicated/Vencord/pull/2280))
- MessageLatency (by [arHSM](https://github.com/arHSM)) (added from arHSM's [pull request](https://github.com/Vendicated/Vencord/pull/2353))
- ValidReply (by [waresnew](https://github.com/waresnew)) (added from waresnew's [pull request](https://github.com/Vendicated/Vencord/pull/2337))
- ModViewBypass (by [Sqaaakoi](https://github.com/Sqaaakoi)) (added from Sqaaakoi's [pull request](https://github.com/Vendicated/Vencord/pull/2220))
- HideChatButtons (by [programminglaboratorys](https://github.com/programminglaboratorys/Vencord/blob/fun/src/plugins/hideChatButtons))

## Disclaimer

Expand Down
99 changes: 99 additions & 0 deletions src/suncordplugins/hideChatButtons/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import { ChatBarButton } from "@api/ChatButtons";
import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType,StartAt } from "@utils/types";
import { useMemo,useState } from "@webpack/common";
import { MouseEventHandler, ReactNode } from "react";

let hidechatbuttonsopen: boolean | undefined;

const settings = definePluginSettings({
Color: {
type: OptionType.BOOLEAN,
description: "Color it red on open", // something extra
default: false,
},
Open: {
type: OptionType.BOOLEAN,
description: "opened by default",
default: false,
onChange: (store: { open: boolean; }) => {
console.log("changing open", store.open);
hidechatbuttonsopen = store.open;
}
},
});

// id={"menu-button-" + (props.open ? "close" : "open")}
function HideToggleButton(props: { open: boolean | undefined, onClick: MouseEventHandler<HTMLButtonElement>; }) {
console.log(props.open);
return (<ChatBarButton
onClick={props.onClick}
tooltip={props.open ? "Close" : "Open"}
>
<svg
fill={settings.store.Color && props.open ? "#c32a32" : "currentColor"}
fillRule="evenodd"
width="24"
height="24"
viewBox="0 0 24 24"
style={{ scale: "1.096", translate: "0 -1px" }}
>
{props.open ?
<><path d="M1.3 21.3a1 1 0 1 0 1.4 1.4l20-20a1 1 0 0 0-1.4-1.4l-20 20ZM3.16 16.05c.18.24.53.26.74.05l.72-.72c.18-.18.2-.45.05-.66a15.7 15.7 0 0 1-1.43-2.52.48.48 0 0 1 0-.4c.4-.9 1.18-2.37 2.37-3.72C7.13 6.38 9.2 5 12 5c.82 0 1.58.12 2.28.33.18.05.38 0 .52-.13l.8-.8c.25-.25.18-.67-.15-.79A9.79 9.79 0 0 0 12 3C4.89 3 1.73 10.11 1.11 11.7a.83.83 0 0 0 0 .6c.25.64.9 2.15 2.05 3.75Z"></path><path d="M8.18 10.81c-.13.43.36.65.67.34l2.3-2.3c.31-.31.09-.8-.34-.67a4 4 0 0 0-2.63 2.63ZM12.85 15.15c-.31.31-.09.8.34.67a4.01 4.01 0 0 0 2.63-2.63c.13-.43-.36-.65-.67-.34l-2.3 2.3Z"></path> <path d="M9.72 18.67a.52.52 0 0 0-.52.13l-.8.8c-.25.25-.18.67.15.79 1.03.38 2.18.61 3.45.61 7.11 0 10.27-7.11 10.89-8.7a.83.83 0 0 0 0-.6c-.25-.64-.9-2.15-2.05-3.75a.49.49 0 0 0-.74-.05l-.72.72a.51.51 0 0 0-.05.66 15.7 15.7 0 0 1 1.43 2.52c.06.13.06.27 0 .4-.4.9-1.18 2.37-2.37 3.72C16.87 17.62 14.8 19 12 19c-.82 0-1.58-.12-2.28-.33Z"></path></> :
<path d="M22.89 11.7c.07.2.07.4 0 .6C22.27 13.9 19.1 21 12 21c-7.11 0-10.27-7.11-10.89-8.7a.83.83 0 0 1 0-.6C1.73 10.1 4.9 3 12 3c7.11 0 10.27 7.11 10.89 8.7Zm-4.5-3.62A15.11 15.11 0 0 1 20.85 12c-.38.88-1.18 2.47-2.46 3.92C16.87 17.62 14.8 19 12 19c-2.8 0-4.87-1.38-6.39-3.08A15.11 15.11 0 0 1 3.15 12c.38-.88 1.18-2.47 2.46-3.92C7.13 6.38 9.2 5 12 5c2.8 0 4.87 1.38 6.39 3.08ZM15.56 11.77c.2-.1.44.02.44.23a4 4 0 1 1-4-4c.21 0 .33.25.23.44a2.5 2.5 0 0 0 3.32 3.32Z" />
}
</svg>
</ChatBarButton>);
}
function buttonsInner(buttons: ReactNode[]) {
const [open, setOpen] = useState(hidechatbuttonsopen);
useMemo(() => {
console.log("useMemo: changing open", open);
hidechatbuttonsopen = open;
}, [open]);

const buttonList = (
<div id="chat-bar-buttons-menu" style={{
display: "flex",
flexWrap: "nowrap",
overflowX: "auto"
}}>
{open && buttons.map((button, _) => (
// console.log(button, index),
<>
{button}
</>
))}
<HideToggleButton onClick={() => setOpen(!open)} open={open}></HideToggleButton>
</div>
);
buttons = [buttonList];
return buttons;
}


export default definePlugin({
name: "hideChatButtons",
description: "able to hide the chat buttons",
settings: settings,
authors: [Devs.iamme],
patches: [
{
find: ".default.getRecipientEligibility",
replacement: {
match: /(.buttons,children:)(\i)\}/,
replace: "$1$self.buttonsInner($2)}"
}
}
],
startAt: StartAt.Init,
buttonsInner: buttonsInner,
start: async () => { hidechatbuttonsopen = settings.store.Open; }
});
30 changes: 30 additions & 0 deletions src/suncordplugins/messageLatency/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# MessageLatency

Displays an indicator for messages that took ≥n seconds to send.

> **NOTE**
>
> - This plugin only applies to messages received after opening the channel
> - False positives can exist if the user's system clock has drifted.
> - Grouped messages only display latency of the first message
## Demo

### Chat View

![chat-view](https://github.com/Vendicated/Vencord/assets/82430093/69430881-60b3-422f-aa3d-c62953837566)

### Clock -ve Drift

![pissbot-on-top](https://github.com/Vendicated/Vencord/assets/82430093/d9248b66-e761-4872-8829-e8bf4fea6ec8)

### Clock +ve Drift

![dumb-ai](https://github.com/Vendicated/Vencord/assets/82430093/0e9783cf-51d5-4559-ae10-42399e7d4099)

### Connection Delay

![who-this](https://github.com/Vendicated/Vencord/assets/82430093/fd68873d-8630-42cc-a166-e9063d2718b2)

### Icons

![icons](https://github.com/Vendicated/Vencord/assets/82430093/17630bd9-44ee-4967-bcdf-3315eb6eca85)
147 changes: 147 additions & 0 deletions src/suncordplugins/messageLatency/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import { isNonNullish } from "@utils/guards";
import definePlugin, { OptionType } from "@utils/types";
import { waitFor } from "@webpack";
import { SnowflakeUtils, Tooltip } from "@webpack/common";
import { Message } from "discord-types/general";

type FillValue = ("status-danger" | "status-warning" | "text-muted");
type Fill = [FillValue, FillValue, FillValue];
type DiffKey = keyof Diff;

interface Diff {
days: number,
hours: number,
minutes: number,
seconds: number;
}

let HiddenVisually;
waitFor("HiddenVisually", mod => {
HiddenVisually = mod.HiddenVisually;
});

export default definePlugin({
name: "MessageLatency",
description: "Displays an indicator for messages that took ≥n seconds to send",
authors: [Devs.arHSM],
settings: definePluginSettings({
latency: {
type: OptionType.NUMBER,
description: "Threshold in seconds for latency indicator",
default: 2
}
}),
patches: [
{
find: "showCommunicationDisabledStyles",
replacement: {
match: /(message:(\i),avatar:\i,username:\(0,\i.jsxs\)\(\i.Fragment,\{children:\[)(\i&&)/,
replace: "$1$self.Tooltip($2),$3"
}
}
],
stringDelta(delta: number) {
const diff: Diff = {
days: Math.round(delta / (60 * 60 * 24)),
hours: Math.round((delta / (60 * 60)) % 24),
minutes: Math.round((delta / (60)) % 60),
seconds: Math.round(delta % 60),
};

const str = (k: DiffKey) => diff[k] > 0 ? `${diff[k]} ${k}` : null;
const keys: DiffKey[] = ["days", "hours", "minutes", "seconds"];

return keys.map(str).filter(isNonNullish).join(" ");
},
latencyTooltipData(message: Message) {
const { id, nonce } = message;

// Message wasn't received through gateway
if (!isNonNullish(nonce)) return null;

const delta = Math.round((SnowflakeUtils.extractTimestamp(id) - SnowflakeUtils.extractTimestamp(nonce)) / 1000);

// Thanks dziurwa (I hate you)
// This is when the user's clock is ahead
// Can't do anything if the clock is behind
const abs = Math.abs(delta);
const ahead = abs !== delta;

const stringDelta = this.stringDelta(abs);

// Also thanks dziurwa
// 2 minutes
const TROLL_LIMIT = 2 * 60;
const { latency } = this.settings.store;

const fill: Fill = delta >= TROLL_LIMIT || ahead ? ["text-muted", "text-muted", "text-muted"] : delta >= (latency * 2) ? ["status-danger", "text-muted", "text-muted"] : ["status-warning", "status-warning", "text-muted"];

return abs >= latency ? { delta: stringDelta, ahead: abs !== delta, fill } : null;
},
Tooltip(message: Message) {

const d = this.latencyTooltipData(message);

if (!isNonNullish(d)) return null;

return <Tooltip
text={d.ahead ? `This user's clock is ${d.delta} ahead` : `This message was sent with a delay of ${d.delta}.`}
position="top"
>
{
props => <>
{<this.Icon delta={d.delta} fill={d.fill} props={props} />}
{/* Time Out indicator uses this, I think this is for a11y */}
<HiddenVisually>Delayed Message</HiddenVisually>
</>
}
</Tooltip>;
},
Icon({ delta, fill, props }: {
delta: string;
fill: Fill,
props: {
onClick(): void;
onMouseEnter(): void;
onMouseLeave(): void;
onContextMenu(): void;
onFocus(): void;
onBlur(): void;
"aria-label"?: string;
};
}) {
return <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="12"
height="12"
role="img"
fill="none"
style={{ marginRight: "8px", verticalAlign: -1 }}
aria-label={delta}
aria-hidden="false"
{...props}
>
<path
fill={`var(--${fill[0]})`}
d="M4.8001 12C4.8001 11.5576 4.51344 11.2 4.16023 11.2H2.23997C1.88676 11.2 1.6001 11.5576 1.6001 12V13.6C1.6001 14.0424 1.88676 14.4 2.23997 14.4H4.15959C4.5128 14.4 4.79946 14.0424 4.79946 13.6L4.8001 12Z"
/>
<path
fill={`var(--${fill[1]})`}
d="M9.6001 7.12724C9.6001 6.72504 9.31337 6.39998 8.9601 6.39998H7.0401C6.68684 6.39998 6.40011 6.72504 6.40011 7.12724V13.6727C6.40011 14.0749 6.68684 14.4 7.0401 14.4H8.9601C9.31337 14.4 9.6001 14.0749 9.6001 13.6727V7.12724Z"
/>
<path
fill={`var(--${fill[2]})`}
d="M14.4001 2.31109C14.4001 1.91784 14.1134 1.59998 13.7601 1.59998H11.8401C11.4868 1.59998 11.2001 1.91784 11.2001 2.31109V13.6888C11.2001 14.0821 11.4868 14.4 11.8401 14.4H13.7601C14.1134 14.4 14.4001 14.0821 14.4001 13.6888V2.31109Z"
/>
</svg>;
}
});
27 changes: 27 additions & 0 deletions src/suncordplugins/modViewBypass/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";

export default definePlugin({
name: "ModViewBypass",
description: "Open the mod view sidebar in guilds you don't have moderator permissions in.",
authors: [Devs.Sqaaakoi],
patches: [
"useCanAccessGuildMemberModView",
// these can probably be removed safely now and revert to the regular patch style
"canAccessGuildMemberModViewWithExperiment",
"isInGuildMemberModViewExperiment",
"useGuildMemberModViewExperiment",
].map(f => ({
find: `${f}:`,
replacement: {
match: new RegExp(`(${f}:function\\(\\){return\\s)\\i`),
replace: "$1()=>true;",
}
}))
});
Loading

0 comments on commit be163bc

Please sign in to comment.