summary refs log tree commit diff
path: root/src/system/mod.rs
blob: f5327e3a60dbb2d5247ec3e2d5c0a6422f41db2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
mod aggregator;
mod types;
mod plugin;
mod util;

use twilight_gateway::{Intents, Shard, ShardId};
use twilight_http::Client;
use twilight_model::channel::Message;
pub use types::SystemThreadCommand;
use crate::SystemUiEvent;
use std::{num::NonZeroU64, sync::Arc};
use tokio::sync::Mutex;
use plugin::SeancePlugin;

use std::sync::mpsc::Sender as ThreadSender;
use types::{Member, Response, System};

pub struct Manager;
impl Manager {
    pub async fn start(system_name: String, system_config: crate::config::System, ui_sender : ThreadSender<(String, SystemUiEvent)>) {
        let gateway_intents = Intents::GUILD_MEMBERS | Intents::GUILD_PRESENCES | Intents::GUILD_MESSAGES | Intents::MESSAGE_CONTENT;
        let system = System {
            followed_user: NonZeroU64::try_from(system_config.reference_user_id.parse::<u64>().unwrap()).unwrap().into(),
            command_prefix: "!".to_string(),
            members: system_config.members.iter().map(|member| Member {
                discord_token: member.discord_token.clone(),
                message_pattern: member.message_pattern.clone(),
                shard: Arc::new(Mutex::new(Shard::new(
                    ShardId::ONE,
                    member.discord_token.clone(),
                    gateway_intents.clone(),
                ))),
                client: Arc::new(Mutex::new(Client::new(member.discord_token.clone())))
            }).collect(),
        };

        let mut message_receiver = aggregator::MessageAggregator::start(&system);

        let mut plugins : Vec<Box<dyn SeancePlugin>> = vec![
            Box::new(plugin::ProxyPrefixes),
            Box::new(plugin::Autoproxy::new()),
        ];

        loop {
            match message_receiver.recv().await {
                None => (),
                Some((message, seen_by)) => {
                    println!("Checking message: {}", message.content.clone());
                    if message.content.starts_with(&system.command_prefix) {
                        for plugin in &mut plugins {
                            match plugin.handle_command(&system, &message).await {
                                plugin::CommandOutcome::Skipped => continue,
                                plugin::CommandOutcome::Handled => break,
                                plugin::CommandOutcome::Errored {message} => {
                                    println!("Error: {message}");
                                    break
                                },
                            }
                        }
                    } else {
                        let mut message_response = Response::Noop { delete_source: false };
                        for plugin in &plugins {
                            plugin.handle_message(&system, &message, &mut message_response).await;
                        }

                        match message_response.clone() {
                            Response::Noop { delete_source } => {
                                if delete_source {
                                    println!("Deleting source message");
                                    let client = system.members.iter().find(|m| m.discord_token == seen_by).map(|m| m.client.clone())
                                        .expect("No such client");

                                    let _ = client.lock().await.delete_message(message.channel_id, message.id)
                                        .await;
                                }
                            },
                            Response::Proxy { member, content } => {
                                if let Ok(new_message) = util::duplicate_message(&member.client, &message, content.as_str()).await {
                                    if let Err(err) = {member.client.lock().await.delete_message(message.channel_id, message.id).await.map(|_| ()).map_err(|err| err.to_string()).clone() } {
                                        println!("Error proxying message: {err}");
                                        {let _ = member.client.lock().await.delete_message(new_message.channel_id, new_message.id).await;}
                                    }

                                    for plugin in &plugins {
                                        plugin.post_response(&system, &new_message, message.channel_id, &message_response).await;
                                    }
                                }
                            },
                        }
                    }
                },
            }
        }
    }
}