Metalloriff / BetterDiscordPlugins

NOTE: Due to loss of interest in BetterDiscord development, I'm pursuing other projects and no longer maintaining this repository. I will try to keep up with pull requests, but I will likely not be fixing any plugins myself. I apologize for the inconvenience.
https://metalloriff.github.io/toms-discord-stuff/
187 stars 357 forks source link

GuildAndFriendRemovalAlerts [unexpected error] pls fix #262

Open BlueStarBRS opened 2 years ago

BlueStarBRS commented 2 years ago

this plugin is very important for me sadly its actually broken for me image

Soulivan71 commented 1 year ago

@Metalloriff this error still present

BlueStarBRS commented 1 year ago

@Metalloriff this error still present

https://github.com/iyu46/RemovedConnectionAlerts try using this

Pharaoh2k commented 1 week ago

I have modified the original plugin and it seems to work. I couldn't test it, but it compiles fine and the settings panel looks good. Please let me know if it works for you or not.

/**
 * @name GuildAndFriendRemovalAlerts
 * @version 3.2.2
 * @description Displays alerts when you are kicked/banned from a server, a server is deleted, and when a friend removes you.
 * @author ...
 * @source https://github.com/Metalloriff/BetterDiscordPlugins/GuildAndFriendRemovalAlerts
 * @updateUrl https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/GuildAndFriendRemovalAlerts/GuildAndFriendRemovalAlerts.plugin.js
 * @website https://metalloriff.github.io/toms-discord-stuff/#/
 * @donate https://paypal.me/israelboone
 * @invite yNqzuJa
 */

