You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

client.rs 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. use std::collections::*;
  2. use std::path::PathBuf;
  3. use std::sync::Arc;
  4. use tokio::io::{AsyncRead, AsyncReadExt};
  5. use tokio::sync::mpsc;
  6. use futures::prelude::*;
  7. //use ruma_client::Client;
  8. //use ruma_client_api::r0::message as rumamessage;
  9. //use ruma_events::{self, room::message::*};
  10. use matrix_sdk::events::{
  11. room::message::{MessageEventContent, TextMessageEventContent},
  12. AnyMessageEventContent,
  13. };
  14. use matrix_sdk::identifiers::RoomId;
  15. use matrix_sdk::uuid::Uuid;
  16. use crate::config::*;
  17. #[derive(Debug)]
  18. pub enum Error {
  19. BadUrl,
  20. UnknownRoom(RoomId),
  21. Matrix(matrix_sdk::Error),
  22. }
  23. pub struct Message {
  24. dest_room: RoomId,
  25. text: String,
  26. delay_secs: u32,
  27. }
  28. pub type MatrixClient = matrix_sdk::Client;
  29. impl Message {
  30. pub fn new(dest_room: RoomId, msg: String) -> Self {
  31. Self::new_delay(dest_room, msg, 0)
  32. }
  33. pub fn new_delay(dest_room: RoomId, text: String, delay_secs: u32) -> Self {
  34. Self {
  35. dest_room,
  36. text,
  37. delay_secs,
  38. }
  39. }
  40. }
  41. pub async fn create_and_auth_client(acct: Account) -> Result<Arc<MatrixClient>, Error> {
  42. let hs_url = url::Url::parse(&acct.homeserver).map_err(|_| Error::BadUrl)?;
  43. // This is so annoying, why don't they use `&mut`?
  44. let cc = matrix_sdk::ClientConfig::new()
  45. .user_agent("mtxspooler")
  46. .unwrap();
  47. let cc = match acct.store_dir {
  48. Some(sdir) => cc.store_path(sdir),
  49. None => cc,
  50. };
  51. let c = matrix_sdk::Client::new_with_config(hs_url, cc).map_err(Error::Matrix)?;
  52. // Now log in.
  53. match acct.auth {
  54. Auth::UsernamePass(un, pw) => {
  55. let didref = acct.device_id.as_deref();
  56. c.login(&un, &pw, didref, didref)
  57. .map_err(Error::Matrix)
  58. .await?;
  59. }
  60. }
  61. // I think we need to spawn a task to sync.
  62. let c_sync = c.clone();
  63. tokio::spawn(async move {
  64. c_sync.sync(matrix_sdk::SyncSettings::new()).await;
  65. });
  66. // Let's list all the rooms we know about!
  67. tokio::time::sleep(::std::time::Duration::from_secs(1)).await;
  68. for r in c.rooms() {
  69. if let Some(name) = r.name() {
  70. eprintln!("[client] found room: {}", name);
  71. } else {
  72. eprintln!("[client] found room: {:?}", r.room_id());
  73. }
  74. }
  75. Ok(Arc::new(c))
  76. }
  77. pub async fn submit_messages(cli: Arc<MatrixClient>, mut recv: mpsc::Receiver<Message>) {
  78. while let Some(msg) = recv.recv().await {
  79. if let Err(e) = do_submit_msg(&msg, &cli).await {
  80. panic!("[client] error handling message submission: {:?}", e);
  81. }
  82. }
  83. }
  84. async fn do_submit_msg(msg: &Message, cli: &Arc<MatrixClient>) -> Result<(), Error> {
  85. let jroom = get_room_try_join(cli, &msg.dest_room).await?;
  86. let mec = MessageEventContent::text_plain(&msg.text);
  87. let ec = AnyMessageEventContent::RoomMessage(mec);
  88. jroom.send(ec, None).map_err(Error::Matrix).await?;
  89. Ok(())
  90. }
  91. pub async fn get_room_try_join(
  92. cli: &Arc<MatrixClient>,
  93. rid: &RoomId,
  94. ) -> Result<matrix_sdk::room::Joined, Error> {
  95. use matrix_sdk::room::*;
  96. match cli
  97. .get_room(rid)
  98. .ok_or_else(|| Error::UnknownRoom(rid.clone()))?
  99. {
  100. Room::Joined(j) => Ok(j),
  101. Room::Invited(i) => {
  102. i.accept_invitation().map_err(Error::Matrix).await?;
  103. Ok(cli.get_joined_room(rid).expect("client: get invited room"))
  104. }
  105. Room::Left(l) => {
  106. l.join().map_err(Error::Matrix).await?;
  107. Ok(cli.get_joined_room(rid).expect("client: get room joined"))
  108. }
  109. }
  110. }
  111. fn gen_device_id(un: &str, pw: &str) -> String {
  112. use sha2::Digest;
  113. let mut hasher = sha2::Sha256::new();
  114. hasher.update(un.as_bytes());
  115. hasher.update("\0");
  116. hasher.update(pw.as_bytes());
  117. hasher.update("\0_mtxspooler_salt");
  118. let h: [u8; 32] = hasher.finalize().into();
  119. hex::encode(h)
  120. }