This commit is contained in:
parent
ce57417a2d
commit
ab9ed8c1f9
|
@ -539,6 +539,12 @@ dependencies = [
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "if_chain"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.9.1"
|
version = "1.9.1"
|
||||||
|
@ -1037,6 +1043,7 @@ dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"if_chain",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
|
|
|
@ -10,6 +10,7 @@ anyhow = "1"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
if_chain = "1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
|
|
|
@ -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;
|
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
#![feature(let_chains)]
|
|
||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -8,6 +7,7 @@ use anyhow::{Context, Result};
|
||||||
use sqlx::{Executor, Pool, Sqlite};
|
use sqlx::{Executor, Pool, Sqlite};
|
||||||
use sqlx::migrate::Migrator;
|
use sqlx::migrate::Migrator;
|
||||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
||||||
|
use tokio::runtime::Handle;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -107,8 +107,32 @@ async fn main() -> Result<()> {
|
||||||
println!("adding packs");
|
println!("adding packs");
|
||||||
state.update_packs().await?;
|
state.update_packs().await?;
|
||||||
|
|
||||||
|
spawn_command_reader(Arc::clone(&state), Handle::current());
|
||||||
let address = state.config.address;
|
let address = state.config.address;
|
||||||
println!("listening at {}", address);
|
println!("listening at {}", address);
|
||||||
warp::serve(web::routes(state)).run(address).await;
|
warp::serve(web::routes(state)).run(address).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spawn_command_reader(state: Arc<State>, 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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub struct RetrievedMessage {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub created: NaiveDateTime,
|
pub created: NaiveDateTime,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub user: String,
|
pub user: i64,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub last_seen_minutes: i64,
|
pub last_seen_minutes: i64,
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,15 @@ impl Pack {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut formatted = if template_1.contains("{0}") && let Some((w1_list, w1_word)) = word_1_idx {
|
let mut formatted = if_chain::if_chain! {
|
||||||
let word_1 = self.words.get(w1_list)?.words.get(w1_word)?;
|
if template_1.contains("{0}");
|
||||||
template_1.replace("{0}", word_1)
|
if let Some((w1_list, w1_word)) = word_1_idx;
|
||||||
} else {
|
then {
|
||||||
template_1.clone()
|
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 {
|
if let Some(conj_idx) = conjunction {
|
||||||
|
@ -49,15 +53,15 @@ impl Pack {
|
||||||
}
|
}
|
||||||
|
|
||||||
let template_2 = self.templates.get(template_2_idx)?;
|
let template_2 = self.templates.get(template_2_idx)?;
|
||||||
if template_2.contains("{0}") && word_2_idx.is_none() {
|
let append = if_chain::if_chain! {
|
||||||
return None;
|
if template_2.contains("{0}");
|
||||||
}
|
if let Some((w2_list, w2_word)) = word_2_idx;
|
||||||
|
then {
|
||||||
let append = if let Some((w2_list, w2_word)) = word_2_idx {
|
let word_2 = self.words.get(w2_list)?.words.get(w2_word)?;
|
||||||
let word_2 = self.words.get(w2_list)?.words.get(w2_word)?;
|
template_2.replace("{0}", word_2)
|
||||||
template_2.replace("{0}", word_2)
|
} else {
|
||||||
} else {
|
template_2.clone()
|
||||||
template_2.clone()
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
formatted.push_str(&append);
|
formatted.push_str(&append);
|
||||||
|
|
|
@ -59,12 +59,9 @@ async fn logic(state: Arc<State>, id: i64, location: u32) -> Result<impl Reply,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_messages(messages: &mut Vec<RetrievedMessage>, id: i64) {
|
fn filter_messages(messages: &mut Vec<RetrievedMessage>, 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
|
// 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)
|
// 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
|
// shuffle messages since we'll be excluding later based on messages
|
||||||
// that have already been included, so this will be more fair
|
// that have already been included, so this will be more fair
|
||||||
|
@ -73,7 +70,7 @@ fn filter_messages(messages: &mut Vec<RetrievedMessage>, id: i64) {
|
||||||
// just count nearby messages. this is O(n^2) but alternatives are hard
|
// just count nearby messages. this is O(n^2) but alternatives are hard
|
||||||
let mut ids = Vec::with_capacity(messages.len());
|
let mut ids = Vec::with_capacity(messages.len());
|
||||||
for a in messages.iter() {
|
for a in messages.iter() {
|
||||||
if a.user == id_str {
|
if a.user == id {
|
||||||
// always include own messages
|
// always include own messages
|
||||||
ids.push(a.id.clone());
|
ids.push(a.id.clone());
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue