commit 7e83bbb93ab45956318523ed83509fcab05e7489
parent 49a644d83b1eb5fcdff002614fe781367c45c50f
Author: Marcel <mtrnord1@gmail.com>
Date: Sat, 27 Jun 2020 16:19:37 +0200
Fix some issues
Took 1 hour 4 minutes
Diffstat:
8 files changed, 167 insertions(+), 28 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1 +1,2 @@
/target
+config.yml
diff --git a/Cargo.lock b/Cargo.lock
@@ -909,6 +909,12 @@ dependencies = [
]
[[package]]
+name = "linked-hash-map"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
+
+[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -963,6 +969,8 @@ dependencies = [
"reqwest",
"ruma-api",
"serde",
+ "serde_json",
+ "serde_yaml",
"tokio",
"tracing",
"tracing-subscriber",
@@ -1803,6 +1811,18 @@ dependencies = [
]
[[package]]
+name = "serde_yaml"
+version = "0.8.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5"
+dependencies = [
+ "dtoa",
+ "linked-hash-map",
+ "serde",
+ "yaml-rust",
+]
+
+[[package]]
name = "sha-1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2480,6 +2500,15 @@ dependencies = [
]
[[package]]
+name = "yaml-rust"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
name = "zeroize"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
@@ -19,5 +19,7 @@ async-trait = "0.1.31"
tracing = "0.1"
ruma-api = "0.16.1"
serde = "1.0.114"
+serde_json = "1.0.48"
+serde_yaml = "0.8"
reqwest = { version = "0.10", features = ["json"] }
bytes = "0.5"
diff --git a/Readme.md b/Readme.md
@@ -0,0 +1,2 @@
+## Best practice
+Make your upload ipfs gateway public and use it for links for best performance
diff --git a/config_example.yml b/config_example.yml
@@ -0,0 +1,2 @@
+ipfs_gateway: "https://cloudflare-ipfs.com"
+ipfs_api: "http://localhost:5001"
diff --git a/src/config.rs b/src/config.rs
@@ -0,0 +1,16 @@
+use serde::{Deserialize, Serialize};
+use std::fs::OpenOptions;
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+pub struct Config {
+ pub ipfs_gateway: String,
+ pub ipfs_api: String,
+}
+
+impl Config {
+ pub fn load() -> Self {
+ let f = OpenOptions::new().read(true).open("./config.yml").unwrap();
+ let json: Self = serde_yaml::from_reader(f).expect("config should be proper YAML");
+ json
+ }
+}
diff --git a/src/main.rs b/src/main.rs
@@ -1,43 +1,48 @@
-use std::fs::File;
+use std::convert::TryFrom;
+use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::PathBuf;
use std::{env, fs, process::exit};
use bytes::buf::Buf;
-use ipfs_api::response::AddResponse;
use ipfs_api::{IpfsClient, TryFromUri};
use matrix_sdk::{
self,
events::collections::all::RoomEvent,
- events::room::message::{
- MessageEvent, MessageEventContent, NoticeMessageEventContent, RelatesTo,
+ events::room::{
+ member::MemberEventContent,
+ message::{MessageEvent, MessageEventContent, NoticeMessageEventContent, RelatesTo},
},
- identifiers::RoomId,
- Client, ClientConfig, EventEmitter, SyncRoom, SyncSettings,
+ events::stripped::StrippedRoomMember,
+ identifiers::{RoomId, UserId},
+ Client, ClientConfig, EventEmitter, Session as SDKSession, SyncRoom, SyncSettings,
};
-use tracing::{debug, info, warn, Level};
+use tracing::{info, warn, Level};
use tracing_subscriber::FmtSubscriber;
use url::Url;
-use crate::utils::get_media_download_url;
-
-mod utils;
+use crate::config::Config;
+use crate::utils::{get_media_download_url, Session};
+mod config;
mod get_room_event;
+mod utils;
struct CommandBot {
/// This clone of the `Client` will send requests to the server,
/// while the other keeps us in sync with the server using `sync_forever`.
client: Client,
ipfs_client: IpfsClient,
+ config: Config,
}
impl CommandBot {
- pub fn new(client: Client) -> Self {
+ pub fn new(client: Client, config: Config) -> Self {
+ let ipfs_client = IpfsClient::from_str(&config.ipfs_api).unwrap();
Self {
client,
- ipfs_client: IpfsClient::from_str("http://172.27.0.1:5001").unwrap(),
- //ipfs_client: Default::default(),
+ ipfs_client,
+ config,
}
}
@@ -67,7 +72,10 @@ impl CommandBot {
related_event_original: Option<RelatesTo>,
) {
let content = MessageEventContent::Notice(NoticeMessageEventContent {
- body: format!("https://ipfs.io/ipfs/{}?filename={}", hash, filename),
+ body: format!(
+ "{}/ipfs/{}?filename={}",
+ self.config.ipfs_gateway, hash, filename
+ ),
format: None,
formatted_body: None,
relates_to: related_event_original,
@@ -95,7 +103,7 @@ impl CommandBot {
self.remove_file(raw_filename);
let hash = ipfs_resp.first().unwrap().hash.clone();
- self.ipfs_client.pin_add(&hash, true).await;
+ self.ipfs_client.pin_add(&hash, true).await.unwrap();
hash
}
@@ -103,6 +111,20 @@ impl CommandBot {
#[matrix_sdk_common_macros::async_trait]
impl EventEmitter for CommandBot {
+ async fn on_stripped_state_member(
+ &self,
+ room: SyncRoom,
+ _: &StrippedRoomMember,
+ _: Option<MemberEventContent>,
+ ) {
+ println!("room: {:?}", room);
+ if let SyncRoom::Invited(room) = room {
+ let room_id = room.read().await.room_id.clone();
+ println!("room_id: {:?}", &room_id);
+ let resp = self.client.join_room_by_id(&room_id).await.unwrap();
+ println!("JoinResp: {:?}", resp);
+ }
+ }
async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) {
if let SyncRoom::Joined(room) = room {
if let MessageEventContent::Text(text_event) = event.clone().content {
@@ -152,16 +174,28 @@ impl EventEmitter for CommandBot {
match resp {
Ok(mut resp) => {
+ println!("{:?}", resp.event.deserialize());
let (event, _updated) = self
.client
.base_client
.receive_joined_timeline_event(&room_id, &mut resp.event)
.await
.unwrap();
- if let Ok(RoomEvent::RoomMessage(msg_event)) =
- event.unwrap().deserialize()
- {
- related_events.push(msg_event);
+ match event {
+ Some(event) => {
+ if let Ok(RoomEvent::RoomMessage(msg_event)) =
+ event.deserialize()
+ {
+ related_events.push(msg_event);
+ }
+ }
+ None => {
+ if let Ok(RoomEvent::RoomMessage(msg_event)) =
+ resp.event.deserialize()
+ {
+ related_events.push(msg_event);
+ }
+ }
}
}
Err(e) => {
@@ -307,6 +341,20 @@ impl EventEmitter for CommandBot {
}
}
} else {
+ let content = MessageEventContent::Notice(NoticeMessageEventContent {
+ body: "Unable to find related event!".to_string(),
+ format: None,
+ formatted_body: None,
+ relates_to: related_event_original.clone(),
+ });
+
+ self.client
+ // send our message to the room we found the "!party" command in
+ // the last parameter is an optional Uuid which we don't care about.
+ .room_send(&room_id, content, None)
+ .await
+ .unwrap();
+
warn!("Unable to find related_event");
}
}
@@ -333,21 +381,49 @@ async fn login_and_sync(
// create a new Client with the given homeserver url and config
let mut client = Client::new_with_config(homeserver_url, client_config).unwrap();
- client
- .login(
- username.clone(),
- password,
- None,
- Some("ipfs bot".to_string()),
- )
- .await?;
+ let mut session = home.clone();
+ session.push("session.json");
+ if session.exists() {
+ let f = OpenOptions::new().read(true).open(&session).unwrap();
+ let json: Session = serde_json::from_reader(f).expect("file should be proper JSON");
+ let session = SDKSession {
+ access_token: json.access_token,
+ user_id: UserId::try_from(json.user_id).unwrap(),
+ device_id: json.device_id,
+ };
+ client.restore_login(session).await.unwrap();
+ } else {
+ let f = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(true)
+ .open(&session)
+ .unwrap();
+
+ let login_response = client
+ .login(
+ username.clone(),
+ password,
+ None,
+ Some("ipfs bot".to_string()),
+ )
+ .await?;
+
+ let session = Session {
+ access_token: login_response.access_token,
+ user_id: login_response.user_id.to_string(),
+ device_id: login_response.device_id,
+ };
+
+ serde_json::to_writer(&f, &session).unwrap();
+ }
println!("logged in as {}", username);
// add our CommandBot to be notified of incoming messages, we do this after the initial
// sync to avoid responding to messages before the bot was running.
client
- .add_event_emitter(Box::new(CommandBot::new(client.clone())))
+ .add_event_emitter(Box::new(CommandBot::new(client.clone(), Config::load())))
.await;
// since we called sync before we `sync_forever` we must pass that sync token to
diff --git a/src/utils.rs b/src/utils.rs
@@ -1,3 +1,4 @@
+use serde::{Deserialize, Serialize};
use url::Url;
pub fn get_media_download_url(homeserver: &Url, mxc_url: String) -> String {
@@ -10,3 +11,13 @@ pub fn get_media_download_url(homeserver: &Url, mxc_url: String) -> String {
new_url.set_path(new_path.as_str());
new_url.to_string()
}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct Session {
+ /// The access token used for this session.
+ pub access_token: String,
+ /// The user the access token was issued for.
+ pub user_id: String,
+ /// The ID of the client device
+ pub device_id: String,
+}