mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
WIP: Actions API
This commit is contained in:
parent
f9d4419513
commit
92bad0038d
9 changed files with 603 additions and 1 deletions
|
@ -154,6 +154,14 @@ impl Jid {
|
|||
Jid::Bare(BareJid { domain, .. }) | Jid::Full(FullJid { domain, .. }) => domain,
|
||||
}
|
||||
}
|
||||
|
||||
/// The resource part of the Jabber ID.
|
||||
pub fn resource(self) -> Option<String> {
|
||||
match self {
|
||||
Jid::Bare(_) => None,
|
||||
Jid::Full(full_jid) => Some(full_jid.resource),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Jid> for BareJid {
|
||||
|
|
|
@ -17,14 +17,22 @@ edition = "2018"
|
|||
tokio-xmpp = "3.2"
|
||||
xmpp-parsers = "0.19"
|
||||
futures = "0.3"
|
||||
tokio = { version = "1", features = ["fs"] }
|
||||
tokio = { version = "1", features = ["fs", "sync" ] }
|
||||
log = "0.4"
|
||||
reqwest = { version = "0.11.8", features = ["stream"] }
|
||||
tokio-util = { version = "0.7", features = ["codec"] }
|
||||
# For actions API
|
||||
async-trait = { version = "0.1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.10"
|
||||
xmpp = { path = ".", features = [ "actions" ] }
|
||||
|
||||
[features]
|
||||
default = ["avatars"]
|
||||
avatars = []
|
||||
actions = [ "dep:async-trait" ]
|
||||
|
||||
[[example]]
|
||||
name = "actions_bot"
|
||||
required-features = [ "actions" ]
|
152
xmpp/examples/actions_bot.rs
Normal file
152
xmpp/examples/actions_bot.rs
Normal file
|
@ -0,0 +1,152 @@
|
|||
// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use env_logger;
|
||||
use std::str::FromStr;
|
||||
use xmpp::{Action, ClientBuilder, ClientFeature, ClientType, Event};
|
||||
use xmpp_parsers::{BareJid, JidParseError};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Error {
|
||||
Syntax(String),
|
||||
Jid(String, JidParseError),
|
||||
XMPP(tokio_xmpp::Error),
|
||||
}
|
||||
|
||||
impl From<tokio_xmpp::Error> for Error {
|
||||
fn from(e: tokio_xmpp::Error) -> Error {
|
||||
Error::XMPP(e)
|
||||
}
|
||||
}
|
||||
|
||||
struct Args {
|
||||
jid: BareJid,
|
||||
password: String,
|
||||
room: BareJid,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
fn from_cli() -> Result<Option<Args>, Error> {
|
||||
let mut args = std::env::args();
|
||||
let binary_name = args.next().unwrap();
|
||||
|
||||
let jid = args
|
||||
.next()
|
||||
.ok_or(Error::Syntax("Missing argument: jid".into()))?;
|
||||
match jid.to_lowercase().as_str() {
|
||||
"help" | "-h" | "--help" => {
|
||||
help(&binary_name);
|
||||
return Ok(None);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let jid = BareJid::from_str(&jid).map_err(|e| Error::Jid(jid, e))?;
|
||||
|
||||
let password = args
|
||||
.next()
|
||||
.ok_or(Error::Syntax("Missing argument: password".into()))?;
|
||||
|
||||
let room = args
|
||||
.next()
|
||||
.ok_or(Error::Syntax("Missing argument: room".into()))?;
|
||||
let room = BareJid::from_str(&room).map_err(|e| Error::Jid(room, e))?;
|
||||
|
||||
Ok(Some(Args {
|
||||
jid,
|
||||
password,
|
||||
room,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn help(name: &str) {
|
||||
println!("A bot that welcomes you when you say hello");
|
||||
println!("Usage: {} <jid> <password> <room>", name);
|
||||
println!("NOTE: Run with RUST_LOG=debug for debug logs");
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Error> {
|
||||
env_logger::init();
|
||||
|
||||
let args = if let Some(args) = Args::from_cli()? {
|
||||
args
|
||||
} else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let nick = String::from("actions_bot");
|
||||
|
||||
// Client instance
|
||||
let mut client = ClientBuilder::new(args.jid.clone(), &args.password)
|
||||
.set_client(ClientType::Bot, "xmpp-rs")
|
||||
.set_website("https://gitlab.com/xmpp-rs/xmpp-rs")
|
||||
.set_default_nick(&nick)
|
||||
.enable_feature(ClientFeature::JoinRooms)
|
||||
.build();
|
||||
|
||||
while let Some(events) = client.wait_for_events().await {
|
||||
for event in events {
|
||||
match event {
|
||||
Event::Online => {
|
||||
println!("Online.");
|
||||
client
|
||||
.action(Action::join_room(args.room.clone(), &nick))
|
||||
.await?;
|
||||
}
|
||||
Event::Disconnected => {
|
||||
println!("Disconnected");
|
||||
}
|
||||
Event::RoomMessage(_id, room_jid, author, body) => {
|
||||
println!(
|
||||
"Message in room {} from {}: {}",
|
||||
&room_jid, &author, &body.0
|
||||
);
|
||||
let msg = body.0.trim().to_lowercase();
|
||||
if msg == "hello" {
|
||||
client
|
||||
.action(Action::group_message(
|
||||
room_jid,
|
||||
format!("Hello, {}", &author),
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
Event::RoomPrivateMessage(_id, room_jid, nick, body) => {
|
||||
println!(
|
||||
"Private Message from room {} from {}: {}",
|
||||
&room_jid, &nick, body.0
|
||||
);
|
||||
client
|
||||
.action(Action::group_private_message(
|
||||
room_jid,
|
||||
nick,
|
||||
format!("You said: {}", body.0),
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
Event::ChatMessage(_id, jid, body) => {
|
||||
println!("Message from {}: {}", jid, body.0);
|
||||
client
|
||||
.action(Action::private_message(
|
||||
jid,
|
||||
format!("You said: {}", body.0),
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
Event::RoomJoined(jid) => {
|
||||
println!("Joined room {}.", jid);
|
||||
client
|
||||
.action(Action::group_message(jid, "Hello, world!"))
|
||||
.await?;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
65
xmpp/src/action/group_message.rs
Normal file
65
xmpp/src/action/group_message.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use crate::{Act, Action, Agent, Error};
|
||||
use std::str::FromStr;
|
||||
use xmpp_parsers::{message::Message, BareJid, Element, JidParseError};
|
||||
|
||||
pub struct GroupMessageAction {
|
||||
pub room: BareJid,
|
||||
pub msg: String,
|
||||
pub lang: String,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Act<()> for GroupMessageAction {
|
||||
async fn act(self, agent: &mut Agent) -> Result<(), Error> {
|
||||
agent.client.send_stanza(self.into()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GroupMessageAction> for Action {
|
||||
fn from(action: GroupMessageAction) -> Action {
|
||||
Action::GroupMessage(action)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GroupMessageAction> for Element {
|
||||
fn from(action: GroupMessageAction) -> Element {
|
||||
let GroupMessageAction { room, msg, lang } = action;
|
||||
|
||||
Message::groupchat(Some(room.into()))
|
||||
.with_body(lang, msg)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupMessageAction {
|
||||
/// Generates a new [`Action`] to send a group message to a parsed MUC chatroom [`BareJid`]. By default,
|
||||
/// the language used in the message is considered unknown.
|
||||
pub fn new<T: Into<BareJid>, U: AsRef<str>>(room: T, msg: U) -> GroupMessageAction {
|
||||
GroupMessageAction {
|
||||
room: room.into(),
|
||||
msg: msg.as_ref().to_string(),
|
||||
lang: "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a new [`Action`] to send a group message to a stringy MUC chatroom. By default,
|
||||
/// the language used in the message is considered unknown. Errors if the chatroom Jid cannot be
|
||||
/// parsed into a [`BareJid`].
|
||||
pub fn new_str<T: AsRef<str>, U: AsRef<str>>(
|
||||
room: T,
|
||||
msg: U,
|
||||
) -> Result<GroupMessageAction, JidParseError> {
|
||||
Ok(GroupMessageAction {
|
||||
room: BareJid::from_str(room.as_ref())?,
|
||||
msg: msg.as_ref().to_string(),
|
||||
lang: "".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Specify the language your message is written in, if you know it.
|
||||
pub fn lang(mut self, lang: &str) -> GroupMessageAction {
|
||||
self.lang = lang.to_string();
|
||||
self
|
||||
}
|
||||
}
|
80
xmpp/src/action/group_private_message.rs
Normal file
80
xmpp/src/action/group_private_message.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use crate::{Act, Action, Agent, Error, RoomNick};
|
||||
use std::str::FromStr;
|
||||
use xmpp_parsers::{message::Message, muc::MucUser, BareJid, Element, JidParseError};
|
||||
|
||||
pub struct GroupPrivateMessageAction {
|
||||
pub room: BareJid,
|
||||
pub recipient: RoomNick,
|
||||
pub msg: String,
|
||||
pub lang: String,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Act<()> for GroupPrivateMessageAction {
|
||||
async fn act(self, agent: &mut Agent) -> Result<(), Error> {
|
||||
agent.client.send_stanza(self.into()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GroupPrivateMessageAction> for Action {
|
||||
fn from(action: GroupPrivateMessageAction) -> Action {
|
||||
Action::GroupPrivateMessage(action)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GroupPrivateMessageAction> for Element {
|
||||
fn from(action: GroupPrivateMessageAction) -> Element {
|
||||
let GroupPrivateMessageAction {
|
||||
room,
|
||||
recipient,
|
||||
msg,
|
||||
lang,
|
||||
} = action;
|
||||
|
||||
let recipient = room.with_resource(recipient);
|
||||
|
||||
Message::chat(Some(recipient.into()))
|
||||
.with_body(lang, msg)
|
||||
.with_payload(MucUser::new())
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl GroupPrivateMessageAction {
|
||||
/// Generates a new [`Action`] to send a private a parsed MUC participant (room [`BareJid`] + participant [`RoomNick`]. By default, the language used in the message is considered unknown.
|
||||
pub fn new<T: Into<BareJid>, U: AsRef<str>>(
|
||||
room: T,
|
||||
recipient: RoomNick,
|
||||
msg: U,
|
||||
) -> GroupPrivateMessageAction {
|
||||
GroupPrivateMessageAction {
|
||||
room: room.into(),
|
||||
recipient,
|
||||
msg: msg.as_ref().to_string(),
|
||||
lang: "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a new [`Action`] to send a private message to a stringy MUC participant (stringy room + stringy participant).
|
||||
/// By default, the language used in the message is considered unknown. Errors if the chatroom Jid cannot be
|
||||
/// parsed into a [`BareJid`].
|
||||
pub fn new_str<T: AsRef<str>, U: AsRef<str>>(
|
||||
room: T,
|
||||
recipient: RoomNick,
|
||||
msg: U,
|
||||
) -> Result<GroupPrivateMessageAction, JidParseError> {
|
||||
Ok(GroupPrivateMessageAction {
|
||||
room: BareJid::from_str(room.as_ref())?,
|
||||
recipient,
|
||||
msg: msg.as_ref().to_string(),
|
||||
lang: "".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Specify the language your message is written in, if you know it.
|
||||
pub fn lang(mut self, lang: &str) -> GroupPrivateMessageAction {
|
||||
self.lang = lang.to_string();
|
||||
self
|
||||
}
|
||||
}
|
151
xmpp/src/action/join_room.rs
Normal file
151
xmpp/src/action/join_room.rs
Normal file
|
@ -0,0 +1,151 @@
|
|||
use crate::{Act, Action, Agent, Error};
|
||||
use std::str::FromStr;
|
||||
use xmpp_parsers::{
|
||||
date::DateTime,
|
||||
muc::muc::{History, Muc},
|
||||
presence::Presence,
|
||||
BareJid, Element, JidParseError,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct JoinRoomAction {
|
||||
pub room: BareJid,
|
||||
pub nick: String,
|
||||
pub password: Option<String>,
|
||||
pub lang: Option<String>,
|
||||
pub status: Option<String>,
|
||||
pub history: History,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Act<()> for JoinRoomAction {
|
||||
async fn act(self, agent: &mut Agent) -> Result<(), Error> {
|
||||
agent.client.send_stanza(self.clone().into()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JoinRoomAction> for Action {
|
||||
fn from(action: JoinRoomAction) -> Action {
|
||||
Action::JoinRoom(action)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<JoinRoomAction> for Element {
|
||||
fn from(action: JoinRoomAction) -> Element {
|
||||
let JoinRoomAction {
|
||||
room,
|
||||
nick,
|
||||
password,
|
||||
lang,
|
||||
status,
|
||||
history,
|
||||
} = action;
|
||||
|
||||
let mut muc = Muc::new().with_history(history);
|
||||
|
||||
if let Some(password) = password {
|
||||
muc = muc.with_password(password);
|
||||
}
|
||||
|
||||
let room_jid = room.with_resource(nick);
|
||||
|
||||
let mut presence = Presence::available()
|
||||
.with_to(room_jid.clone())
|
||||
.with_payload(muc);
|
||||
|
||||
if let Some(status) = status {
|
||||
// lang None is treated as unknown language (empty string)
|
||||
presence.set_status(lang.unwrap_or("".to_string()), status);
|
||||
}
|
||||
|
||||
presence.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl JoinRoomAction {
|
||||
/// Creates an [`Action`] to join a MUC chatroom from a parsed [`BareJid`]. By default,
|
||||
/// legacy history management is disabled. In the future, it should be replaced with MAM, but if
|
||||
/// you really need legacy history right now we still provide helpers for it.
|
||||
pub fn new<T: Into<BareJid>, U: AsRef<str>>(room: T, nick: U) -> JoinRoomAction {
|
||||
JoinRoomAction {
|
||||
room: room.into(),
|
||||
nick: nick.as_ref().to_string(),
|
||||
password: None,
|
||||
lang: None,
|
||||
status: None,
|
||||
history: History::new().with_maxchars(0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an [`Action`] to join a MUC chatroom from a stringy bare JID. By default,
|
||||
/// legacy history management is disabled. Errors if the room JID is not parseable into a [`BareJid`].
|
||||
/// In the future, it should be replaced with MAM, but if you really need legacy history right now we still
|
||||
/// provide helpers for it.
|
||||
pub fn new_str<T: AsRef<str>, U: AsRef<str>>(
|
||||
room: T,
|
||||
nick: U,
|
||||
) -> Result<JoinRoomAction, JidParseError> {
|
||||
Ok(JoinRoomAction {
|
||||
room: BareJid::from_str(room.as_ref())?,
|
||||
nick: nick.as_ref().to_string(),
|
||||
password: None,
|
||||
lang: None,
|
||||
status: None,
|
||||
history: History::new().with_maxchars(0),
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the nick associated with the client on the chatroom to be joined.
|
||||
pub fn nick(mut self, nick: &str) -> JoinRoomAction {
|
||||
self.nick = nick.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the password required to enter the MUC chatroom.
|
||||
pub fn password(mut self, password: &str) -> JoinRoomAction {
|
||||
self.password = Some(password.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets a status associated with the client, when joining the room. The status
|
||||
/// should define a language associated with it, but None will be treated as explicitly
|
||||
/// not knowing the language, i.e. `xml:lang=""` as explained [here](https://gitlab.com/xmpp-rs/xmpp-rs/-/issues/80).
|
||||
pub fn status(mut self, lang: Option<String>, status: &str) -> JoinRoomAction {
|
||||
if let Some(lang) = lang {
|
||||
self.lang = Some(lang);
|
||||
}
|
||||
self.status = Some(status.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Request specific [`History`] settings from legacy MUC history.
|
||||
pub fn history(mut self, history: History) -> JoinRoomAction {
|
||||
self.history = history;
|
||||
self
|
||||
}
|
||||
|
||||
/// Request a maximum of `maxchars` characters from legacy MUC history.
|
||||
pub fn history_maxchars(mut self, maxchars: u32) -> JoinRoomAction {
|
||||
self.history = History::new().with_maxchars(maxchars);
|
||||
self
|
||||
}
|
||||
|
||||
/// Request a maximum of `maxstanzas` stanzas from legacy MUC history.
|
||||
pub fn history_maxstanzas(mut self, maxstanzas: u32) -> JoinRoomAction {
|
||||
self.history = History::new().with_maxstanzas(maxstanzas);
|
||||
self
|
||||
}
|
||||
|
||||
/// Request all messages since `sec` seconds from legacy MUC history.
|
||||
pub fn history_since_sec(mut self, sec: u32) -> JoinRoomAction {
|
||||
self.history = History::new().with_seconds(sec);
|
||||
self
|
||||
}
|
||||
|
||||
/// Request all messages since `since` [`DateTime`] from legacy MUC history.
|
||||
pub fn history_since(mut self, since: DateTime) -> JoinRoomAction {
|
||||
self.history = History::new().with_since(since);
|
||||
self
|
||||
}
|
||||
}
|
62
xmpp/src/action/mod.rs
Normal file
62
xmpp/src/action/mod.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
//! The [`Action`] API allows to create type-safe actions for an [`Agent`].
|
||||
//!
|
||||
//! You can build an Action manually by generating one of the enum variants, or use one of the associated builders:
|
||||
//!
|
||||
//! - [`Action::join_room`]
|
||||
//! - [`Action::private_message`]
|
||||
//! - [`Action::group_message`]
|
||||
//! - [`Action::group_private_message`]
|
||||
|
||||
use crate::{Agent, Error, RoomNick};
|
||||
use xmpp_parsers::{BareJid, Jid};
|
||||
|
||||
pub mod join_room;
|
||||
pub use join_room::JoinRoomAction;
|
||||
pub mod group_message;
|
||||
pub use group_message::GroupMessageAction;
|
||||
pub mod group_private_message;
|
||||
pub use group_private_message::GroupPrivateMessageAction;
|
||||
pub mod private_message;
|
||||
pub use private_message::PrivateMessageAction;
|
||||
|
||||
pub enum Action {
|
||||
///
|
||||
JoinRoom(JoinRoomAction),
|
||||
GroupMessage(GroupMessageAction),
|
||||
GroupPrivateMessage(GroupPrivateMessageAction),
|
||||
PrivateMessage(PrivateMessageAction),
|
||||
}
|
||||
|
||||
impl Action {
|
||||
/// Starts building a [`JoinRoomAction`]
|
||||
pub fn join_room<T: Into<BareJid>, U: AsRef<str>>(room: T, nick: U) -> JoinRoomAction {
|
||||
JoinRoomAction::new(room, nick)
|
||||
}
|
||||
|
||||
/// Starts building a [`GroupMessageAction`]
|
||||
pub fn group_message<T: Into<BareJid>, U: AsRef<str>>(room: T, msg: U) -> GroupMessageAction {
|
||||
GroupMessageAction::new(room, msg)
|
||||
}
|
||||
|
||||
/// Starts building a [`GroupPrivateMessageAction`]
|
||||
pub fn group_private_message<T: Into<BareJid>, U: AsRef<str>>(
|
||||
room: T,
|
||||
nick: RoomNick,
|
||||
msg: U,
|
||||
) -> GroupPrivateMessageAction {
|
||||
GroupPrivateMessageAction::new(room, nick, msg)
|
||||
}
|
||||
|
||||
/// Starts building a [`PrivateMessageAction`]
|
||||
pub fn private_message<T: Into<Jid>, U: AsRef<str>>(room: T, msg: U) -> PrivateMessageAction {
|
||||
PrivateMessageAction::new(room, msg)
|
||||
}
|
||||
}
|
||||
|
||||
/// The trait to implement for typed actions to be consumed by an [`Agent`].
|
||||
/// It contains a single method for the action logic.
|
||||
#[async_trait]
|
||||
pub trait Act<T> {
|
||||
/// The method called by the [`Agent`] to perform the action.
|
||||
async fn act(self, client: &mut Agent) -> Result<T, Error>;
|
||||
}
|
63
xmpp/src/action/private_message.rs
Normal file
63
xmpp/src/action/private_message.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use crate::{Act, Action, Agent, Error};
|
||||
use std::str::FromStr;
|
||||
use xmpp_parsers::{message::Message, Element, Jid, JidParseError};
|
||||
|
||||
pub struct PrivateMessageAction {
|
||||
pub jid: Jid,
|
||||
pub msg: String,
|
||||
pub lang: String,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Act<()> for PrivateMessageAction {
|
||||
async fn act(self, agent: &mut Agent) -> Result<(), Error> {
|
||||
agent.client.send_stanza(self.into()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PrivateMessageAction> for Action {
|
||||
fn from(action: PrivateMessageAction) -> Action {
|
||||
Action::PrivateMessage(action)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PrivateMessageAction> for Element {
|
||||
fn from(action: PrivateMessageAction) -> Element {
|
||||
let PrivateMessageAction { jid, msg, lang } = action;
|
||||
|
||||
Message::chat(Some(jid.into())).with_body(lang, msg).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl PrivateMessageAction {
|
||||
/// Generates a new [`Action`] to send a private message to a parsed [`Jid`]. By default,
|
||||
/// the language used in the message is considered unknown.
|
||||
pub fn new<T: Into<Jid>, U: AsRef<str>>(jid: T, msg: U) -> PrivateMessageAction {
|
||||
PrivateMessageAction {
|
||||
jid: jid.into(),
|
||||
msg: msg.as_ref().to_string(),
|
||||
lang: "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a new [`Action`] to send a private message to a stringy JID. By default,
|
||||
/// the language used in the message is considered unknown. Errors if the recipient Jid cannot be
|
||||
/// parsed into a [`Jid`].
|
||||
pub fn new_str<T: AsRef<str>, U: AsRef<str>>(
|
||||
jid: T,
|
||||
msg: U,
|
||||
) -> Result<PrivateMessageAction, JidParseError> {
|
||||
Ok(PrivateMessageAction {
|
||||
jid: Jid::from_str(jid.as_ref())?,
|
||||
msg: msg.as_ref().to_string(),
|
||||
lang: "".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Specify the language your message is written in, if you know it.
|
||||
pub fn lang(mut self, lang: &str) -> PrivateMessageAction {
|
||||
self.lang = lang.to_string();
|
||||
self
|
||||
}
|
||||
}
|
|
@ -40,6 +40,15 @@ extern crate log;
|
|||
|
||||
mod pubsub;
|
||||
|
||||
#[cfg(feature = "actions")]
|
||||
#[macro_use]
|
||||
extern crate async_trait;
|
||||
|
||||
#[cfg(feature = "actions")]
|
||||
pub mod action;
|
||||
#[cfg(feature = "actions")]
|
||||
pub use action::{Act, Action};
|
||||
|
||||
pub type Error = tokio_xmpp::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -219,6 +228,10 @@ impl Agent {
|
|||
self.client.send_end().await
|
||||
}
|
||||
|
||||
pub async fn action<Success, T: Act<Success>>(&mut self, action: T) -> Result<Success, Error> {
|
||||
action.act(self).await
|
||||
}
|
||||
|
||||
pub async fn join_room(
|
||||
&mut self,
|
||||
room: BareJid,
|
||||
|
|
Loading…
Reference in a new issue