import { Key, Clipboard, Globe, Plus } from "@styled-icons/boxicons-regular"; import { LockAlt } from "@styled-icons/boxicons-solid"; import { observer } from "mobx-react-lite"; import { Bot } from "revolt-api/types/Bots"; import { User } from "revolt.js/dist/maps/Users"; import styled from "styled-components"; import styles from "./Panes.module.scss"; import { Text } from "preact-i18n"; import { useEffect, useState } from "preact/hooks"; import { internalEmit } from "../../../lib/eventEmitter"; import { stopPropagation } from "../../../lib/stopPropagation"; import { useIntermediate } from "../../../context/intermediate/Intermediate"; import { FileUploader } from "../../../context/revoltjs/FileUploads"; import { useClient } from "../../../context/revoltjs/RevoltClient"; import Tooltip from "../../../components/common/Tooltip"; import UserIcon from "../../../components/common/user/UserIcon"; import Button from "../../../components/ui/Button"; import Checkbox from "../../../components/ui/Checkbox"; import InputBox from "../../../components/ui/InputBox"; import Tip from "../../../components/ui/Tip"; import CategoryButton from "../../../components/ui/fluent/CategoryButton"; import type { AxiosError } from "axios"; interface Data { _id: string; username: string; public: boolean; interactions_url?: string; } interface Changes { name?: string; public?: boolean; interactions_url?: string; remove?: "InteractionsURL"; } const BotBadge = styled.div` display: inline-block; height: 1.3em; padding: 0px 4px; font-size: 0.7em; user-select: none; margin-inline-start: 2px; text-transform: uppercase; color: var(--foreground); background: var(--accent); border-radius: calc(var(--border-radius) / 2); `; interface Props { bot: Bot; onDelete(): void; onUpdate(changes: Changes): void; } function BotCard({ bot, onDelete, onUpdate }: Props) { const client = useClient(); const [user, setUser] = useState(client.users.get(bot._id)!); const [data, setData] = useState({ _id: bot._id, username: user.username, public: bot.public, interactions_url: bot.interactions_url, }); const [error, setError] = useState(""); const [saving, setSaving] = useState(false); const [editMode, setEditMode] = useState(false); const [usernameRef, setUsernameRef] = useState( null, ); const [interactionsRef, setInteractionsRef] = useState(null); const { writeClipboard, openScreen } = useIntermediate(); async function save() { const changes: Changes = {}; if (data.username !== user!.username) changes.name = data.username; if (data.public !== bot.public) changes.public = data.public; if (data.interactions_url === "") changes.remove = "InteractionsURL"; else if (data.interactions_url !== bot.interactions_url) changes.interactions_url = data.interactions_url; setSaving(true); setError(""); try { await client.bots.edit(bot._id, changes); onUpdate(changes); setEditMode(false); } catch (e) { const err = e as AxiosError; if (err.isAxiosError && err.response?.data?.type) { switch (err.response.data.type) { case "UsernameTaken": setError("That username is taken!"); break; default: setError(`Error: ${err.response.data.type}`); break; } } else setError(err.toString()); } setSaving(false); } async function editBotAvatar(avatar?: string) { setSaving(true); setError(""); await client.request("PATCH", "/users/id", { headers: { "x-bot-token": bot.token }, transformRequest: (data, headers) => { // Remove user headers for this request delete headers["x-user-id"]; delete headers["x-session-token"]; return data; }, data: JSON.stringify(avatar ? { avatar } : { remove: "Avatar" }), }); const res = await client.bots.fetch(bot._id); if (!avatar) res.user.update({}, "Avatar"); setUser(res.user); setSaving(false); } return (
{!editMode ? ( openScreen({ id: "profile", user_id: user._id, }) } /> ) : ( editBotAvatar(avatar)} remove={() => editBotAvatar()} defaultPreview={user.generateAvatarURL( { max_side: 256 }, true, )} previewURL={user.generateAvatarURL( { max_side: 256 }, true, )} /> )} {!editMode ? ( ) : ( setData({ ...data, username: e.currentTarget.value, }) } /> )}
{!editMode && ( }> {bot.public ? ( ) : ( )} )}
{!editMode && ( } onClick={() => writeClipboard(bot.token)} description={ <> {"••••••••••••••••••••••••••••••••••••"}{" "} stopPropagation( ev, openScreen({ id: "token_reveal", token: bot.token, username: user!.username, }), ) }> } action={}> )} {editMode && (
} onChange={(v) => setData({ ...data, public: v })}>

setData({ ...data, interactions_url: e.currentTarget.value, }) } />
)} {error && (
{error}
)}
{editMode && ( <> )} {!editMode && ( <> )}
); } export const MyBots = observer(() => { const client = useClient(); const [bots, setBots] = useState(undefined); useEffect(() => { client.bots.fetchOwned().then(({ bots }) => setBots(bots)); // eslint-disable-next-line }, []); const { openScreen } = useIntermediate(); return (
} onClick={() => openScreen({ id: "create_bot", onCreate: (bot) => setBots([...(bots ?? []), bot]), }) } action="chevron"> {bots?.map((bot) => { return ( setBots(bots.filter((x) => x._id !== bot._id)) } onUpdate={(changes: Changes) => setBots( bots.map((x) => { if (x._id === bot._id) { if ( "public" in changes && typeof changes.public === "boolean" ) x.public = changes.public; if ("interactions_url" in changes) x.interactions_url = changes.interactions_url; if ( changes.remove === "InteractionsURL" ) x.interactions_url = undefined; } return x; }), ) } /> ); })}
); });