feat(dashboard): add tos/privacy/about pages, add delete all data page + endpoint
This commit is contained in:
parent
ac54b78a13
commit
31b6ac2cac
21 changed files with 527 additions and 28 deletions
110
Catalogger.Backend/Api/GuildsController.Remove.cs
Normal file
110
Catalogger.Backend/Api/GuildsController.Remove.cs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (C) 2021-present sam (starshines.gay)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Net;
|
||||
using Catalogger.Backend.Api.Middleware;
|
||||
using Catalogger.Backend.Bot;
|
||||
using Catalogger.Backend.Database.Queries;
|
||||
using Catalogger.Backend.Extensions;
|
||||
using Catalogger.Backend.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Remora.Discord.Extensions.Embeds;
|
||||
|
||||
namespace Catalogger.Backend.Api;
|
||||
|
||||
public partial class GuildsController
|
||||
{
|
||||
[HttpPost("leave")]
|
||||
public async Task<IActionResult> LeaveGuildAsync(string id, [FromBody] LeaveGuildRequest req)
|
||||
{
|
||||
var (guildId, guild) = await ParseGuildAsync(id);
|
||||
if (guild.Name != req.Name)
|
||||
{
|
||||
throw new ApiError(
|
||||
HttpStatusCode.BadRequest,
|
||||
ErrorCode.BadRequest,
|
||||
"You must spell the server name correctly."
|
||||
);
|
||||
}
|
||||
|
||||
var guildConfig = await db.GetGuildAsync(guildId.Value);
|
||||
var logChannelId =
|
||||
webhookExecutor.GetLogChannel(guildConfig, LogChannelType.GuildUpdate)
|
||||
?? webhookExecutor.GetLogChannel(guildConfig, LogChannelType.GuildMemberRemove);
|
||||
if (logChannelId != null)
|
||||
{
|
||||
var currentUser = await discordRequestService.GetMeAsync(CurrentToken);
|
||||
|
||||
var embed = new EmbedBuilder()
|
||||
.WithTitle("Catalogger is leaving this server")
|
||||
.WithDescription(
|
||||
$"A moderator in this server ({currentUser.Tag}, <@{currentUser.Id}>) requested that Catalogger leave. "
|
||||
+ "All data related to this server will be deleted."
|
||||
)
|
||||
.WithColour(DiscordUtils.Red)
|
||||
.WithCurrentTimestamp()
|
||||
.Build()
|
||||
.GetOrThrow();
|
||||
|
||||
await webhookExecutor.SendLogAsync(logChannelId.Value, [embed], []);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Information(
|
||||
"Can't send guild {GuildId} a heads up when leaving as neither the guild update nor member remove events are logged",
|
||||
guildId
|
||||
);
|
||||
}
|
||||
|
||||
var leaveRes = await userApi.LeaveGuildAsync(guildId);
|
||||
if (!leaveRes.IsSuccess)
|
||||
{
|
||||
_logger.Error("Couldn't leave guild {GuildId}: {Error}", guildId, leaveRes.Error);
|
||||
throw new ApiError(
|
||||
HttpStatusCode.InternalServerError,
|
||||
ErrorCode.InternalServerError,
|
||||
"There was an error making Catalogger leave the server."
|
||||
);
|
||||
}
|
||||
|
||||
await using var tx = await db.Database.BeginTransactionAsync();
|
||||
var inviteCount = await db
|
||||
.Invites.Where(i => i.GuildId == guildId.Value)
|
||||
.ExecuteDeleteAsync();
|
||||
var watchlistCount = await db
|
||||
.Watchlists.Where(w => w.GuildId == guildId.Value)
|
||||
.ExecuteDeleteAsync();
|
||||
var messageCount = await db
|
||||
.Messages.Where(m => m.GuildId == guildId.Value)
|
||||
.ExecuteDeleteAsync();
|
||||
await db.Guilds.Where(g => g.Id == guildId.Value).ExecuteDeleteAsync();
|
||||
await tx.CommitAsync();
|
||||
|
||||
_logger.Information(
|
||||
"Deleted {InviteCount} invites, {WatchlistCount} watchlist entries, and {MessageCount} messages for guild {GuildId}",
|
||||
inviteCount,
|
||||
watchlistCount,
|
||||
messageCount,
|
||||
guildId
|
||||
);
|
||||
|
||||
_logger.Information("Left guild {GuildId} and removed all data for it", guildId);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
public record LeaveGuildRequest(string Name);
|
||||
}
|
||||
|
|
@ -20,9 +20,11 @@ using Catalogger.Backend.Cache.InMemoryCache;
|
|||
using Catalogger.Backend.Database;
|
||||
using Catalogger.Backend.Database.Queries;
|
||||
using Catalogger.Backend.Database.Redis;
|
||||
using Catalogger.Backend.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Remora.Discord.API;
|
||||
using Remora.Discord.API.Abstractions.Objects;
|
||||
using Remora.Discord.API.Abstractions.Rest;
|
||||
using Remora.Rest.Core;
|
||||
|
||||
namespace Catalogger.Backend.Api;
|
||||
|
|
@ -30,13 +32,17 @@ namespace Catalogger.Backend.Api;
|
|||
[Route("/api/guilds/{id}")]
|
||||
public partial class GuildsController(
|
||||
Config config,
|
||||
ILogger logger,
|
||||
DatabaseContext db,
|
||||
ChannelCache channelCache,
|
||||
RedisService redisService,
|
||||
IMemberCache memberCache,
|
||||
DiscordRequestService discordRequestService
|
||||
DiscordRequestService discordRequestService,
|
||||
IDiscordRestUserAPI userApi,
|
||||
WebhookExecutorService webhookExecutor
|
||||
) : ApiControllerBase
|
||||
{
|
||||
private readonly ILogger _logger = logger.ForContext<GuildsController>();
|
||||
|
||||
private async Task<(Snowflake GuildId, Guild Guild)> ParseGuildAsync(string id)
|
||||
{
|
||||
var guilds = await discordRequestService.GetGuildsAsync(CurrentToken);
|
||||
|
|
|
|||
|
|
@ -20,13 +20,25 @@ using Microsoft.AspNetCore.Mvc;
|
|||
namespace Catalogger.Backend.Api;
|
||||
|
||||
[Route("/api")]
|
||||
public class MetaController(GuildCache guildCache, DiscordRequestService discordRequestService)
|
||||
: ApiControllerBase
|
||||
public class MetaController(
|
||||
Config config,
|
||||
GuildCache guildCache,
|
||||
DiscordRequestService discordRequestService
|
||||
) : ApiControllerBase
|
||||
{
|
||||
[HttpGet("meta")]
|
||||
public IActionResult GetMeta()
|
||||
{
|
||||
return Ok(new MetaResponse(Guilds: (int)CataloggerMetrics.GuildsCached.Value));
|
||||
var inviteUrl =
|
||||
$"https://discord.com/oauth2/authorize?client_id={config.Discord.ApplicationId}"
|
||||
+ "&permissions=537250993&scope=bot+applications.commands";
|
||||
|
||||
return Ok(
|
||||
new MetaResponse(
|
||||
Guilds: (int)CataloggerMetrics.GuildsCached.Value,
|
||||
InviteUrl: inviteUrl
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[HttpGet("current-user")]
|
||||
|
|
@ -48,7 +60,7 @@ public class MetaController(GuildCache guildCache, DiscordRequestService discord
|
|||
);
|
||||
}
|
||||
|
||||
private record MetaResponse(int Guilds);
|
||||
private record MetaResponse(int Guilds, string InviteUrl);
|
||||
|
||||
private record CurrentUserResponse(ApiUser User, IEnumerable<ApiGuild> Guilds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,35 @@
|
|||
[Logging]
|
||||
# The minimum level that will be logged. Possible options are: Debug, Information, Warning, Error, Fatal
|
||||
LogEventLevel = Debug
|
||||
# Whether to log SQL queries. This is extremely verbose.
|
||||
LogQueries = false
|
||||
# URL for a Seq instance to log to. Generally not needed if you're self-hosting.
|
||||
SeqLogUrl = http://localhost:5341
|
||||
# Whether to enable Prometheus metrics. If disabled, Catalogger will update metrics manually every so often.
|
||||
EnableMetrics = false
|
||||
|
||||
[Database]
|
||||
Url = Host=localhost;Database=postgres;Username=postgres;Password=postgres
|
||||
# URL for a Redis-compatible database. Not required; Catalogger will fall back to in-memory caching if it's not set.
|
||||
Redis = localhost:6379
|
||||
EncryptionKey = changeMe!FNmZbotJnAAJ7grWHDluCoKIwj6NcUagKE= # base64 key
|
||||
# The key used to encrypt message data. This should be base64;
|
||||
# you can use `openssl rand -base64 32` on the command line to generate a key.
|
||||
EncryptionKey = changeMe!FNmZbotJnAAJ7grWHDluCoKIwj6NcUagKE=
|
||||
|
||||
[Discord]
|
||||
ApplicationId = <applicationIdHere>
|
||||
Token = <discordTokenHere>
|
||||
CommandsGuildId = <testGuildIdHere>
|
||||
# If you only want to sync commands with a single server, uncomment the line below and put its ID.
|
||||
# CommandsGuildId = <testGuildIdHere>
|
||||
# If disabled, commands will not be synced with Discord. This generally shouldn't be turned off.
|
||||
SyncCommands = true
|
||||
# The channel where guild join/leave logs are sent. The bot needs to have permission to manage webhooks in this channel.
|
||||
GuildLogId = 803961980758261800
|
||||
# This is not necessary when not using the dashboard.
|
||||
# ClientSecret = <secret>
|
||||
|
||||
# Dashboard related settings. You shouldn't need to change these.
|
||||
[Web]
|
||||
Host = localhost
|
||||
Port = 5005
|
||||
BaseUrl = https://catalogger.localhost
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
"svelte-check": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"typescript-eslint": "^8.0.0",
|
||||
"vite": "^5.0.3"
|
||||
"vite": "^5.0.3",
|
||||
"vite-plugin-markdown": "^2.2.0"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<Navbar expand="lg">
|
||||
<Navbar expand="lg" color="dark" dark={true}>
|
||||
<NavbarBrand href="/">Catalogger</NavbarBrand>
|
||||
<NavbarToggler on:click={() => (isOpen = !isOpen)} />
|
||||
<Collapse {isOpen} navbar expand="lg">
|
||||
|
|
|
|||
|
|
@ -8,16 +8,30 @@
|
|||
export let data: LayoutData;
|
||||
</script>
|
||||
|
||||
<Navbar user={data.user} />
|
||||
|
||||
<div class="container">
|
||||
<slot />
|
||||
<div class="position-absolute top-0 start-50 translate-middle-x">
|
||||
{#each $toastStore as toast}
|
||||
<Toast class="mt-2">
|
||||
{#if toast.header}<ToastHeader>{toast.header}</ToastHeader>{/if}
|
||||
<ToastBody>{toast.body}</ToastBody>
|
||||
</Toast>
|
||||
{/each}
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<Navbar user={data.user} />
|
||||
<div class="container mt-2 flex-grow-1">
|
||||
<slot />
|
||||
<div class="position-absolute top-0 start-50 translate-middle-x">
|
||||
{#each $toastStore as toast}
|
||||
<Toast class="mt-2">
|
||||
{#if toast.header}<ToastHeader>{toast.header}</ToastHeader>{/if}
|
||||
<ToastBody>{toast.body}</ToastBody>
|
||||
</Toast>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="container pt-2 pb-4">
|
||||
<hr />
|
||||
<div class="flex flex-column flex-lg-row">
|
||||
<a href="/about/contact">Contact</a>
|
||||
·
|
||||
<a href="/about/tos">Terms of service</a>
|
||||
·
|
||||
<a href="/about/privacy">Privacy</a>
|
||||
·
|
||||
<a href="https://codeberg.org/starshine/catalogger" target="_blank">Source code</a>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,20 @@
|
|||
<script lang="ts">
|
||||
import apiFetch from "$lib/api";
|
||||
import { onMount } from "svelte";
|
||||
import type { PageData } from "./$types";
|
||||
import { Button, ButtonGroup } from "@sveltestrap/sveltestrap";
|
||||
|
||||
let guildCount: number | null = 0;
|
||||
export let data: PageData;
|
||||
|
||||
type MetaResponse = { guilds: number };
|
||||
let guildCount: number | null = null;
|
||||
let inviteUrl: string | null = null;
|
||||
|
||||
type MetaResponse = { guilds: number; invite_url: string };
|
||||
|
||||
onMount(async () => {
|
||||
const meta = await apiFetch<MetaResponse>("GET", "/api/meta");
|
||||
guildCount = meta.guilds;
|
||||
inviteUrl = meta.invite_url;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -16,11 +22,40 @@
|
|||
<title>Catalogger</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>Welcome to SvelteKit</h1>
|
||||
<h1>Catalogger</h1>
|
||||
|
||||
<p>
|
||||
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
||||
Catalogger is a logging bot for Discord that integrates with <a
|
||||
href="https://pluralkit.me"
|
||||
target="_blank">PluralKit</a
|
||||
>'s message proxying.
|
||||
</p>
|
||||
<p>
|
||||
It adds extra information to edited and deleted messages: system ID, member
|
||||
ID, and the linked account. It also ignores messages that trigger proxies, so
|
||||
your deleted message logs will be free of duplicate messages.
|
||||
<br />It also shows system information for new members joining your server,
|
||||
and can notify you if an account linked to a banned system joins your server.
|
||||
Which invite a member used is also logged.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In {guildCount ?? "(loading)"} servers!
|
||||
</p>
|
||||
|
||||
{#if data.user || inviteUrl}
|
||||
<p>
|
||||
<ButtonGroup>
|
||||
{#if inviteUrl}
|
||||
<Button color="primary" href={inviteUrl}
|
||||
>Add Catalogger to your server</Button
|
||||
>
|
||||
{/if}
|
||||
{#if data.user}
|
||||
<Button color="secondary" href="/dash">Open the dashboard</Button>
|
||||
{:else}
|
||||
<Button color="secondary" href="/api/authorize">Log in</Button>
|
||||
{/if}
|
||||
</ButtonGroup>
|
||||
</p>
|
||||
{/if}
|
||||
|
|
|
|||
1
Catalogger.Frontend/src/routes/about/+layout.svelte
Normal file
1
Catalogger.Frontend/src/routes/about/+layout.svelte
Normal file
|
|
@ -0,0 +1 @@
|
|||
<slot />
|
||||
1
Catalogger.Frontend/src/routes/about/+layout.ts
Normal file
1
Catalogger.Frontend/src/routes/about/+layout.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export const prerender = true;
|
||||
5
Catalogger.Frontend/src/routes/about/contact.md
Normal file
5
Catalogger.Frontend/src/routes/about/contact.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Contact
|
||||
|
||||
The best way to contact us is through [the support server](https://discord.gg/b5jjJ96Jbv).
|
||||
|
||||
If you would rather use email, please send an email to `catalogger [at] starshines [dot] gay`.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { html } from "../contact.md";
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Catalogger - Contact</title>
|
||||
</svelte:head>
|
||||
|
||||
{@html html}
|
||||
34
Catalogger.Frontend/src/routes/about/privacy.md
Normal file
34
Catalogger.Frontend/src/routes/about/privacy.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Privacy policy
|
||||
|
||||
We're not lawyers and never will be, and we don't want to write a document no one can (or wants to) read.
|
||||
That being said, this bot handles sensitive information, so here's a list of what the bot collects.
|
||||
|
||||
By using Catalogger's commands, or by participating in a server where it's logging events,
|
||||
you consent to have your data processed by the bot.
|
||||
|
||||
This is the data Catalogger collects:
|
||||
|
||||
- Messages, in servers where edited and/or deleted message logging is enabled.
|
||||
- Server-specific settings: which channels to log to, and which channels to ignore.
|
||||
|
||||
You can opt out of your messages being collected by leaving servers the bot is in.
|
||||
Because this data is stored for moderation purposes, you cannot opt out while still staying in those servers.
|
||||
|
||||
Messages are stored encrypted in the database, and automatically deleted after fifteen days.
|
||||
This retention time may be lowered in the future.
|
||||
|
||||
This is the data Catalogger fetches from Discord, and is stored while the bot is running:
|
||||
|
||||
- User information: IDs, usernames, and avatars.
|
||||
- Member information: Nicknames and roles.
|
||||
- Server information: all channels and all roles in a server.
|
||||
- Webhooks used for logging.
|
||||
|
||||
Additionally, the dashboard collects the following data:
|
||||
|
||||
- The servers a logged-in user is in, to check their permissions and provide a list of all servers they can manage.
|
||||
|
||||
To clear your server's data, use the "Delete all data" page on the dashboard.
|
||||
Catalogger will automatically leave your server after confirmation.
|
||||
|
||||
Note that that command won't remove any data from database backups. [Contact us](/about/contact) if you want those wiped too.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { html } from "../privacy.md";
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Privacy policy - Catalogger</title>
|
||||
</svelte:head>
|
||||
|
||||
{@html html}
|
||||
22
Catalogger.Frontend/src/routes/about/tos.md
Normal file
22
Catalogger.Frontend/src/routes/about/tos.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Terms of Service
|
||||
|
||||
By using the Catalogger Discord bot (henceforth referred to as “the bot”) or the Catalogger dashboard (henceforth referred to as “the website”), you accept and agree to abide by the terms and provisions of this agreement.
|
||||
|
||||
In addition, when using the bot’s services, or those of the website, you shall be subject to any posted guidelines or rules applicable to such services, which may be posted and modified from time to time.
|
||||
|
||||
All such guidelines or rules are hereby incorporated by reference into the Terms Of Service (henceforth referred to as ‘the ToS’).
|
||||
|
||||
ANY USE OF THE BOT OR THE WEBSITE CONSTITUTES AGREEMENT TO THESE TERMS OF SERVICE. IF YOU DO NOT AGREE TO THE TOS, DO NOT USE THE BOT OR THE WEBSITE.
|
||||
|
||||
The service is offered in the hopes that it will be useful, but without any warranty. The developer shall not be responsible or liable for the accuracy, correctness, usefulness or availability of any information transmitted or made available via bot or the website or any other officially associated media, and shall not be responsible or liable for any error or omissions in that information. The developer is also not liable for any damage, data loss or harm caused by the use or misuse of the bot or the website, however unlikely that may be. By using the bot or the website, you agree to this and you understand that the developer is not liable for damage, data loss or other harm, caused by the use or misuse of the bot or the website, or association with the developer in any other way.
|
||||
|
||||
The developer reserves the right to modify, remove or revoke access to the service, whether to discontinue it as a whole or bar specific persons or parties from accessing or using the bot, the website, or any other officially associated media for any reason, including but not limited to:
|
||||
deliberately interfering with the service’s operation, such as by attempting a denial of service attack;
|
||||
using the service to break the law;
|
||||
using the service to break other organizations’ Terms of Service, including Discord.
|
||||
|
||||
The developer will take whatever steps are necessary to preserve the integrity of the software and hardware the service runs upon, and again reserves the right to bar and take any reasonable measure against parties or persons who attempt to prevent that. In the event of a data breach, the developer will handle it in accordance with the law.
|
||||
|
||||
Catalogger is proud to have good privacy practices and is GDPR compliant. You can find the privacy policy [here](/about/privacy).
|
||||
|
||||
If you believe your intellectual property rights have been infringed by the developer, please contact us [here](/about/contact).
|
||||
9
Catalogger.Frontend/src/routes/about/tos/+page.svelte
Normal file
9
Catalogger.Frontend/src/routes/about/tos/+page.svelte
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { html } from "../tos.md";
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Catalogger - Terms of Service</title>
|
||||
</svelte:head>
|
||||
|
||||
{@html html}
|
||||
|
|
@ -69,6 +69,12 @@
|
|||
>
|
||||
Key roles
|
||||
</NavLink>
|
||||
<NavLink
|
||||
href="/dash/{data.guild.id}/delete"
|
||||
active={$page.url.pathname === `/dash/${data.guild.id}/delete`}
|
||||
>
|
||||
Delete all data
|
||||
</NavLink>
|
||||
</Nav>
|
||||
|
||||
{#if $page.url.pathname === `/dash/${data.guild.id}` || $page.url.pathname === `/dash/${data.guild.id}/ignored-channels`}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
<script lang="ts">
|
||||
import { Alert, Button, Input, InputGroup } from "@sveltestrap/sveltestrap";
|
||||
import type { PageData } from "./$types";
|
||||
import { fastFetch, type ApiError } from "$lib/api";
|
||||
import { addToast } from "$lib/toast";
|
||||
import { goto } from "$app/navigation";
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let guildName: string = "";
|
||||
|
||||
const deleteData = async () => {
|
||||
try {
|
||||
await fastFetch("POST", `/api/guilds/${data.guild.id}/leave`, {
|
||||
name: guildName,
|
||||
});
|
||||
addToast({
|
||||
header: "Left server",
|
||||
body: `Successfully left ${data.guild.name} and deleted all data related to it.`,
|
||||
});
|
||||
|
||||
await goto("/dash");
|
||||
} catch (e) {
|
||||
addToast({
|
||||
header: "Error leaving server",
|
||||
body: (e as ApiError).message || "Unknown error",
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<h3>Delete this server's data</h3>
|
||||
|
||||
<p>
|
||||
To make Catalogger leave your server and delete all data from your server,
|
||||
fill its name in below and press "Delete".
|
||||
<br />
|
||||
<strong>
|
||||
This is irreversible. If you change your mind later, your data cannot be
|
||||
restored.
|
||||
</strong>
|
||||
<br />
|
||||
If you just want to make Catalogger leave your server but not delete data, simply
|
||||
kick it via Discord.
|
||||
</p>
|
||||
|
||||
<Alert color="danger">
|
||||
<h4 class="alert-heading">This is irreversible!</h4>
|
||||
|
||||
We <strong>cannot</strong> help you recover data deleted in this way.
|
||||
</Alert>
|
||||
|
||||
<p>
|
||||
<InputGroup>
|
||||
<Input type="text" placeholder="Server name" bind:value={guildName} />
|
||||
<Button
|
||||
color="danger"
|
||||
disabled={guildName !== data.guild.name}
|
||||
on:click={deleteData}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</InputGroup>
|
||||
</p>
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
import { sveltekit } from "@sveltejs/kit/vite";
|
||||
import { defineConfig } from "vite";
|
||||
import { Mode, plugin as markdown } from "vite-plugin-markdown";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
plugins: [sveltekit(), markdown({ mode: [Mode.HTML] })],
|
||||
server: {
|
||||
port: 5173,
|
||||
strictPort: true,
|
||||
|
|
|
|||
|
|
@ -613,6 +613,13 @@ ansi-styles@^4.1.0:
|
|||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
|
||||
dependencies:
|
||||
sprintf-js "~1.0.2"
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
|
|
@ -762,6 +769,46 @@ devalue@^5.1.0:
|
|||
resolved "https://registry.yarnpkg.com/devalue/-/devalue-5.1.1.tgz#a71887ac0f354652851752654e4bd435a53891ae"
|
||||
integrity sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==
|
||||
|
||||
dom-serializer@^1.0.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
|
||||
integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==
|
||||
dependencies:
|
||||
domelementtype "^2.0.1"
|
||||
domhandler "^4.2.0"
|
||||
entities "^2.0.0"
|
||||
|
||||
domelementtype@^2.0.1, domelementtype@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
|
||||
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
|
||||
|
||||
domhandler@^4.0.0, domhandler@^4.2.0:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
|
||||
integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==
|
||||
dependencies:
|
||||
domelementtype "^2.2.0"
|
||||
|
||||
domutils@^2.5.2:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
|
||||
integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
|
||||
dependencies:
|
||||
dom-serializer "^1.0.1"
|
||||
domelementtype "^2.2.0"
|
||||
domhandler "^4.2.0"
|
||||
|
||||
entities@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||
|
||||
entities@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||
|
||||
esbuild@^0.21.3:
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
|
||||
|
|
@ -915,6 +962,11 @@ espree@^9.6.1:
|
|||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
esprima@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
||||
|
||||
esquery@^1.5.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
|
||||
|
|
@ -1019,6 +1071,13 @@ flatted@^3.2.9:
|
|||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
|
||||
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
|
||||
|
||||
front-matter@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-4.0.2.tgz#b14e54dc745cfd7293484f3210d15ea4edd7f4d5"
|
||||
integrity sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==
|
||||
dependencies:
|
||||
js-yaml "^3.13.1"
|
||||
|
||||
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
|
|
@ -1068,6 +1127,16 @@ has-flag@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
htmlparser2@^6.0.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
|
||||
integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
|
||||
dependencies:
|
||||
domelementtype "^2.0.1"
|
||||
domhandler "^4.0.0"
|
||||
domutils "^2.5.2"
|
||||
entities "^2.0.0"
|
||||
|
||||
ignore@^5.2.0, ignore@^5.3.1:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||
|
|
@ -1125,6 +1194,14 @@ isexe@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||
|
||||
js-yaml@^3.13.1:
|
||||
version "3.14.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
|
||||
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
|
|
@ -1177,6 +1254,13 @@ lilconfig@^2.0.5:
|
|||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
|
||||
integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
|
||||
|
||||
linkify-it@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e"
|
||||
integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
locate-character@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-character/-/locate-character-3.0.0.tgz#0305c5b8744f61028ef5d01f444009e00779f974"
|
||||
|
|
@ -1201,11 +1285,27 @@ magic-string@^0.30.10, magic-string@^0.30.4, magic-string@^0.30.5:
|
|||
dependencies:
|
||||
"@jridgewell/sourcemap-codec" "^1.5.0"
|
||||
|
||||
markdown-it@^12.0.0:
|
||||
version "12.3.2"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
|
||||
integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
entities "~2.1.0"
|
||||
linkify-it "^3.0.1"
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
mdn-data@2.0.30:
|
||||
version "2.0.30"
|
||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc"
|
||||
integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
|
|
@ -1485,6 +1585,11 @@ sirv@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
|
||||
|
||||
strip-json-comments@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
|
|
@ -1607,6 +1712,11 @@ typescript@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b"
|
||||
integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||
|
|
@ -1619,6 +1729,16 @@ util-deprecate@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
vite-plugin-markdown@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/vite-plugin-markdown/-/vite-plugin-markdown-2.2.0.tgz#a0c5bd7bb88f385fa4ea983bf51b1ee35057c90a"
|
||||
integrity sha512-eH2tXMZcx3EHb5okd+/0VIyoR8Gp9pGe24UXitOOcGkzObbJ1vl48aGOAbakoT88FBdzC8MXNkMfBIB9VK0Ndg==
|
||||
dependencies:
|
||||
domhandler "^4.0.0"
|
||||
front-matter "^4.0.0"
|
||||
htmlparser2 "^6.0.0"
|
||||
markdown-it "^12.0.0"
|
||||
|
||||
vite@^5.0.3:
|
||||
version "5.4.9"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.9.tgz#215c80cbebfd09ccbb9ceb8c0621391c9abdc19c"
|
||||
|
|
|
|||
19
README.md
19
README.md
|
|
@ -17,6 +17,24 @@ Add these with `dotnet nuget add source --username <githubUsername> --password <
|
|||
|
||||
You must generate a personal access token (classic) [here](personal-access-token). Only give it the `read:packages` permission.
|
||||
|
||||
## Deploying Catalogger yourself
|
||||
|
||||
The bot itself should run on any server with .NET 8 and PostgreSQL 15 or later.
|
||||
A Redis-compatible database is *not* a hard dependency for the bot,
|
||||
but may be used for faster restarts (when Redis is used, certain data will be cached there instead of in memory).
|
||||
|
||||
The dashboard isn't made for self-hosting. While it *should* work, the about/contact/ToS/privacy policy pages are hardcoded for our own convenience.
|
||||
|
||||
For now, you'll also have to follow the instructions in the "Nuget" section above.
|
||||
|
||||
Steps to build and run the bot:
|
||||
|
||||
1. Clone the repository
|
||||
2. Run `dotnet publish` ([documentation][dotnet-publish])
|
||||
3. Change directory into `Catalogger.Backend/`
|
||||
4. Copy `config.example.ini` to `config.ini` and fill it out.
|
||||
5. Run the bot by executing `bin/Release/net8.0/Catalogger.Backend` (or net9.0 if you're using that version)
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2021-present sam (https://starshines.gay)
|
||||
|
|
@ -38,3 +56,4 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
[husky]: https://github.com/alirezanet/Husky.Net
|
||||
[csharpier]: https://csharpier.com/
|
||||
[personal-access-token]: https://github.com/settings/tokens
|
||||
[dotnet-publish]: https://learn.microsoft.com/en-us/dotnet/core/deploying/
|
||||
Loading…
Add table
Add a link
Reference in a new issue