diff --git a/src/plugins/Timezones/Utils.ts b/src/plugins/Timezones/Utils.ts new file mode 100644 index 000000000..576e7b878 --- /dev/null +++ b/src/plugins/Timezones/Utils.ts @@ -0,0 +1,57 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2022 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import { findByPropsLazy } from "@webpack"; + + +const API_URL = "https://timezonedb.catvibers.me/"; +const Cache = new Map(); +export const moment: typeof import("moment") = findByPropsLazy("parseTwoDigitYear"); + +export interface Timezone { + userID: string, + timezoneId: String, + timezone: string; + error: string; +} +const getSettings = () => Vencord.Settings.plugins.Timezones; + +export async function getUserTimezone(discordID: string): Promise { + + if (getSettings()[`timezones.${discordID}`]) + return { + timezone: getSettings()[`timezones.${discordID}`], + } as Timezone; + + if (Cache.has(discordID)) { + return Cache.get(discordID).timezone; + } + + const timezone = await fetch(API_URL + "api/user/" + discordID).then( + r => r.json() + ); + Cache.set(discordID, timezone); + return timezone.timezone; +} + +export function getTimeString(timezone: Timezone, timestamp = moment()): string { + + const time = timestamp.utcOffset(Number(timezone)); + + return time.format(Vencord.Settings.plugins.Timezones.use24hr ? "HH:mm" : "h:mm A"); +} diff --git a/src/plugins/Timezones/index.tsx b/src/plugins/Timezones/index.tsx new file mode 100644 index 000000000..b567feb2b --- /dev/null +++ b/src/plugins/Timezones/index.tsx @@ -0,0 +1,186 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2022 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + + +import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands"; +import { Devs } from "@utils/constants"; +import { classes } from "@utils/misc"; +import definePlugin, { OptionType } from "@utils/types"; +import { findByPropsLazy } from "@webpack"; +import { React } from "@webpack/common"; +import { Message, User } from "discord-types/general"; + +import { getTimeString, getUserTimezone, Timezone } from "./Utils"; +const styles = findByPropsLazy("timestampInline"); + +export default definePlugin({ + name: "Timezones", + description: "Shows the timezones of users", + authors: [Devs.mantikafasi], + options: { + use24hr: { + type: OptionType.BOOLEAN, + description: "Use 24h format", + default: true, + }, + + showTimezonesInChat: { + type: OptionType.BOOLEAN, + description: "Show timezones in chat", + default: true, + }, + + showTimezonesInProfile: { + type: OptionType.BOOLEAN, + description: "Show timezones in profile", + default: true, + }, + }, + commands: [ + { + name: "settimezone", + description: "Set a users timezone", + inputType: ApplicationCommandInputType.BUILT_IN, + options: [ + { + name: "user", + description: "User to set timezone for", + type: ApplicationCommandOptionType.USER, + }, + { + name: "timezone", + description: "Timezone to set (+3, -5, etc.)", + type: ApplicationCommandOptionType.STRING, + } + + + ], + execute(args, ctx) { + const user = findOption(args, "user"); + const timezone = findOption(args, "timezone"); + Vencord.Settings.plugins.Timezones[`timezones.${user}`] = timezone; + sendBotMessage(ctx.channel.id, {content: "Timezone set"}); + }, + }, + { + name: "deletetimezone", + description: "Delete a users timezone", + inputType: ApplicationCommandInputType.BUILT_IN, + options: [ + { + name: "user", + description: "User to delete timezone for", + type: ApplicationCommandOptionType.USER, + }, + ], + execute(args, ctx) { + const user = findOption(args, "user"); + if (!Vencord.Settings.plugins.Timezones[`timezones.${user}`]) { + sendBotMessage(ctx.channel.id, {content: "No timezone"}); + return; + } + delete Vencord.Settings.plugins.Timezones[`timezones.${user}`]; + sendBotMessage(ctx.channel.id, {content: "Timezone deleted"}); + } + }, + { + name: "gettimezones", + description: "Get all timezones", + inputType: ApplicationCommandInputType.BUILT_IN, + execute(args, ctx) { + const timezones = Vencord.Settings.plugins.Timezones; + let str = Object.entries(timezones).filter(t => t.toString().startsWith("timezones.")).map(([user, timezone]) => `<@${user.slice(10)}>: ${timezone}`).join("\n"); + + if (str.length === 0) { + str = "No timezones set"; + } + sendBotMessage(ctx.channel.id, {content:str}); + } + } + ], + + patches: [ + { + find: "showCommunicationDisabledStyles", + replacement: { + + match: /(?<=return\s*\(0,\w{1,3}\.jsxs?\)\(.+!\w{1,3}&&)(\[{0,1}\(0,\w{1,3}.jsxs?\)\(.+?\{.+?\}\)*\]{0,1})/, + // DONT EVER ASK ME HOW THIS WORKS I DONT KNOW EITHER I STOLE IT FROM TYMEN + replace: "[$1, Vencord.Plugins.plugins.Timezones.getTimezonesComponent(e)]" + }, + }, + { + find: "().popoutNoBannerPremium", + replacement: { + match: /return(\(0,.\.jsx\)\(.\..,\{.*\}\))/, + replace: "return [$1, Vencord.Plugins.plugins.Timezones.getProfileTimezonesComponent(e)]" + } + } + ], + + getProfileTimezonesComponent: (e: any) => { + + if (!Vencord.Settings.plugins.Timezones.showTimezonesInProfile) { + return (<>); + } + + const user = e.user as User; + + const [timezone, setTimezone] = React.useState(null); + + React.useEffect(() => { + getUserTimezone(user.id).then(timezone => setTimezone(timezone)); + }, [user.id]); + + + return ( + + {timezone && getTimeString(timezone)} + + + + ); + } + , + getTimezonesComponent: (e: any) => { + if (Vencord.Settings.plugins.showTimezonesInChat || e.user) + return (<>); + + const message = e.message as Message; + + const [timezone, setTimezone] = React.useState(null); + + React.useEffect(() => { + getUserTimezone(e.message.author.id).then(timezone => setTimezone(timezone)); + }, [message.author.id]); + + + return ( + + {timezone && "• " + getTimeString(timezone, message.timestamp)} + ); + } +});