attempt to add ignored channels page
This commit is contained in:
parent
cb425fe3cd
commit
1c43beb82f
13 changed files with 238 additions and 124 deletions
|
|
@ -49,6 +49,17 @@ public class AuthController(
|
||||||
return Redirect(url);
|
return Redirect(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("add-guild/{id}")]
|
||||||
|
public IActionResult AddGuild(ulong id)
|
||||||
|
{
|
||||||
|
var url =
|
||||||
|
$"https://discord.com/oauth2/authorize?client_id={config.Discord.ApplicationId}"
|
||||||
|
+ "&permissions=537250993&scope=bot+applications.commands"
|
||||||
|
+ $"&guild_id={id}";
|
||||||
|
|
||||||
|
return Redirect(url);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("callback")]
|
[HttpPost("callback")]
|
||||||
[ProducesResponseType<CallbackResponse>(statusCode: StatusCodes.Status200OK)]
|
[ProducesResponseType<CallbackResponse>(statusCode: StatusCodes.Status200OK)]
|
||||||
public async Task<IActionResult> CallbackAsync([FromBody] CallbackRequest req)
|
public async Task<IActionResult> CallbackAsync([FromBody] CallbackRequest req)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ using Catalogger.Backend.Api.Middleware;
|
||||||
using Catalogger.Backend.Cache.InMemoryCache;
|
using Catalogger.Backend.Cache.InMemoryCache;
|
||||||
using Catalogger.Backend.Database;
|
using Catalogger.Backend.Database;
|
||||||
using Catalogger.Backend.Database.Queries;
|
using Catalogger.Backend.Database.Queries;
|
||||||
|
using Catalogger.Backend.Database.Redis;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Remora.Discord.API;
|
using Remora.Discord.API;
|
||||||
using Remora.Discord.API.Abstractions.Objects;
|
using Remora.Discord.API.Abstractions.Objects;
|
||||||
|
|
@ -30,16 +31,10 @@ public partial class GuildsController(
|
||||||
Config config,
|
Config config,
|
||||||
DatabaseContext db,
|
DatabaseContext db,
|
||||||
ChannelCache channelCache,
|
ChannelCache channelCache,
|
||||||
|
RedisService redisService,
|
||||||
DiscordRequestService discordRequestService
|
DiscordRequestService discordRequestService
|
||||||
) : ApiControllerBase
|
) : ApiControllerBase
|
||||||
{
|
{
|
||||||
public IActionResult AddGuild(ulong id) =>
|
|
||||||
Redirect(
|
|
||||||
$"https://discord.com/oauth2/authorize?client_id={config.Discord.ApplicationId}"
|
|
||||||
+ "&permissions=537250993&scope=bot%20applications.commands"
|
|
||||||
+ $"&guild_id={id}"
|
|
||||||
);
|
|
||||||
|
|
||||||
private async Task<(Snowflake GuildId, Guild Guild)> ParseGuildAsync(string id)
|
private async Task<(Snowflake GuildId, Guild Guild)> ParseGuildAsync(string id)
|
||||||
{
|
{
|
||||||
var guilds = await discordRequestService.GetGuildsAsync(CurrentToken);
|
var guilds = await discordRequestService.GetGuildsAsync(CurrentToken);
|
||||||
|
|
@ -135,6 +130,28 @@ public partial class GuildsController(
|
||||||
.ToList();
|
.ToList();
|
||||||
var guildConfig = await db.GetGuildAsync(guildId);
|
var guildConfig = await db.GetGuildAsync(guildId);
|
||||||
|
|
||||||
|
if (req.IgnoredChannels != null)
|
||||||
|
{
|
||||||
|
var categories = channelCache
|
||||||
|
.GuildChannels(guildId)
|
||||||
|
.Where(c => c.Type is ChannelType.GuildCategory)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (
|
||||||
|
req.IgnoredChannels.Any(cId =>
|
||||||
|
guildChannels.All(c => c.ID.Value != cId)
|
||||||
|
&& categories.All(c => c.ID.Value != cId)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
throw new ApiError(
|
||||||
|
HttpStatusCode.BadRequest,
|
||||||
|
ErrorCode.BadRequest,
|
||||||
|
"One or more ignored channels are unknown"
|
||||||
|
);
|
||||||
|
|
||||||
|
guildConfig.Channels.IgnoredChannels = req.IgnoredChannels.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
// i love repeating myself wheeeeee
|
// i love repeating myself wheeeeee
|
||||||
if (
|
if (
|
||||||
req.GuildUpdate == null
|
req.GuildUpdate == null
|
||||||
|
|
@ -295,6 +312,7 @@ public partial class GuildsController(
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ChannelRequest(
|
public record ChannelRequest(
|
||||||
|
ulong[]? IgnoredChannels = null,
|
||||||
ulong? GuildUpdate = null,
|
ulong? GuildUpdate = null,
|
||||||
ulong? GuildEmojisUpdate = null,
|
ulong? GuildEmojisUpdate = null,
|
||||||
ulong? GuildRoleCreate = null,
|
ulong? GuildRoleCreate = null,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ public class Guild
|
||||||
|
|
||||||
public class ChannelConfig
|
public class ChannelConfig
|
||||||
{
|
{
|
||||||
public List<ulong> IgnoredChannels { get; init; } = [];
|
public List<ulong> IgnoredChannels { get; set; } = [];
|
||||||
public List<ulong> IgnoredUsers { get; init; } = [];
|
public List<ulong> IgnoredUsers { get; init; } = [];
|
||||||
public Dictionary<ulong, List<ulong>> IgnoredUsersPerChannel { get; init; } = [];
|
public Dictionary<ulong, List<ulong>> IgnoredUsersPerChannel { get; init; } = [];
|
||||||
public Dictionary<ulong, ulong> Redirects { get; init; } = [];
|
public Dictionary<ulong, ulong> Redirects { get; init; } = [];
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
|
import { page } from "$app/stores";
|
||||||
import { TOKEN_KEY, type User } from "$lib/api";
|
import { TOKEN_KEY, type User } from "$lib/api";
|
||||||
import { addToast } from "$lib/toast";
|
import { addToast } from "$lib/toast";
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
Navbar,
|
Navbar,
|
||||||
NavbarBrand,
|
NavbarBrand,
|
||||||
NavbarToggler,
|
NavbarToggler,
|
||||||
|
|
@ -11,6 +11,10 @@
|
||||||
Nav,
|
Nav,
|
||||||
NavItem,
|
NavItem,
|
||||||
NavLink,
|
NavLink,
|
||||||
|
Dropdown,
|
||||||
|
DropdownToggle,
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownItem,
|
||||||
} from "@sveltestrap/sveltestrap";
|
} from "@sveltestrap/sveltestrap";
|
||||||
|
|
||||||
export let user: User | null;
|
export let user: User | null;
|
||||||
|
|
@ -32,15 +36,28 @@
|
||||||
<Collapse {isOpen} navbar expand="lg">
|
<Collapse {isOpen} navbar expand="lg">
|
||||||
<Nav class="ms-auto" navbar>
|
<Nav class="ms-auto" navbar>
|
||||||
<NavItem>
|
<NavItem>
|
||||||
<NavLink href="/">Home</NavLink>
|
<NavLink href="/" active={$page.url.pathname === "/"}>About</NavLink>
|
||||||
</NavItem>
|
</NavItem>
|
||||||
{#if user}
|
{#if user}
|
||||||
<NavItem>
|
<Dropdown nav inNavbar>
|
||||||
<NavLink href="/dash">Dashboard</NavLink>
|
<DropdownToggle nav caret>
|
||||||
</NavItem>
|
<img
|
||||||
<NavItem>
|
src={user.avatar_url}
|
||||||
<NavLink on:click={logOut}>Log out</NavLink>
|
alt="Your avatar"
|
||||||
</NavItem>
|
style="border-radius: 0.75em; height: 1.5em;"
|
||||||
|
/>
|
||||||
|
{user.tag}
|
||||||
|
</DropdownToggle>
|
||||||
|
<DropdownMenu end>
|
||||||
|
<DropdownItem
|
||||||
|
href="/dash"
|
||||||
|
active={$page.url.pathname.startsWith("/dash")}
|
||||||
|
>
|
||||||
|
Dashboard
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem on:click={logOut}>Log out</DropdownItem>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
{:else}
|
{:else}
|
||||||
<NavItem>
|
<NavItem>
|
||||||
<NavLink href="/api/authorize">Log in with Discord</NavLink>
|
<NavLink href="/api/authorize">Log in with Discord</NavLink>
|
||||||
|
|
|
||||||
77
Catalogger.Frontend/src/lib/util.ts
Normal file
77
Catalogger.Frontend/src/lib/util.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
import type { FullGuild } from "./api";
|
||||||
|
|
||||||
|
export const makeFullOptions = (guild: FullGuild, ignore: string[]) => {
|
||||||
|
const options = [];
|
||||||
|
|
||||||
|
options.push(
|
||||||
|
...guild.categories
|
||||||
|
.filter((cat) => !ignore.some((k) => k === cat.id))
|
||||||
|
.map((cat) => ({
|
||||||
|
label: `${cat.name} (category)`,
|
||||||
|
value: cat.id,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Filter these channels
|
||||||
|
const channelsWithoutCategory = guild.channels_without_category.filter(
|
||||||
|
(c) => c.can_redirect_from && !ignore.some((k) => k === c.id),
|
||||||
|
);
|
||||||
|
if (channelsWithoutCategory.length > 0)
|
||||||
|
options.push({
|
||||||
|
label: "(no category)",
|
||||||
|
options: channelsWithoutCategory.map((c) => ({
|
||||||
|
value: c.id,
|
||||||
|
label: `#${c.name}`,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
options.push(
|
||||||
|
...guild.categories
|
||||||
|
.map((cat) => ({
|
||||||
|
label: cat.name,
|
||||||
|
options: cat.channels
|
||||||
|
.filter((c) => c.can_redirect_from && !ignore.some((k) => k === c.id))
|
||||||
|
.map((c) => ({ value: c.id, label: `#${c.name}` })),
|
||||||
|
}))
|
||||||
|
.filter((c) => c.options.length > 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const makeFullOptions2 = (guild: FullGuild, ignore: string[]) => {
|
||||||
|
const options: Array<{ label: string; value: string; group: string }> = [];
|
||||||
|
|
||||||
|
options.push(
|
||||||
|
...guild.categories
|
||||||
|
.filter((cat) => !ignore.some((k) => k === cat.id))
|
||||||
|
.map((cat) => ({
|
||||||
|
label: `${cat.name} (category)`,
|
||||||
|
value: cat.id,
|
||||||
|
group: "Categories",
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Filter these channels
|
||||||
|
const channelsWithoutCategory = guild.channels_without_category.filter(
|
||||||
|
(c) => c.can_redirect_from && !ignore.some((k) => k === c.id),
|
||||||
|
);
|
||||||
|
if (channelsWithoutCategory.length > 0)
|
||||||
|
options.push(
|
||||||
|
...channelsWithoutCategory.map((c) => ({
|
||||||
|
value: c.id,
|
||||||
|
label: `#${c.name}`,
|
||||||
|
group: "(no category)",
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
options.push(
|
||||||
|
...guild.categories.flatMap((cat) =>
|
||||||
|
cat.channels
|
||||||
|
.filter((c) => c.can_redirect_from && !ignore.some((k) => k === c.id))
|
||||||
|
.map((c) => ({ value: c.id, label: `#${c.name}`, group: cat.name })),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<slot />
|
<slot />
|
||||||
<div class="position-absolute top-0 start-50 translate-middle-x">
|
<div class="position-absolute top-0 start-50 translate-middle-x px-2">
|
||||||
{#each $toastStore as toast}
|
{#each $toastStore as toast}
|
||||||
<Toast>
|
<Toast>
|
||||||
{#if toast.header}<ToastHeader>{toast.header}</ToastHeader>{/if}
|
{#if toast.header}<ToastHeader>{toast.header}</ToastHeader>{/if}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,11 @@
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const code = params.get("code");
|
const code = params.get("code");
|
||||||
const state = params.get("state");
|
const state = params.get("state");
|
||||||
|
const guildId = params.get("guild_id");
|
||||||
|
|
||||||
if (data.user) {
|
if (data.user) {
|
||||||
|
if (guildId) return await goto(`/dash/${guildId}`);
|
||||||
|
|
||||||
addToast({ header: "Cannot log in", body: "You are already logged in." });
|
addToast({ header: "Cannot log in", body: "You are already logged in." });
|
||||||
await goto("/dash");
|
await goto("/dash");
|
||||||
return;
|
return;
|
||||||
|
|
@ -37,7 +40,11 @@
|
||||||
|
|
||||||
localStorage.setItem(TOKEN_KEY, resp.token);
|
localStorage.setItem(TOKEN_KEY, resp.token);
|
||||||
|
|
||||||
|
if (guildId) {
|
||||||
|
await goto(`/dash/${guildId}`, { invalidateAll: true });
|
||||||
|
} else {
|
||||||
await goto("/dash", { invalidateAll: true });
|
await goto("/dash", { invalidateAll: true });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Callback request failed: ", e);
|
console.error("Callback request failed: ", e);
|
||||||
error = true;
|
error = true;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ListGroup, ListGroupItem } from "@sveltestrap/sveltestrap";
|
import { ListGroup, ListGroupItem } from "@sveltestrap/sveltestrap";
|
||||||
import type { PageData } from "./$types";
|
import type { PageData } from "./$types";
|
||||||
|
import GuildCard from "./GuildCard.svelte";
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
|
|
@ -15,9 +16,9 @@
|
||||||
<h1>Manage your servers</h1>
|
<h1>Manage your servers</h1>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{#if joinedGuilds.length > 0}
|
|
||||||
<div class="col-lg">
|
<div class="col-lg">
|
||||||
<h2>Servers you can manage</h2>
|
<h2>Servers you can configure</h2>
|
||||||
|
{#if joinedGuilds.length > 0}
|
||||||
<ListGroup>
|
<ListGroup>
|
||||||
{#each joinedGuilds as guild (guild.id)}
|
{#each joinedGuilds as guild (guild.id)}
|
||||||
<ListGroupItem tag="a" href="/dash/{guild.id}">
|
<ListGroupItem tag="a" href="/dash/{guild.id}">
|
||||||
|
|
@ -30,14 +31,21 @@
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
{/each}
|
{/each}
|
||||||
</ListGroup>
|
</ListGroup>
|
||||||
</div>
|
{:else}
|
||||||
|
<p>None of the servers you manage have Catalogger added.</p>
|
||||||
{/if}
|
{/if}
|
||||||
{#if unjoinedGuilds.length > 0}
|
</div>
|
||||||
|
|
||||||
<div class="col-lg">
|
<div class="col-lg">
|
||||||
<h2>Servers you can add Catalogger to</h2>
|
<h2>Servers you can add Catalogger to</h2>
|
||||||
|
{#if unjoinedGuilds.length > 0}
|
||||||
<ListGroup>
|
<ListGroup>
|
||||||
{#each unjoinedGuilds as guild (guild.id)}
|
{#each unjoinedGuilds as guild (guild.id)}
|
||||||
<ListGroupItem tag="a" href="/api/add-guild/{guild.id}">
|
<ListGroupItem
|
||||||
|
tag="a"
|
||||||
|
href="/api/add-guild/{guild.id}"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src={guild.icon_url}
|
src={guild.icon_url}
|
||||||
alt="Icon for {guild.name}"
|
alt="Icon for {guild.name}"
|
||||||
|
|
@ -47,6 +55,8 @@
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
{/each}
|
{/each}
|
||||||
</ListGroup>
|
</ListGroup>
|
||||||
</div>
|
{:else}
|
||||||
|
<p>All of the servers you manage already have Catalogger added.</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@
|
||||||
data.guild.config,
|
data.guild.config,
|
||||||
);
|
);
|
||||||
data.guild.config = resp;
|
data.guild.config = resp;
|
||||||
|
|
||||||
|
addToast({
|
||||||
|
header: "Saved log channels.",
|
||||||
|
body: "Successfully edited log channels and ignored channels.",
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
addToast({
|
addToast({
|
||||||
header: "Error saving changes to log channels",
|
header: "Error saving changes to log channels",
|
||||||
|
|
@ -31,55 +36,43 @@
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="d-flex flex-column flex-lg-row justify-content-lg-between">
|
<div class="d-flex flex-column flex-lg-row justify-content-lg-between">
|
||||||
<Nav pills={true} class="flex-column flex-lg-row">
|
<Nav pills={true} class="flex-column flex-lg-row mb-2">
|
||||||
<NavItem
|
<NavLink href="#" disabled>Managing {data.guild.name}</NavLink>
|
||||||
><NavLink href="#" disabled>Managing {data.guild.name}</NavLink></NavItem
|
<NavLink
|
||||||
>
|
|
||||||
<NavItem
|
|
||||||
><NavLink
|
|
||||||
href="/dash/{data.guild.id}"
|
href="/dash/{data.guild.id}"
|
||||||
active={$page.url.pathname === `/dash/${data.guild.id}`}
|
active={$page.url.pathname === `/dash/${data.guild.id}`}
|
||||||
>
|
>
|
||||||
Log channels
|
Log channels
|
||||||
</NavLink></NavItem
|
</NavLink>
|
||||||
>
|
<NavLink
|
||||||
<NavItem
|
|
||||||
><NavLink
|
|
||||||
href="/dash/{data.guild.id}/redirects"
|
href="/dash/{data.guild.id}/redirects"
|
||||||
active={$page.url.pathname === `/dash/${data.guild.id}/redirects`}
|
active={$page.url.pathname === `/dash/${data.guild.id}/redirects`}
|
||||||
>
|
>
|
||||||
Redirects
|
Redirects
|
||||||
</NavLink></NavItem
|
</NavLink>
|
||||||
>
|
<NavLink
|
||||||
<NavItem
|
|
||||||
><NavLink
|
|
||||||
href="/dash/{data.guild.id}/ignored-channels"
|
href="/dash/{data.guild.id}/ignored-channels"
|
||||||
active={$page.url.pathname ===
|
active={$page.url.pathname === `/dash/${data.guild.id}/ignored-channels`}
|
||||||
`/dash/${data.guild.id}/ignored-channels`}
|
|
||||||
>
|
>
|
||||||
Ignored channels
|
Ignored channels
|
||||||
</NavLink></NavItem
|
</NavLink>
|
||||||
>
|
<NavLink
|
||||||
<NavItem
|
|
||||||
><NavLink
|
|
||||||
href="/dash/{data.guild.id}/ignored-users"
|
href="/dash/{data.guild.id}/ignored-users"
|
||||||
active={$page.url.pathname === `/dash/${data.guild.id}/ignored-users`}
|
active={$page.url.pathname === `/dash/${data.guild.id}/ignored-users`}
|
||||||
>
|
>
|
||||||
Ignored users
|
Ignored users
|
||||||
</NavLink></NavItem
|
</NavLink>
|
||||||
>
|
|
||||||
<NavItem
|
<NavLink
|
||||||
><NavLink
|
|
||||||
href="/dash/{data.guild.id}/key-roles"
|
href="/dash/{data.guild.id}/key-roles"
|
||||||
active={$page.url.pathname === `/dash/${data.guild.id}/key-roles`}
|
active={$page.url.pathname === `/dash/${data.guild.id}/key-roles`}
|
||||||
>
|
>
|
||||||
Key roles
|
Key roles
|
||||||
</NavLink></NavItem
|
</NavLink>
|
||||||
>
|
|
||||||
</Nav>
|
</Nav>
|
||||||
|
|
||||||
{#if $page.url.pathname === `/dash/${data.guild.id}`}
|
{#if $page.url.pathname === `/dash/${data.guild.id}` || $page.url.pathname === `/dash/${data.guild.id}/ignored-channels`}
|
||||||
<Button on:click={save}>Save changes</Button>
|
<Button on:click={save} class="mb-2">Save changes</Button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
$: channels = data.guild.config as GuildChannelConfig;
|
$: channels = data.guild.config as GuildChannelConfig;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<h3>Log channels</h3>
|
||||||
|
|
||||||
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3">
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3">
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<Label><strong>Server changes</strong></Label>
|
<Label><strong>Server changes</strong></Label>
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,18 @@
|
||||||
type Option = { label: string; value: string };
|
type Option = { label: string; value: string };
|
||||||
|
|
||||||
export let options: Array<Group | Option>;
|
export let options: Array<Group | Option>;
|
||||||
|
export let multiple = false;
|
||||||
|
export let max: number | undefined = undefined;
|
||||||
export let placeholder: string = "Select a channel";
|
export let placeholder: string = "Select a channel";
|
||||||
export let value: string | null;
|
export let value: string | string[] | null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Svelecte
|
<Svelecte
|
||||||
bind:value
|
bind:value
|
||||||
{options}
|
{options}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
|
{multiple}
|
||||||
|
{max}
|
||||||
labelField="label"
|
labelField="label"
|
||||||
valueField="value"
|
valueField="value"
|
||||||
groupLabelField="label"
|
groupLabelField="label"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Label } from "@sveltestrap/sveltestrap";
|
||||||
|
import type { PageData } from "./$types";
|
||||||
|
import { makeFullOptions } from "$lib/util";
|
||||||
|
import ChannelSelect from "../ChannelSelect.svelte";
|
||||||
|
|
||||||
|
export let data: PageData;
|
||||||
|
|
||||||
|
$: ignored = data.guild.config.ignored_channels;
|
||||||
|
$: options = makeFullOptions(data.guild, ignored);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h3>Ignored channels</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Messages from ignored channels will not be logged. Note that this does not
|
||||||
|
ignore channel update events, any changes to the channel will still be logged.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="p-2">
|
||||||
|
<Label><strong>Ignored channels</strong></Label>
|
||||||
|
<ChannelSelect bind:value={ignored} {options} multiple={true} />
|
||||||
|
</div>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { ApiError, FullGuild } from "$lib/api";
|
import type { ApiError } from "$lib/api";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Label,
|
Label,
|
||||||
|
|
@ -10,60 +10,12 @@
|
||||||
import ChannelSelect from "../ChannelSelect.svelte";
|
import ChannelSelect from "../ChannelSelect.svelte";
|
||||||
import { fastFetch } from "$lib/api";
|
import { fastFetch } from "$lib/api";
|
||||||
import { addToast } from "$lib/toast";
|
import { addToast } from "$lib/toast";
|
||||||
|
import { makeFullOptions } from "$lib/util";
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
$: redirects = data.guild.config.redirects;
|
$: redirects = data.guild.config.redirects;
|
||||||
|
|
||||||
const makeSourceOptions = (
|
|
||||||
guild: FullGuild,
|
|
||||||
redirects: Record<string, string>,
|
|
||||||
) => {
|
|
||||||
const options = [];
|
|
||||||
|
|
||||||
// We shouldn't list channels that are already being redirected.
|
|
||||||
const redirectedChannels = Object.keys(redirects);
|
|
||||||
|
|
||||||
options.push(
|
|
||||||
...guild.categories
|
|
||||||
.filter((cat) => !redirectedChannels.some((k) => k === cat.id))
|
|
||||||
.map((cat) => ({
|
|
||||||
label: `${cat.name} (category)`,
|
|
||||||
value: cat.id,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter these channels
|
|
||||||
const channelsWithoutCategory = guild.channels_without_category.filter(
|
|
||||||
(c) => c.can_redirect_from && !redirectedChannels.some((k) => k === c.id),
|
|
||||||
);
|
|
||||||
if (channelsWithoutCategory.length > 0)
|
|
||||||
options.push({
|
|
||||||
label: "(no category)",
|
|
||||||
options: channelsWithoutCategory.map((c) => ({
|
|
||||||
value: c.id,
|
|
||||||
label: `#${c.name}`,
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
options.push(
|
|
||||||
...guild.categories
|
|
||||||
.map((cat) => ({
|
|
||||||
label: cat.name,
|
|
||||||
options: cat.channels
|
|
||||||
.filter(
|
|
||||||
(c) =>
|
|
||||||
c.can_redirect_from &&
|
|
||||||
!redirectedChannels.some((k) => k === c.id),
|
|
||||||
)
|
|
||||||
.map((c) => ({ value: c.id, label: `#${c.name}` })),
|
|
||||||
}))
|
|
||||||
.filter((c) => c.options.length > 0),
|
|
||||||
);
|
|
||||||
|
|
||||||
return options;
|
|
||||||
};
|
|
||||||
|
|
||||||
$: allChannels = [
|
$: allChannels = [
|
||||||
...data.guild.channels_without_category.map((c) => ({
|
...data.guild.channels_without_category.map((c) => ({
|
||||||
id: c.id,
|
id: c.id,
|
||||||
|
|
@ -78,7 +30,7 @@
|
||||||
const channelName = (id: string) =>
|
const channelName = (id: string) =>
|
||||||
allChannels.find((c) => c.id === id)?.name || `(unknown channel ${id})`;
|
allChannels.find((c) => c.id === id)?.name || `(unknown channel ${id})`;
|
||||||
|
|
||||||
$: sourceOptions = makeSourceOptions(data.guild, redirects);
|
$: sourceOptions = makeFullOptions(data.guild, Object.keys(redirects));
|
||||||
$: targetOptions = data.options;
|
$: targetOptions = data.options;
|
||||||
|
|
||||||
let source: string | null = null;
|
let source: string | null = null;
|
||||||
|
|
@ -143,7 +95,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="my-2 d-grid d-md-block">
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
disabled={!source || !target}
|
disabled={!source || !target}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue