Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use irc::client::Sender;
- use irc::proto::{chan, Command, Message};
- use regex::Regex;
- use serde::{Deserialize, Serialize};
- use std::borrow::BorrowMut;
- use std::error::Error;
- use std::fs;
- use std::path::Path;
- use std::sync::Arc;
- use std::collections::HashMap;
- use tokio::sync::Mutex;
- pub struct KarmaHandler {
- ignore: Vec<String>,
- db: KarmaDatabase,
- }
- #[derive(Serialize, Deserialize, Default)]
- pub struct KarmaItem {
- name: String,
- count: i32,
- whoup: HashMap<String,i32>,
- whodown: HashMap<String,i32>,
- whyup: Vec<String>,
- whydown: Vec<String>,
- }
- struct KarmaDatabase {
- items: HashMap<String, KarmaItem>,
- data_dir: String,
- }
- impl KarmaDatabase {
- fn new(data_dir: &str) -> Self {
- Self {
- items: HashMap::new(),
- data_dir: data_dir.to_string(),
- }
- }
- fn load_item(&mut self, channel: &str, key: &str) -> &mut KarmaItem {
- let lookup = channel.to_string() + "-" + key;
- let filename = channel.replace("#", "-") + "-" + key;
- if !self.items.contains_key(lookup.as_str()) {
- let path = Path::new(&self.data_dir).join(filename);
- if path.exists() {
- let data = fs::read_to_string(path).expect("Unable to read file");
- let item: KarmaItem = serde_json::from_str(&data).expect("Unable to parse JSON");
- self.items.insert(lookup.to_string(), item);
- } else {
- self.items.insert(lookup.to_string(), KarmaItem { name: lookup.to_string(), ..Default::default() });
- }
- }
- self.items.get_mut(lookup.as_str()).unwrap()
- }
- fn save_item(&self, channel: &str, key: &str) {
- let lookup = channel.to_string() + "-" + key;
- let filename = channel.replace("#", "-") + "-" + key;
- if let Some(item) = self.items.get(lookup.as_str()) {
- let path = Path::new(&self.data_dir).join(filename);
- let data = serde_json::to_string(item).expect("Unable to serialize JSON");
- fs::write(path, data).expect("Unable to write file");
- }
- }
- fn sync_item(&mut self, channel: &str, key: &str) {
- self.save_item(channel, key);
- }
- }
- impl KarmaHandler {
- pub fn new() -> KarmaHandler {
- KarmaHandler {
- db: KarmaDatabase::new("."),
- ignore: vec!["aristarchus".to_string()],
- }
- }
- fn prekarma(&self, message: &Message) -> bool {
- if let Command::PRIVMSG(ref target, ref msg) = message.command {
- let re_karma = Regex::new(r"^(?P<item>\([^\)]+\)|\[[^\]]+\]|\w+)(?P<mod>\+\+|--)( |$)").unwrap();
- if let Some(userhost) = message.source_nickname() {
- if self.ignore.contains(&userhost.to_string()) {
- return false;
- }
- }
- if let Some(captures) = re_karma.captures(msg) {
- if let Some(item) = captures.name("item") {
- if let Some(nick) = message.source_nickname() {
- if item.as_str() == nick {
- return false;
- } else {
- return true;
- }
- }
- }
- }
- }
- false
- }
- pub async fn handle_message(&mut self, sender:&Sender, message: &Message) {
- if(!self.prekarma(&message))
- {
- return;
- }
- if let Command::PRIVMSG(ref target, ref msg) = message.command {
- self.handle_privmsg(sender, target, msg, message).await.unwrap();
- }
- }
- async fn handle_privmsg(&mut self, sender: &Sender, target: &str, msg: &str, message: &Message) -> Result<(), Box<dyn std::error::Error>> {
- let re_karma = Regex::new(r"^(?P<item>\([^\)]+\)|\[[^\]]+\]|\w+)(?P<mod>\+\+|--)( |$)").unwrap();
- let channel = if target.starts_with("#") { target.to_lowercase() } else { "".to_string() };
- let reason = msg.split('#').nth(1).map(|s| s.trim().to_string());
- let source = message.source_nickname().unwrap_or("");
- let reply = message.response_target().unwrap_or(source);
- // create a list of output strings to send to the channel
- let mut output = Vec::<String>::new();
- for cap in re_karma.captures_iter(msg) {
- let item = cap.name("item").unwrap().as_str().to_lowercase();
- let modifier = cap.name("mod").unwrap().as_str();
- let mut karma_item = self.db.load_item(channel.as_str(), &item);
- if modifier == "++" {
- karma_item.count += 1;
- if !karma_item.whoup.contains_key(source) {
- karma_item.whoup.insert(source.to_string(), 0);
- }
- *karma_item.whoup.get_mut(source).unwrap() += 1;
- if let Some(ref reason) = reason {
- if !karma_item.whyup.contains(reason) {
- karma_item.whyup.push(reason.clone());
- }
- }
- } else {
- karma_item.count -= 1;
- if !karma_item.whodown.contains_key(source) {
- karma_item.whodown.insert(source.to_string(), 0);
- }
- *karma_item.whodown.get_mut(source).unwrap() -= 1;
- if let Some(ref reason) = reason {
- if !karma_item.whydown.contains(reason) {
- karma_item.whydown.push(reason.clone());
- }
- }
- }
- output.push(format!("{}: {}", item, karma_item.count));
- self.db.sync_item(channel.as_str(), &item);
- }
- sender.send_privmsg(reply, output.join(", ")).unwrap();
- Ok(())
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement