Compare commits

..

10 Commits

Author SHA1 Message Date
jude
109cf16dbb Store guild when creating reminders 2023-08-19 21:24:02 +01:00
jude
6726ca0c2d Correct migration script.
Stub code for routes. Update existing routes to set the reminder's guild
ID.
2023-08-19 21:24:02 +01:00
38133be15d In progress 2023-08-19 21:24:02 +01:00
jude
8587bed703 Bump ver 2023-08-19 17:10:45 +01:00
jude
6c9af1ae8e Correct styles on mobile burger 2023-08-19 17:09:46 +01:00
jude
7695b7a476 Fix delete command 2023-08-19 14:35:07 +01:00
651da7b28e Improve some styles. Add an offline mode 2023-08-19 14:20:48 +01:00
eb086146bf Bump version 2023-08-16 17:05:18 +01:00
4ebd705e5e Add clearer indication of interval patreon requirements 2023-08-16 17:03:38 +01:00
5a85f1d83a Extract error sections to templates 2023-08-13 18:29:30 +01:00
14 changed files with 145 additions and 65 deletions

2
Cargo.lock generated
View File

@ -2217,7 +2217,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "reminder-rs"
version = "1.6.36"
version = "1.6.38"
dependencies = [
"base64 0.21.2",
"chrono",

View File

@ -1,6 +1,6 @@
[package]
name = "reminder-rs"
version = "1.6.36"
version = "1.6.38"
authors = ["Jude Southworth <judesouthworth@pm.me>"]
edition = "2021"
license = "AGPL-3.0 only"

View File

@ -169,7 +169,7 @@ impl ComponentDataModel {
let selected_id = component.data.values.join(",");
sqlx::query!(
"UPDATE reminders SET `status` = 'pending' WHERE FIND_IN_SET(id, ?)",
"UPDATE reminders SET `status` = 'deleted' WHERE FIND_IN_SET(id, ?)",
selected_id
)
.execute(&data.database)

View File

@ -72,10 +72,14 @@ pub async fn initialize(
db_pool: Pool<Database>,
) -> Result<(), Box<dyn std::error::Error>> {
info!("Checking environment variables...");
env::var("OAUTH2_CLIENT_ID").expect("`OAUTH2_CLIENT_ID' not supplied");
env::var("OAUTH2_CLIENT_SECRET").expect("`OAUTH2_CLIENT_SECRET' not supplied");
env::var("OAUTH2_DISCORD_CALLBACK").expect("`OAUTH2_DISCORD_CALLBACK' not supplied");
env::var("PATREON_GUILD_ID").expect("`PATREON_GUILD_ID' not supplied");
if env::var("OFFLINE").map_or(true, |v| v != "1") {
env::var("OAUTH2_CLIENT_ID").expect("`OAUTH2_CLIENT_ID' not supplied");
env::var("OAUTH2_CLIENT_SECRET").expect("`OAUTH2_CLIENT_SECRET' not supplied");
env::var("OAUTH2_DISCORD_CALLBACK").expect("`OAUTH2_DISCORD_CALLBACK' not supplied");
env::var("PATREON_GUILD_ID").expect("`PATREON_GUILD_ID' not supplied");
}
info!("Done!");
let oauth2_client = BasicClient::new(
@ -186,6 +190,8 @@ pub async fn initialize(
}
pub async fn check_subscription(cache_http: impl CacheHttp, user_id: impl Into<UserId>) -> bool {
offline!(true);
if let Some(subscription_guild) = *CNC_GUILD {
let guild_member = GuildId(subscription_guild).member(cache_http, user_id).await;
@ -207,6 +213,8 @@ pub async fn check_guild_subscription(
cache_http: impl CacheHttp,
guild_id: impl Into<GuildId>,
) -> bool {
offline!(true);
if let Some(guild) = cache_http.cache().unwrap().guild(guild_id) {
let owner = guild.owner_id;

View File

@ -1,3 +1,11 @@
macro_rules! offline {
($field:expr) => {
if std::env::var("OFFLINE").map_or(false, |v| v == "1") {
return $field;
}
};
}
macro_rules! check_length {
($max:ident, $field:expr) => {
if $field.len() > $max {
@ -52,43 +60,45 @@ macro_rules! check_authorization {
let user_id = $cookies.get_private("userid").map(|c| c.value().parse::<u64>().ok()).flatten();
match user_id {
Some(user_id) => {
match GuildId($guild).to_guild_cached($ctx) {
Some(guild) => {
let member_res = guild.member($ctx, UserId(user_id)).await;
if std::env::var("OFFLINE").map_or(true, |v| v != "1") {
match user_id {
Some(user_id) => {
match GuildId($guild).to_guild_cached($ctx) {
Some(guild) => {
let member_res = guild.member($ctx, UserId(user_id)).await;
match member_res {
Err(_) => {
return Err(json!({"error": "User not in guild"}));
}
match member_res {
Err(_) => {
return Err(json!({"error": "User not in guild"}));
}
Ok(member) => {
let permissions_res = member.permissions($ctx);
Ok(member) => {
let permissions_res = member.permissions($ctx);
match permissions_res {
Err(_) => {
return Err(json!({"error": "Couldn't fetch permissions"}));
}
match permissions_res {
Err(_) => {
return Err(json!({"error": "Couldn't fetch permissions"}));
}
Ok(permissions) => {
if !(permissions.manage_messages() || permissions.manage_guild() || permissions.administrator()) {
return Err(json!({"error": "Incorrect permissions"}));
Ok(permissions) => {
if !(permissions.manage_messages() || permissions.manage_guild() || permissions.administrator()) {
return Err(json!({"error": "Incorrect permissions"}));
}
}
}
}
}
}
}
None => {
return Err(json!({"error": "Bot not in guild"}));
None => {
return Err(json!({"error": "Bot not in guild"}));
}
}
}
}
None => {
return Err(json!({"error": "User not authorized"}));
None => {
return Err(json!({"error": "User not authorized"}));
}
}
}
}

View File

@ -46,6 +46,7 @@ pub async fn get_guild_patreon(
cookies: &CookieJar<'_>,
ctx: &State<Context>,
) -> JsonResult {
offline!(Ok(json!({ "patreon": true })));
check_authorization!(cookies, ctx.inner(), id);
match GuildId(id).to_guild_cached(ctx.inner()) {
@ -73,6 +74,12 @@ pub async fn get_guild_channels(
cookies: &CookieJar<'_>,
ctx: &State<Context>,
) -> JsonResult {
offline!(Ok(json!(vec![ChannelInfo {
name: "general".to_string(),
id: "1".to_string(),
webhook_avatar: None,
webhook_name: None,
}])));
check_authorization!(cookies, ctx.inner(), id);
match GuildId(id).to_guild_cached(ctx.inner()) {
@ -111,6 +118,7 @@ struct RoleInfo {
#[get("/api/guild/<id>/roles")]
pub async fn get_guild_roles(id: u64, cookies: &CookieJar<'_>, ctx: &State<Context>) -> JsonResult {
offline!(Ok(json!(vec![RoleInfo { name: "@everyone".to_string(), id: "1".to_string() }])));
check_authorization!(cookies, ctx.inner(), id);
let roles_res = ctx.cache.guild_roles(id);

View File

@ -54,6 +54,8 @@ pub async fn get_user_info(
ctx: &State<Context>,
pool: &State<Pool<MySql>>,
) -> JsonValue {
offline!(json!(UserInfo { name: "Discord".to_string(), patreon: true, timezone: None }));
if let Some(user_id) =
cookies.get_private("userid").map(|u| u.value().parse::<u64>().ok()).flatten()
{
@ -116,6 +118,8 @@ pub async fn update_user_info(
#[get("/api/user/guilds")]
pub async fn get_user_guilds(cookies: &CookieJar<'_>, reqwest_client: &State<Client>) -> JsonValue {
offline!(json!(vec![GuildInfo { id: "1".to_string(), name: "Guild".to_string() }]));
if let Some(access_token) = cookies.get_private("access_token") {
let request_res = reqwest_client
.get(format!("{}/users/@me/guilds", DISCORD_API))

View File

@ -249,11 +249,11 @@ div#pageNavbar a {
.navbar-item.pageTitle {
flex-shrink: 1;
text-wrap: nowrap;
white-space: nowrap;
overflow: hidden;
}
.navbar-burger, .navbar-burger:active, .navbar-burger.is-active {
.dashboard-burger, .dashboard-burger:active, .dashboard-burger.is-active {
background-color: #adc99c !important;
border-radius: 14px;
padding: 6px;
@ -644,9 +644,11 @@ li.highlight {
}
p.title.pageTitle {
visibility: hidden;
text-wrap: nowrap;
overflow: hidden;
display: none;
}
.dashboard-frame {
margin-top: 4rem !important;
}
}
@ -665,6 +667,7 @@ li.highlight {
/* loader */
#loader {
position: fixed;
top: 0;
background-color: rgba(255, 255, 255, 0.8);
width: 100vw;
z-index: 999;
@ -719,9 +722,20 @@ a.switch-pane {
.is-locked {
pointer-events: none;
}
.is-locked > :not(.patreon-invert) {
opacity: 0.4;
}
.is-locked .patreon-invert {
display: block;
}
.patreon-invert {
display: none;
}
.is-locked .foreground {
pointer-events: auto;
}
@ -751,5 +765,5 @@ a.switch-pane {
}
.figure-num {
font-size: 2em;
font-size: 2rem;
}

View File

@ -0,0 +1,19 @@
let _reminderErrors = [];
const reminderErrors = () => {
return _reminderErrors;
}
const guildId = () => {
let selected: HTMLElement = document.querySelector(".guildList a.is-active");
return selected.dataset["guild"];
}
function loadErrors() {
fetch(`/dashboard/api/guild/${guildId()}/errors`).then(response => response.json())
}
document.addEventListener('DOMContentLoaded', () => {
})

View File

@ -47,7 +47,7 @@
<p class="navbar-item pageTitle">
</p>
<a role="button" class="navbar-burger is-right" aria-label="menu" aria-expanded="false"
<a role="button" class="dashboard-burger navbar-burger is-right" aria-label="menu" aria-expanded="false"
data-target="mobileSidebar">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
@ -335,34 +335,14 @@
<section id="guild" class="is-hidden">
{% include "reminder_dashboard/reminder_dashboard" %}
</section>
<section id="guild-error" class="is-hidden hero is-fullheight">
<div class="hero-body">
<div class="container has-text-centered">
<p class="title">
We couldn't get this server's data
</p>
<p class="subtitle">
Please check Reminder Bot is in the server, and has correct permissions.
</p>
<a class="button is-size-4 is-rounded is-success" href="https://invite.reminder-bot.com">
<p class="is-size-4">
<span>Add to Server</span> <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p>
</a>
</div>
</div>
<section id="reminder-errors" class="is-hidden">
{% include "reminder_dashboard/reminder_errors" %}
</section>
<section id="user-error" class="is-hidden hero is-fullheight">
<div class="hero-body">
<div class="container has-text-centered">
<p class="title">
You do not have permissions for this server
</p>
<p class="subtitle">
Ask an admin to grant you the "Manage Messages" permission.
</p>
</div>
</div>
<section id="guild-error" class="is-hidden">
{% include "reminder_dashboard/guild_error" %}
</section>
<section id="user-error" class="is-hidden">
{% include "reminder_dashboard/user_error" %}
</section>
</div>
<!-- /main content -->

View File

@ -0,0 +1,17 @@
<div class="hero is-fullheight">
<div class="hero-body">
<div class="container has-text-centered">
<p class="title">
We couldn't get this server's data
</p>
<p class="subtitle">
Please check Reminder Bot is in the server, and has correct permissions.
</p>
<a class="button is-size-4 is-rounded is-success" href="https://invite.reminder-bot.com">
<p class="is-size-4">
<span>Add to Server</span> <span class="icon"><i class="fas fa-chevron-right"></i></span>
</p>
</a>
</div>
</div>
</div>

View File

@ -165,6 +165,9 @@
<div class="collapses split-controls">
<div>
<div class="patreon-only">
<div class="patreon-invert foreground">
Intervals available on <a href="https://patreon.com/jellywx">Patreon</a> or <a href="https://gitea.jellypro.xyz/jude/reminder-bot">self-hosting</a>
</div>
<div class="field">
<label class="label">Interval <a class="foreground" href="/help/intervals"><i class="fas fa-question-circle"></i></a></label>
<div class="control intervalSelector">

View File

@ -0,0 +1,5 @@
<div>
</div>
<script src="/static/js/reminder_errors.js"></script>

View File

@ -0,0 +1,12 @@
<div class="hero is-fullheight">
<div class="hero-body">
<div class="container has-text-centered">
<p class="title">
You do not have permissions for this server
</p>
<p class="subtitle">
Ask an admin to grant you the "Manage Messages" permission.
</p>
</div>
</div>
</div>