module.exports = (() => {
    const config = {
        info: {
            name: "GuildAndFriendRemovalAlerts",
            version: "3.2.2",
            description: "Displays alerts when you are kicked/banned from a server, a server is deleted, and when a friend removes you.",
            authors: [{
                name: "Metalloriff",
                discord_id: "264163473179672576",
                github_username: "Metalloriff"
            }],
            github: "https://github.com/Metalloriff/BetterDiscordPlugins/GuildAndFriendRemovalAlerts",
            github_raw: "https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/GuildAndFriendRemovalAlerts/GuildAndFriendRemovalAlerts.plugin.js",
            website: "https://metalloriff.github.io/toms-discord-stuff/#/",
            donate: "https://paypal.me/israelboone",
            invite: "yNqzuJa"
        },
        changelog: [{
            title: "3.2.2 Update",
            type: "fixed",
            items: [
                "Updated to fix errors caused by Discord API changes.",
                "Now uses dynamic module retrieval to stay compatible with future updates."
            ]
        }],
        defaultConfig: [
            {
                type: "switch",
                id: "showModal",
                name: "Auto Show Modal",
                note: "Automatically show the modal when a guild/friend is removed.",
                value: true
            },
            {
                type: "switch",
                id: "showDeskNotifs",
                name: "Show Desktop Notifications",
                note: "Show desktop notifications when a guild/friend is removed.",
                value: false
            }
        ]
    };

    return !global.ZeresPluginLibrary ? class {
        constructor() { this._config = config; }
        getName() { return config.info.name; }
        getAuthor() { return config.info.authors.map(a => a.name).join(", "); }
        getDescription() { return `${config.info.description}. __**ZeresPluginLibrary was not found! This plugin will not work!**__`; }
        getVersion() { return config.info.version; }
        load() {
            BdApi.showConfirmationModal(
                "Library plugin is needed",
                [`The library plugin needed for ${config.info.name} is missing. Please click Download to install it.`],
                {
                    confirmText: "Download",
                    cancelText: "Cancel",
                    onConfirm: () => {
                        require("request").get(
                            "https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js",
                            async (error, response, body) => {
                                if (error)
                                    return require("electron").shell.openExternal(
                                        "https://betterdiscord.net/ghdl?url=https://raw.githubusercontent.com/rauenzi/BDPluginLibrary/master/release/0PluginLibrary.plugin.js"
                                    );
                                await new Promise(r =>
                                    require("fs").writeFile(
                                        require("path").join(BdApi.Plugins.folder, "0PluginLibrary.plugin.js"),
                                        body,
                                        r
                                    )
                                );
                            }
                        );
                    }
                }
            );
        }
        start() { }
        stop() { }
    } : (([Plugin, Library]) => {
        const { Patcher, WebpackModules, Logger } = Library;
        const { React } = BdApi;

        const Dispatcher = WebpackModules.getByProps("dispatch", "subscribe");
        const GuildStore = WebpackModules.getModule(m => m.getGuild && (m.getGuilds || m.guilds));
        const RelationshipStore = WebpackModules.getModule(m => m.getRelationships && m.isFriend);
        const UserStore = WebpackModules.getModule(m => m.getUser && m.getCurrentUser);
        const HomeButton = WebpackModules.getByProps("HomeButton");
        const PrivateChannelActions = WebpackModules.getByProps("openPrivateChannel");

        const events = ["GUILD_CREATE", "GUILD_DELETE", "GUILD_UPDATE", "RELATIONSHIP_ADD", "RELATIONSHIP_REMOVE", "RELATIONSHIP_UPDATE", "FRIEND_REQUEST_ACCEPTED"];

        return class GuildAndFriendRemovalAlerts extends Plugin {
            constructor() {
                super();
                // Initialize history and snapshots using this.settings
                this.history = {
                    guilds: this.settings.removedGuildHistory || [],
                    friends: this.settings.removedFriendHistory || [],
                    update: () => {
                        this.settings.removedGuildHistory = this.history.guilds;
                        this.settings.removedFriendHistory = this.history.friends;
                        this.saveSettings();
                    },
                    clear: () => {
                        this.history.guilds = [];
                        this.history.friends = [];
                        this.history.update();
                    }
                };
                this.snapshots = {
                    guilds: this.settings.guildsSnapshot || [],
                    friends: this.settings.friendsSnapshot || [],
                    update: ({ guilds, friends }) => {
                        this.settings.guildsSnapshot = this.snapshots.guilds = guilds;
                        this.settings.friendsSnapshot = this.snapshots.friends = friends;
                        this.saveSettings();
                    }
                };
            }

            getSettingsPanel() {
                return this.buildSettingsPanel().getElement();
            }

            onStart() {
                // Subscribe to events
                events.forEach(eventType => Dispatcher.subscribe(eventType, this.main.bind(this)));
                this.main(); // Initial call to populate snapshots
            }

            onStop() {
                Patcher.unpatchAll();
                events.forEach(eventType => Dispatcher.unsubscribe(eventType, this.main.bind(this)));
            }

            main() {
                const guildsData = typeof GuildStore.getGuilds === 'function' ? GuildStore.getGuilds() : GuildStore.guilds;
                const guilds = Object.keys(guildsData).map(guildId => this.serializeGuild(guildId));

                const relationships = RelationshipStore.getRelationships();
                const friendIds = Object.keys(relationships).filter(id => relationships[id] === 1); // 1 indicates a friend
                const friends = friendIds.map(uid => this.serializeUser(uid));

                const removedGuilds = this.snapshots.guilds.filter(snapshot => !guilds.some(guild => snapshot.id === guild.id));
                const removedFriends = this.snapshots.friends.filter(snapshot => !friends.some(friend => snapshot.id === friend.id));

                if (removedGuilds.length || removedFriends.length) {
                    if (this.settings.showModal) this.openModal(removedGuilds, removedFriends);
                    removedGuilds.forEach(guild => this.history.guilds.unshift(guild));
                    removedFriends.forEach(friend => this.history.friends.unshift(friend));
                    if (this.settings.showDeskNotifs) {
                        removedGuilds.forEach(guild => new Notification(guild.name, {
                            silent: true,
                            body: "Server removed",
                            icon: guild.iconUrl
                        }));
                        removedFriends.forEach(friend => new Notification(friend.tag, {
                            silent: true,
                            body: "Friend removed",
                            icon: friend.avatarUrl
                        }));
                    }
                }

                if (guilds.length !== this.snapshots.guilds.length || friends.length !== this.snapshots.friends.length) {
                    this.history.update();
                    this.snapshots.update({
                        guilds,
                        friends
                    });
                }
            }

            serializeGuild(guildId) {
                const serialized = {
                    id: guildId,
                    invalid: true,
                    name: "Unknown Guild",
                    iconUrl: "/assets/1531b79c2f2927945582023e1edaaa11.png"
                };
                try {
                    const guild = GuildStore.getGuild(guildId);
                    if (guild) Object.assign(serialized, {
                        invalid: false,
                        name: guild.name,
                        ownerId: guild.ownerId,
                        iconUrl: guild.getIconURL ? guild.getIconURL("webp") : serialized.iconUrl
                    });
                } catch (error) {
                    Logger.error('Error serializing guild:', error);
                }
                return serialized;
            }

            serializeUser(userId) {
                const serialized = {
                    id: userId,
                    invalid: true,
                    tag: "Unknown User",
                    avatarUrl: "/assets/1cbd08c76f8af6dddce02c5138971129.png"
                };
                try {
                    const user = UserStore.getUser(userId);
                    if (user) Object.assign(serialized, {
                        invalid: false,
                        tag: user.tag,
                        avatarUrl: user.getAvatarURL ? user.getAvatarURL("webp") : serialized.avatarUrl
                    });
                } catch (error) {
                    Logger.error('Error serializing user:', error);
                }
                return serialized;
            }

            openModal(guilds, friends, showClearButton = false) {
                if (!guilds && !friends) {
                    guilds = this.snapshots.guilds;
                    friends = this.snapshots.friends;
                }
                const clearLogs = () => BdApi.showConfirmationModal("Are you sure?", "Do you really want to clear the logs?\nThis action cannot be undone.", {
                    danger: true,
                    onConfirm: () => {
                        this.history.clear();
                        BdApi.ModalStack.closeModal(modalId);
                    },
                    confirmText: "Clear"
                });
                const ModalStack = BdApi.findModuleByProps("openModal", "closeModal");
                const modalId = ModalStack.openModal(props => {
                    const ModalRoot = BdApi.findModuleByDisplayName("ModalRoot");
                    const ModalHeader = BdApi.findModuleByDisplayName("ModalHeader");
                    const ModalContent = BdApi.findModuleByDisplayName("ModalContent");
                    const ModalCloseButton = BdApi.findModuleByDisplayName("ModalCloseButton");

                    return React.createElement(ModalRoot, Object.assign({}, props, {
                        size: "large",
                        className: "GFRAModal"
                    }),
                        React.createElement(ModalHeader, null, "Guild And Friend Removal Alerts",
                            React.createElement(ModalCloseButton, {
                                onClick: props.onClose
                            })
                        ),
                        React.createElement(ModalContent, null,
                            (guilds && guilds.length) || (friends && friends.length) ? React.createElement(React.Fragment, null,
                                showClearButton ? React.createElement("div", {
                                    className: "GFRA-clearButton",
                                    onClick: clearLogs,
                                    style: { cursor: "pointer", color: "var(--text-link)", marginBottom: "10px" }
                                }, "Clear Logs") : null,
                                guilds && guilds.length ? React.createElement("div", {
                                    className: "GFRA-itemContainer"
                                },
                                    React.createElement("div", {
                                        className: "GFRA-title",
                                        style: { fontWeight: "bold", marginBottom: "5px" }
                                    }, "Guilds - ",
                                        React.createElement("span", {
                                            style: {
                                                color: "var(--text-link)"
                                            }
                                        }, guilds.length)
                                    ),
                                    guilds.map((guild, i) => React.createElement(this.Item, {
                                        key: i,
                                        title: guild.name,
                                        description: "Owner ID - " + guild.ownerId,
                                        icon: guild.iconUrl,
                                        clickId: guild.ownerId,
                                        closeModal: props.onClose
                                    }))
                                ) : null,
                                friends && friends.length ? React.createElement("div", {
                                    className: "GFRA-itemContainer"
                                },
                                    React.createElement("div", {
                                        className: "GFRA-title",
                                        style: { fontWeight: "bold", marginTop: "10px", marginBottom: "5px" }
                                    }, "Friends - ",
                                        React.createElement("span", {
                                            style: {
                                                color: "var(--text-link)"
                                            }
                                        }, friends.length)
                                    ),
                                    friends.map((friend, i) => React.createElement(this.Item, {
                                        key: i,
                                        title: friend.tag,
                                        icon: friend.avatarUrl,
                                        clickId: friend.id,
                                        closeModal: props.onClose
                                    }))
                                ) : null
                            ) : React.createElement("div", {
                                className: "GFRA-nothingHere"
                            }, "No logs to show.")
                        )
                    );
                });
            }

            Item = ({
                title,
                description,
                icon,
                clickId,
                closeModal
            }) => {
                return React.createElement("div", {
                    className: "GFRA-item",
                    style: { display: "flex", alignItems: "center", padding: "5px", cursor: "pointer" },
                    onClick: () => {
                        PrivateChannelActions.openPrivateChannel(clickId);
                        closeModal();
                    }
                },
                    React.createElement("img", {
                        className: "GFRA-image",
                        src: icon || "/assets/485a854d5171c8dc98088041626e6fea.png",
                        alt: "image",
                        style: { width: "40px", height: "40px", borderRadius: "50%", marginRight: "10px" }
                    }),
                    React.createElement("div", {
                        className: "GFRA-inner"
                    },
                        React.createElement("div", {
                            className: "GFRA-title",
                            style: { fontWeight: "bold" }
                        }, title),
                        description ? React.createElement("div", {
                            className: "GFRA-description",
                            style: { fontSize: "12px", color: "var(--text-muted)" }
                        }, description) : null
                    )
                );
            }
        };
    })(global.ZeresPluginLibrary.buildPlugin(config));
})();