commit
680d73b71e
@ -0,0 +1,4 @@ |
||||
/target |
||||
grammar |
||||
config.toml |
||||
*~ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@ |
||||
[package] |
||||
name = "grammar-bot" |
||||
version = "0.1.0" |
||||
authors = ["xenofem <xenofem@xeno.science>"] |
||||
license = "MIT" |
||||
edition = "2018" |
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||
|
||||
[dependencies] |
||||
purrchance = "0.4.0" |
||||
serde = "1.0.112" |
||||
toml = "0.5.6" |
||||
|
||||
[dependencies.serenity] |
||||
git = "https://github.com/Lakelezz/serenity/" |
||||
branch = "await" |
||||
default-features = false |
||||
features = [ |
||||
"builder", |
||||
"cache", |
||||
"client", |
||||
"gateway", |
||||
"http", |
||||
"model", |
||||
"utils", |
||||
"rustls_backend", |
||||
] |
||||
|
||||
[dependencies.tokio] |
||||
version = "0.2" |
||||
features = ["macros"] |
@ -0,0 +1,6 @@ |
||||
grammar_path = "grammar" |
||||
grammar_type = "perchance" |
||||
grammar_symbol = "output" |
||||
token = "t0k3n" |
||||
channel_id = 0000000000000000 |
||||
interval = 7200 |
@ -0,0 +1,142 @@ |
||||
extern crate purrchance; |
||||
extern crate serde; |
||||
extern crate serenity; |
||||
extern crate tokio; |
||||
extern crate toml; |
||||
|
||||
use purrchance::{Grammar, Purrchance, Symbol, parser::load_grammar}; |
||||
use serde::Deserialize; |
||||
use serenity::{ |
||||
async_trait, |
||||
model::{channel::Message, gateway::Ready, id::ChannelId, user::User}, |
||||
prelude::*, |
||||
}; |
||||
use std::fs::read_to_string; |
||||
use std::process::exit; |
||||
use std::sync::Arc; |
||||
use std::time::Duration; |
||||
|
||||
#[derive(Deserialize)] |
||||
#[serde(rename_all = "lowercase")] |
||||
enum GrammarType { |
||||
Perchance, |
||||
} |
||||
|
||||
#[derive(Deserialize)] |
||||
struct Config { |
||||
grammar_path: String, |
||||
grammar_type: GrammarType, |
||||
grammar_symbol: String, |
||||
token: String, |
||||
channel_id: ChannelId, |
||||
interval: u64, |
||||
} |
||||
|
||||
struct TextGenerator { |
||||
grammar: Grammar, |
||||
symbol: Symbol, |
||||
} |
||||
|
||||
impl TextGenerator { |
||||
pub fn generate(&self) -> String { |
||||
self.symbol.eval(&self.grammar).unwrap() |
||||
} |
||||
} |
||||
|
||||
impl TypeMapKey for TextGenerator { |
||||
type Value = TextGenerator; |
||||
} |
||||
|
||||
struct Interval; |
||||
|
||||
impl TypeMapKey for Interval { |
||||
type Value = u64; |
||||
} |
||||
|
||||
struct ChanId; |
||||
|
||||
impl TypeMapKey for ChanId { |
||||
type Value = ChannelId; |
||||
} |
||||
|
||||
struct LoopStatus; |
||||
|
||||
impl TypeMapKey for LoopStatus { |
||||
type Value = bool; |
||||
} |
||||
|
||||
struct Handler; |
||||
|
||||
async fn mentions_me(ctx: &Context, msg: &Message) -> bool { |
||||
let me = User::from(ctx.http.get_current_user().await.unwrap()); |
||||
if msg.mentions_user(&me) { |
||||
return true |
||||
} |
||||
let guild = msg.guild(ctx).await.unwrap(); |
||||
let member = guild.member(ctx, me).await.unwrap(); |
||||
let my_roles = member.roles; |
||||
msg.mention_roles.iter().any(|r| my_roles.contains(r)) |
||||
} |
||||
|
||||
async fn interval_loop(ctx: Arc<Context>) { |
||||
let channel_id = ctx.data.read().await.get::<ChanId>().unwrap().clone(); |
||||
loop { |
||||
let sentence = ctx.data.read().await.get::<TextGenerator>().unwrap().generate(); |
||||
channel_id.say(&ctx.http, sentence).await; |
||||
tokio::time::delay_for(Duration::from_secs(*ctx.data.read().await.get::<Interval>().unwrap())).await; |
||||
} |
||||
} |
||||
|
||||
#[async_trait] |
||||
impl EventHandler for Handler { |
||||
async fn message(&self, ctx: Context, msg: Message) { |
||||
if mentions_me(&ctx, &msg).await { |
||||
let sentence = ctx.data.read().await.get::<TextGenerator>().unwrap().generate(); |
||||
msg.channel_id.say(&ctx.http, sentence).await; |
||||
} |
||||
} |
||||
|
||||
async fn ready(&self, ctx: Context, ready: Ready) { |
||||
eprintln!("{} is connected!", ready.user.name); |
||||
let ctx = Arc::new(ctx); |
||||
let ctx_clone = Arc::clone(&ctx); |
||||
if !ctx.data.read().await.get::<LoopStatus>().unwrap() { |
||||
let interval_loop = tokio::spawn(async move {interval_loop(ctx_clone).await}); |
||||
{ |
||||
let mut data = ctx.data.write().await; |
||||
data.insert::<LoopStatus>(true); |
||||
} |
||||
let _ = interval_loop.await; |
||||
{ |
||||
let mut data = ctx.data.write().await; |
||||
data.insert::<LoopStatus>(false); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[tokio::main] |
||||
async fn main() { |
||||
let config: Config = toml::from_str(&read_to_string("config.toml").unwrap()).unwrap(); |
||||
|
||||
match config.grammar_type { |
||||
GrammarType::Perchance => { |
||||
let grammar = load_grammar(&read_to_string(config.grammar_path).unwrap()).unwrap(); |
||||
let symbol = Symbol::NonTerminal(config.grammar_symbol); |
||||
|
||||
let mut client = Client::new(&config.token) |
||||
.event_handler(Handler) |
||||
.await |
||||
.expect("err creating client"); |
||||
|
||||
{ |
||||
let mut data = client.data.write().await; |
||||
data.insert::<TextGenerator>(TextGenerator { grammar, symbol }); |
||||
data.insert::<Interval>(config.interval); |
||||
data.insert::<ChanId>(config.channel_id); |
||||
data.insert::<LoopStatus>(false); |
||||
} |
||||
client.start().await; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue