update dependencies

This commit is contained in:
2022-04-19 15:23:27 +01:00
parent 4c4f0927f1
commit ded750aa2d
13 changed files with 325 additions and 326 deletions

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies]
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master", features = ["tls", "secrets", "json"] }
rocket_dyn_templates = { git = "https://github.com/SergioBenitez/Rocket", branch = "master", features = ["tera"] }
serenity = { git = "https://github.com/serenity-rs/serenity", branch = "next", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] }
serenity = { version = "0.11.1", default-features = false, features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"] }
oauth2 = "4"
log = "0.4"
reqwest = "0.11"

View File

@ -1,7 +1,6 @@
pub const DISCORD_OAUTH_TOKEN: &'static str = "https://discord.com/api/oauth2/token";
pub const DISCORD_OAUTH_AUTHORIZE: &'static str = "https://discord.com/api/oauth2/authorize";
pub const DISCORD_API: &'static str = "https://discord.com/api";
pub const DISCORD_CDN: &'static str = "https://cdn.discordapp.com/avatars";
pub const MAX_CONTENT_LENGTH: usize = 2000;
pub const MAX_EMBED_DESCRIPTION_LENGTH: usize = 4096;

View File

@ -137,6 +137,7 @@ pub async fn initialize(
routes::dashboard::user::get_user_info,
routes::dashboard::user::update_user_info,
routes::dashboard::user::get_user_guilds,
routes::dashboard::guild::get_guild_patreon,
routes::dashboard::guild::get_guild_channels,
routes::dashboard::guild::get_guild_roles,
routes::dashboard::guild::get_reminder_templates,

View File

@ -1,3 +1,5 @@
use std::env;
use base64;
use chrono::Utc;
use rocket::{
@ -10,7 +12,7 @@ use serenity::{
client::Context,
model::{
channel::GuildChannel,
id::{ChannelId, GuildId},
id::{ChannelId, GuildId, RoleId},
},
};
use sqlx::{MySql, Pool};
@ -18,10 +20,10 @@ use sqlx::{MySql, Pool};
use crate::{
check_guild_subscription, check_subscription,
consts::{
DAY, DISCORD_CDN, MAX_CONTENT_LENGTH, MAX_EMBED_AUTHOR_LENGTH,
MAX_EMBED_DESCRIPTION_LENGTH, MAX_EMBED_FIELDS, MAX_EMBED_FIELD_TITLE_LENGTH,
MAX_EMBED_FIELD_VALUE_LENGTH, MAX_EMBED_FOOTER_LENGTH, MAX_EMBED_TITLE_LENGTH,
MAX_URL_LENGTH, MAX_USERNAME_LENGTH, MIN_INTERVAL,
DAY, MAX_CONTENT_LENGTH, MAX_EMBED_AUTHOR_LENGTH, MAX_EMBED_DESCRIPTION_LENGTH,
MAX_EMBED_FIELDS, MAX_EMBED_FIELD_TITLE_LENGTH, MAX_EMBED_FIELD_VALUE_LENGTH,
MAX_EMBED_FOOTER_LENGTH, MAX_EMBED_TITLE_LENGTH, MAX_URL_LENGTH, MAX_USERNAME_LENGTH,
MIN_INTERVAL,
},
routes::dashboard::{
create_database_channel, generate_uid, name_default, template_name_default, DeleteReminder,
@ -37,19 +39,45 @@ struct ChannelInfo {
webhook_name: Option<String>,
}
#[get("/api/guild/<id>/channels")]
pub async fn get_guild_channels(
#[get("/api/guild/<id>/patreon")]
pub async fn get_guild_patreon(
id: u64,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
pool: &State<Pool<MySql>>,
) -> JsonValue {
check_authorization!(cookies, ctx.inner(), id);
match GuildId(id).to_guild_cached(ctx.inner()) {
Some(guild) => {
let mut channel_info = vec![];
let member_res = GuildId(env::var("PATREON_GUILD_ID").unwrap().parse().unwrap())
.member(&ctx.inner(), guild.owner_id)
.await;
let patreon = member_res.map_or(false, |member| {
member
.roles
.contains(&RoleId(env::var("PATREON_ROLE_ID").unwrap().parse().unwrap()))
});
json!({ "patreon": patreon })
}
None => {
json!({"error": "Bot not in guild"})
}
}
}
#[get("/api/guild/<id>/channels")]
pub async fn get_guild_channels(
id: u64,
cookies: &CookieJar<'_>,
ctx: &State<Context>,
) -> JsonValue {
check_authorization!(cookies, ctx.inner(), id);
match GuildId(id).to_guild_cached(ctx.inner()) {
Some(guild) => {
let mut channels = guild
.channels
.iter()
@ -59,17 +87,15 @@ pub async fn get_guild_channels(
channels.sort_by(|(_, c1), (_, c2)| c1.position.cmp(&c2.position));
// todo change to map
for (channel_id, channel) in channels {
let mut ch = ChannelInfo {
let channel_info = channels
.iter()
.map(|(channel_id, channel)| ChannelInfo {
name: channel.name.to_string(),
id: channel_id.to_string(),
webhook_avatar: None,
webhook_name: None,
};
channel_info.push(ch);
}
})
.collect::<Vec<ChannelInfo>>();
json!(channel_info)
}

View File

@ -563,3 +563,16 @@ textarea, input {
.button.is-outlined.is-success {
background-color: white;
}
.is-locked {
pointer-events: none;
opacity: 0.4;
}
.is-locked .foreground {
pointer-events: auto;
}
.is-locked .field:last-of-type {
display: none;
}

View File

@ -17,6 +17,8 @@ let channels = [];
let roles = [];
let templates = {};
let globalPatreon = false;
function guildId() {
return document.querySelector(".guildList a.is-active").dataset["guild"];
}
@ -221,6 +223,10 @@ async function serialize_reminder(node, mode) {
if (node.querySelector('input[name="attachment"]').files.length > 0) {
let file = node.querySelector('input[name="attachment"]').files[0];
if (file.size >= 8 * 1024 * 1024) {
return { error: "File too large." };
}
attachment = await new Promise((resolve) => {
let fileReader = new FileReader();
fileReader.onload = (e) => resolve(fileReader.result);
@ -240,6 +246,34 @@ async function serialize_reminder(node, mode) {
enabled = true;
}
const content = node.querySelector('textarea[name="content"]').value;
const embed_author_url = has_source(node.querySelector("img.embed_author_url").src);
const embed_author = node.querySelector('textarea[name="embed_author"]').value;
const embed_description = node.querySelector(
'textarea[name="embed_description"]'
).value;
const embed_footer = node.querySelector('textarea[name="embed_footer"]').value;
const embed_footer_url = has_source(node.querySelector("img.embed_footer_url").src);
const embed_image_url = has_source(node.querySelector("img.embed_image_url").src);
const embed_thumbnail_url = has_source(
node.querySelector("img.embed_thumbnail_url").src
);
const embed_title = node.querySelector('textarea[name="embed_title"]').value;
if (
attachment === null &&
content.length == 0 &&
embed_author_url === null &&
embed_author.length == 0 &&
embed_description.length == 0 &&
embed_footer.length == 0 &&
embed_footer_url === null &&
embed_image_url === null &&
embed_thumbnail_url === null
) {
return { error: "Reminder needs content." };
}
return {
// if we're creating a reminder, ignore this field
uid: uid,
@ -250,18 +284,16 @@ async function serialize_reminder(node, mode) {
attachment_name: attachment_name,
avatar: has_source(node.querySelector("img.discord-avatar").src),
channel: node.querySelector("select.channel-selector").value,
content: node.querySelector('textarea[name="content"]').value,
embed_author_url: has_source(node.querySelector("img.embed_author_url").src),
embed_author: node.querySelector('textarea[name="embed_author"]').value,
content: content,
embed_author_url: embed_author_url,
embed_author: embed_author,
embed_color: color,
embed_description: node.querySelector('textarea[name="embed_description"]').value,
embed_footer: node.querySelector('textarea[name="embed_footer"]').value,
embed_footer_url: has_source(node.querySelector("img.embed_footer_url").src),
embed_image_url: has_source(node.querySelector("img.embed_image_url").src),
embed_thumbnail_url: has_source(
node.querySelector("img.embed_thumbnail_url").src
),
embed_title: node.querySelector('textarea[name="embed_title"]').value,
embed_description: embed_description,
embed_footer: embed_footer,
embed_footer_url: embed_footer_url,
embed_image_url: embed_image_url,
embed_thumbnail_url: embed_thumbnail_url,
embed_title: embed_title,
embed_fields: fields,
expires: expiration_time,
interval_seconds: mode !== "template" ? interval.seconds : null,
@ -325,7 +357,7 @@ function deserialize_reminder(reminder, frame, mode) {
}).setZone(timezone);
timeInput.value = localTime.toFormat("yyyy-LL-dd'T'HH:mm:ss");
if (reminder['expires']) {
if (reminder["expires"]) {
let expiresInput = frame.querySelector('input[name="time"]');
let expiresTime = luxon.DateTime.fromISO(reminder["expires"], {
zone: "UTC",
@ -522,6 +554,8 @@ document.addEventListener("DOMContentLoaded", () => {
} else {
if (data.timezone !== null) botTimezone = data.timezone;
globalPatreon = data.patreon;
update_times();
}
});
@ -722,19 +756,20 @@ $deleteTemplateBtn.addEventListener("click", (ev) => {
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({id: parseInt($templateSelect.value)}),
body: JSON.stringify({ id: parseInt($templateSelect.value) }),
})
.then((response) => response.json())
.then((data) => {
if (data.error) {
show_error(data.error)
show_error(data.error);
} else {
$templateSelect.querySelector(`option[value="${$templateSelect.value}"]`).remove();
$templateSelect
.querySelector(`option[value="${$templateSelect.value}"]`)
.remove();
}
})
});
});
document.querySelectorAll("textarea.autoresize").forEach((element) => {
element.addEventListener("input", () => {
element.style.height = "";
@ -785,16 +820,6 @@ document.addEventListener("remindersLoaded", () => {
});
});
const $showInterval = document.querySelectorAll("a.intervalLabel");
$showInterval.forEach((element) => {
element.addEventListener("click", () => {
element.querySelector("i").classList.toggle("fa-chevron-right");
element.querySelector("i").classList.toggle("fa-chevron-down");
element.nextElementSibling.classList.toggle("is-hidden");
});
});
document.querySelectorAll(".change-color").forEach((element) => {
element.addEventListener("click", (e) => {
e.preventDefault();

View File

@ -158,43 +158,45 @@
</div>
<div class="collapses">
<div class="field">
<a class="intervalLabel"><label class="label">Interval <i class="fas fa-chevron-down"></i></label></a>
<div class="control intervalSelector" style="min-width: 400px;" >
<div class="input interval-group">
<div class="interval-group-left">
<label>
<span class="is-sr-only">Interval months</span>
<input class="w2" type="text" pattern="\d*" name="interval_months" maxlength="2" placeholder=""> <span class="half-rem"></span> months, <span class="half-rem"></span>
</label>
<label>
<span class="is-sr-only">Interval days</span>
<input class="w3" type="text" pattern="\d*" name="interval_days" maxlength="4" placeholder=""> <span class="half-rem"></span> days, <span class="half-rem"></span>
</label>
<label>
<span class="is-sr-only">Interval hours</span>
<input class="w2" type="text" pattern="\d*" name="interval_hours" maxlength="2" placeholder="HH">:
</label>
<label>
<span class="is-sr-only">Interval minutes</span>
<input class="w2" type="text" pattern="\d*" name="interval_minutes" maxlength="2" placeholder="MM">:
</label>
<label>
<span class="is-sr-only">Interval seconds</span>
<input class="w2" type="text" pattern="\d*" name="interval_seconds" maxlength="2" placeholder="SS">
</label>
<div class="is-locked">
<div class="field">
<label class="label">Interval <a class="foreground" href="/help/interval"><i class="fas fa-question-circle"></i></a></label>
<div class="control intervalSelector" style="min-width: 400px;" >
<div class="input interval-group">
<div class="interval-group-left">
<label>
<span class="is-sr-only">Interval months</span>
<input class="w2" type="text" pattern="\d*" name="interval_months" maxlength="2" placeholder=""> <span class="half-rem"></span> months, <span class="half-rem"></span>
</label>
<label>
<span class="is-sr-only">Interval days</span>
<input class="w3" type="text" pattern="\d*" name="interval_days" maxlength="4" placeholder=""> <span class="half-rem"></span> days, <span class="half-rem"></span>
</label>
<label>
<span class="is-sr-only">Interval hours</span>
<input class="w2" type="text" pattern="\d*" name="interval_hours" maxlength="2" placeholder="HH">:
</label>
<label>
<span class="is-sr-only">Interval minutes</span>
<input class="w2" type="text" pattern="\d*" name="interval_minutes" maxlength="2" placeholder="MM">:
</label>
<label>
<span class="is-sr-only">Interval seconds</span>
<input class="w2" type="text" pattern="\d*" name="interval_seconds" maxlength="2" placeholder="SS">
</label>
</div>
<button class="clear"><span class="is-sr-only">Clear interval</span><span class="icon"><i class="fas fa-trash"></i></span></button>
</div>
<button class="clear"><span class="is-sr-only">Clear interval</span><span class="icon"><i class="fas fa-trash"></i></span></button>
</div>
</div>
</div>
<div class="field">
<div class="control">
<label class="label">
Expiration
<input class="input" type="datetime-local" step="1" name="expiration">
</label>
<div class="field">
<div class="control">
<label class="label">
Expiration
<input class="input" type="datetime-local" step="1" name="expiration">
</label>
</div>
</div>
</div>
@ -226,27 +228,29 @@
</div>
</div>
<span class="pad-left"></span>
{% if creating %}
<button class="button is-success" id="createReminder">
<span>Create Reminder</span> <span class="icon"><i class="fas fa-sparkles"></i></span>
</button>
<button class="button is-success is-outlined" id="createTemplate">
<span>Create Template</span> <span class="icon"><i class="fas fa-file-spreadsheet"></i></span>
</button>
<button class="button is-outlined show-modal is-pulled-right" data-modal="chooseTemplateModal">
Load Template
</button>
{% else %}
<button class="button is-success save-btn">
<span>Save</span> <span class="icon"><i class="fas fa-save"></i></span>
</button>
<button class="button is-warning disable-enable">
</button>
<button class="button is-danger delete-reminder">
Delete
</button>
{% endif %}
<div>
<span class="pad-left"></span>
{% if creating %}
<button class="button is-success" id="createReminder">
<span>Create Reminder</span> <span class="icon"><i class="fas fa-sparkles"></i></span>
</button>
<button class="button is-success is-outlined" id="createTemplate">
<span>Create Template</span> <span class="icon"><i class="fas fa-file-spreadsheet"></i></span>
</button>
<button class="button is-outlined show-modal is-pulled-right" data-modal="chooseTemplateModal">
Load Template
</button>
{% else %}
<button class="button is-success save-btn">
<span>Save</span> <span class="icon"><i class="fas fa-save"></i></span>
</button>
<button class="button is-warning disable-enable">
</button>
<button class="button is-danger delete-reminder">
Delete
</button>
{% endif %}
</div>
</div>
</div>
</div>