commit
f1aae8e3c2
@ -1,4 +1,5 @@
|
||||
# jid and password exactly like this, nothing else
|
||||
# jid and password exactly like this
|
||||
|
||||
jid = "jid@example.org"
|
||||
password = "sOmePa55W0rD"
|
||||
# nick = "foobar" # optional nick for Multi-User Chat
|
||||
|
55
src/main.rs
55
src/main.rs
@ -3,6 +3,7 @@ use std::fs::File;
|
||||
use std::io::{stdin, Read, Write};
|
||||
use std::iter::Iterator;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use die::{die, Die};
|
||||
use gumdrop::Options;
|
||||
@ -10,9 +11,10 @@ use serde_derive::Deserialize;
|
||||
|
||||
use std::process::{Command, Stdio};
|
||||
use tokio_xmpp::{xmpp_stream, SimpleClient as Client};
|
||||
use xmpp_parsers::message::{Body, Message};
|
||||
use xmpp_parsers::message::{Body, Message, MessageType};
|
||||
use xmpp_parsers::muc::Muc;
|
||||
use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType};
|
||||
use xmpp_parsers::{Element, Jid};
|
||||
use xmpp_parsers::{BareJid, Element, FullJid, Jid};
|
||||
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio_tls::TlsStream;
|
||||
@ -23,6 +25,7 @@ use anyhow::{anyhow, bail, Result};
|
||||
struct Config {
|
||||
jid: String,
|
||||
password: String,
|
||||
nick: Option<String>,
|
||||
}
|
||||
|
||||
fn parse_cfg<P: AsRef<Path>>(path: P) -> Result<Config> {
|
||||
@ -54,6 +57,12 @@ struct MyOptions {
|
||||
|
||||
#[options(help = "Send a <presence/> after connecting before sending messages, required for receiving for --raw")]
|
||||
presence: bool,
|
||||
|
||||
#[options(help = "Recipients are Multi-User Chats")]
|
||||
muc: bool,
|
||||
|
||||
#[options(help = "Nickname to use in Multi-User Chats")]
|
||||
nick: Option<String>,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@ -81,10 +90,19 @@ async fn main() {
|
||||
if !recipients.is_empty() {
|
||||
die!("--raw is incompatible with recipients");
|
||||
}
|
||||
if opts.muc {
|
||||
die!("--raw is incompatible with --muc");
|
||||
}
|
||||
} else if recipients.is_empty() {
|
||||
die!("no recipients specified!");
|
||||
}
|
||||
|
||||
if opts.muc {
|
||||
if opts.force_pgp || opts.attempt_pgp {
|
||||
die!("--force-pgp and --attempt-pgp isn't implemented with --muc");
|
||||
}
|
||||
}
|
||||
|
||||
let recipients = &recipients;
|
||||
|
||||
let cfg = match opts.config {
|
||||
@ -153,28 +171,46 @@ async fn main() {
|
||||
}
|
||||
|
||||
for recipient in recipients {
|
||||
if opts.muc {
|
||||
let nick = opts
|
||||
.nick
|
||||
.clone()
|
||||
.or(cfg.nick.clone())
|
||||
.or_else(|| BareJid::from_str(cfg.jid.as_str()).unwrap().node)
|
||||
.die("couldn't find a nick to use");
|
||||
let participant = match recipient.clone() {
|
||||
Jid::Full(_) => die!("Invalid room address"),
|
||||
Jid::Bare(bare) => bare.with_resource(nick.clone()),
|
||||
};
|
||||
let join = make_join(participant.clone());
|
||||
client.send_stanza(join).await.die("failed to join MUC");
|
||||
|
||||
let reply = make_reply(recipient.clone(), &data, opts.muc);
|
||||
client.send_stanza(reply).await.die("sending message failed");
|
||||
} else {
|
||||
let reply = if opts.force_pgp || opts.attempt_pgp {
|
||||
let encrypted = gpg_encrypt(recipient.clone(), &data);
|
||||
if encrypted.is_err() {
|
||||
if opts.force_pgp {
|
||||
die!("pgp encryption to jid '{}' failed!", recipient);
|
||||
} else {
|
||||
make_reply(recipient.clone(), &data)
|
||||
make_reply(recipient.clone(), &data, opts.muc)
|
||||
}
|
||||
} else {
|
||||
let encrypted = encrypted.unwrap();
|
||||
let encrypted = encrypted.trim();
|
||||
let mut reply = make_reply(recipient.clone(), "pgp");
|
||||
let mut reply = make_reply(recipient.clone(), "pgp", opts.muc);
|
||||
let mut x = Element::bare("x", "jabber:x:encrypted");
|
||||
x.append_text_node(encrypted);
|
||||
reply.append_child(x);
|
||||
reply
|
||||
}
|
||||
} else {
|
||||
make_reply(recipient.clone(), &data)
|
||||
make_reply(recipient.clone(), &data, opts.muc)
|
||||
};
|
||||
client.send_stanza(reply).await.die("sending message failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Close client connection
|
||||
client.end().await.ok(); // ignore errors here, I guess
|
||||
@ -188,9 +224,16 @@ fn make_presence() -> Element {
|
||||
presence.into()
|
||||
}
|
||||
|
||||
fn make_join(to: FullJid) -> Element {
|
||||
Presence::new(PresenceType::None).with_to(Jid::Full(to)).with_payloads(vec![Muc::new().into()]).into()
|
||||
}
|
||||
|
||||
// Construct a chat <message/>
|
||||
fn make_reply(to: Jid, body: &str) -> Element {
|
||||
fn make_reply(to: Jid, body: &str, groupchat: bool) -> Element {
|
||||
let mut message = Message::new(Some(to));
|
||||
if groupchat {
|
||||
message.type_ = MessageType::Groupchat;
|
||||
}
|
||||
message.bodies.insert(String::new(), Body(body.to_owned()));
|
||||
message.into()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user