Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion src/ircd/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use futures::{SinkExt, StreamExt};
use irc::client::prelude::{Command, Message, Prefix};
use irc::proto::{ChannelMode, IrcCodec, Mode};
use log::{info, trace, warn};
use matrix_sdk::RoomMemberships;
use std::cmp::min;
use std::time::SystemTime;
use tokio::net::TcpStream;
use tokio::sync::mpsc;
use tokio_util::codec::Framed;

use crate::{matrirc::Matrirc, matrix::MatrixMessageType};
use crate::{matrirc::Matrirc, matrix::room_mappings::RoomTargetType, matrix::MatrixMessageType};

/// it's a bit of a pain to redo the work twice for notice/privmsg,
/// so these types wrap it around a bit
Expand Down Expand Up @@ -162,6 +163,44 @@ pub async fn ircd_sync_write(
Ok(())
}

pub async fn list_channels(target: &str, matrirc: &Matrirc) -> Result<()> {
let irc = matrirc.irc();
let matrix = matrirc.matrix();
let mapping = matrirc.mappings();

irc.send(raw_msg(format!(
":matrirc 321 {} Channel :Users Name",
target
)))
.await?;
for joined in matrix.joined_rooms() {
if joined.is_tombstoned() {
trace!(
"Skipping tombstoned {}",
joined
.name()
.unwrap_or_else(|| joined.room_id().to_string())
);
continue;
}
let roomtarget = mapping.try_room_target(&joined).await?;
let chantype = roomtarget.target_type().await;
let channame = roomtarget.target().await;
if chantype != RoomTargetType::Query {
let users = joined.members_no_sync(RoomMemberships::ACTIVE).await?.len();
let topic = joined.topic().unwrap_or_default();
irc.send(raw_msg(format!(
":matrirc 322 {} #{} {} :{}",
target, channame, users, topic
)))
.await?;
}
}
irc.send(raw_msg(format!(":matrirc 323 {} :End of /LIST", target)))
.await?;
Ok(())
}

pub async fn ircd_sync_read(
mut reader: SplitStream<Framed<TcpStream, IrcCodec>>,
matrirc: Matrirc,
Expand Down Expand Up @@ -268,6 +307,13 @@ pub async fn ircd_sync_read(
warn!("Could not reply to mode: {:?}", e)
}
}
Command::LIST(_, _) => {
if let Err(e) =
list_channels(message.response_target().unwrap_or("matrirc"), &matrirc).await
{
warn!("Could not list channels: {:?}", e)
}
}
_ => info!("Unhandled message {:?}", message),
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/matrix/room_mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ pub struct RoomTarget {
inner: Arc<RwLock<RoomTargetInner>>,
}

#[derive(Debug, PartialEq)]
enum RoomTargetType {
#[derive(Debug, PartialEq, Clone)]
pub enum RoomTargetType {
/// room maps to a query e.g. single other member (or alone!)
Query,
/// room maps to a chan, and irc side has it joined
Expand Down Expand Up @@ -213,6 +213,9 @@ impl RoomTarget {
pub async fn target(&self) -> String {
self.inner.read().await.target.clone()
}
pub async fn target_type(&self) -> RoomTargetType {
self.inner.read().await.target_type.clone()
}

async fn join_chan(&self, irc: &IrcClient) -> bool {
let mut lock = self.inner.write().await;
Expand Down Expand Up @@ -458,7 +461,7 @@ impl Mappings {
// long enough to check for deduplicate and it's a bit of a mess; it could be done
// with a more generic 'insert_free_target' that takes a couple of callbacks but
// it's just not worth it
async fn try_room_target(&self, room: &Room) -> Result<RoomTarget> {
pub async fn try_room_target(&self, room: &Room) -> Result<RoomTarget> {
// happy case first
if let Some(target) = self.inner.read().await.rooms.get(room.room_id()) {
return Ok(target.clone());
Expand Down