aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Perry <avaglir@gmail.com>2019-03-03 02:39:24 -0500
committerNathan Perry <avaglir@gmail.com>2019-03-03 02:39:24 -0500
commit83a06bfbd18e4f539b8e42e8e65d719040863100 (patch)
tree93e93db99ee97b75672f714e48fdfd3ce53bde92
parent410596f875111fab3d666a472c61be8869d7f7ec (diff)
record meme invocations
-rw-r--r--migrations/2019-03-03-045503_meme_invocation_records/down.sql5
-rw-r--r--migrations/2019-03-03-045503_meme_invocation_records/up.sql12
-rw-r--r--src/commands/meme.rs79
-rw-r--r--src/commands/mod.rs6
-rw-r--r--src/db/models.rs49
-rw-r--r--src/db/schema.rs12
6 files changed, 138 insertions, 25 deletions
diff --git a/migrations/2019-03-03-045503_meme_invocation_records/down.sql b/migrations/2019-03-03-045503_meme_invocation_records/down.sql
new file mode 100644
index 0000000..41333ae
--- /dev/null
+++ b/migrations/2019-03-03-045503_meme_invocation_records/down.sql
@@ -0,0 +1,5 @@
+DROP INDEX invocation_user_id;
+DROP INDEX invocation_time;
+DROP INDEX invocation_meme_random;
+
+DROP TABLE invocation_records;
diff --git a/migrations/2019-03-03-045503_meme_invocation_records/up.sql b/migrations/2019-03-03-045503_meme_invocation_records/up.sql
new file mode 100644
index 0000000..a81c273
--- /dev/null
+++ b/migrations/2019-03-03-045503_meme_invocation_records/up.sql
@@ -0,0 +1,12 @@
+CREATE TABLE invocation_records (
+ id SERIAL PRIMARY KEY,
+ user_id BIGINT NOT NULL,
+ message_id BIGINT NOT NULL,
+ meme_id INTEGER NOT NULL,
+ time TIMESTAMP NOT NULL DEFAULT current_timestamp,
+ random BOOLEAN NOT NULL
+);
+
+CREATE INDEX invocation_user_id ON invocation_records (user_id);
+CREATE INDEX invocation_time ON invocation_records (time);
+CREATE INDEX invocation_meme_random ON invocation_records (meme_id, random);
diff --git a/src/commands/meme.rs b/src/commands/meme.rs
index f83b793..84035ff 100644
--- a/src/commands/meme.rs
+++ b/src/commands/meme.rs
@@ -4,12 +4,10 @@ use std::{
Command,
Stdio,
},
- sync::RwLock,
};
use diesel::PgConnection;
use failure::Error;
-use lazy_static::lazy_static;
use rand::{Rng, thread_rng};
use serenity::{
builder::CreateMessage,
@@ -38,17 +36,6 @@ use crate::{
Result,
};
-lazy_static! {
- static ref LAST_MEME: RwLock<Option<i32>> = RwLock::new(None);
-}
-
-fn update_meme(meme: &Meme) -> Result<()> {
- let mut opt = LAST_MEME.write().map_err(|_| crate::failure::err_msg("unable to acquire lock"))?;
- *opt = Some(meme.id);
-
- Ok(())
-}
-
#[inline]
pub fn meme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
_meme(ctx, msg, args, false)
@@ -69,7 +56,7 @@ fn _meme(ctx: &mut Context, msg: &Message, args: Args, audio_only: bool) -> Resu
let conn = connection()?;
let mem = match find_meme(&conn, search) {
Ok(x) => {
- update_meme(&x)?;
+ InvocationRecord::create(&conn, msg.author.id.0, msg.id.0, x.id, false)?;
x
},
@@ -90,17 +77,13 @@ fn _meme(ctx: &mut Context, msg: &Message, args: Args, audio_only: bool) -> Resu
}
pub fn wat(_: &mut Context, msg: &Message, _: Args) -> Result<()> {
- use failure::err_msg;
-
let conn = connection()?;
- let meme = LAST_MEME.read()
- .map_err(|_| err_msg("unable to acquire read lock"))
- .and_then(|id| {
- id.ok_or(err_msg("no previous meme"))
- .and_then(|id| {
- Meme::find(&conn, id)
- })
- });
+
+ let record = match InvocationRecord::last(&conn) {
+ Ok(x) => x,
+ Err(_) => return send(msg.channel_id, "no one has ever memed before", msg.tts),
+ };
+ let meme = Meme::find(&conn, record.meme_id);
match meme {
Ok(ref meme) => {
@@ -117,6 +100,52 @@ pub fn wat(_: &mut Context, msg: &Message, _: Args) -> Result<()> {
meme.map(|_| {})
}
+pub fn history(_: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
+ use itertools::Itertools;
+
+ const MAX_HIST: usize = 8;
+ const DEFAULT_HIST: usize = 3;
+
+ let conn = connection()?;
+
+ let n = args.single_quoted::<usize>().unwrap_or(DEFAULT_HIST);
+
+ if n > MAX_HIST {
+ send(msg.channel_id, "YER PUSHIN ME OVER THE FUCKIN LINE", true)?;
+ }
+
+ let n = n.min(MAX_HIST);
+
+ let records = InvocationRecord::last_n(&conn, n)?;
+
+ if records.len() == 0 {
+ return send(msg.channel_id, "i don't remember anything :(", msg.tts);
+ }
+
+ let resp = records
+ .into_iter()
+ .enumerate()
+ .rev()
+ .map(|(i, rec)| {
+ Meme::find(&conn, rec.meme_id)
+ .and_then(|meme| {
+ Metadata::find(&conn, meme.metadata_id).map(|metadata| (metadata, meme))
+ })
+ .map(|(metadata, meme)| {
+ let author_name = crate::TARGET_GUILD_ID.member(metadata.created_by as u64).map(|m| m.display_name().into_owned()).unwrap_or("???".to_owned());
+ let invoker_name = crate::TARGET_GUILD_ID.member(rec.user_id as u64).map(|m| m.display_name().into_owned()).unwrap_or("???".to_owned());
+ format!("{}. \"{}\" by {} ({}). invoked by {} at {}", i + 1, meme.title, author_name, metadata.created.date(), invoker_name, rec.time)
+ })
+ .unwrap_or_else(|_| {
+ let invoker_name = crate::TARGET_GUILD_ID.member(rec.user_id as u64).map(|m| m.display_name().into_owned()).unwrap_or("???".to_owned());
+ format!("{}. not found. invoked by {} at {}", i + 1, invoker_name, rec.time)
+ })
+ })
+ .join("\n");
+
+ send(msg.channel_id, &resp, false)
+}
+
pub fn addmeme(_: &mut Context, msg: &Message, args: Args) -> Result<()> {
let mut args = Args::new(args.rest(), &[" ".to_owned(), "\n".to_owned(), "\t".to_owned()]);
@@ -273,7 +302,7 @@ fn rand_meme(ctx: &Context, message: &Message, audio_only: bool) -> Result<()> {
match mem {
Ok(mem) => {
- update_meme(&mem)?;
+ InvocationRecord::create(&conn, message.author.id.0, message.id.0, mem.id, true)?;
send_meme(ctx, &mem, &conn, message).map_err(Error::from)
},
err @ Err(_) => {
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 8009093..2f18e9f 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -116,6 +116,12 @@ fn register_db(f: StandardFramework) -> StandardFramework {
.desc("get meme stats")
.cmd(stats)
)
+ .command("history", |c| c
+ .known_as("hist")
+ .guild_only(true)
+ .desc("history of recent messages")
+ .cmd(history)
+ )
}
#[cfg(not(feature = "diesel"))]
diff --git a/src/db/models.rs b/src/db/models.rs
index 67aa1ca..66e161a 100644
--- a/src/db/models.rs
+++ b/src/db/models.rs
@@ -235,3 +235,52 @@ pub struct NewTombstone {
pub metadata_id: i32,
pub meme_id: i32,
}
+
+#[derive(Queryable, Identifiable, PartialEq, Debug)]
+#[table_name="invocation_records"]
+pub struct InvocationRecord {
+ pub id: i32,
+ pub user_id: i64,
+ pub message_id: i64,
+ pub meme_id: i32,
+ pub time: NaiveDateTime,
+ pub random: bool,
+}
+
+#[derive(Insertable, PartialEq, Debug)]
+#[table_name="invocation_records"]
+pub struct NewInvocationRecord {
+ pub user_id: i64,
+ pub message_id: i64,
+ pub meme_id: i32,
+ pub random: bool,
+}
+
+impl InvocationRecord {
+ pub fn create(conn: &PgConnection, user_id: u64, message_id: u64, meme_id: i32, random: bool) -> Result<Self> {
+ ::diesel::insert_into(invocation_records::table)
+ .values(&NewInvocationRecord {
+ user_id: user_id as i64,
+ message_id: message_id as i64,
+ meme_id,
+ random,
+ })
+ .get_result::<InvocationRecord>(conn)
+ .map_err(Error::from)
+ }
+
+ pub fn last(conn: &PgConnection) -> Result<Self> {
+ invocation_records::table
+ .order(invocation_records::time.desc())
+ .first(conn)
+ .map_err(Error::from)
+ }
+
+ pub fn last_n(conn: &PgConnection, n: usize) -> Result<Vec<Self>> {
+ invocation_records::table
+ .order(invocation_records::time.desc())
+ .limit(n as i64)
+ .load(conn)
+ .map_err(Error::from)
+ }
+}
diff --git a/src/db/schema.rs b/src/db/schema.rs
index 8749731..1ab5fa1 100644
--- a/src/db/schema.rs
+++ b/src/db/schema.rs
@@ -27,6 +27,17 @@ table! {
}
table! {
+ invocation_records (id) {
+ id -> Int4,
+ user_id -> Int8,
+ message_id -> Int8,
+ meme_id -> Int4,
+ time -> Timestamp,
+ random -> Bool,
+ }
+}
+
+table! {
memes (id) {
id -> Int4,
title -> Varchar,
@@ -67,6 +78,7 @@ allow_tables_to_appear_in_same_query!(
audio,
audit_records,
images,
+ invocation_records,
memes,
metadata,
tombstones,