Update schemas and resolve some warnings
This commit is contained in:
		
							
								
								
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -2645,9 +2645,9 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rocket_dyn_templates"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
version = "0.2.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "04bfc006e547e4f72b760ab861f5943b688aed8a82c4977b5500c98f5d17dbfa"
 | 
			
		||||
checksum = "5bbab919c9e67df3f7ac6624a32ef897df4cd61c0969f4d66f3ced0534660d7a"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "normpath",
 | 
			
		||||
 "notify",
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ secrecy = "0.8.0"
 | 
			
		||||
futures = "0.3.30"
 | 
			
		||||
prometheus = "0.13.3"
 | 
			
		||||
rocket = { version = "0.5.0", features = ["tls", "secrets", "json"] }
 | 
			
		||||
rocket_dyn_templates = { version = "0.1.0", features = ["tera"] }
 | 
			
		||||
rocket_dyn_templates = { version = "0.2.0", features = ["tera"] }
 | 
			
		||||
serenity = { version = "0.12", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] }
 | 
			
		||||
oauth2 = "4"
 | 
			
		||||
csv = "1.2"
 | 
			
		||||
 
 | 
			
		||||
@@ -136,9 +136,9 @@ CREATE TABLE reminders (
 | 
			
		||||
    set_by INT UNSIGNED,
 | 
			
		||||
 | 
			
		||||
    PRIMARY KEY (id),
 | 
			
		||||
    FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE RESTRICT,
 | 
			
		||||
    FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE,
 | 
			
		||||
    FOREIGN KEY (set_by) REFERENCES users(id) ON DELETE SET NULL
 | 
			
		||||
    CONSTRAINT `reminder_message_fk` FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE RESTRICT,
 | 
			
		||||
    CONSTRAINT `reminder_channel_fk` FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE,
 | 
			
		||||
    CONSTRAINT `reminder_user_fk` FOREIGN KEY (set_by) REFERENCES users(id) ON DELETE SET NULL
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
CREATE TRIGGER message_cleanup AFTER DELETE ON reminders
 | 
			
		||||
@@ -157,9 +157,9 @@ CREATE TABLE todos (
 | 
			
		||||
    value VARCHAR(2000) NOT NULL,
 | 
			
		||||
 | 
			
		||||
    PRIMARY KEY (id),
 | 
			
		||||
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
 | 
			
		||||
    FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE,
 | 
			
		||||
    FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE SET NULL
 | 
			
		||||
    CONSTRAINT todos_ibfk_5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
 | 
			
		||||
    CONSTRAINT todos_ibfk_4 FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE,
 | 
			
		||||
    CONSTRAINT todos_ibfk_3 FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE SET NULL
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
CREATE TABLE command_restrictions (
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ CREATE TABLE reminders_new (
 | 
			
		||||
    PRIMARY KEY (id),
 | 
			
		||||
 | 
			
		||||
    FOREIGN KEY (`channel_id`) REFERENCES channels (`id`) ON DELETE CASCADE,
 | 
			
		||||
    FOREIGN KEY (`set_by`) REFERENCES users (`id`) ON DELETE SET NULL
 | 
			
		||||
    CONSTRAINT `reminders_ibfk_2` FOREIGN KEY (`set_by`) REFERENCES `users` (`id`) ON DELETE SET NULL
 | 
			
		||||
 | 
			
		||||
    # disallow having a reminder as restartable if it has no interval
 | 
			
		||||
    -- , CONSTRAINT restartable_interval_mutex CHECK (`restartable` = 0 OR `interval` IS NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
-- Tables no longer needed as old dashboard is decomm.
 | 
			
		||||
DROP TABLE guild_users;
 | 
			
		||||
DROP TABLE events;
 | 
			
		||||
 | 
			
		||||
ALTER TABLE users ADD COLUMN `reset_inputs_on_create` BOOLEAN NOT NULL DEFAULT 0;
 | 
			
		||||
ALTER TABLE users ADD COLUMN `use_browser_timezone` BOOLEAN NOT NULL DEFAULT 1;
 | 
			
		||||
ALTER TABLE users ADD COLUMN `dashboard_color_scheme` ENUM('system', 'light', 'dark') NOT NULL DEFAULT 'system';
 | 
			
		||||
@@ -7,4 +11,14 @@ ALTER TABLE users DROP COLUMN `patreon`;
 | 
			
		||||
ALTER TABLE users DROP COLUMN `name`;
 | 
			
		||||
 | 
			
		||||
ALTER TABLE users DROP PRIMARY KEY, ADD PRIMARY KEY (`user`);
 | 
			
		||||
 | 
			
		||||
ALTER TABLE todos DROP CONSTRAINT todos_ibfk_5, MODIFY COLUMN user_id BIGINT UNSIGNED;
 | 
			
		||||
UPDATE todos SET user_id = (SELECT user FROM users WHERE id = user_id);
 | 
			
		||||
ALTER TABLE todos ADD CONSTRAINT todos_user_fk FOREIGN KEY (user_id) REFERENCES users(user);
 | 
			
		||||
 | 
			
		||||
ALTER TABLE reminders DROP CONSTRAINT reminders_ibfk_2, MODIFY COLUMN set_by BIGINT UNSIGNED;
 | 
			
		||||
UPDATE reminders SET set_by = (SELECT user FROM users WHERE id = set_by);
 | 
			
		||||
ALTER TABLE reminders ADD CONSTRAINT reminder_user_fk FOREIGN KEY (set_by) REFERENCES users(user);
 | 
			
		||||
 | 
			
		||||
ALTER TABLE users DROP COLUMN `id`;
 | 
			
		||||
ALTER TABLE users RENAME COLUMN `user` TO `id`;
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@
 | 
			
		||||
	<title>Reminder Bot | Dashboard</title>
 | 
			
		||||
 | 
			
		||||
	<!-- styles -->
 | 
			
		||||
	<link rel="stylesheet" href="/static/css/bulma.min.css">
 | 
			
		||||
	<link rel="stylesheet" href="/static/css/fa.css">
 | 
			
		||||
	<link rel="stylesheet" href="/static/css/font.css">
 | 
			
		||||
	<link rel="stylesheet" href="/static/css/style.css">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,27 @@
 | 
			
		||||
import axios from "axios";
 | 
			
		||||
 | 
			
		||||
enum ColorScheme {
 | 
			
		||||
    System = "system",
 | 
			
		||||
    Dark = "dark",
 | 
			
		||||
    Light = "light",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UserInfo = {
 | 
			
		||||
    name: string;
 | 
			
		||||
    patreon: boolean;
 | 
			
		||||
    preferences: {
 | 
			
		||||
        timezone: string | null;
 | 
			
		||||
        reset_inputs_on_create: boolean;
 | 
			
		||||
        dashboard_color_scheme: ColorScheme;
 | 
			
		||||
        use_browser_timezone: boolean;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type UpdateUserInfo = {
 | 
			
		||||
    timezone?: string;
 | 
			
		||||
    reset_inputs_on_create?: boolean;
 | 
			
		||||
    dashboard_color_scheme?: ColorScheme;
 | 
			
		||||
    use_browser_timezone?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type GuildInfo = {
 | 
			
		||||
@@ -110,7 +127,7 @@ export const fetchUserInfo = () => ({
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const patchUserInfo = () => ({
 | 
			
		||||
    mutationFn: (timezone: string) => axios.patch(`/dashboard/api/user`, { timezone }),
 | 
			
		||||
    mutationFn: (userInfo: UpdateUserInfo) => axios.patch(`/dashboard/api/user`, userInfo),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const fetchUserGuilds = () => ({
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,27 @@
 | 
			
		||||
import { createContext } from "preact";
 | 
			
		||||
import { useContext } from "preact/compat";
 | 
			
		||||
import { useState } from "preact/hooks";
 | 
			
		||||
import { useEffect, useState } from "preact/hooks";
 | 
			
		||||
import { DateTime } from "luxon";
 | 
			
		||||
import { fetchUserInfo } from "../../api";
 | 
			
		||||
import { useQuery } from "react-query";
 | 
			
		||||
 | 
			
		||||
type TTimezoneContext = [string, (tz: string) => void];
 | 
			
		||||
 | 
			
		||||
const TimezoneContext = createContext(["UTC", () => {}] as TTimezoneContext);
 | 
			
		||||
 | 
			
		||||
export const TimezoneProvider = ({ children }) => {
 | 
			
		||||
    const { data } = useQuery({ ...fetchUserInfo() });
 | 
			
		||||
 | 
			
		||||
    const [timezone, setTimezone] = useState(DateTime.now().zoneName);
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        setTimezone(
 | 
			
		||||
            data === undefined || data.preferences.use_browser_timezone
 | 
			
		||||
                ? DateTime.now().zoneName
 | 
			
		||||
                : data.preferences.timezone,
 | 
			
		||||
        );
 | 
			
		||||
    }, [data]);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <TimezoneContext.Provider value={[timezone, setTimezone]}>
 | 
			
		||||
            {children}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,14 +13,14 @@ export function App() {
 | 
			
		||||
    const queryClient = new QueryClient();
 | 
			
		||||
 | 
			
		||||
    let scheme = "light";
 | 
			
		||||
    if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
 | 
			
		||||
        scheme = "dark";
 | 
			
		||||
    }
 | 
			
		||||
    // if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
 | 
			
		||||
    //     scheme = "dark";
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <QueryClientProvider client={queryClient}>
 | 
			
		||||
            <TimezoneProvider>
 | 
			
		||||
                <FlashProvider>
 | 
			
		||||
                <QueryClientProvider client={queryClient}>
 | 
			
		||||
                    <Router base={"/dashboard"}>
 | 
			
		||||
                        <div class={`columns is-gapless dashboard-frame scheme-${scheme}`}>
 | 
			
		||||
                            <Sidebar />
 | 
			
		||||
@@ -52,8 +52,8 @@ export function App() {
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </Router>
 | 
			
		||||
                </QueryClientProvider>
 | 
			
		||||
                </FlashProvider>
 | 
			
		||||
            </TimezoneProvider>
 | 
			
		||||
        </QueryClientProvider>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import { useGuild } from "../App/useGuild";
 | 
			
		||||
 | 
			
		||||
export const Settings = () => {
 | 
			
		||||
    const guild = useGuild();
 | 
			
		||||
    const { isSuccess: userFetched, data: userInfo } = useQuery(fetchUserInfo());
 | 
			
		||||
    const { isSuccess: userFetched, data: userInfo } = useQuery({ ...fetchUserInfo() });
 | 
			
		||||
 | 
			
		||||
    const [reminder, setReminder] = useReminder();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,3 +26,11 @@
 | 
			
		||||
textarea.autoresize {
 | 
			
		||||
    resize: vertical !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.reminderContent {
 | 
			
		||||
    margin-top: 10px;
 | 
			
		||||
    margin-bottom: 10px;
 | 
			
		||||
    padding: 14px;
 | 
			
		||||
    background-color: #f5f5f5;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ const SidebarContent = ({ guilds }: ContentProps) => {
 | 
			
		||||
                <Brand />
 | 
			
		||||
            </a>
 | 
			
		||||
            <Wave />
 | 
			
		||||
            <aside class="menu">
 | 
			
		||||
            <aside class="menu theme-dark">
 | 
			
		||||
                <ul class="menu-list">
 | 
			
		||||
                    <li>
 | 
			
		||||
                        <Link
 | 
			
		||||
@@ -44,7 +44,6 @@ const SidebarContent = ({ guilds }: ContentProps) => {
 | 
			
		||||
                    style={{
 | 
			
		||||
                        position: "sticky",
 | 
			
		||||
                        bottom: "0px",
 | 
			
		||||
                        backgroundColor: "rgb(54, 54, 54)",
 | 
			
		||||
                    }}
 | 
			
		||||
                >
 | 
			
		||||
                    <p class="menu-label">Options</p>
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ aside.menu {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dashboard-sidebar {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    display: flex !important;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    background-color: #363636;
 | 
			
		||||
    width: 230px !important;
 | 
			
		||||
@@ -49,3 +49,19 @@ aside.menu {
 | 
			
		||||
.aside-footer {
 | 
			
		||||
    justify-self: end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu a {
 | 
			
		||||
    color: #fff !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu a:hover {
 | 
			
		||||
    color: #424242 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu .menu-label {
 | 
			
		||||
    color: #bbb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu {
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -53,10 +53,10 @@ export const TimezonePicker = () => {
 | 
			
		||||
 | 
			
		||||
const TimezoneModal = ({ setModalOpen }) => {
 | 
			
		||||
    const browserTimezone = DateTime.now().zoneName;
 | 
			
		||||
    const [selectedZone] = useTimezone();
 | 
			
		||||
    const [selectedZone, setTimezone] = useTimezone();
 | 
			
		||||
 | 
			
		||||
    const queryClient = useQueryClient();
 | 
			
		||||
    const { isLoading, isError, data } = useQuery(fetchUserInfo());
 | 
			
		||||
    const { isLoading, isError, data } = useQuery({ ...fetchUserInfo() });
 | 
			
		||||
    const userInfoMutation = useMutation({
 | 
			
		||||
        ...patchUserInfo(),
 | 
			
		||||
        onSuccess: () => {
 | 
			
		||||
@@ -79,7 +79,7 @@ const TimezoneModal = ({ setModalOpen }) => {
 | 
			
		||||
                        {isLoading ? (
 | 
			
		||||
                            <i className="fas fa-cog fa-spin"></i>
 | 
			
		||||
                        ) : (
 | 
			
		||||
                            <TimezoneDisplay timezone={data.timezone || "UTC"}></TimezoneDisplay>
 | 
			
		||||
                            <TimezoneDisplay timezone={data.preferences.timezone || "UTC"} />
 | 
			
		||||
                        )}
 | 
			
		||||
                    </>
 | 
			
		||||
                )}
 | 
			
		||||
@@ -93,10 +93,29 @@ const TimezoneModal = ({ setModalOpen }) => {
 | 
			
		||||
                        margin: "2px",
 | 
			
		||||
                    }}
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                        userInfoMutation.mutate(browserTimezone);
 | 
			
		||||
                        userInfoMutation.mutate({ timezone: browserTimezone });
 | 
			
		||||
                    }}
 | 
			
		||||
                >
 | 
			
		||||
                    Set Bot Timezone
 | 
			
		||||
                    Set bot timezone
 | 
			
		||||
                </button>
 | 
			
		||||
                <button
 | 
			
		||||
                    class="button is-success is-outlined"
 | 
			
		||||
                    id="update-bot-timezone"
 | 
			
		||||
                    style={{
 | 
			
		||||
                        margin: "2px",
 | 
			
		||||
                    }}
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                        userInfoMutation.mutate({
 | 
			
		||||
                            use_browser_timezone: !data.preferences.use_browser_timezone,
 | 
			
		||||
                        });
 | 
			
		||||
                        setTimezone(
 | 
			
		||||
                            data.preferences.use_browser_timezone
 | 
			
		||||
                                ? data.preferences.timezone
 | 
			
		||||
                                : DateTime.now().zoneName,
 | 
			
		||||
                        );
 | 
			
		||||
                    }}
 | 
			
		||||
                >
 | 
			
		||||
                    Use {data.preferences.use_browser_timezone ? "bot" : "browser"} timezone
 | 
			
		||||
                </button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </Modal>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
@import "node_modules/bulma/bulma";
 | 
			
		||||
 | 
			
		||||
/* override styles for when the div is collapsed */
 | 
			
		||||
div.reminderContent.is-collapsed .column.discord-frame {
 | 
			
		||||
    display: none;
 | 
			
		||||
@@ -47,3 +49,11 @@ div.reminderContent.is-collapsed .hide-box {
 | 
			
		||||
div.reminderContent.is-collapsed .hide-box i {
 | 
			
		||||
    transform: rotate(90deg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button.is-success:not(.is-outlined) {
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button.is-outlined.is-success:not(.is-focused, :hover, :focus) {
 | 
			
		||||
    background-color: white;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								reminder-dashboard/src/vars.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								reminder-dashboard/src/vars.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
$primary-background-light: #ffffff;
 | 
			
		||||
$secondary-background-light: #f5f5f5;
 | 
			
		||||
$contrast-background-light: #363636;
 | 
			
		||||
$primary-text-light: #4a4a4a;
 | 
			
		||||
$secondary-text-light: #4a4a4a;
 | 
			
		||||
$contrast-text-light: #ffffff;
 | 
			
		||||
 | 
			
		||||
$primary-background-dark: #363636;
 | 
			
		||||
$secondary-background-dark: #424242;
 | 
			
		||||
$contrast-background-dark: #242424;
 | 
			
		||||
$primary-text-dark: #ffffff;
 | 
			
		||||
$secondary-text-dark: #ffffff;
 | 
			
		||||
$contrast-text-dark: #ffffff;
 | 
			
		||||
@@ -17,10 +17,7 @@ impl Recordable for Options {
 | 
			
		||||
        sqlx::query!(
 | 
			
		||||
            "
 | 
			
		||||
            INSERT INTO todos (user_id, value)
 | 
			
		||||
            VALUES (
 | 
			
		||||
                (SELECT id FROM users WHERE user = ?),
 | 
			
		||||
                ?
 | 
			
		||||
            )
 | 
			
		||||
            VALUES (?, ?)
 | 
			
		||||
            ",
 | 
			
		||||
            ctx.author().id.get(),
 | 
			
		||||
            self.task
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,7 @@ impl Recordable for Options {
 | 
			
		||||
        let values = sqlx::query!(
 | 
			
		||||
            "
 | 
			
		||||
            SELECT todos.id, value FROM todos
 | 
			
		||||
            INNER JOIN users ON todos.user_id = users.id
 | 
			
		||||
            WHERE users.user = ?
 | 
			
		||||
            WHERE user_id = ?
 | 
			
		||||
            ",
 | 
			
		||||
            ctx.author().id.get(),
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -191,8 +191,7 @@ impl ComponentDataModel {
 | 
			
		||||
                        sqlx::query!(
 | 
			
		||||
                            "
 | 
			
		||||
                            SELECT todos.id, value FROM todos
 | 
			
		||||
                            INNER JOIN users ON todos.user_id = users.id
 | 
			
		||||
                            WHERE users.user = ?
 | 
			
		||||
                            WHERE user_id = ?
 | 
			
		||||
                            ",
 | 
			
		||||
                            uid,
 | 
			
		||||
                        )
 | 
			
		||||
@@ -286,8 +285,7 @@ impl ComponentDataModel {
 | 
			
		||||
                            sqlx::query!(
 | 
			
		||||
                                "
 | 
			
		||||
                                SELECT todos.id, value FROM todos
 | 
			
		||||
                            INNER JOIN users ON todos.user_id = users.id
 | 
			
		||||
                            WHERE users.user = ?
 | 
			
		||||
                                WHERE user_id = ?
 | 
			
		||||
                                ",
 | 
			
		||||
                                uid,
 | 
			
		||||
                            )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
use poise::{
 | 
			
		||||
    serenity_prelude as serenity,
 | 
			
		||||
    serenity_prelude::{ActivityData, CreateEmbed, CreateMessage, FullEvent},
 | 
			
		||||
    serenity_prelude::{CreateEmbed, CreateMessage, FullEvent},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
use poise::{serenity_prelude::model::channel::Channel, CommandInteractionType, CreateReply};
 | 
			
		||||
use poise::{CommandInteractionType, CreateReply};
 | 
			
		||||
 | 
			
		||||
use crate::{consts::MACRO_MAX_COMMANDS, models::command_macro::RecordedCommand, Context, Error};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -85,17 +85,13 @@ impl Reminder {
 | 
			
		||||
                reminders.enabled,
 | 
			
		||||
                reminders.content,
 | 
			
		||||
                reminders.embed_description,
 | 
			
		||||
                users.user AS set_by
 | 
			
		||||
                reminders.set_by
 | 
			
		||||
            FROM
 | 
			
		||||
                reminders
 | 
			
		||||
            INNER JOIN
 | 
			
		||||
                channels
 | 
			
		||||
            ON
 | 
			
		||||
                reminders.channel_id = channels.id
 | 
			
		||||
            LEFT JOIN
 | 
			
		||||
                users
 | 
			
		||||
            ON
 | 
			
		||||
                reminders.set_by = users.id
 | 
			
		||||
            WHERE
 | 
			
		||||
                reminders.uid = ?
 | 
			
		||||
            ",
 | 
			
		||||
@@ -122,17 +118,13 @@ impl Reminder {
 | 
			
		||||
                reminders.enabled,
 | 
			
		||||
                reminders.content,
 | 
			
		||||
                reminders.embed_description,
 | 
			
		||||
                users.user AS set_by
 | 
			
		||||
                reminders.set_by
 | 
			
		||||
            FROM
 | 
			
		||||
                reminders
 | 
			
		||||
            INNER JOIN
 | 
			
		||||
                channels
 | 
			
		||||
            ON
 | 
			
		||||
                reminders.channel_id = channels.id
 | 
			
		||||
            LEFT JOIN
 | 
			
		||||
                users
 | 
			
		||||
            ON
 | 
			
		||||
                reminders.set_by = users.id
 | 
			
		||||
            WHERE
 | 
			
		||||
                reminders.id = ?
 | 
			
		||||
            ",
 | 
			
		||||
@@ -166,17 +158,13 @@ impl Reminder {
 | 
			
		||||
                reminders.enabled,
 | 
			
		||||
                reminders.content,
 | 
			
		||||
                reminders.embed_description,
 | 
			
		||||
                users.user AS set_by
 | 
			
		||||
                reminders.set_by
 | 
			
		||||
            FROM
 | 
			
		||||
                reminders
 | 
			
		||||
            INNER JOIN
 | 
			
		||||
                channels
 | 
			
		||||
            ON
 | 
			
		||||
                reminders.channel_id = channels.id
 | 
			
		||||
            LEFT JOIN
 | 
			
		||||
                users
 | 
			
		||||
            ON
 | 
			
		||||
                reminders.set_by = users.id
 | 
			
		||||
            WHERE
 | 
			
		||||
                `status` = 'pending' AND
 | 
			
		||||
                channels.channel = ? AND
 | 
			
		||||
@@ -230,17 +218,13 @@ impl Reminder {
 | 
			
		||||
                            reminders.enabled,
 | 
			
		||||
                            reminders.content,
 | 
			
		||||
                            reminders.embed_description,
 | 
			
		||||
                            users.user AS set_by
 | 
			
		||||
                            reminders.set_by
 | 
			
		||||
                        FROM
 | 
			
		||||
                            reminders
 | 
			
		||||
                        LEFT JOIN
 | 
			
		||||
                            channels
 | 
			
		||||
                        ON
 | 
			
		||||
                            channels.id = reminders.channel_id
 | 
			
		||||
                        LEFT JOIN
 | 
			
		||||
                            users
 | 
			
		||||
                        ON
 | 
			
		||||
                            reminders.set_by = users.id
 | 
			
		||||
                        WHERE
 | 
			
		||||
                            `status` = 'pending' AND
 | 
			
		||||
                            FIND_IN_SET(channels.channel, ?)
 | 
			
		||||
@@ -266,17 +250,13 @@ impl Reminder {
 | 
			
		||||
                            reminders.enabled,
 | 
			
		||||
                            reminders.content,
 | 
			
		||||
                            reminders.embed_description,
 | 
			
		||||
                            users.user AS set_by
 | 
			
		||||
                            reminders.set_by
 | 
			
		||||
                        FROM
 | 
			
		||||
                            reminders
 | 
			
		||||
                        LEFT JOIN
 | 
			
		||||
                            channels
 | 
			
		||||
                        ON
 | 
			
		||||
                            channels.id = reminders.channel_id
 | 
			
		||||
                        LEFT JOIN
 | 
			
		||||
                            users
 | 
			
		||||
                        ON
 | 
			
		||||
                            reminders.set_by = users.id
 | 
			
		||||
                        WHERE
 | 
			
		||||
                            `status` = 'pending' AND
 | 
			
		||||
                            channels.guild_id = (SELECT id FROM guilds WHERE guild = ?)
 | 
			
		||||
@@ -303,20 +283,16 @@ impl Reminder {
 | 
			
		||||
                    reminders.enabled,
 | 
			
		||||
                    reminders.content,
 | 
			
		||||
                    reminders.embed_description,
 | 
			
		||||
                    users.user AS set_by
 | 
			
		||||
                    reminders.set_by
 | 
			
		||||
                FROM
 | 
			
		||||
                    reminders
 | 
			
		||||
                INNER JOIN
 | 
			
		||||
                    channels
 | 
			
		||||
                ON
 | 
			
		||||
                    channels.id = reminders.channel_id
 | 
			
		||||
                LEFT JOIN
 | 
			
		||||
                    users
 | 
			
		||||
                ON
 | 
			
		||||
                    reminders.set_by = users.id
 | 
			
		||||
                WHERE
 | 
			
		||||
                    `status` = 'pending' AND
 | 
			
		||||
                    channels.id = (SELECT dm_channel FROM users WHERE user = ?)
 | 
			
		||||
                    channels.id = (SELECT dm_channel FROM users WHERE id = ?)
 | 
			
		||||
                ",
 | 
			
		||||
                user.get()
 | 
			
		||||
            )
 | 
			
		||||
 
 | 
			
		||||
@@ -16,17 +16,15 @@ pub async fn get_guild_roles(id: u64, cookies: &CookieJar<'_>, ctx: &State<Conte
 | 
			
		||||
    offline!(Ok(json!(vec![RoleInfo { name: "@everyone".to_string(), id: "1".to_string() }])));
 | 
			
		||||
    check_authorization(cookies, ctx.inner(), id).await?;
 | 
			
		||||
 | 
			
		||||
    let roles_res = ctx.cache.guild_roles(id);
 | 
			
		||||
 | 
			
		||||
    match roles_res {
 | 
			
		||||
        Some(roles) => {
 | 
			
		||||
            let roles = roles
 | 
			
		||||
    let roles_res = ctx.cache.guild(id).map(|g| {
 | 
			
		||||
        g.roles
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|(_, r)| RoleInfo { id: r.id.to_string(), name: r.name.to_string() })
 | 
			
		||||
                .collect::<Vec<RoleInfo>>();
 | 
			
		||||
            .collect::<Vec<RoleInfo>>()
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
            Ok(json!(roles))
 | 
			
		||||
        }
 | 
			
		||||
    match roles_res {
 | 
			
		||||
        Some(roles) => Ok(json!(roles)),
 | 
			
		||||
        None => {
 | 
			
		||||
            warn!("Could not fetch roles from {}", id);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ use std::env;
 | 
			
		||||
 | 
			
		||||
use chrono_tz::Tz;
 | 
			
		||||
pub use guilds::*;
 | 
			
		||||
use log::warn;
 | 
			
		||||
pub use reminders::*;
 | 
			
		||||
use rocket::{
 | 
			
		||||
    get,
 | 
			
		||||
@@ -57,7 +58,7 @@ pub async fn get_user_info(
 | 
			
		||||
        patreon: true,
 | 
			
		||||
        preferences: UserPreferences {
 | 
			
		||||
            timezone: "UTC".to_string(),
 | 
			
		||||
            use_browser_timezone: false,
 | 
			
		||||
            use_browser_timezone: true,
 | 
			
		||||
            dashboard_color_scheme: "system".to_string(),
 | 
			
		||||
            reset_inputs_on_create: false,
 | 
			
		||||
        }
 | 
			
		||||
@@ -70,10 +71,10 @@ pub async fn get_user_info(
 | 
			
		||||
            .member(&ctx.inner(), user_id)
 | 
			
		||||
            .await;
 | 
			
		||||
 | 
			
		||||
        let prefs = sqlx::query!(
 | 
			
		||||
        let preferences = sqlx::query!(
 | 
			
		||||
            "
 | 
			
		||||
            SELECT
 | 
			
		||||
                IFNULL(timezone, 'UTC') AS timezone,
 | 
			
		||||
                timezone,
 | 
			
		||||
                use_browser_timezone,
 | 
			
		||||
                dashboard_color_scheme,
 | 
			
		||||
                reset_inputs_on_create
 | 
			
		||||
@@ -84,7 +85,20 @@ pub async fn get_user_info(
 | 
			
		||||
        )
 | 
			
		||||
        .fetch_one(pool.inner())
 | 
			
		||||
        .await
 | 
			
		||||
        .map_or(None, |q| Some(q.timezone));
 | 
			
		||||
        .map_or(
 | 
			
		||||
            UserPreferences {
 | 
			
		||||
                timezone: "UTC".to_string(),
 | 
			
		||||
                use_browser_timezone: false,
 | 
			
		||||
                dashboard_color_scheme: "system".to_string(),
 | 
			
		||||
                reset_inputs_on_create: false,
 | 
			
		||||
            },
 | 
			
		||||
            |q| UserPreferences {
 | 
			
		||||
                timezone: q.timezone,
 | 
			
		||||
                use_browser_timezone: q.use_browser_timezone != 0,
 | 
			
		||||
                dashboard_color_scheme: q.dashboard_color_scheme,
 | 
			
		||||
                reset_inputs_on_create: q.reset_inputs_on_create != 0,
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let user_info = UserInfo {
 | 
			
		||||
            name: cookies
 | 
			
		||||
@@ -95,12 +109,7 @@ pub async fn get_user_info(
 | 
			
		||||
                    .roles
 | 
			
		||||
                    .contains(&RoleId::new(env::var("PATREON_ROLE_ID").unwrap().parse().unwrap()))
 | 
			
		||||
            }),
 | 
			
		||||
            preferences: UserPreferences {
 | 
			
		||||
                timezone: prefs.timezone,
 | 
			
		||||
                use_browser_timezone: prefs.use_browser_timezone,
 | 
			
		||||
                dashboard_color_scheme: prefs.dashboard_color_scheme,
 | 
			
		||||
                reset_inputs_on_create: prefs.reset_inputs_on_create,
 | 
			
		||||
            },
 | 
			
		||||
            preferences,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        json!(user_info)
 | 
			
		||||
@@ -137,7 +146,7 @@ pub async fn update_user_info(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if let Some(dashboard_color_scheme) = &preferences.dashboard_color_scheme {
 | 
			
		||||
            if vec!["system", "light", "dark"].contains(dashboard_color_scheme) {
 | 
			
		||||
            if vec!["system", "light", "dark"].contains(&dashboard_color_scheme.as_str()) {
 | 
			
		||||
                let _ = sqlx::query!(
 | 
			
		||||
                    "
 | 
			
		||||
                    UPDATE users
 | 
			
		||||
@@ -154,10 +163,42 @@ pub async fn update_user_info(
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // todo handle other two options
 | 
			
		||||
        if let Some(reset_inputs_on_create) = &preferences.reset_inputs_on_create {
 | 
			
		||||
            let _ = sqlx::query!(
 | 
			
		||||
                "
 | 
			
		||||
                UPDATE users
 | 
			
		||||
                SET reset_inputs_on_create = ?
 | 
			
		||||
                WHERE id = ?
 | 
			
		||||
                ",
 | 
			
		||||
                reset_inputs_on_create,
 | 
			
		||||
                user_id,
 | 
			
		||||
            )
 | 
			
		||||
            .execute(transaction.executor())
 | 
			
		||||
            .await;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        transaction.commit().await;
 | 
			
		||||
        json!({})
 | 
			
		||||
        if let Some(use_browser_timezone) = &preferences.use_browser_timezone {
 | 
			
		||||
            let _ = sqlx::query!(
 | 
			
		||||
                "
 | 
			
		||||
                UPDATE users
 | 
			
		||||
                SET use_browser_timezone = ?
 | 
			
		||||
                WHERE id = ?
 | 
			
		||||
                ",
 | 
			
		||||
                use_browser_timezone,
 | 
			
		||||
                user_id,
 | 
			
		||||
            )
 | 
			
		||||
            .execute(transaction.executor())
 | 
			
		||||
            .await;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        match transaction.commit().await {
 | 
			
		||||
            Ok(_) => json!({}),
 | 
			
		||||
            Err(e) => {
 | 
			
		||||
                warn!("Error updating user preferences for {}: {:?}", user_id, e);
 | 
			
		||||
 | 
			
		||||
                json!({"error": "Couldn't update preferences"})
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        json!({"error": "Not authorized"})
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -593,18 +593,11 @@ pub(crate) async fn create_reminder(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn check_channel_matches_guild(ctx: &Context, channel_id: ChannelId, guild_id: GuildId) -> bool {
 | 
			
		||||
    // validate channel
 | 
			
		||||
    let channel = channel_id.to_channel_cached(&ctx.cache);
 | 
			
		||||
    let channel_exists = channel.is_some();
 | 
			
		||||
    return match ctx.cache.guild(guild_id) {
 | 
			
		||||
        Some(guild) => guild.channels.get(&channel_id).is_some(),
 | 
			
		||||
 | 
			
		||||
    if !channel_exists {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let channel_matches_guild =
 | 
			
		||||
        channel.map_or(false, |c| c.guild(&ctx.cache).map_or(false, |g| g.id == guild_id));
 | 
			
		||||
 | 
			
		||||
    channel_matches_guild
 | 
			
		||||
        None => false,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn create_database_channel(
 | 
			
		||||
 
 | 
			
		||||
@@ -100,14 +100,6 @@ div.split-controls {
 | 
			
		||||
    flex-basis: 50%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.reminderContent {
 | 
			
		||||
    margin-top: 10px;
 | 
			
		||||
    margin-bottom: 10px;
 | 
			
		||||
    padding: 14px;
 | 
			
		||||
    background-color: #f5f5f5;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.left-pad {
 | 
			
		||||
    padding-left: 1rem;
 | 
			
		||||
    padding-right: 0.2rem;
 | 
			
		||||
@@ -214,18 +206,6 @@ div.dashboard-frame {
 | 
			
		||||
    min-width: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu a {
 | 
			
		||||
    color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu .menu-label {
 | 
			
		||||
    color: #bbb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu {
 | 
			
		||||
    padding-left: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dashboard-navbar {
 | 
			
		||||
    background-color: #8fb677 !important;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
@@ -680,14 +660,6 @@ div.reminderError .reminderMessage {
 | 
			
		||||
    margin: 0 12px 12px 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button.is-success:not(.is-outlined) {
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button.is-outlined.is-success {
 | 
			
		||||
    background-color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a.switch-pane {
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
@@ -733,27 +705,3 @@ a.switch-pane.is-active ~ .guild-submenu {
 | 
			
		||||
.is-locked .field:last-of-type {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.stat-row {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.stat-box {
 | 
			
		||||
    flex-grow: 1;
 | 
			
		||||
    border-radius: 6px;
 | 
			
		||||
    background-color: #fcfcfc;
 | 
			
		||||
    border-color: #efefef;
 | 
			
		||||
    border-style: solid;
 | 
			
		||||
    border-width: 1px;
 | 
			
		||||
    margin: 4px;
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.figure {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.figure-num {
 | 
			
		||||
    font-size: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user