Add invite button for the bot tokens
All checks were successful
Lint Pull Request / lint (push) Successful in 23s
release-image / release-image (push) Successful in 10m15s

This commit is contained in:
Logan Cusano
2025-06-29 22:13:47 -04:00
parent aaa362ec0e
commit a1fda6fe87

View File

@@ -166,10 +166,10 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
setError(errorMsg); setError(errorMsg);
} }
} catch (err: any) { } catch (err: any) {
if (err.message === 'Unauthorized: Session expired or invalid token.') { if (err.message === 'Unauthorized: Session expired or invalid token.') {
setLoading(false); // already handled by authAwareFetch setLoading(false); // already handled by authAwareFetch
return; return;
} }
setError(`Network error during ${editingId ? 'update' : 'add'} Discord ID.`); setError(`Network error during ${editingId ? 'update' : 'add'} Discord ID.`);
console.error(err); console.error(err);
} }
@@ -195,10 +195,10 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
setError(errorMsg); setError(errorMsg);
} }
} catch (err: any) { } catch (err: any) {
if (err.message === 'Unauthorized: Session expired or invalid token.') { if (err.message === 'Unauthorized: Session expired or invalid token.') {
setLoading(false); // already handled by authAwareFetch setLoading(false); // already handled by authAwareFetch
return; return;
} }
setError('Network error during delete Discord ID.'); setError('Network error during delete Discord ID.');
console.error(err); console.error(err);
} }
@@ -207,8 +207,8 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
const handleAssignDismiss = async (): Promise<void> => { const handleAssignDismiss = async (): Promise<void> => {
setError(''); setError('');
if (!selectedBotClientId || !selectedSystemId) { if (!selectedBotClientId || !selectedSystemId) {
setError("Bot Client ID and System must be selected."); setError("Bot Client ID and System must be selected.");
return; return;
} }
if (!token) { if (!token) {
setError('Authentication token is missing. Please log in.'); setError('Authentication token is missing. Please log in.');
@@ -236,10 +236,10 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
setError(errorMsg); setError(errorMsg);
} }
} catch (err: any) { } catch (err: any) {
if (err.message === 'Unauthorized: Session expired or invalid token.') { if (err.message === 'Unauthorized: Session expired or invalid token.') {
setLoading(false); // already handled by authAwareFetch setLoading(false); // already handled by authAwareFetch
return; return;
} }
setError(`Network error during ${assignDismissAction} bot.`); setError(`Network error during ${assignDismissAction} bot.`);
console.error(err); console.error(err);
} }
@@ -277,7 +277,7 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
<Link href={`/nodes/${active_bot.client_id}`} className="text-blue-600 hover:underline"> <Link href={`/nodes/${active_bot.client_id}`} className="text-blue-600 hover:underline">
{active_bot.nickname} ({active_bot.client_id}) {active_bot.nickname} ({active_bot.client_id})
</Link> </Link>
</TableCell> </TableCell>
</TableRow> </TableRow>
); );
}) })
@@ -292,7 +292,7 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
<div> <div>
<h3 className="text-lg font-semibold mb-2">Manage Discord IDs</h3> <h3 className="text-lg font-semibold mb-2">Manage Discord IDs</h3>
<Button onClick={() => { setEditingId(null); setNewIdData({ discord_id: '', name: '', token: '', active: false, guild_ids: '', fixed_node: '' }); setIsAddIdDialogOpen(true);}} className="mb-4" disabled={!token}>Add New Discord ID</Button> <Button onClick={() => { setEditingId(null); setNewIdData({ discord_id: '', name: '', token: '', active: false, guild_ids: '', fixed_node: '' }); setIsAddIdDialogOpen(true); }} className="mb-4" disabled={!token}>Add New Discord ID</Button>
<Button onClick={() => setIsAssignDismissDialogOpen(true)} className="mb-4 ml-2" disabled={!token}>Assign/Dismiss Bot System</Button> <Button onClick={() => setIsAssignDismissDialogOpen(true)} className="mb-4 ml-2" disabled={!token}>Assign/Dismiss Bot System</Button>
<Table> <Table>
@@ -318,6 +318,12 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
<TableCell>{dId.guild_ids?.join(', ')}</TableCell> <TableCell>{dId.guild_ids?.join(', ')}</TableCell>
<TableCell>{dId?.fixed_node ? dId?.fixed_node : "None"}</TableCell> <TableCell>{dId?.fixed_node ? dId?.fixed_node : "None"}</TableCell>
<TableCell> <TableCell>
<Link href={`https://discord.com/oauth2/authorize?client_id=${dId?.discord_id}&permissions=3146752&response_type=code&redirect_uri=https%3A%2F%2Fradio.vpn.cusano.net%2F&integration_type=0&scope=bot+rpc.voice.read+rpc.voice.write+rpc+voice+guilds.channels.read+guilds+guilds.join+gdm.join+guilds.members.read+connections`}>
<Button variant="outline" size="sm" className="mr-2"
disabled={!dId?.discord_id}>
Invite
</Button>
</Link>
<Button variant="outline" size="sm" className="mr-2" <Button variant="outline" size="sm" className="mr-2"
onClick={() => { onClick={() => {
setEditingId(dId); setEditingId(dId);
@@ -349,129 +355,129 @@ const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) =>
</Table> </Table>
</div> </div>
<Dialog open={isAddIdDialogOpen} onOpenChange={setIsAddIdDialogOpen}> <Dialog open={isAddIdDialogOpen} onOpenChange={setIsAddIdDialogOpen}>
<DialogContent className="sm:max-w-[425px]"> <DialogContent className="sm:max-w-[425px]">
<DialogHeader> <DialogHeader>
<DialogTitle>{editingId ? 'Edit Discord ID' : 'Add New Discord ID'}</DialogTitle> <DialogTitle>{editingId ? 'Edit Discord ID' : 'Add New Discord ID'}</DialogTitle>
</DialogHeader> </DialogHeader>
<div className="grid gap-4 py-4"> <div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4"> <div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="name" className="text-right">Name</Label> <Label htmlFor="name" className="text-right">Name</Label>
<Input <Input
id="name" id="name"
value={newIdData.name} value={newIdData.name}
onChange={(e) => setNewIdData({ ...newIdData, name: e.target.value })} onChange={(e) => setNewIdData({ ...newIdData, name: e.target.value })}
className="col-span-3" className="col-span-3"
/> />
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="discord_id" className="text-right">Discord ID</Label>
<Input
id="discord_id"
value={newIdData.discord_id}
onChange={(e) => setNewIdData({ ...newIdData, discord_id: e.target.value })}
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="token" className="text-right">Token</Label>
<Input
id="token"
value={newIdData.token}
onChange={(e) => setNewIdData({ ...newIdData, token: e.target.value })}
className="col-span-3"
placeholder={editingId ? "Token hidden for security, re-enter to change" : ""}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="guild_ids" className="text-right">Guild IDs (comma-separated)</Label>
<Input
id="guild_ids"
value={newIdData.guild_ids}
onChange={(e) => setNewIdData({ ...newIdData, guild_ids: e.target.value })}
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="guild_ids" className="text-right">Fixed Node</Label>
<Input
id="fixed_node"
value={newIdData?.fixed_node}
onChange={(e) => setNewIdData({ ...newIdData, fixed_node: e.target.value })}
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="active" className="text-right">Active</Label>
<Checkbox
id="active"
checked={newIdData.active}
onCheckedChange={(checked) => setNewIdData({ ...newIdData, active: checked === true })}
className="col-span-3"
/>
</div>
</div> </div>
<div className="grid grid-cols-4 items-center gap-4"> <DialogFooter>
<Label htmlFor="discord_id" className="text-right">Discord ID</Label> <Button onClick={handleAddId} disabled={!token}>
<Input {editingId ? 'Save Changes' : 'Add Discord ID'}
id="discord_id" </Button>
value={newIdData.discord_id} </DialogFooter>
onChange={(e) => setNewIdData({ ...newIdData, discord_id: e.target.value })} </DialogContent>
className="col-span-3" </Dialog>
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="token" className="text-right">Token</Label>
<Input
id="token"
value={newIdData.token}
onChange={(e) => setNewIdData({ ...newIdData, token: e.target.value })}
className="col-span-3"
placeholder={editingId ? "Token hidden for security, re-enter to change" : ""}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="guild_ids" className="text-right">Guild IDs (comma-separated)</Label>
<Input
id="guild_ids"
value={newIdData.guild_ids}
onChange={(e) => setNewIdData({ ...newIdData, guild_ids: e.target.value })}
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="guild_ids" className="text-right">Fixed Node</Label>
<Input
id="fixed_node"
value={newIdData?.fixed_node}
onChange={(e) => setNewIdData({ ...newIdData, fixed_node: e.target.value })}
className="col-span-3"
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="active" className="text-right">Active</Label>
<Checkbox
id="active"
checked={newIdData.active}
onCheckedChange={(checked) => setNewIdData({ ...newIdData, active: checked === true })}
className="col-span-3"
/>
</div>
</div>
<DialogFooter>
<Button onClick={handleAddId} disabled={!token}>
{editingId ? 'Save Changes' : 'Add Discord ID'}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<Dialog open={isAssignDismissDialogOpen} onOpenChange={setIsAssignDismissDialogOpen}> <Dialog open={isAssignDismissDialogOpen} onOpenChange={setIsAssignDismissDialogOpen}>
<DialogContent className="sm:max-w-[425px]"> <DialogContent className="sm:max-w-[425px]">
<DialogHeader> <DialogHeader>
<DialogTitle>Assign/Dismiss Bot to System</DialogTitle> <DialogTitle>Assign/Dismiss Bot to System</DialogTitle>
</DialogHeader> </DialogHeader>
<div className="grid gap-4 py-4"> <div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4"> <div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="bot-client-id" className="text-right">Bot Client ID</Label> <Label htmlFor="bot-client-id" className="text-right">Bot Client ID</Label>
<Select onValueChange={setSelectedBotClientId} value={selectedBotClientId}> <Select onValueChange={setSelectedBotClientId} value={selectedBotClientId}>
<SelectTrigger className="col-span-3"> <SelectTrigger className="col-span-3">
<SelectValue placeholder="Select a bot client ID" /> <SelectValue placeholder="Select a bot client ID" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{bots.map((active_bot) => ( {bots.map((active_bot) => (
<SelectItem key={active_bot.client_id} value={active_bot.client_id}>{active_bot.client_id}</SelectItem> <SelectItem key={active_bot.client_id} value={active_bot.client_id}>{active_bot.client_id}</SelectItem>
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="system-id" className="text-right">System</Label>
<Select onValueChange={setSelectedSystemId} value={selectedSystemId}>
<SelectTrigger className="col-span-3">
<SelectValue placeholder="Select a system" />
</SelectTrigger>
<SelectContent>
{systems.map((system) => (
<SelectItem key={system._id} value={system._id}>{system.name} ({system._id})</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="action" className="text-right">Action</Label>
<Select
onValueChange={(value: string) => setAssignDismissAction(value as 'assign' | 'dismiss')}
value={assignDismissAction}
>
<SelectTrigger className="col-span-3">
<SelectValue placeholder="Select action" />
</SelectTrigger>
<SelectContent>
<SelectItem value="assign">Assign</SelectItem>
<SelectItem value="dismiss">Dismiss</SelectItem>
</SelectContent>
</Select>
</div>
</div> </div>
<div className="grid grid-cols-4 items-center gap-4"> <DialogFooter>
<Label htmlFor="system-id" className="text-right">System</Label> <Button onClick={handleAssignDismiss} disabled={!selectedBotClientId || !selectedSystemId || !token}>Perform Action</Button>
<Select onValueChange={setSelectedSystemId} value={selectedSystemId}> </DialogFooter>
<SelectTrigger className="col-span-3"> </DialogContent>
<SelectValue placeholder="Select a system" /> </Dialog>
</SelectTrigger>
<SelectContent>
{systems.map((system) => (
<SelectItem key={system._id} value={system._id}>{system.name} ({system._id})</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="action" className="text-right">Action</Label>
<Select
onValueChange={(value: string) => setAssignDismissAction(value as 'assign' | 'dismiss')}
value={assignDismissAction}
>
<SelectTrigger className="col-span-3">
<SelectValue placeholder="Select action" />
</SelectTrigger>
<SelectContent>
<SelectItem value="assign">Assign</SelectItem>
<SelectItem value="dismiss">Dismiss</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<DialogFooter>
<Button onClick={handleAssignDismiss} disabled={!selectedBotClientId || !selectedSystemId || !token}>Perform Action</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</CardContent> </CardContent>
</Card> </Card>
); );