2021-05-04 00:01:36 +02:00
use async_trait ::async_trait ;
2021-05-03 21:50:44 +02:00
use inbox ::* ;
use lazy_static ::lazy_static ;
2021-04-09 17:32:03 +02:00
use serenity ::client ::Client ;
use serenity ::framework ::standard ::{
macros ::{ command , group } ,
2021-05-04 00:01:36 +02:00
CommandResult , StandardFramework ,
2021-04-09 17:32:03 +02:00
} ;
2021-11-20 16:01:23 +01:00
use serenity ::model ::channel ::{ Reaction , ReactionType } ;
2021-04-09 17:32:03 +02:00
use serenity ::model ::{
channel ::Message ,
2021-05-03 22:06:19 +02:00
id ::{ ChannelId , GuildId , UserId } ,
2021-04-09 17:32:03 +02:00
prelude ::User ,
} ;
use serenity ::prelude ::* ;
use std ::fs ::File ;
use std ::io ::{ self , BufRead , BufReader } ;
use time ::Duration ;
2021-05-03 21:50:44 +02:00
mod inbox ;
const APPLICATION_NAME : & str = " didgeridoo " ;
2021-05-03 22:06:19 +02:00
const INBOX_OWNER : UserId = UserId ( 354694403798990848 ) ;
2021-05-03 21:50:44 +02:00
lazy_static! {
static ref INBOX : Inbox = Inbox ( redis ::Client ::open ( " redis://127.0.0.1/ " ) . unwrap ( ) ) ;
}
2021-04-09 17:32:03 +02:00
2021-05-03 22:06:19 +02:00
macro_rules ! send_or_log {
( $e : expr ) = > {
if let Err ( e ) = $e {
eprintln! ( " Couldn’t send message because {:?} " , e ) ;
}
} ;
}
2021-04-09 17:32:03 +02:00
#[ group ]
2021-05-03 21:50:44 +02:00
#[ commands(name, message, question, inbox) ]
2021-04-09 17:32:03 +02:00
struct Fluff ;
struct Handler ;
2021-05-04 00:01:36 +02:00
#[ async_trait ]
2021-04-09 17:32:03 +02:00
impl EventHandler for Handler {
2021-05-04 00:01:36 +02:00
async fn guild_ban_addition ( & self , ctx : Context , guild_id : GuildId , _ : User ) {
2021-04-09 17:32:03 +02:00
if guild_id = = 427456811973738498 {
2021-05-04 00:01:36 +02:00
send_or_log! ( {
ChannelId ( 562731470423064587 )
. say ( & ctx , " Dies ist eine flauschige Diktatur! " )
. await
} ) ;
2021-04-09 17:32:03 +02:00
}
}
2021-11-20 16:01:23 +01:00
async fn reaction_add ( & self , ctx : Context , reaction : Reaction ) {
if reaction . message_id = = 911630315376738384
& & reaction . emoji = = ReactionType ::Unicode ( String ::from ( " 🧪 " ) )
{
reaction
. guild_id
. unwrap ( )
. member ( & ctx , reaction . user_id . unwrap ( ) )
. await
. unwrap ( )
. add_role ( & ctx , 356421827708321795 )
. await
. unwrap ( )
}
}
async fn reaction_remove ( & self , ctx : Context , reaction : Reaction ) {
if reaction . message_id = = 911630315376738384
& & reaction . emoji = = ReactionType ::Unicode ( String ::from ( " 🧪 " ) )
{
reaction
. guild_id
. unwrap ( )
. member ( & ctx , reaction . user_id . unwrap ( ) )
. await
. unwrap ( )
. remove_role ( & ctx , 356421827708321795 )
. await
. unwrap ( )
}
}
2021-04-09 17:32:03 +02:00
}
fn read_token ( ) -> io ::Result < String > {
let reader = BufReader ::new ( File ::open ( " secret " ) ? ) ;
reader . lines ( ) . next ( ) . unwrap ( )
}
2021-05-04 00:01:36 +02:00
#[ tokio::main ]
async fn main ( ) {
let mut client = Client ::builder ( & read_token ( ) . expect ( " no secret file " ) )
. event_handler ( Handler )
. framework (
StandardFramework ::new ( )
. configure ( | c | c . prefix ( " ! " ) )
. group ( & FLUFF_GROUP ) ,
)
. await
2021-04-09 17:32:03 +02:00
. expect ( " Error creating client " ) ;
2021-05-03 21:50:44 +02:00
INBOX . count_messages ( " test " ) ; // initialize the lazy static so we know if redis is unavailable
2021-05-04 00:01:36 +02:00
if let Err ( why ) = client . start ( ) . await {
2021-04-09 17:32:03 +02:00
println! ( " An error occurred while running the client: {:?} " , why ) ;
}
}
#[ command ]
2021-05-04 00:01:36 +02:00
async fn name ( ctx : & Context , msg : & Message ) -> CommandResult {
2021-04-09 17:32:03 +02:00
if let Some ( ( _ , name ) ) = msg . content . split_once ( ' ' ) {
let ( name , adjustment ) = name . split_once ( " - " ) . unwrap_or ( ( name , " 0 " ) ) ;
let adjustment = adjustment . strip_suffix ( " h " ) . unwrap_or ( adjustment ) ;
msg . guild ( & ctx )
2021-05-04 00:01:36 +02:00
. await
2021-04-09 17:32:03 +02:00
. unwrap ( )
2021-05-04 00:01:36 +02:00
. edit_member ( & ctx , msg . author . id , | m | m . nickname ( name ) )
. await ? ;
2021-04-09 17:32:03 +02:00
let now = time ::OffsetDateTime ::now_utc ( )
- adjustment
. parse ::< f32 > ( )
. map ( | a | ( a * 3600.0 ) as i64 )
. map ( Duration ::seconds )
. ok ( )
. unwrap_or_else ( Duration ::zero ) ;
println! (
" {},{},{},{},{} " ,
now . format ( " %d.%m.%Y %H:%M " ) ,
name ,
now . format ( " %y%m " ) ,
msg . author . id ,
now . unix_timestamp ( )
) ;
2021-07-20 20:31:58 +02:00
if msg . author . id = = INBOX_OWNER {
2021-07-20 20:36:13 +02:00
let msg_count = INBOX . count_messages ( name ) ;
2021-07-20 20:31:58 +02:00
if msg_count > 0 {
send_or_log! (
msg . reply ( & ctx , format! ( " {} neue Nachrichten für {} " , msg_count , name ) )
. await
) ;
} else {
send_or_log! (
msg . reply ( & ctx , format! ( " Keine neuen Nachrichten für {} " , name ) )
. await
) ;
}
}
2021-04-09 17:32:03 +02:00
} else {
2021-05-04 00:01:36 +02:00
send_or_log! ( msg . reply ( & ctx , " Please specify a new name. " ) . await ) ;
2021-05-03 21:50:44 +02:00
}
Ok ( ( ) )
}
#[ command ]
2021-05-04 00:01:36 +02:00
async fn inbox ( ctx : & Context , msg : & Message ) -> CommandResult {
2021-05-04 13:23:12 +02:00
if msg . author . id ! = INBOX_OWNER | | ! msg . is_private ( ) {
2021-05-04 00:01:36 +02:00
send_or_log! (
msg . reply ( & ctx , " You don’t have the permission to do that " )
. await
) ;
2021-05-03 22:06:19 +02:00
return Ok ( ( ) ) ;
}
2021-05-03 21:50:44 +02:00
if let Some ( ( _ , name ) ) = msg . content . split_once ( ' ' ) {
let messages = INBOX . fetch_messages ( name ) ;
if messages . is_empty ( ) {
2021-05-04 00:01:36 +02:00
send_or_log! (
msg . reply ( & ctx , format! ( " Keine neuen Nachrichten für {} . " , name ) )
. await
) ;
2021-05-03 21:50:44 +02:00
return Ok ( ( ) ) ;
}
2021-05-04 13:23:12 +02:00
for message in & messages {
let content = message . to_string ( ) ;
// Since we’re prepending a name (and later a time) to the message,
// it could go over the limit of 2000 characters.
// There is some leniency in the numbers here because unicode codepoints are meh.
if content . len ( ) > 1900 {
let ( first , second ) = content . split_at ( 1500 ) ;
send_or_log! ( msg . channel_id . say ( & ctx , & first ) . await ) ;
send_or_log! ( msg . channel_id . say ( & ctx , & second ) . await ) ;
} else {
send_or_log! ( msg . channel_id . say ( & ctx , & content ) . await ) ;
}
}
println! ( " {:?} " , messages ) ; // paranoia for now so the messages aren’t lost
if let Err ( e ) = INBOX . clear_messages ( name ) {
eprintln! ( " Could not clear inbox of user {} because {} " , name , e ) ;
}
2021-05-03 21:50:44 +02:00
} else {
2021-05-04 00:01:36 +02:00
send_or_log! ( msg . reply ( & ctx , " Kein Name für die Abfrage. " ) . await ) ;
2021-04-09 17:32:03 +02:00
}
Ok ( ( ) )
}
2021-05-03 21:50:44 +02:00
2021-05-03 22:06:19 +02:00
#[ command ]
2021-05-04 00:01:36 +02:00
async fn message ( ctx : & Context , msg : & Message ) -> CommandResult {
message_internal ( ctx , msg , & msg . content ) . await
2021-05-03 22:06:19 +02:00
}
2021-05-03 21:50:44 +02:00
#[ command ]
2021-05-04 00:01:36 +02:00
async fn question ( ctx : & Context , msg : & Message ) -> CommandResult {
2021-05-03 22:06:19 +02:00
message_internal (
ctx ,
msg ,
2021-05-03 21:50:44 +02:00
& msg . content . replacen ( " !question " , " !message Stream: " , 1 ) ,
)
2021-05-04 00:01:36 +02:00
. await
2021-05-03 22:06:19 +02:00
}
2021-05-04 00:01:36 +02:00
async fn message_internal ( ctx : & Context , msg : & Message , content : & str ) -> CommandResult {
let result = InboxMessage ::parse ( content , msg . author . id )
2021-05-03 22:06:19 +02:00
. ok_or_else ( | | {
String ::from (
" Nachricht konnte nicht gesendet werden.
2021-05-03 21:50:44 +02:00
Bitte achte auf die richtige Formulierung : “ ! message < name > : < text > ” ,
z . B . “ ! message Lana : Hawwu ! ” " ,
2021-05-03 22:06:19 +02:00
)
} )
2021-05-04 00:01:36 +02:00
. and_then ( | m | INBOX . queue_message ( & m ) ) ;
match result {
Ok ( name ) = > send_or_log! (
msg . reply (
2021-05-03 22:06:19 +02:00
& ctx ,
2021-05-04 00:01:36 +02:00
format! ( " Deine Nachricht wurde erfolgreich an {} gesendet " , name ) ,
)
. await
) ,
Err ( e ) = > send_or_log! ( msg . reply ( & ctx , e ) . await ) ,
} ;
Ok ( ( ) )
2021-05-03 21:50:44 +02:00
}