forked from blasthavers/blastmud
Implement "report abuse" command.
This commit is contained in:
parent
590d4640dd
commit
a1495e6731
@ -193,7 +193,7 @@ impl DBPool {
|
|||||||
let conn = self.get_conn().await?;
|
let conn = self.get_conn().await?;
|
||||||
Ok(conn
|
Ok(conn
|
||||||
.query(
|
.query(
|
||||||
"SELECT item, session, listener, message FROM sendqueue ORDER BY item ASC LIMIT 10",
|
"SELECT item, session, listener, message FROM sendqueue WHERE sent_at IS NULL ORDER BY item ASC LIMIT 10",
|
||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
@ -204,7 +204,18 @@ impl DBPool {
|
|||||||
|
|
||||||
pub async fn delete_from_sendqueue(self: &DBPool, item: &SendqueueItem) -> DResult<()> {
|
pub async fn delete_from_sendqueue(self: &DBPool, item: &SendqueueItem) -> DResult<()> {
|
||||||
let conn = self.get_conn().await?;
|
let conn = self.get_conn().await?;
|
||||||
conn.execute("DELETE FROM sendqueue WHERE item=$1", &[&item.item])
|
conn.execute(
|
||||||
|
"UPDATE sendqueue SET sent_at = NOW() WHERE item=$1",
|
||||||
|
&[&item.item],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
conn.execute("DELETE FROM sendqueue WHERE item IN (\
|
||||||
|
WITH item_rows AS (\
|
||||||
|
SELECT item, row_number() OVER (ORDER BY sent_at DESC) AS rn FROM sendqueue
|
||||||
|
WHERE sent_at IS NOT NULL AND \
|
||||||
|
session = $1 AND listener = $2) \
|
||||||
|
SELECT item FROM item_rows WHERE rn > 80 \
|
||||||
|
)", &[&item.session.session, &item.session.listener])
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1670,6 +1681,42 @@ impl DBTrans {
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn sendqueue_to_abusereport(
|
||||||
|
&self,
|
||||||
|
uuid: &Uuid,
|
||||||
|
username: &str,
|
||||||
|
session: &ListenerSession,
|
||||||
|
) -> DResult<()> {
|
||||||
|
self.pg_trans()?
|
||||||
|
.execute(
|
||||||
|
"INSERT INTO abuselog (id, triggered_by, logdata, expires) \
|
||||||
|
VALUES ($1, $2, (\
|
||||||
|
SELECT json_build_object(\
|
||||||
|
'sendqueue', json_build_array(array_agg(json_build_object(\
|
||||||
|
'message', message, 'sent_at', sent_at)))) FROM sendqueue WHERE \
|
||||||
|
listener = $3 AND session = $4), \
|
||||||
|
NOW() + INTERVAL '60 days')",
|
||||||
|
&[&uuid, &username, &session.listener, &session.session],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn clean_and_count_abusereports(&self, username: &str) -> DResult<i64> {
|
||||||
|
let trans = self.pg_trans()?;
|
||||||
|
trans
|
||||||
|
.execute("DELETE FROM abuselog WHERE expires < NOW()", &[])
|
||||||
|
.await?;
|
||||||
|
Ok(trans
|
||||||
|
.query_one(
|
||||||
|
"SELECT COUNT(*) AS n FROM abuselog \
|
||||||
|
WHERE triggered_by = $1",
|
||||||
|
&[&username],
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.get("n"))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn commit(mut self: Self) -> DResult<()> {
|
pub async fn commit(mut self: Self) -> DResult<()> {
|
||||||
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
||||||
if let Some(trans) = trans_opt {
|
if let Some(trans) = trans_opt {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::message_handler::ListenerSession;
|
|
||||||
use crate::DResult;
|
|
||||||
use crate::db::DBPool;
|
use crate::db::DBPool;
|
||||||
|
use crate::message_handler::ListenerSession;
|
||||||
|
use crate::models::session::Session;
|
||||||
|
use crate::DResult;
|
||||||
use ansi::ansi;
|
use ansi::ansi;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use crate::models::session::Session;
|
|
||||||
|
|
||||||
// ANSI art version of the symbol we are legally required to display per:
|
// ANSI art version of the symbol we are legally required to display per:
|
||||||
// https://www.legislation.gov.au/Details/F2017C00102
|
// https://www.legislation.gov.au/Details/F2017C00102
|
||||||
@ -35,7 +35,14 @@ const AUS_RATING_SYMBOL: &'static str = "\x1b[48;5;234m \x1b[38;5;252;48;5;235m
|
|||||||
\x1b[49;38;5;233m▀▀\x1b[49;38;5;235m▀\x1b[49;38;5;242m▀\x1b[49;38;5;249m▀\x1b[49;38;5;254m▀\x1b[49;38;5;255m▀\x1b[49;38;5;253m▀▀\x1b[49;38;5;255m▀\x1b[49;38;5;254m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\x1b[49;38;5;255m▀\x1b[49;38;5;254m▀\x1b[49;38;5;7m▀\x1b[49;38;5;243m▀\x1b[49;38;5;235m▀\x1b[49;38;5;233m▀\x1b[49;38;5;234m▀\x1b[49;38;5;233m▀\x1b[m";
|
\x1b[49;38;5;233m▀▀\x1b[49;38;5;235m▀\x1b[49;38;5;242m▀\x1b[49;38;5;249m▀\x1b[49;38;5;254m▀\x1b[49;38;5;255m▀\x1b[49;38;5;253m▀▀\x1b[49;38;5;255m▀\x1b[49;38;5;254m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\x1b[49;38;5;255m▀\x1b[49;38;5;254m▀\x1b[49;38;5;7m▀\x1b[49;38;5;243m▀\x1b[49;38;5;235m▀\x1b[49;38;5;233m▀\x1b[49;38;5;234m▀\x1b[49;38;5;233m▀\x1b[m";
|
||||||
|
|
||||||
pub async fn handle(session: &ListenerSession, source: String, pool: &DBPool) -> DResult<()> {
|
pub async fn handle(session: &ListenerSession, source: String, pool: &DBPool) -> DResult<()> {
|
||||||
pool.start_session(session, &Session { source, ..Default::default() }).await?;
|
pool.start_session(
|
||||||
|
session,
|
||||||
|
&Session {
|
||||||
|
source,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
pool.queue_for_session(&session, Some(&(ansi!("\
|
pool.queue_for_session(&session, Some(&(ansi!("\
|
||||||
Welcome to <red>BlastMud<reset> - a text-based post-apocalyptic \
|
Welcome to <red>BlastMud<reset> - a text-based post-apocalyptic \
|
||||||
game <bold>restricted to adults (18+)<reset>\r\n").to_owned() + AUS_RATING_SYMBOL + ansi!("\r\n\
|
game <bold>restricted to adults (18+)<reset>\r\n").to_owned() + AUS_RATING_SYMBOL + ansi!("\r\n\
|
||||||
@ -47,7 +54,8 @@ pub async fn handle(session: &ListenerSession, source: String, pool: &DBPool) ->
|
|||||||
\t<bold>help<reset> to learn more.\r\n\
|
\t<bold>help<reset> to learn more.\r\n\
|
||||||
[Please contact staff@blastmud.org with any feedback or suggestions on how to \r\n\
|
[Please contact staff@blastmud.org with any feedback or suggestions on how to \r\n\
|
||||||
improve Blastmud, to report any inappropriate user generated content or behaviour, or if you \r\n\
|
improve Blastmud, to report any inappropriate user generated content or behaviour, or if you \r\n\
|
||||||
need any other help from the game's operators].\r\n\
|
need any other help from the game's operators; use <bold>report abuse<reset> immediately after \r\n\
|
||||||
|
receiving any inappropriate message to store evidence].\r\n\
|
||||||
Blastmud's privacy policy: https://blastmud.org/privacy/\r\n")))).await?;
|
Blastmud's privacy policy: https://blastmud.org/privacy/\r\n")))).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ mod quit;
|
|||||||
pub mod register;
|
pub mod register;
|
||||||
pub mod remove;
|
pub mod remove;
|
||||||
pub mod rent;
|
pub mod rent;
|
||||||
|
mod report;
|
||||||
pub mod say;
|
pub mod say;
|
||||||
mod score;
|
mod score;
|
||||||
mod sign;
|
mod sign;
|
||||||
@ -200,9 +201,9 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
|||||||
"reply" => page::VERB,
|
"reply" => page::VERB,
|
||||||
|
|
||||||
"put" => put::VERB,
|
"put" => put::VERB,
|
||||||
|
|
||||||
"remove" => remove::VERB,
|
"remove" => remove::VERB,
|
||||||
"rent" => rent::VERB,
|
"rent" => rent::VERB,
|
||||||
|
"report" => report::VERB,
|
||||||
|
|
||||||
"\'" => say::VERB,
|
"\'" => say::VERB,
|
||||||
"say" => say::VERB,
|
"say" => say::VERB,
|
||||||
|
41
blastmud_game/src/message_handler/user_commands/report.rs
Normal file
41
blastmud_game/src/message_handler/user_commands/report.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use super::{get_user_or_fail, user_error, UResult, UserVerb, UserVerbRef, VerbContext};
|
||||||
|
use ansi::ansi;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub struct Verb;
|
||||||
|
#[async_trait]
|
||||||
|
impl UserVerb for Verb {
|
||||||
|
async fn handle(
|
||||||
|
self: &Self,
|
||||||
|
ctx: &mut VerbContext,
|
||||||
|
_verb: &str,
|
||||||
|
remaining: &str,
|
||||||
|
) -> UResult<()> {
|
||||||
|
if remaining != "abuse" {
|
||||||
|
user_error(ansi!("Try <bold>report abuse<reset>.").to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let user = get_user_or_fail(ctx)?;
|
||||||
|
let username = user.username.to_lowercase();
|
||||||
|
if ctx.trans.clean_and_count_abusereports(&username).await? > 10 {
|
||||||
|
user_error(
|
||||||
|
ansi!(
|
||||||
|
"You have too many recent abuse reports logged to record any more. \
|
||||||
|
Contact staff@blastmud.org for help."
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uuid = Uuid::new_v4();
|
||||||
|
ctx.trans
|
||||||
|
.sendqueue_to_abusereport(&uuid, &username, &ctx.session)
|
||||||
|
.await?;
|
||||||
|
ctx.trans.queue_for_session(ctx.session, Some(&format!("Up to the last 80 things we sent you since you logged in will now be retained for at least 60 days under reference {}. Send an email to staff@blastmud.org explaining exactly what happened, and include this reference. We'll be able to look it up and investigate.\n", &uuid))).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VERB_INT: Verb = Verb;
|
||||||
|
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -7,7 +7,7 @@ CREATE DATABASE blast_schemaonly;
|
|||||||
|
|
||||||
CREATE TABLE listeners (
|
CREATE TABLE listeners (
|
||||||
listener UUID NOT NULL PRIMARY KEY,
|
listener UUID NOT NULL PRIMARY KEY,
|
||||||
last_seen TIMESTAMP WITH TIME ZONE
|
last_seen TIMESTAMPTZ
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE sessions (
|
CREATE TABLE sessions (
|
||||||
@ -48,9 +48,19 @@ CREATE UNLOGGED TABLE sendqueue (
|
|||||||
item BIGSERIAL NOT NULL PRIMARY KEY,
|
item BIGSERIAL NOT NULL PRIMARY KEY,
|
||||||
session UUID NOT NULL REFERENCES sessions(session),
|
session UUID NOT NULL REFERENCES sessions(session),
|
||||||
listener UUID REFERENCES listeners(listener),
|
listener UUID REFERENCES listeners(listener),
|
||||||
message TEXT /* Nullable, null means disconnect */
|
message TEXT, /* Nullable, null means disconnect */
|
||||||
|
sent_at TIMESTAMPTZ
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE abuselog (
|
||||||
|
id UUID NOT NULL PRIMARY KEY,
|
||||||
|
triggered_by TEXT NOT NULL,
|
||||||
|
logdata JSONB NOT NULL,
|
||||||
|
expires TIMESTAMPTZ NOT NULL
|
||||||
|
);
|
||||||
|
CREATE INDEX abuselog_by_triggerer ON abuselog(triggered_by);
|
||||||
|
CREATE INDEX abuselog_by_expires ON abuselog(expires);
|
||||||
|
|
||||||
CREATE TABLE tasks (
|
CREATE TABLE tasks (
|
||||||
task_id BIGSERIAL NOT NULL PRIMARY KEY,
|
task_id BIGSERIAL NOT NULL PRIMARY KEY,
|
||||||
details JSONB NOT NULL
|
details JSONB NOT NULL
|
||||||
|
Loading…
Reference in New Issue
Block a user