Browse Source

I keep forgetting to do this more often

master
Thomas Johnson 3 years ago
parent
commit
c716642aff
  1. 1
      .gitignore
  2. 113
      src/discord_endpoint.rs
  3. 32
      src/endpoint.rs
  4. 37
      src/itercomb.rs
  5. 34
      src/main.rs
  6. 7
      src/refset.rs

1
.gitignore

@ -1,3 +1,4 @@
/target
**/*.rs.bk
Cargo.lock
config.json

113
src/discord_endpoint.rs

@ -3,6 +3,7 @@ use std::collections::hash_map::HashMap;
use std::sync::Arc;
use std::mem;
use std::thread;
use serenity::client::Client;
use serenity::prelude::*;
use serenity::model;
@ -10,19 +11,127 @@ use serenity::client::bridge::gateway::{ShardManager, event::ShardStageUpdateEve
use serenity::gateway::ConnectionStage;
use serenity::cache::Cache;
use serde::Deserialize;
use crate::endpoint::{Endpoint, Bridge, BridgeResult, Message, ReceiveCallback};
use crate::refset::RefSet;
pub struct DiscordManager
#[derive(Deserialize, Debug)]
pub struct DiscordConfig
{
instances: Vec<DiscordInstanceConfig>,
}
#[derive(Deserialize, Debug)]
pub struct DiscordInstanceConfig
{
token: String,
channels: HashMap<String, ChannelSer>,
}
struct DiscordEndpoint(Arc<RwLock<DiscordEndpointInner>>);
struct DiscordEndpointInner
{
bridges: RefSet<RwLock<Bridge>>,
instance: Mutex<Option<DiscordInstance>>,
manager: DiscordManager,
}
impl DiscordEndpoint
{
pub fn originate_message(&self, msg: Message)
{
for br in self.0.read().bridges.iter()
{
}
}
}
impl Endpoint<Arc<dyn ReceiveCallback>> for DiscordEndpoint
{
fn send(&self, msg: Message) -> BridgeResult
{
Ok(())
}
fn add_bridge(&mut self, br: Bridge)
{
}
fn remove_bridge(&mut self, br: Bridge)
{
}
fn add_receive_callback(&mut self, cb: Arc<dyn ReceiveCallback>)
{
}
fn remove_receive_callback(&mut self, cb: Arc<dyn ReceiveCallback>)
{
}
}
impl AsRef<RwLock<DiscordEndpointInner>> for DiscordEndpoint
{
fn as_ref(&self) -> &RwLock<DiscordEndpointInner>
{
self.0.as_ref()
}
}
#[derive(Debug)]
struct ChannelSer(model::id::ChannelId);
impl<'a> Deserialize<'a> for ChannelSer
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
D: serde::Deserializer<'a>
{
struct ChannelVisitor {};
impl<'a> serde::de::Visitor<'a> for ChannelVisitor
{
type Value = ChannelSer;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result
{
formatter.write_str("a Discord channel ID")
}
fn visit_str<E>(self, val: &str) -> Result<Self::Value, E> where
E: serde::de::Error
{
match str::parse::<model::id::ChannelId>(val)
{
Ok(id) => Ok(ChannelSer(id)),
Err(_) => Err(E::invalid_value(serde::de::Unexpected::Str(val), &self)),
}
}
}
let cv = ChannelVisitor {};
deserializer.deserialize_str(cv)
}
}
struct DiscordManager(Arc<Mutex<DiscordManagerInner>>);
struct DiscordManagerInner
{
pub instances: Vec<DiscordInstance>,
pub endpoints: RefSet<DiscordEndpoint>,
}
impl DiscordManager
{
pub fn new() -> DiscordManager
{
DiscordManager { instances: Vec::new() }
DiscordManager(Arc::new(Mutex::new(DiscordManagerInner
{
instances: Vec::new(),
endpoints: RefSet::new(),
})))
}
}

32
src/endpoint.rs

@ -1,5 +1,8 @@
use std::sync::Arc;
use serenity::prelude::Mutex;
use crate::itercomb::DummyIter;
pub enum Message
{
@ -31,19 +34,32 @@ impl From<std::io::Error> for Error
pub type BridgeResult<T = ()> = Result<T, Error>;
pub struct Bridge
pub struct Bridge(Arc<Mutex<BridgeInner<Arc<dyn ReceiveCallback>>>>);
struct BridgeInner<C>
{
endpoints: Vec<Box<dyn Endpoint<C>>>,
}
impl Bridge
{
endpoints: Vec<Arc<dyn Endpoint>>,
fn iter<'a, 'b>(&'a self) -> impl 'b + Iterator<Item = &'b Box<dyn Endpoint<Arc<dyn ReceiveCallback>>>> where
'a: 'b,
{
let guard = self.0.lock();
guard.endpoints.iter()
}
}
pub type ReceiveCallback = Box<dyn Fn(Message)>;
pub trait ReceiveCallback: Fn(Message) {}
pub trait Endpoint
pub trait Endpoint<C>
where C: AsRef<dyn ReceiveCallback>
{
fn send(&self, msg: Message) -> BridgeResult;
fn add_bridge(&mut self, br: Arc<Bridge>);
fn remove_bridge(&mut self, br: Arc<Bridge>);
fn add_receive_callback(&mut self, cb: Arc<ReceiveCallback>);
fn remove_receive_callback(&mut self, cb: Arc<ReceiveCallback>);
fn add_bridge(&mut self, br: Bridge);
fn remove_bridge(&mut self, br: Bridge);
fn add_receive_callback(&mut self, cb: C);
fn remove_receive_callback(&mut self, cb: C);
}

37
src/itercomb.rs

@ -0,0 +1,37 @@
// TODO: Fix lifetimes
pub struct DummyIter<'a, Iter, Item: 'a, Dummy> where
Iter: Iterator<Item = Item>
{
iter: Iter,
dummy: Dummy,
_phantom: core::marker::PhantomData<&'a ()>,
}
impl<'a, Iter, Item: 'a, Dummy> DummyIter<'a, Iter, Item, Dummy> where
Iter: Iterator<Item = Item>
{
pub fn new(iter: Iter, dummy: Dummy) -> DummyIter<'a, Iter, Item, Dummy>
{
DummyIter
{
iter: iter,
dummy: dummy,
_phantom: core::marker::PhantomData,
}
}
}
impl<'a, Iter, Item: 'a, Dummy> Iterator for DummyIter<'a, Iter, Item, Dummy> where
Iter: Iterator<Item = Item>
{
type Item = Item;
fn next(&mut self) -> Option<Item>
{
self.iter.next()
}
}

34
src/main.rs

@ -1,23 +1,39 @@
extern crate serde;
extern crate serde_json;
extern crate serenity;
mod endpoint;
//mod local_endpoint;
mod discord_endpoint;
mod refset;
mod itercomb;
use std::thread;
use std::fs;
use std::path;
use discord_endpoint::DiscordConfig;
fn main()
{
let token = std::env::var("TOKEN").expect("no token");
let inst = discord_endpoint::DiscordInstance::new(token).expect("error during instantiation");
println!("instantiated");
inst.start();
println!("started");
thread::sleep(std::time::Duration::from_millis(10000));
print!("stopping ... ");
inst.stop_sync();
println!("done");
let cfg_string = match fs::read_to_string(path::Path::new("config.json"))
{
Ok(s) => s,
Err(e) =>
{
println!("I/O error: {}", e.to_string());
return;
}
};
let config: DiscordConfig = match serde_json::from_str(&cfg_string)
{
Ok(config) => config,
Err(e) =>
{
println!("deserialization of JSON error: {}", e.to_string());
return;
},
};
println!("config: {:?}", config);
}

7
src/refset.rs

@ -1,6 +1,7 @@
// Implements a type for keeping track of sets of Arcs without having to hash the inside every time an
// indexing operation happens. Not all functions are implemented, just the ones I need.
use std::sync::Arc;
use std::collections::hash_map::HashMap;
@ -23,11 +24,13 @@ T: ?Sized
RefSet { map: HashMap::new(), _pd: std::marker::PhantomData }
}
#[allow(dead_code)]
pub fn with_capacity(capacity: usize) -> RefSet<T, U>
{
RefSet { map: HashMap::with_capacity(capacity), _pd: std::marker::PhantomData }
}
#[allow(dead_code)]
pub fn capacity(&self) -> usize
{
self.map.capacity()
@ -38,16 +41,19 @@ T: ?Sized
self.map.values()
}
#[allow(dead_code)]
pub fn len(&self) -> usize
{
self.map.len()
}
#[allow(dead_code)]
pub fn is_empty(&self) -> bool
{
self.map.is_empty()
}
#[allow(dead_code)]
pub fn clear(&mut self)
{
self.map.clear()
@ -62,6 +68,7 @@ T: ?Sized
}
}
#[allow(dead_code)]
pub fn remove(&mut self, value: U) -> bool
{
match self.map.remove(&(value.as_ref() as *const T as *const () as usize))

Loading…
Cancel
Save