2017-02-08 03:25:03 -06:00
|
|
|
extern crate toml;
|
2017-02-13 00:22:06 -06:00
|
|
|
extern crate crossbeam;
|
2017-02-13 22:13:33 -06:00
|
|
|
extern crate discord;
|
2017-02-16 02:00:38 -06:00
|
|
|
extern crate rand;
|
2017-02-08 03:25:03 -06:00
|
|
|
|
|
|
|
use std::collections::BTreeMap;
|
|
|
|
use toml::Table;
|
|
|
|
|
2017-02-16 01:05:33 -06:00
|
|
|
mod modules;
|
|
|
|
use modules::Module;
|
|
|
|
use modules::loader::{ModuleLoader, ModuleLoaderError};
|
2017-02-13 00:22:06 -06:00
|
|
|
|
|
|
|
mod event;
|
|
|
|
use event::Event;
|
|
|
|
|
2017-02-16 00:16:48 -06:00
|
|
|
use std::sync::Arc;
|
2017-02-13 00:22:06 -06:00
|
|
|
use std::sync::mpsc;
|
2017-02-13 21:44:37 -06:00
|
|
|
use std::sync::mpsc::Sender;
|
2017-02-08 03:25:03 -06:00
|
|
|
|
2017-02-16 02:00:38 -06:00
|
|
|
mod helpers;
|
|
|
|
|
2017-02-17 02:38:15 -06:00
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
|
|
|
|
2017-02-08 03:25:03 -06:00
|
|
|
pub struct Tenquestionmarks {
|
2017-02-16 01:05:33 -06:00
|
|
|
modules: BTreeMap<String, Box<Module>>
|
2017-02-08 03:25:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Tenquestionmarks {
|
2017-02-16 01:05:33 -06:00
|
|
|
pub fn with_modules (modules: BTreeMap<String, Box<Module>>) -> Tenquestionmarks {
|
2017-02-13 00:22:06 -06:00
|
|
|
let tqm = Tenquestionmarks {
|
2017-02-16 01:05:33 -06:00
|
|
|
modules: modules
|
2017-02-13 00:22:06 -06:00
|
|
|
};
|
|
|
|
|
2017-02-16 01:05:33 -06:00
|
|
|
for (key, module) in &tqm.modules {
|
|
|
|
module.register(&tqm);
|
2017-02-08 03:25:03 -06:00
|
|
|
}
|
2017-02-13 00:22:06 -06:00
|
|
|
|
|
|
|
tqm
|
2017-02-08 03:25:03 -06:00
|
|
|
}
|
|
|
|
|
2017-02-16 01:05:33 -06:00
|
|
|
pub fn from_configuration (configuration: Table) -> Result<Tenquestionmarks, ModuleLoaderError> {
|
|
|
|
let loader = ModuleLoader::new();
|
|
|
|
let modules = loader.load_from_configuration(configuration)?;
|
|
|
|
Result::Ok(Tenquestionmarks::with_modules(modules))
|
2017-02-08 03:25:03 -06:00
|
|
|
}
|
2017-02-13 00:22:06 -06:00
|
|
|
|
|
|
|
pub fn run (&self) {
|
|
|
|
crossbeam::scope(|scope| {
|
|
|
|
// Our event channel.
|
2017-02-16 01:05:33 -06:00
|
|
|
// Modules push events to tenquestionmarks using this channel.
|
2017-02-13 00:22:06 -06:00
|
|
|
let (ref sender, ref receiver) = mpsc::channel();
|
|
|
|
|
2017-02-16 01:05:33 -06:00
|
|
|
// Module event consumer threads.
|
|
|
|
// tenquestionmarks propagates all events to each Module through these
|
2017-02-13 00:22:06 -06:00
|
|
|
// channels.
|
2017-02-16 01:05:33 -06:00
|
|
|
let senders: Vec<Sender<Event>> = self.modules.values().map(|module| {
|
2017-02-13 00:22:06 -06:00
|
|
|
let (sender, receiver) = mpsc::channel();
|
2017-02-16 01:05:33 -06:00
|
|
|
scope.spawn(move || module.consume_events(receiver));
|
2017-02-13 00:22:06 -06:00
|
|
|
sender
|
|
|
|
}).collect();
|
|
|
|
|
2017-02-16 01:05:33 -06:00
|
|
|
// Module event producer threads.
|
|
|
|
// Each Module will produce events which tenquestionmarks will push
|
|
|
|
// into all other Modules.
|
|
|
|
for module in self.modules.values() {
|
|
|
|
let module_sender = sender.clone();
|
|
|
|
scope.spawn(move || module.produce_events(module_sender));
|
2017-02-13 00:22:06 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// tenquestionmarks main event loop.
|
2017-02-16 01:05:33 -06:00
|
|
|
// tenquestionmarks receives events produced by Modules and pushes them
|
|
|
|
// into all other Modules
|
2017-02-13 00:22:06 -06:00
|
|
|
loop {
|
|
|
|
match receiver.recv() {
|
|
|
|
Ok(event) => {
|
|
|
|
for sender in &senders {
|
2017-02-17 02:38:15 -06:00
|
|
|
match sender.send(event.clone()) {
|
|
|
|
Err(err) => debug!("Failed to dispatch event to module: {:?}", err),
|
|
|
|
Ok(_) => {}
|
|
|
|
}
|
2017-02-13 00:22:06 -06:00
|
|
|
}
|
|
|
|
},
|
2017-02-17 02:38:15 -06:00
|
|
|
Err(err) => { error!("Failed to receive event in main event loop: {:?}", err); }
|
2017-02-13 00:22:06 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-02-08 03:25:03 -06:00
|
|
|
}
|
|
|
|
|
2017-02-15 22:41:52 -06:00
|
|
|
#[derive(Clone)]
|
2017-02-15 23:41:29 -06:00
|
|
|
pub struct Channel {
|
2017-02-08 03:25:03 -06:00
|
|
|
name: String,
|
|
|
|
description: String,
|
2017-02-15 22:41:52 -06:00
|
|
|
topic: String,
|
2017-02-16 00:16:48 -06:00
|
|
|
sender: Arc<MessageSender>
|
2017-02-08 03:25:03 -06:00
|
|
|
}
|
|
|
|
|
2017-02-15 23:41:29 -06:00
|
|
|
impl Channel {
|
2017-02-13 21:44:37 -06:00
|
|
|
pub fn send (&self, message: &str) {
|
2017-02-15 23:41:29 -06:00
|
|
|
self.sender.send_message(message);
|
2017-02-13 21:44:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-15 22:41:52 -06:00
|
|
|
#[derive(Clone)]
|
2017-02-15 23:41:29 -06:00
|
|
|
pub struct User {
|
2017-02-15 22:41:52 -06:00
|
|
|
name: String,
|
2017-02-16 00:16:48 -06:00
|
|
|
sender: Arc<MessageSender>
|
2017-02-08 03:25:03 -06:00
|
|
|
}
|
2017-02-13 21:44:37 -06:00
|
|
|
|
2017-02-15 23:41:29 -06:00
|
|
|
impl User {
|
2017-02-13 21:44:37 -06:00
|
|
|
pub fn send (&self, message: &str) {
|
2017-02-15 23:41:29 -06:00
|
|
|
self.sender.send_message(message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait MessageSender : Sync + Send {
|
|
|
|
fn send_message (&self, message: &str) {}
|
|
|
|
}
|