From ab9ed8c1f99225912484d2d3b1f62363409a73e9 Mon Sep 17 00:00:00 2001 From: Anna Date: Sat, 10 Sep 2022 03:06:49 -0400 Subject: [PATCH] ye --- server/Cargo.lock | 7 +++ server/Cargo.toml | 1 + server/migrations/9_fix_user_col.sql | 70 +++++++++++++++++++++++++ server/packs/pack.schema.json | 76 ++++++++++++++++++++++++++++ server/src/main.rs | 26 +++++++++- server/src/message.rs | 2 +- server/src/pack.rs | 32 +++++++----- server/src/web/get_location.rs | 7 +-- 8 files changed, 200 insertions(+), 21 deletions(-) create mode 100644 server/migrations/9_fix_user_col.sql create mode 100644 server/packs/pack.schema.json diff --git a/server/Cargo.lock b/server/Cargo.lock index a18f066..b890d5a 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -539,6 +539,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + [[package]] name = "indexmap" version = "1.9.1" @@ -1037,6 +1043,7 @@ dependencies = [ "base64", "bytes", "chrono", + "if_chain", "rand", "serde", "serde_yaml", diff --git a/server/Cargo.toml b/server/Cargo.toml index adbd44c..70f2b27 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -10,6 +10,7 @@ anyhow = "1" base64 = "0.13" bytes = "1" chrono = "0.4" +if_chain = "1" rand = "0.8" serde = { version = "1", features = ["derive"] } serde_yaml = "0.9" diff --git a/server/migrations/9_fix_user_col.sql b/server/migrations/9_fix_user_col.sql new file mode 100644 index 0000000..1007102 --- /dev/null +++ b/server/migrations/9_fix_user_col.sql @@ -0,0 +1,70 @@ +-- 7. Making Other Kinds Of Table Schema Changes +-- https://www.sqlite.org/lang_altertable.html + +-- step 0. (we're already in a transaction!) +end transaction; + +-- step 1. +pragma foreign_keys = off; + +-- step 2. +begin transaction; + +-- step 3 skipped (no code for that) + +-- step 4. +-- fixing the user column to be an integer instead of string +create table new_messages +( + id text not null primary key, + user integer not null references users (id) on delete cascade, + created timestamp not null default current_timestamp, + territory integer not null, + glyph integer not null, + x float not null, + y float not null, + z float not null, + yaw float not null, + message text not null +); + +-- step 5. +insert into new_messages +select id, + cast(user as integer), + created, + territory, + glyph, + x, + y, + z, + yaw, + message +from messages; + +-- step 6. +drop table messages; + +-- step 7. +alter table new_messages + rename to messages; + +-- step 8. +-- actually adding a new index here, rather than recreating any old ones +-- only old ones were from the primary key, so don't need to remake +create index messages_user_idx on messages (user); +create index messages_territory_idx on messages (territory); + +-- step 9 skipped (no views) + +-- step 10. +pragma foreign_key_check; + +-- step 11. +commit transaction; + +-- step 12. +pragma foreign_keys = on; + +-- step 13. (start the transaction from earlier!) +begin transaction; diff --git a/server/packs/pack.schema.json b/server/packs/pack.schema.json new file mode 100644 index 0000000..68947de --- /dev/null +++ b/server/packs/pack.schema.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://anna.lgbt/schemas/orange-guidance-tomestone/pack.schema.json", + "title": "Orange Guidance Tomestone Pack", + "description": "A pack of templates, conjunctions, and word lists for use in the Dalamud plugin Orange Guidance Tomestone.", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user-friendly name of this pack." + }, + "id": { + "type": "string", + "description": "A UUID for this pack.", + "format": "uuid", + "pattern": "^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}|[a-fA-F0-9]{32})$" + }, + "visible": { + "type": "boolean", + "description": "Whether this pack is visible to users or archived for backwards-compatibility reasons." + }, + "order": { + "type": "integer", + "description": "The order in a client's UI that this pack should appear, 1 being first, 2 second, etc. 0 should be used for archived packs.", + "minimum": 0 + }, + "templates": { + "type": "array", + "description": "An array of template strings, using {0} for where the chosen word should be inserted (if any).", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "conjunctions": { + "type": "array", + "description": "An array of conjunctions, one of which may be inserted between two templates to form a longer message.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "words": { + "type": "array", + "description": "An array of word lists for using with the templates.", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The user-friendly name of this word list." + }, + "words": { + "type": "array", + "description": "The words in this word list.", + "items": { + "type": "string" + }, + "minItems": 1 + } + }, + "required": [ + "name", + "words" + ] + }, + "minItems": 1 + } + }, + "required": [ + "name", + "id", + "conjunctions", + "words" + ] +} diff --git a/server/src/main.rs b/server/src/main.rs index 4eeb28d..96ea583 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,4 +1,3 @@ -#![feature(let_chains)] #![feature(drain_filter)] use std::collections::HashMap; @@ -8,6 +7,7 @@ use anyhow::{Context, Result}; use sqlx::{Executor, Pool, Sqlite}; use sqlx::migrate::Migrator; use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; +use tokio::runtime::Handle; use tokio::sync::RwLock; use uuid::Uuid; @@ -107,8 +107,32 @@ async fn main() -> Result<()> { println!("adding packs"); state.update_packs().await?; + spawn_command_reader(Arc::clone(&state), Handle::current()); let address = state.config.address; println!("listening at {}", address); warp::serve(web::routes(state)).run(address).await; Ok(()) } + +fn spawn_command_reader(state: Arc, handle: Handle) { + std::thread::spawn(move || { + let mut line = String::new(); + while let Ok(size) = std::io::stdin().read_line(&mut line) { + let read = line[..size].trim(); + + match read { + "reload packs" => { + let state = Arc::clone(&state); + handle.spawn(async move { + if let Err(e) = state.update_packs().await { + eprintln!("failed to update packs: {:#?}", e); + } + }); + } + _ => {} + } + + line.clear(); + } + }); +} diff --git a/server/src/message.rs b/server/src/message.rs index 061cba7..278a2b8 100644 --- a/server/src/message.rs +++ b/server/src/message.rs @@ -43,7 +43,7 @@ pub struct RetrievedMessage { #[serde(skip)] pub created: NaiveDateTime, #[serde(skip)] - pub user: String, + pub user: i64, #[serde(skip)] pub last_seen_minutes: i64, } diff --git a/server/src/pack.rs b/server/src/pack.rs index 074c6ae..fff0405 100644 --- a/server/src/pack.rs +++ b/server/src/pack.rs @@ -28,11 +28,15 @@ impl Pack { return None; } - let mut formatted = if template_1.contains("{0}") && let Some((w1_list, w1_word)) = word_1_idx { - let word_1 = self.words.get(w1_list)?.words.get(w1_word)?; - template_1.replace("{0}", word_1) - } else { - template_1.clone() + let mut formatted = if_chain::if_chain! { + if template_1.contains("{0}"); + if let Some((w1_list, w1_word)) = word_1_idx; + then { + let word_1 = self.words.get(w1_list)?.words.get(w1_word)?; + template_1.replace("{0}", word_1) + } else { + template_1.clone() + } }; if let Some(conj_idx) = conjunction { @@ -49,15 +53,15 @@ impl Pack { } let template_2 = self.templates.get(template_2_idx)?; - if template_2.contains("{0}") && word_2_idx.is_none() { - return None; - } - - let append = if let Some((w2_list, w2_word)) = word_2_idx { - let word_2 = self.words.get(w2_list)?.words.get(w2_word)?; - template_2.replace("{0}", word_2) - } else { - template_2.clone() + let append = if_chain::if_chain! { + if template_2.contains("{0}"); + if let Some((w2_list, w2_word)) = word_2_idx; + then { + let word_2 = self.words.get(w2_list)?.words.get(w2_word)?; + template_2.replace("{0}", word_2) + } else { + template_2.clone() + } }; formatted.push_str(&append); diff --git a/server/src/web/get_location.rs b/server/src/web/get_location.rs index e45eb3b..42660de 100644 --- a/server/src/web/get_location.rs +++ b/server/src/web/get_location.rs @@ -59,12 +59,9 @@ async fn logic(state: Arc, id: i64, location: u32) -> Result, id: i64) { - // FIXME: make a migration to fix this, smh I'm dumb - let id_str = id.to_string(); - // remove messages where the user has been offline for over 35 minutes // also remove messages with low score (that aren't the from the user) - messages.drain_filter(|msg| msg.last_seen_minutes >= 35 || (msg.user != id_str && (msg.positive_votes - msg.negative_votes) < crate::consts::VOTE_THRESHOLD_HIDE)); + messages.drain_filter(|msg| msg.last_seen_minutes >= 35 || (msg.user != id && (msg.positive_votes - msg.negative_votes) < crate::consts::VOTE_THRESHOLD_HIDE)); // shuffle messages since we'll be excluding later based on messages // that have already been included, so this will be more fair @@ -73,7 +70,7 @@ fn filter_messages(messages: &mut Vec, id: i64) { // just count nearby messages. this is O(n^2) but alternatives are hard let mut ids = Vec::with_capacity(messages.len()); for a in messages.iter() { - if a.user == id_str { + if a.user == id { // always include own messages ids.push(a.id.clone()); continue;