Compare commits
152
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a6b65f3a3 | ||
|
|
b6ff149d51 | ||
|
|
748e33566b | ||
|
|
d7e90614c8 | ||
|
|
b5dbfe336d | ||
|
|
218be2f0b1 | ||
|
|
d7515f3611 | ||
|
|
6ae1096d79 | ||
|
|
1f0d7adae3 | ||
|
|
fc96ae526f | ||
|
|
8881ef0f85 | ||
|
|
5e82a687f9 | ||
|
|
de4ecf8dd6 | ||
|
|
064efd4386 | ||
|
|
65b8ba3b47 | ||
|
|
9d452ed8cb | ||
|
|
441419b92b | ||
|
|
aecf2c15be | ||
|
|
79da56c794 | ||
|
|
ef10902c1e | ||
|
|
c277f85c2a | ||
|
|
035653c7fa | ||
|
|
6358bc3deb | ||
|
|
9f5066f982 | ||
|
|
1d06999e41 | ||
|
|
1cf707140c | ||
|
|
e38c63f5ba | ||
|
|
d52b8b26f2 | ||
|
|
bb2128a7ed | ||
|
|
5e99a6f9de | ||
|
|
5406e6b8ec | ||
|
|
4ee0bc4e37 | ||
|
|
b99bb7dcbf | ||
|
|
98f925dc84 | ||
|
|
24e316b12f | ||
|
|
4063334953 | ||
|
|
e128b9848f | ||
|
|
9989ab3b35 | ||
|
|
b951db3f55 | ||
|
|
884a47bf36 | ||
|
|
b0f932445c | ||
|
|
2861cdda0b | ||
|
|
7ba8fcd6b7 | ||
|
|
850f0fad57 | ||
|
|
a770a17ee7 | ||
|
|
d15a66d9d9 | ||
|
|
30f011fcd5 | ||
|
|
15dbed2f0f | ||
|
|
18cac0345b | ||
|
|
334b1bc084 | ||
|
|
ba3c76c25f | ||
|
|
67b6f30c62 | ||
|
|
8ae311190f | ||
|
|
016164affb | ||
|
|
2c0aeef700 | ||
|
|
ecd75d6f55 | ||
|
|
4a80d42f86 | ||
|
|
075fde71df | ||
|
|
55136aecdc | ||
|
|
63fc2cdcbc | ||
|
|
3190738fc5 | ||
|
|
8f4810b532 | ||
|
|
a5e6c41fa5 | ||
|
|
5f0aa0f834 | ||
|
|
dbe8e8e358 | ||
|
|
85a114e55c | ||
|
|
329492b244 | ||
|
|
66135ecd08 | ||
|
|
382c2a5a1e | ||
|
|
b91245a3f7 | ||
|
|
6f0bdf9852 | ||
|
|
dcee9e0d2a | ||
|
|
8e6e1a18b7 | ||
|
|
72af0532fa | ||
|
|
e83b643d86 | ||
|
|
0e0ab053f3 | ||
|
|
8c2296b9c8 | ||
|
|
1c6103142f | ||
|
|
328127c55e | ||
|
|
b0e37b56c0 | ||
|
|
45f5b6261a | ||
|
|
5f6326179c | ||
|
|
6254f91841 | ||
|
|
60b90a61d4 | ||
|
|
90f05758d0 | ||
|
|
74b7b5d711 | ||
|
|
90550dc2c7 | ||
|
|
79e6498245 | ||
|
|
a8ef3d03f9 | ||
|
|
53e13844f9 | ||
|
|
dd7e681285 | ||
|
|
6c20bf2a0f | ||
|
|
15aa9ccffd | ||
|
|
525471bcad | ||
|
|
86d53b63b6 | ||
|
|
d8f266852a | ||
|
|
76a286076b | ||
|
|
5e39e16060 | ||
|
|
c1305cfb36 | ||
|
|
4823754955 | ||
|
|
eb92eacb90 | ||
|
|
d0833b7bca | ||
|
|
b81c3c80c1 | ||
|
|
2f6d035efe | ||
|
|
96012ce43c | ||
|
|
fa7ec8731b | ||
|
|
def43bfa78 | ||
|
|
e4e9af2bb4 | ||
|
|
cce0de7c75 | ||
|
|
e7803b98e8 | ||
|
|
7aae246388 | ||
|
|
a2d442bc54 | ||
|
|
59982df827 | ||
|
|
7a6372ed02 | ||
|
|
14a54471f7 | ||
|
|
5d3b77f1cd | ||
|
|
1d64c8bb79 | ||
|
|
8ba0f02b98 | ||
|
|
d36438c6ce | ||
|
|
e0c60e2ce3 | ||
|
|
e7160215b0 | ||
|
|
6eaa6f0f28 | ||
|
|
9db0fa2513 | ||
|
|
ca13fd4fa7 | ||
|
|
55acc8fd16 | ||
|
|
145711fa5d | ||
|
|
5524215786 | ||
|
|
e8bd05893f | ||
|
|
e3d3418f99 | ||
|
|
2681280a39 | ||
|
|
00579428a1 | ||
|
|
b8ef999710 | ||
|
|
e8f84e281a | ||
|
|
8ddff698e5 | ||
|
|
541633270c | ||
|
|
25286da5e0 | ||
|
|
4bad1324b9 | ||
|
|
bd1462a00c | ||
|
|
56ffc43616 | ||
|
|
52cf642455 | ||
|
|
0bf578357a | ||
|
|
6e9eccb62e | ||
|
|
6ea28284ce | ||
|
|
a6525f3052 | ||
|
|
348639270d | ||
|
|
37177c2431 | ||
|
|
8587bed703 | ||
|
|
6c9af1ae8e | ||
|
|
7695b7a476 | ||
|
|
651da7b28e | ||
|
|
eb086146bf | ||
|
|
4ebd705e5e |
No files matched your search
+26
-3
@@ -1,7 +1,30 @@
|
|||||||
/target
|
target
|
||||||
.env
|
.env
|
||||||
/venv
|
/venv
|
||||||
.cargo
|
.cargo
|
||||||
/.idea
|
.idea
|
||||||
|
web/static/index.html
|
||||||
|
web/static/assets
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
node_modules/
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
Generated
+1697
-1122
File diff suppressed because it is too large.
Load diff
+31
-18
@@ -1,22 +1,21 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "reminder-rs"
|
name = "reminder-rs"
|
||||||
version = "1.6.36"
|
version = "1.7.27"
|
||||||
authors = ["Jude Southworth <judesouthworth@pm.me>"]
|
authors = ["Jude Southworth <judesouthworth@pm.me>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0 only"
|
license = "AGPL-3.0 only"
|
||||||
description = "Reminder Bot for Discord, now in Rust"
|
description = "Reminder Bot for Discord, now in Rust"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
poise = "0.5.5"
|
poise = "0.6.1"
|
||||||
dotenv = "0.15"
|
dotenv = "0.15"
|
||||||
tokio = { version = "1", features = ["process", "full"] }
|
tokio = { version = "1", features = ["process", "full"] }
|
||||||
reqwest = "0.11"
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
lazy-regex = "2.3.0"
|
regex = "1.10"
|
||||||
regex = "1.6"
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.10"
|
env_logger = "0.11"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
chrono-tz = { version = "0.8", features = ["serde"] }
|
chrono-tz = { version = "0.9", features = ["serde"] }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
num-integer = "0.1"
|
num-integer = "0.1"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
@@ -25,14 +24,23 @@ serde_repr = "0.1"
|
|||||||
rmp-serde = "1.1"
|
rmp-serde = "1.1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
levenshtein = "1.0"
|
levenshtein = "1.0"
|
||||||
sqlx = { version = "0.6", features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal", "chrono", "migrate"]}
|
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal", "chrono", "migrate"] }
|
||||||
base64 = "0.21.0"
|
base64 = "0.22"
|
||||||
|
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"] }
|
||||||
|
serenity = { version = "0.12", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] }
|
||||||
|
oauth2 = "4"
|
||||||
|
csv = "1.2"
|
||||||
|
sd-notify = "0.4.1"
|
||||||
|
|
||||||
[dependencies.postman]
|
[dependencies.extract_derive]
|
||||||
path = "postman"
|
path = "extract_derive"
|
||||||
|
|
||||||
[dependencies.reminder_web]
|
[dependencies.recordable_derive]
|
||||||
path = "web"
|
path = "recordable_derive"
|
||||||
|
|
||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
depends = "$auto, python3-dateparser (>= 1.0.0)"
|
depends = "$auto, python3-dateparser (>= 1.0.0)"
|
||||||
@@ -40,13 +48,18 @@ suggests = "mysql-server-8.0, nginx"
|
|||||||
maintainer-scripts = "debian"
|
maintainer-scripts = "debian"
|
||||||
assets = [
|
assets = [
|
||||||
["target/release/reminder-rs", "usr/bin/reminder-rs", "755"],
|
["target/release/reminder-rs", "usr/bin/reminder-rs", "755"],
|
||||||
|
["static/css/*", "lib/reminder-rs/static/css", "644"],
|
||||||
|
["static/favicon/*", "lib/reminder-rs/static/favicon", "644"],
|
||||||
|
["static/img/*", "lib/reminder-rs/static/img", "644"],
|
||||||
|
["static/js/*", "lib/reminder-rs/static/js", "644"],
|
||||||
|
["static/webfonts/*", "lib/reminder-rs/static/webfonts", "644"],
|
||||||
|
["static/site.webmanifest", "lib/reminder-rs/static/site.webmanifest", "644"],
|
||||||
|
["templates/**/*", "lib/reminder-rs/templates", "644"],
|
||||||
|
["reminder-dashboard/dist/static/assets/*", "lib/reminder-rs/static/assets", "644"],
|
||||||
|
["reminder-dashboard/dist/index.html", "lib/reminder-rs/static/index.html", "644"],
|
||||||
["conf/default.env", "etc/reminder-rs/config.env", "600"],
|
["conf/default.env", "etc/reminder-rs/config.env", "600"],
|
||||||
["conf/Rocket.toml", "etc/reminder-rs/Rocket.toml", "600"],
|
["conf/Rocket.toml", "etc/reminder-rs/Rocket.toml", "600"],
|
||||||
["$OUT_DIR/web/static/**/*", "lib/reminder-rs/static", "644"],
|
# ["nginx/reminder-rs", "etc/nginx/sites-available/reminder-rs", "755"]
|
||||||
["web/templates/**/*", "lib/reminder-rs/templates", "644"],
|
|
||||||
["healthcheck", "lib/reminder-rs/healthcheck", "755"],
|
|
||||||
["cron.d/reminder_health", "etc/cron.d/reminder_health", "644"],
|
|
||||||
# ["nginx/reminder-rs", "etc/nginx/sites-available/reminder-rs", "755"]
|
|
||||||
]
|
]
|
||||||
conf-files = [
|
conf-files = [
|
||||||
"/etc/reminder-rs/config.env",
|
"/etc/reminder-rs/config.env",
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@ ENV RUSTUP_HOME=/usr/local/rustup \
|
|||||||
CARGO_HOME=/usr/local/cargo \
|
CARGO_HOME=/usr/local/cargo \
|
||||||
PATH=/usr/local/cargo/bin:$PATH
|
PATH=/usr/local/cargo/bin:$PATH
|
||||||
|
|
||||||
RUN apt update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt install -y gcc gcc-multilib cmake pkg-config libssl-dev curl mysql-client-8.0
|
RUN apt update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt install -y gcc gcc-multilib cmake pkg-config libssl-dev curl mysql-client-8.0 npm
|
||||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --profile minimal --default-toolchain nightly
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --profile minimal --default-toolchain nightly
|
||||||
RUN cargo install cargo-deb
|
RUN cargo install cargo-deb
|
||||||
+11
-11
@@ -1,28 +1,28 @@
|
|||||||
[default]
|
[default]
|
||||||
address = "0.0.0.0"
|
address = "0.0.0.0"
|
||||||
port = 18920
|
port = 18920
|
||||||
template_dir = "web/templates"
|
template_dir = "templates"
|
||||||
limits = { json = "10MiB" }
|
limits = { json = "10MiB" }
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
secret_key = "tR8krio5FXTnnyIZNiJDXPondz0kI1v6X6BXZcBGIRY="
|
secret_key = "tR8krio5FXTnnyIZNiJDXPondz0kI1v6X6BXZcBGIRY="
|
||||||
|
|
||||||
[debug.tls]
|
[debug.tls]
|
||||||
certs = "web/private/rsa_sha256_cert.pem"
|
certs = "private/rsa_sha256_cert.pem"
|
||||||
key = "web/private/rsa_sha256_key.pem"
|
key = "private/rsa_sha256_key.pem"
|
||||||
|
|
||||||
[debug.rsa_sha256.tls]
|
[debug.rsa_sha256.tls]
|
||||||
certs = "web/private/rsa_sha256_cert.pem"
|
certs = "private/rsa_sha256_cert.pem"
|
||||||
key = "web/private/rsa_sha256_key.pem"
|
key = "private/rsa_sha256_key.pem"
|
||||||
|
|
||||||
[debug.ecdsa_nistp256_sha256.tls]
|
[debug.ecdsa_nistp256_sha256.tls]
|
||||||
certs = "web/private/ecdsa_nistp256_sha256_cert.pem"
|
certs = "private/ecdsa_nistp256_sha256_cert.pem"
|
||||||
key = "web/private/ecdsa_nistp256_sha256_key_pkcs8.pem"
|
key = "private/ecdsa_nistp256_sha256_key_pkcs8.pem"
|
||||||
|
|
||||||
[debug.ecdsa_nistp384_sha384.tls]
|
[debug.ecdsa_nistp384_sha384.tls]
|
||||||
certs = "web/private/ecdsa_nistp384_sha384_cert.pem"
|
certs = "private/ecdsa_nistp384_sha384_cert.pem"
|
||||||
key = "web/private/ecdsa_nistp384_sha384_key_pkcs8.pem"
|
key = "private/ecdsa_nistp384_sha384_key_pkcs8.pem"
|
||||||
|
|
||||||
[debug.ed25519.tls]
|
[debug.ed25519.tls]
|
||||||
certs = "web/private/ed25519_cert.pem"
|
certs = "private/ed25519_cert.pem"
|
||||||
key = "eb/private/ed25519_key.pem"
|
key = "private/ed25519_key.pem"
|
||||||
@@ -1,99 +1,13 @@
|
|||||||
#[cfg(not(debug_assertions))]
|
use std::{path::Path, process::Command};
|
||||||
use std::{
|
|
||||||
env, fs,
|
|
||||||
fs::{create_dir_all, DirEntry, File},
|
|
||||||
io,
|
|
||||||
io::Write,
|
|
||||||
path::Path,
|
|
||||||
process::Command,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> {
|
|
||||||
if dir.is_dir() {
|
|
||||||
for entry in fs::read_dir(dir)? {
|
|
||||||
let entry = entry?;
|
|
||||||
let path = entry.path();
|
|
||||||
if path.is_dir() {
|
|
||||||
visit_dirs(&path, cb)?;
|
|
||||||
} else {
|
|
||||||
cb(&entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
fn process_static(file: &DirEntry) {
|
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
|
||||||
let path = file.path();
|
|
||||||
|
|
||||||
let in_path = path.to_str().unwrap();
|
|
||||||
let art_path = format!("{}/{}", out_dir, in_path);
|
|
||||||
let art_dir = format!("{}/{}", out_dir, path.parent().unwrap().to_str().unwrap());
|
|
||||||
|
|
||||||
match path.extension().map(|o| o.to_str()).flatten() {
|
|
||||||
Some("ts") => {}
|
|
||||||
Some("js") => {
|
|
||||||
create_dir_all(art_dir).unwrap();
|
|
||||||
|
|
||||||
if art_path.ends_with(".min.js") {
|
|
||||||
Command::new("cp").arg(in_path).arg(art_path).spawn().expect("Could not copy");
|
|
||||||
} else {
|
|
||||||
let minified = Command::new("npx")
|
|
||||||
.arg("minify")
|
|
||||||
.arg(in_path)
|
|
||||||
.output()
|
|
||||||
.expect("Could not minify");
|
|
||||||
|
|
||||||
let mut fh = File::create(art_path).expect("Couldn't create file");
|
|
||||||
fh.write(&minified.stdout).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some("css") => {
|
|
||||||
create_dir_all(art_dir).unwrap();
|
|
||||||
|
|
||||||
if art_path.ends_with(".min.css") {
|
|
||||||
Command::new("cp").arg(in_path).arg(art_path).spawn().expect("Could not copy");
|
|
||||||
} else {
|
|
||||||
let minified = Command::new("npx")
|
|
||||||
.arg("minify")
|
|
||||||
.arg(in_path)
|
|
||||||
.output()
|
|
||||||
.expect("Could not minify");
|
|
||||||
|
|
||||||
let mut fh = File::create(art_path).expect("Couldn't create file");
|
|
||||||
fh.write(&minified.stdout).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
create_dir_all(art_dir).unwrap();
|
|
||||||
|
|
||||||
Command::new("cp").arg(in_path).arg(art_path).spawn().expect("Could not copy");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn compile_tsc(file: &DirEntry) {
|
|
||||||
// if path.extension() == Some("ts") {
|
|
||||||
// let out_dir = env::var("OUT_DIR").unwrap();
|
|
||||||
// let path = file.path();
|
|
||||||
//
|
|
||||||
// Command::new("npx")
|
|
||||||
// .arg("tsc")
|
|
||||||
// .arg(in_path)
|
|
||||||
// .arg(art_path)
|
|
||||||
// .spawn()
|
|
||||||
// .expect("Could not compile");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=migrations");
|
println!("cargo:rerun-if-changed=migrations");
|
||||||
|
println!("cargo:rerun-if-changed=reminder-dashboard");
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
Command::new("npm")
|
||||||
visit_dirs("web/static".as_ref(), &process_static).unwrap();
|
.arg("run")
|
||||||
|
.arg("build")
|
||||||
// visit_dirs("web/static".as_ref(), &compile_tsc).unwrap();
|
.current_dir(Path::new("reminder-dashboard"))
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to build NPM");
|
||||||
}
|
}
|
||||||
Generated
+46
@@ -0,0 +1,46 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "extract_macro"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.78"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.49"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "extract_derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.35"
|
||||||
|
syn = { version = "2.0.49", features = ["full"] }
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
use proc_macro::TokenStream;
|
||||||
|
use syn::{spanned::Spanned, Data, Fields};
|
||||||
|
|
||||||
|
#[proc_macro_derive(Extract)]
|
||||||
|
pub fn extract(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = syn::parse_macro_input!(input);
|
||||||
|
|
||||||
|
impl_extract(&ast)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn impl_extract(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
let name = &ast.ident;
|
||||||
|
|
||||||
|
match &ast.data {
|
||||||
|
// Dispatch over struct: extract args directly from context
|
||||||
|
Data::Struct(st) => match &st.fields {
|
||||||
|
Fields::Named(fields) => {
|
||||||
|
let extracted = fields.named.iter().map(|field| {
|
||||||
|
let ident = &field.ident;
|
||||||
|
let ty = &field.ty;
|
||||||
|
|
||||||
|
quote::quote_spanned! {field.span()=>
|
||||||
|
#ident : crate::utils::extract_arg!(ctx, #ident, #ty)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TokenStream::from(quote::quote! {
|
||||||
|
impl Extract for #name {
|
||||||
|
fn extract(ctx: crate::ApplicationContext) -> Self {
|
||||||
|
Self {
|
||||||
|
#(#extracted,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Fields::Unit => TokenStream::from(quote::quote! {
|
||||||
|
impl Extract for #name {
|
||||||
|
fn extract(ctx: crate::ApplicationContext) -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_ => {
|
||||||
|
panic!("Only named/unit structs can derive Extract");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
panic!("Only structs can derive Extract");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export $(grep -v '^#' /etc/reminder-rs/config.env | xargs -d '\n')
|
|
||||||
|
|
||||||
REGEX='mysql://([A-Za-z]+)@(.+)/(.+)'
|
|
||||||
[[ $DATABASE_URL =~ $REGEX ]]
|
|
||||||
|
|
||||||
VAR=$(mysql -u "${BASH_REMATCH[1]}" -h "${BASH_REMATCH[2]}" -N -D "${BASH_REMATCH[3]}" -e "SELECT COUNT(1) FROM reminders WHERE utc_time < NOW() - INTERVAL 10 MINUTE AND enabled = 1 AND status = 'pending'")
|
|
||||||
|
|
||||||
if [ "$VAR" -gt 0 ]
|
|
||||||
then
|
|
||||||
echo "This is to inform that there is a reminder backlog which must be resolved." | mail -s "Backlog: $VAR" "$REPORT_EMAIL"
|
|
||||||
fi
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `reminder_template` ADD COLUMN `interval_seconds` INT UNSIGNED;
|
||||||
|
ALTER TABLE `reminder_template` ADD COLUMN `interval_days` INT UNSIGNED;
|
||||||
|
ALTER TABLE `reminder_template` ADD COLUMN `interval_months` INT UNSIGNED;
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
CREATE TABLE command_macro (
|
||||||
|
id INT UNSIGNED AUTO_INCREMENT,
|
||||||
|
guild_id INT UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
description VARCHAR(100),
|
||||||
|
commands JSON NOT NULL,
|
||||||
|
|
||||||
|
FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
# New JSON structure is {command_name: "Remind", "<option name>": "<option value>", ...}
|
||||||
|
INSERT INTO command_macro (guild_id, description, name, commands)
|
||||||
|
SELECT
|
||||||
|
guild_id,
|
||||||
|
description,
|
||||||
|
name,
|
||||||
|
(
|
||||||
|
SELECT JSON_ARRAYAGG(
|
||||||
|
(
|
||||||
|
SELECT JSON_OBJECTAGG(t2.name, t2.value)
|
||||||
|
FROM JSON_TABLE(
|
||||||
|
JSON_ARRAY_APPEND(t1.options, '$', JSON_OBJECT('name', 'command_name', 'value', t1.command_name)),
|
||||||
|
'$[*]' COLUMNS (
|
||||||
|
name VARCHAR(64) PATH '$.name' ERROR ON ERROR,
|
||||||
|
value TEXT PATH '$.value' ERROR ON ERROR
|
||||||
|
)) AS t2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
FROM macro m2
|
||||||
|
JOIN JSON_TABLE(
|
||||||
|
commands,
|
||||||
|
'$[*]' COLUMNS (
|
||||||
|
command_name VARCHAR(64) PATH '$.command_name' ERROR ON ERROR,
|
||||||
|
options JSON PATH '$.options' ERROR ON ERROR
|
||||||
|
)) AS t1
|
||||||
|
WHERE m1.id = m2.id
|
||||||
|
)
|
||||||
|
FROM macro m1;
|
||||||
|
|
||||||
|
# # Check which commands are used in macros
|
||||||
|
# SELECT DISTINCT command_name
|
||||||
|
# FROM macro m2
|
||||||
|
# JOIN JSON_TABLE(
|
||||||
|
# commands,
|
||||||
|
# '$[*]' COLUMNS (
|
||||||
|
# command_name VARCHAR(64) PATH '$.command_name' ERROR ON ERROR,
|
||||||
|
# options JSON PATH '$.options' ERROR ON ERROR
|
||||||
|
# )) AS t1
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
ALTER TABLE reminders
|
||||||
|
ADD INDEX `utc_time_index` (`utc_time`);
|
||||||
|
ALTER TABLE reminders
|
||||||
|
ADD INDEX `status_index` (`status`);
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
server {
|
||||||
|
server_name www.reminder-bot.com;
|
||||||
|
|
||||||
|
return 301 https://reminder-bot.com$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name beta.reminder-bot.com;
|
||||||
|
|
||||||
|
return 301 https://reminder-bot.com$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name beta.reminder-bot.com;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/beta.reminder-bot.com/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/beta.reminder-bot.com/privkey.pem;
|
||||||
|
|
||||||
|
return 301 https://reminder-bot.com$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name reminder-bot.com;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/reminder-bot.com/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/reminder-bot.com/privkey.pem;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log;
|
||||||
|
error_log /var/log/nginx/error.log;
|
||||||
|
|
||||||
|
proxy_buffer_size 128k;
|
||||||
|
proxy_buffers 4 256k;
|
||||||
|
proxy_busy_buffers_size 256k;
|
||||||
|
|
||||||
|
client_max_body_size 10M;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:18920;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /static {
|
||||||
|
alias /var/www/reminder-rs/static;
|
||||||
|
expires 30d;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
server {
|
|
||||||
server_name www.reminder-bot.com;
|
|
||||||
|
|
||||||
return 301 $scheme://reminder-bot.com$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name reminder-bot.com;
|
|
||||||
|
|
||||||
return 301 https://reminder-bot.com$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name reminder-bot.com;
|
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/reminder-bot.com/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/reminder-bot.com/privkey.pem;
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log;
|
|
||||||
error_log /var/log/nginx/error.log;
|
|
||||||
|
|
||||||
proxy_buffer_size 128k;
|
|
||||||
proxy_buffers 4 256k;
|
|
||||||
proxy_busy_buffers_size 256k;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://localhost:18920;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /static {
|
|
||||||
alias /var/www/reminder-rs/static;
|
|
||||||
expires 30d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Generated
-485
@@ -1,485 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "reminder-rs",
|
|
||||||
"lockfileVersion": 3,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"devDependencies": {
|
|
||||||
"minify": "^10.3.0",
|
|
||||||
"prettier": "^3.0.1",
|
|
||||||
"tsc": "^2.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
|
||||||
"version": "0.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
|
||||||
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@jridgewell/set-array": "^1.0.1",
|
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
|
||||||
"@jridgewell/trace-mapping": "^0.3.9"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jridgewell/resolve-uri": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jridgewell/set-array": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jridgewell/source-map": {
|
|
||||||
"version": "0.3.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
|
|
||||||
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@jridgewell/gen-mapping": "^0.3.0",
|
|
||||||
"@jridgewell/trace-mapping": "^0.3.9"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
|
||||||
"version": "1.4.15",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
|
||||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
|
||||||
"version": "0.3.19",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
|
|
||||||
"integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@putout/minify": {
|
|
||||||
"version": "1.49.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@putout/minify/-/minify-1.49.0.tgz",
|
|
||||||
"integrity": "sha512-T/eS9rJC0tgq/s8uLpB0cpbsUaY7KSML3UbvPri2qjVCcEK/qwi8+lNWdp8VSyOWiC25Ntrt/DewOu6dXRX1ng==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/acorn": {
|
|
||||||
"version": "8.10.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
|
||||||
"integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"acorn": "bin/acorn"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/buffer-from": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/camel-case": {
|
|
||||||
"version": "4.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
|
|
||||||
"integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"pascal-case": "^3.1.2",
|
|
||||||
"tslib": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/clean-css": {
|
|
||||||
"version": "5.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz",
|
|
||||||
"integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"source-map": "~0.6.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/commander": {
|
|
||||||
"version": "10.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
|
||||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/css-b64-images": {
|
|
||||||
"version": "0.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz",
|
|
||||||
"integrity": "sha512-TgQBEdP07adhrDfXvI5o6bHGukKBNMzp2Ngckc/6d09zpjD2gc1Hl3Ca1CKgb8FXjHi88+Phv2Uegs2kTL4zjg==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"css-b64-images": "bin/css-b64-images"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
|
||||||
"version": "4.3.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"ms": "2.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"supports-color": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dot-case": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"no-case": "^3.0.4",
|
|
||||||
"tslib": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/entities": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
|
||||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/find-up": {
|
|
||||||
"version": "6.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
|
|
||||||
"integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"locate-path": "^7.1.0",
|
|
||||||
"path-exists": "^5.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/html-minifier-terser": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz",
|
|
||||||
"integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"camel-case": "^4.1.2",
|
|
||||||
"clean-css": "~5.3.2",
|
|
||||||
"commander": "^10.0.0",
|
|
||||||
"entities": "^4.4.0",
|
|
||||||
"param-case": "^3.0.4",
|
|
||||||
"relateurl": "^0.2.7",
|
|
||||||
"terser": "^5.15.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"html-minifier-terser": "cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^14.13.1 || >=16.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/jju": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
|
|
||||||
"integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/locate-path": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
|
|
||||||
"integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"p-locate": "^6.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/lower-case": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/minify": {
|
|
||||||
"version": "10.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/minify/-/minify-10.3.0.tgz",
|
|
||||||
"integrity": "sha512-eRkx2J1ykkGBVi1gI2sksmovWFzts+GYi2u3Jd/S5eNIkzj0pidciICsWRWdTKTLZVFUP7b6IvoAzasvQkMicg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@putout/minify": "^1.0.4",
|
|
||||||
"clean-css": "^5.0.1",
|
|
||||||
"css-b64-images": "~0.2.5",
|
|
||||||
"debug": "^4.1.0",
|
|
||||||
"find-up": "^6.1.0",
|
|
||||||
"html-minifier-terser": "^7.1.0",
|
|
||||||
"readjson": "^2.2.2",
|
|
||||||
"simport": "^1.2.0",
|
|
||||||
"try-catch": "^3.0.0",
|
|
||||||
"try-to-catch": "^3.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"minify": "bin/minify.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ms": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/no-case": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"lower-case": "^2.0.2",
|
|
||||||
"tslib": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/p-limit": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"yocto-queue": "^1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/p-locate": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"p-limit": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/param-case": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"dot-case": "^3.0.4",
|
|
||||||
"tslib": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pascal-case": {
|
|
||||||
"version": "3.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
|
|
||||||
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"no-case": "^3.0.4",
|
|
||||||
"tslib": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/path-exists": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/prettier": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"prettier": "bin/prettier.cjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/readjson": {
|
|
||||||
"version": "2.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/readjson/-/readjson-2.2.2.tgz",
|
|
||||||
"integrity": "sha512-PdeC9tsmLWBiL8vMhJvocq+OezQ3HhsH2HrN7YkhfYcTjQSa/iraB15A7Qvt7Xpr0Yd2rDNt6GbFwVQDg3HcAw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"jju": "^1.4.0",
|
|
||||||
"try-catch": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/relateurl": {
|
|
||||||
"version": "0.2.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
|
|
||||||
"integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/simport": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/simport/-/simport-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-85Bm7pKsqiiQ8rmYCaPDdlXZjJvuW6/k/FY8MTtLFMgU7f8S00CgTHfRtWB6KwSb6ek4p9YyG2enG1+yJbl+CA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"readjson": "^2.2.0",
|
|
||||||
"try-to-catch": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/source-map": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/source-map-support": {
|
|
||||||
"version": "0.5.21",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
|
||||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"buffer-from": "^1.0.0",
|
|
||||||
"source-map": "^0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/terser": {
|
|
||||||
"version": "5.19.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz",
|
|
||||||
"integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@jridgewell/source-map": "^0.3.3",
|
|
||||||
"acorn": "^8.8.2",
|
|
||||||
"commander": "^2.20.0",
|
|
||||||
"source-map-support": "~0.5.20"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"terser": "bin/terser"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/terser/node_modules/commander": {
|
|
||||||
"version": "2.20.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/try-catch": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/try-catch/-/try-catch-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-91yfXw1rr/P6oLpHSyHDOHm0vloVvUoo9FVdw8YwY05QjJQG9OT0LUxe2VRAzmHG+0CUOmI3nhxDUMLxDN/NEQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/try-to-catch": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-hOY83V84Hx/1sCzDSaJA+Xz2IIQOHRvjxzt+F0OjbQGPZ6yLPLArMA0gw/484MlfUkQbCpKYMLX3VDCAjWKfzQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tsc": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/tsc/-/tsc-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"tsc": "bin/tsc"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tslib": {
|
|
||||||
"version": "2.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
|
|
||||||
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/yocto-queue": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.20"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"devDependencies": {
|
|
||||||
"minify": "^10.3.0",
|
|
||||||
"prettier": "^3.0.1",
|
|
||||||
"tsc": "^2.0.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "postman"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
tokio = { version = "1", features = ["process", "full"] }
|
|
||||||
regex = "1.4"
|
|
||||||
log = "0.4"
|
|
||||||
chrono = "0.4"
|
|
||||||
chrono-tz = { version = "0.5", features = ["serde"] }
|
|
||||||
lazy_static = "1.4"
|
|
||||||
num-integer = "0.1"
|
|
||||||
serde = "1.0"
|
|
||||||
sqlx = { version = "0.6", features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal", "chrono", "json"]}
|
|
||||||
serenity = { version = "0.11.1", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] }
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "recordable_derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.35"
|
||||||
|
syn = { version = "2.0.49", features = ["full"] }
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
use proc_macro::TokenStream;
|
||||||
|
use syn::{spanned::Spanned, Data};
|
||||||
|
|
||||||
|
/// Macro to allow Recordable to be implemented on an enum by dispatching over each variant.
|
||||||
|
#[proc_macro_derive(Recordable)]
|
||||||
|
pub fn extract(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = syn::parse_macro_input!(input);
|
||||||
|
|
||||||
|
impl_recordable(&ast)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn impl_recordable(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
let name = &ast.ident;
|
||||||
|
|
||||||
|
match &ast.data {
|
||||||
|
Data::Enum(en) => {
|
||||||
|
let extracted = en.variants.iter().map(|var| {
|
||||||
|
let ident = &var.ident;
|
||||||
|
|
||||||
|
quote::quote_spanned! {var.span()=>
|
||||||
|
Self::#ident (opt) => opt.run(ctx).await?
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TokenStream::from(quote::quote! {
|
||||||
|
impl Recordable for #name {
|
||||||
|
async fn run(self, ctx: crate::Context<'_>) -> Result<(), crate::Error> {
|
||||||
|
match self {
|
||||||
|
#(#extracted,)*
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
panic!("Only enums can derive Recordable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
printWidth = 100
|
||||||
|
tabWidth = 4
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# reminder-dashboard
|
||||||
|
|
||||||
|
The re-re-rewrite of the dashboard.
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
The existing beta variant of the dashboard is written using vanilla JavaScript. This is fine,
|
||||||
|
but annoying to update. This would've been okay if I was more dedicated to updating the vanilla
|
||||||
|
JavaScript too, but I want to experiment with "new" things.
|
||||||
|
|
||||||
|
This also allows me to expand my frontend skills, which is relevant to part of my job.
|
||||||
|
|
||||||
|
## Developing
|
||||||
|
|
||||||
|
1. Run both `npm run dev` and `cargo run`
|
||||||
|
2. Symlink assets: assuming cloned
|
||||||
|
into `$HOME`, `ln -s $HOME/reminder-bot/reminder-dashboard/dist/index.html $HOME/reminder-bot/web/static/index.html`
|
||||||
|
and
|
||||||
|
`ln -s $HOME/reminder-bot/reminder-dashboard/dist/static/assets $HOME/reminder-bot/web/static/assets`
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="EN">
|
||||||
|
<head>
|
||||||
|
<meta name="description" content="The most powerful Discord Reminders Bot">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="yandex-verification" content="bb77b8681eb64a90"/>
|
||||||
|
<meta name="google-site-verification" content="7h7UVTeEe0AOzHiH3cFtsqMULYGN-zCZdMT_YCkW1Ho"/>
|
||||||
|
<!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src *; font-src fonts.gstatic.com 'self'"> -->
|
||||||
|
|
||||||
|
<!-- favicon -->
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180"
|
||||||
|
href="/static/favicon/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32"
|
||||||
|
href="/static/favicon/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16"
|
||||||
|
href="/static/favicon/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/static/site.webmanifest">
|
||||||
|
<meta name="msapplication-TileColor" content="#da532c">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
<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">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Generated
+5626
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "example",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite build --watch --mode development",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.5.1",
|
||||||
|
"bulma": "^0.9.4",
|
||||||
|
"luxon": "^3.4.3",
|
||||||
|
"preact": "^10.13.1",
|
||||||
|
"react-colorful": "^5.6.1",
|
||||||
|
"react-query": "^3.39.3",
|
||||||
|
"tributejs": "^5.1.3",
|
||||||
|
"use-debounce": "^10.0.0",
|
||||||
|
"wouter": "^3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@preact/preset-vite": "^2.5.0",
|
||||||
|
"@types/luxon": "^3.3.2",
|
||||||
|
"eslint": "^8.50.0",
|
||||||
|
"eslint-config-preact": "^1.3.0",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"react-datepicker": "^4.21.0",
|
||||||
|
"sass": "^1.71.1",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -15,6 +15,22 @@ div.reminderContent.is-collapsed .column.settings {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.reminderContent.is-collapsed .reminder-settings {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderContent.is-collapsed .button-row {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderContent.is-collapsed .button-row-edit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderContent.is-collapsed .reminder-topbar {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
div.reminderContent.is-collapsed .invert-collapses {
|
div.reminderContent.is-collapsed .invert-collapses {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
@@ -129,6 +145,12 @@ div.split-controls {
|
|||||||
margin-top: 0 !important;
|
margin-top: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reminder-settings > .column {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-basis: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
div.reminderContent {
|
div.reminderContent {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
@@ -249,11 +271,11 @@ div#pageNavbar a {
|
|||||||
|
|
||||||
.navbar-item.pageTitle {
|
.navbar-item.pageTitle {
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
text-wrap: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-burger, .navbar-burger:active, .navbar-burger.is-active {
|
.dashboard-burger, .dashboard-burger:active, .dashboard-burger.is-active {
|
||||||
background-color: #adc99c !important;
|
background-color: #adc99c !important;
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
@@ -286,17 +308,24 @@ div.dashboard-sidebar {
|
|||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.dashboard-sidebar:not(.mobile-sidebar) {
|
ul.guildList {
|
||||||
display: flex;
|
flex-grow: 1;
|
||||||
flex-direction: column;
|
flex-shrink: 1;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.dashboard-sidebar:not(.mobile-sidebar) .aside-footer {
|
div.dashboard-sidebar:not(.mobile-sidebar) .aside-footer {
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 226px;
|
width: 226px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.dashboard-sidebar svg {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
div.mobile-sidebar {
|
div.mobile-sidebar {
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
@@ -444,8 +473,7 @@ input.default-width {
|
|||||||
.customizable.is-400x300 img {
|
.customizable.is-400x300 img {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100px;
|
height: 100px;
|
||||||
max-height: 400px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.customizable.is-32x32 img {
|
.customizable.is-32x32 img {
|
||||||
@@ -589,6 +617,14 @@ input.default-width {
|
|||||||
border-bottom: 1px solid #fff;
|
border-bottom: 1px solid #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.channel-selector {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
li.highlight {
|
li.highlight {
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
@@ -612,7 +648,22 @@ li.highlight {
|
|||||||
padding: 2px;
|
padding: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1408px) {
|
@media only screen and (max-width: 1023px) {
|
||||||
|
p.title.pageTitle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-frame {
|
||||||
|
margin-top: 4rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customizable.thumbnail img {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
.button-row {
|
.button-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -630,41 +681,20 @@ li.highlight {
|
|||||||
.button-row button {
|
.button-row button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
.reminder-settings {
|
||||||
.button-row-edit {
|
margin-bottom: 0 !important;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-row-edit > button {
|
.tts-row {
|
||||||
width: 100%;
|
padding-bottom: 0;
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.title.pageTitle {
|
|
||||||
visibility: hidden;
|
|
||||||
text-wrap: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
.customizable.thumbnail img {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.customizable.is-24x24 img {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loader */
|
/* loader */
|
||||||
#loader {
|
#loader {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
@@ -676,6 +706,86 @@ li.highlight {
|
|||||||
|
|
||||||
/* END */
|
/* END */
|
||||||
|
|
||||||
|
div.reminderError {
|
||||||
|
margin: 10px;
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError .errorHead {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError .errorIcon {
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError .errorIcon .fas {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError[data-case="deleted"] .errorIcon {
|
||||||
|
background-color: #e7e5e4;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError[data-case="failed"] .errorIcon {
|
||||||
|
background-color: #fecaca;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError[data-case="sent"] .errorIcon {
|
||||||
|
background-color: #d9f99d;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError[data-case="deleted"] .errorIcon .fas.fa-trash {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError[data-case="failed"] .errorIcon .fas.fa-exclamation-triangle {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError[data-case="sent"] .errorIcon .fas.fa-check {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError .errorHead .reminderName {
|
||||||
|
font-size: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
color: rgb(54, 54, 54);
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError .errorHead .reminderTime {
|
||||||
|
font-size: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-shrink: 1;
|
||||||
|
justify-content: center;
|
||||||
|
color: rgb(54, 54, 54);
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-color: #e5e5e5;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.reminderError .reminderMessage {
|
||||||
|
font-size: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
color: rgb(54, 54, 54);
|
||||||
|
flex-grow: 1;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
/* other stuff */
|
/* other stuff */
|
||||||
|
|
||||||
.half-rem {
|
.half-rem {
|
||||||
@@ -713,15 +823,38 @@ a.switch-pane {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.guild-submenu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guild-submenu li {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.switch-pane.is-active ~ .guild-submenu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.feedback {
|
.feedback {
|
||||||
background-color: #5865F2;
|
background-color: #5865F2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-locked {
|
.is-locked {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-locked > :not(.patreon-invert) {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.is-locked .patreon-invert {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.patreon-invert {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.is-locked .foreground {
|
.is-locked .foreground {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
@@ -751,5 +884,5 @@ a.switch-pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.figure-num {
|
.figure-num {
|
||||||
font-size: 2em;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -223,11 +223,10 @@ async function fetch_reminders(guild_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function serialize_reminder(node, mode) {
|
async function serialize_reminder(node, mode) {
|
||||||
let interval, utc_time, expiration_time;
|
let utc_time, expiration_time;
|
||||||
|
let interval = get_interval(node);
|
||||||
|
|
||||||
if (mode !== "template") {
|
if (mode !== "template") {
|
||||||
interval = get_interval(node);
|
|
||||||
|
|
||||||
utc_time = luxon.DateTime.fromISO(
|
utc_time = luxon.DateTime.fromISO(
|
||||||
node.querySelector('input[name="time"]').value
|
node.querySelector('input[name="time"]').value
|
||||||
).setZone("UTC");
|
).setZone("UTC");
|
||||||
@@ -356,9 +355,9 @@ async function serialize_reminder(node, mode) {
|
|||||||
embed_title: embed_title,
|
embed_title: embed_title,
|
||||||
embed_fields: fields,
|
embed_fields: fields,
|
||||||
expires: expiration_time,
|
expires: expiration_time,
|
||||||
interval_seconds: mode !== "template" ? interval.seconds : null,
|
interval_seconds: interval.seconds,
|
||||||
interval_days: mode !== "template" ? interval.days : null,
|
interval_days: interval.days,
|
||||||
interval_months: mode !== "template" ? interval.months : null,
|
interval_months: interval.months,
|
||||||
name: node.querySelector('input[name="name"]').value,
|
name: node.querySelector('input[name="name"]').value,
|
||||||
tts: node.querySelector('input[name="tts"]').checked,
|
tts: node.querySelector('input[name="tts"]').checked,
|
||||||
username: node.querySelector('input[name="username"]').value,
|
username: node.querySelector('input[name="username"]').value,
|
||||||
@@ -420,9 +419,9 @@ function deserialize_reminder(reminder, frame, mode) {
|
|||||||
.insertBefore(embed_field, lastChild);
|
.insertBefore(embed_field, lastChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode !== "template") {
|
if (reminder["interval_seconds"]) update_interval(frame);
|
||||||
if (reminder["interval_seconds"]) update_interval(frame);
|
|
||||||
|
|
||||||
|
if (mode !== "template") {
|
||||||
let $enableBtn = frame.querySelector(".disable-enable");
|
let $enableBtn = frame.querySelector(".disable-enable");
|
||||||
$enableBtn.dataset["action"] = reminder["enabled"] ? "disable" : "enable";
|
$enableBtn.dataset["action"] = reminder["enabled"] ? "disable" : "enable";
|
||||||
|
|
||||||
@@ -604,6 +603,16 @@ function show_error(error) {
|
|||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function show_success(error) {
|
||||||
|
document.getElementById("success").querySelector("span.success-message").textContent =
|
||||||
|
error;
|
||||||
|
document.getElementById("success").classList.add("is-active");
|
||||||
|
|
||||||
|
window.setTimeout(() => {
|
||||||
|
document.getElementById("success").classList.remove("is-active");
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
$colorPickerInput.value = colorPicker.color.hexString;
|
$colorPickerInput.value = colorPicker.color.hexString;
|
||||||
|
|
||||||
$colorPickerInput.addEventListener("input", () => {
|
$colorPickerInput.addEventListener("input", () => {
|
||||||
@@ -754,12 +763,26 @@ $uploader.addEventListener("change", (ev) => {
|
|||||||
fileReader.onload = (e) => resolve(fileReader.result);
|
fileReader.onload = (e) => resolve(fileReader.result);
|
||||||
fileReader.readAsDataURL($uploader.files[0]);
|
fileReader.readAsDataURL($uploader.files[0]);
|
||||||
}).then((dataUrl) => {
|
}).then((dataUrl) => {
|
||||||
|
$importBtn.setAttribute("disabled", true);
|
||||||
|
|
||||||
fetch(`/dashboard/api/guild/${guildId()}/export/${urlTail}`, {
|
fetch(`/dashboard/api/guild/${guildId()}/export/${urlTail}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
body: JSON.stringify({ body: dataUrl.split(",")[1] }),
|
body: JSON.stringify({ body: dataUrl.split(",")[1] }),
|
||||||
}).then(() => {
|
})
|
||||||
delete $uploader.files[0];
|
.then((response) => response.json())
|
||||||
});
|
.then((data) => {
|
||||||
|
$importBtn.removeAttribute("disabled");
|
||||||
|
|
||||||
|
if (data.error) {
|
||||||
|
show_error(data.error);
|
||||||
|
} else {
|
||||||
|
show_success(data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
delete $uploader.files[0];
|
||||||
|
fetch_reminders(guild);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 366 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user