peachpub mostly working
This commit is contained in:
parent
fc2ea78876
commit
bf05149d93
@ -29,67 +29,67 @@ pub fn build_template() -> PreEscaped<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
" to start the sbot. If the server starts successfully, you will see a green smiley face on the home page. If the face is orange and sleeping, that means the sbot is still inactive (ie. the process is not running). If the face is red and dead, that means the sbot failed to start - indicated an error. For now, the best way to gain insight into the problem is to check the systemd log. Open a terminal and enter: "
|
" to start the sbot. If the server starts successfully, you will see a green smiley face on the home page. If the face is orange and sleeping, that means the sbot is still inactive (ie. the process is not running). If the face is red and dead, that means the sbot failed to start - indicated an error. For now, the best way to gain insight into the problem is to check the systemd log. Open a terminal and enter: "
|
||||||
code { "systemctl status go-sbot.service" }
|
code { "systemctl status tilde-sbot.service" }
|
||||||
". The log output may give some clues about the source of the error."
|
". The log output may give some clues about the source of the error."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(PreEscaped("<!-- BUG REPORTS -->"))
|
// (PreEscaped("<!-- BUG REPORTS -->"))
|
||||||
details {
|
// details {
|
||||||
summary class="card-text link" { "Submit a bug report" }
|
// summary class="card-text link" { "Submit a bug report" }
|
||||||
p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
// p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
||||||
"Bug reports can be submitted by "
|
// "Bug reports can be submitted by "
|
||||||
strong {
|
// strong {
|
||||||
a href="https://git.coopcloud.tech/PeachCloud/peach-workspace/issues/new?template=BUG_TEMPLATE.md" class="link font-gray" {
|
// a href="https://git.coopcloud.tech/PeachCloud/peach-workspace/issues/new?template=BUG_TEMPLATE.md" class="link font-gray" {
|
||||||
"filing an issue"
|
// "filing an issue"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
" on the peach-workspace git repo. Before filing a report, first check to see if an issue already exists for the bug you've encountered. If not, you're invited to submit a new report; the template will guide you through several questions."
|
// " on the peach-workspace git repo. Before filing a report, first check to see if an issue already exists for the bug you've encountered. If not, you're invited to submit a new report; the template will guide you through several questions."
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
(PreEscaped("<!-- REQUEST SUPPORT -->"))
|
// (PreEscaped("<!-- REQUEST SUPPORT -->"))
|
||||||
details {
|
// details {
|
||||||
summary class="card-text link" { "Share feedback & request support" }
|
// summary class="card-text link" { "Share feedback & request support" }
|
||||||
p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
// p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
||||||
"You're invited to share your thoughts and experiences of PeachCloud in the #peachcloud channel on Scuttlebutt. The channel is also a good place to ask for help."
|
// "You're invited to share your thoughts and experiences of PeachCloud in the #peachcloud channel on Scuttlebutt. The channel is also a good place to ask for help."
|
||||||
}
|
// }
|
||||||
p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
// p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
||||||
"Alternatively, we have a "
|
// "Alternatively, we have a "
|
||||||
strong {
|
// strong {
|
||||||
a href="https://matrix.to/#/#peachcloud:matrix.org" class="link font-gray" {
|
// a href="https://matrix.to/#/#peachcloud:matrix.org" class="link font-gray" {
|
||||||
"Matrix channel"
|
// "Matrix channel"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
" for discussion about PeachCloud and you can also reach out to @glyph "
|
// " for discussion about PeachCloud and you can also reach out to @glyph "
|
||||||
strong {
|
// strong {
|
||||||
a href="mailto:glyph@mycelial.technology" class="link font-gray" {
|
// a href="mailto:glyph@mycelial.technology" class="link font-gray" {
|
||||||
"via email"
|
// "via email"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
"."
|
// "."
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
(PreEscaped("<!-- CONTRIBUTE -->"))
|
// (PreEscaped("<!-- CONTRIBUTE -->"))
|
||||||
details {
|
// details {
|
||||||
summary class="card-text link" { "Contribute to PeachCloud" }
|
// summary class="card-text link" { "Contribute to PeachCloud" }
|
||||||
p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
// p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
||||||
"PeachCloud is free, open-source software and relies on donations and grants to fund develop. Donations can be made on our "
|
// "PeachCloud is free, open-source software and relies on donations and grants to fund develop. Donations can be made on our "
|
||||||
strong {
|
// strong {
|
||||||
a href="https://opencollective.com/peachcloud" class="link font-gray" {
|
// a href="https://opencollective.com/peachcloud" class="link font-gray" {
|
||||||
"Open Collective"
|
// "Open Collective"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
" page."
|
// " page."
|
||||||
}
|
// }
|
||||||
p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
// p class="card-text" style="margin-top: 1rem; margin-bottom: 1rem;" {
|
||||||
"Programmers, designers, artists and writers are also welcome to contribute to the project. Please visit the "
|
// "Programmers, designers, artists and writers are also welcome to contribute to the project. Please visit the "
|
||||||
strong {
|
// strong {
|
||||||
a href="https://git.coopcloud.tech/PeachCloud/peach-workspace" class="link font-gray" {
|
// a href="https://git.coopcloud.tech/PeachCloud/peach-workspace" class="link font-gray" {
|
||||||
"main PeachCloud git repository"
|
// "main PeachCloud git repository"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
" to find out more details or contact the team via Scuttlebutt, Matrix or email."
|
// " to find out more details or contact the team via Scuttlebutt, Matrix or email."
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -17,10 +17,10 @@ pub fn build_template() -> PreEscaped<String> {
|
|||||||
div class="card-container" {
|
div class="card-container" {
|
||||||
(PreEscaped("<!-- BUTTONS -->"))
|
(PreEscaped("<!-- BUTTONS -->"))
|
||||||
div id="buttons" {
|
div id="buttons" {
|
||||||
a id="search" class="button button-primary center" href="/scuttlebutt/search" title="Search for a peer" { "Search" }
|
// a id="search" class="button button-primary center" href="/scuttlebutt/search" title="Search for a peer" { "Search" }
|
||||||
a id="friends" class="button button-primary center" href="/scuttlebutt/friends" title="List friends" { "Friends" }
|
// a id="friends" class="button button-primary center" href="/scuttlebutt/friends" title="List friends" { "Friends" }
|
||||||
a id="follows" class="button button-primary center" href="/scuttlebutt/follows" title="List follows" { "Follows" }
|
// a id="follows" class="button button-primary center" href="/scuttlebutt/follows" title="List follows" { "Follows" }
|
||||||
a id="blocks" class="button button-primary center" href="/scuttlebutt/blocks" title="List blocks" { "Blocks" }
|
// a id="blocks" class="button button-primary center" href="/scuttlebutt/blocks" title="List blocks" { "Blocks" }
|
||||||
a id="invites" class="button button-primary center" href="/scuttlebutt/invites" title="Create invites" { "Invites" }
|
a id="invites" class="button button-primary center" href="/scuttlebutt/invites" title="Create invites" { "Invites" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,9 @@ pub fn build_template() -> PreEscaped<String> {
|
|||||||
div class="card center" {
|
div class="card center" {
|
||||||
(PreEscaped("<!-- BUTTONS -->"))
|
(PreEscaped("<!-- BUTTONS -->"))
|
||||||
div id="settingsButtons" {
|
div id="settingsButtons" {
|
||||||
a id="configure" class="button button-primary center" href="/settings/admin/configure" title="Configure Admin" { "Configure Admin" }
|
// a id="configure" class="button button-primary center" href="/settings/admin/configure" title="Configure Admin" { "Configure Admin" }
|
||||||
a id="change" class="button button-primary center" href="/auth/change" title="Change Password" { "Change Password" }
|
a id="change" class="button button-primary center" href="/auth/change" title="Change Password" { "Change Password" }
|
||||||
a id="reset" class="button button-primary center" href="/auth/reset" title="Reset Password" { "Reset Password" }
|
// a id="reset" class="button button-primary center" href="/auth/reset" title="Reset Password" { "Reset Password" }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ use peach_lib::ssb_messages::SsbMessageKVT;
|
|||||||
use rouille::input::post::BufferedFile;
|
use rouille::input::post::BufferedFile;
|
||||||
use temporary::Directory;
|
use temporary::Directory;
|
||||||
use peach_lib::serde_json::json;
|
use peach_lib::serde_json::json;
|
||||||
use peach_lib::tilde_client::TildeClient;
|
use peach_lib::tilde_client::{TildeClient, TildeError};
|
||||||
use crate::{error::PeachWebError, utils::sbot};
|
use crate::{error::PeachWebError, utils::sbot};
|
||||||
|
|
||||||
// SBOT HELPER FUNCTIONS
|
// SBOT HELPER FUNCTIONS
|
||||||
@ -114,14 +114,15 @@ pub fn validate_public_key(public_key: &str) -> Result<(), String> {
|
|||||||
/// reverses the list and reads the sequence number of the most recently
|
/// reverses the list and reads the sequence number of the most recently
|
||||||
/// authored message. This gives us the size of the database in terms of
|
/// authored message. This gives us the size of the database in terms of
|
||||||
/// the total number of locally-authored messages.
|
/// the total number of locally-authored messages.
|
||||||
pub fn latest_sequence_number() -> Result<u64, PeachWebError> {
|
pub fn latest_sequence_number() -> Result<String, PeachWebError> {
|
||||||
// retrieve latest solar-sbot configuration parameters
|
// retrieve latest solar-sbot configuration parameters
|
||||||
let sbot_config = SbotConfig::read().ok();
|
let sbot_config = SbotConfig::read().ok();
|
||||||
|
|
||||||
task::block_on(async {
|
task::block_on(async {
|
||||||
let mut sbot_client = init_sbot_client().await?;
|
let mut sbot_client = init_sbot_client().await?;
|
||||||
|
|
||||||
Err(PeachWebError::NotYetImplemented)
|
let sequence_num = sbot_client.latest_sequence_number().await?;
|
||||||
|
Ok(sequence_num)
|
||||||
|
|
||||||
// retrieve the local id
|
// retrieve the local id
|
||||||
// let id = sbot_client.whoami().await?;
|
// let id = sbot_client.whoami().await?;
|
||||||
@ -278,67 +279,67 @@ pub fn update_profile_info(
|
|||||||
let sbot_config = SbotConfig::read().ok();
|
let sbot_config = SbotConfig::read().ok();
|
||||||
|
|
||||||
task::block_on(async {
|
task::block_on(async {
|
||||||
let mut sbot_client = init_sbot_client()
|
let mut sbot_client = init_sbot_client().await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
Err(PeachWebError::NotYetImplemented)
|
|
||||||
// // track whether the name, description or image have been updated
|
// // track whether the name, description or image have been updated
|
||||||
// let mut name_updated: bool = false;
|
let mut name_updated: bool = false;
|
||||||
// let mut description_updated: bool = false;
|
let mut description_updated: bool = false;
|
||||||
// let mut image_updated: bool = false;
|
let mut image_updated: bool = false;
|
||||||
//
|
|
||||||
// // check if a new_name value has been submitted in the form
|
// check if a new_name value has been submitted in the form
|
||||||
// if let Some(name) = new_name {
|
if let Some(name) = new_name {
|
||||||
// // only update the name if it has changed
|
// only update the name if it has changed
|
||||||
// if name != current_name {
|
if name != current_name {
|
||||||
// debug!("Publishing a new Scuttlebutt profile name");
|
debug!("Publishing a new Scuttlebutt profile name");
|
||||||
// if let Err(e) = sbot_client.publish_name(&name).await {
|
if let Err(e) = sbot_client.publish_name(&name).await {
|
||||||
// return Err(format!("Failed to update name: {}", e));
|
return Err(PeachWebError::Tilde(TildeError {message: (format!("Failed to update name: {}", e))}));
|
||||||
// } else {
|
} else {
|
||||||
// name_updated = true
|
name_updated = true;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// if let Some(description) = new_description {
|
if let Some(description) = new_description {
|
||||||
// // only update the description if it has changed
|
// only update the description if it has changed
|
||||||
// if description != current_description {
|
if description != current_description {
|
||||||
// debug!("Publishing a new Scuttlebutt profile description");
|
debug!("Publishing a new Scuttlebutt profile description");
|
||||||
// if let Err(e) = sbot_client.publish_description(&description).await {
|
if let Err(e) = sbot_client.publish_description(&description).await {
|
||||||
// return Err(format!("Failed to update description: {}", e));
|
return Err(PeachWebError::Tilde(TildeError {message: (format!("Failed to update description: {}", e))}));
|
||||||
// } else {
|
} else {
|
||||||
// description_updated = true
|
description_updated = true
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // only update the image if a file was uploaded
|
// only update the image if a file was uploaded
|
||||||
// if let Some(img) = image {
|
if let Some(img) = image {
|
||||||
// // only write the blob if it has a filename and data > 0 bytes
|
// only write the blob if it has a filename and data > 0 bytes
|
||||||
// if img.filename.is_some() && !img.data.is_empty() {
|
if img.filename.is_some() && !img.data.is_empty() {
|
||||||
// match write_blob_to_store(img).await {
|
match write_blob_to_store(img).await {
|
||||||
// Ok(blob_id) => {
|
Ok(blob_id) => {
|
||||||
// // if the file was successfully added to the blobstore,
|
// if the file was successfully added to the blobstore,
|
||||||
// // publish an about image message with the blob id
|
// publish an about image message with the blob id
|
||||||
// if let Err(e) = sbot_client.publish_image(&blob_id).await {
|
if let Err(e) = sbot_client.publish_image(&blob_id).await {
|
||||||
// return Err(format!("Failed to update image: {}", e));
|
return Err(PeachWebError::Tilde(TildeError {message: (format!("Failed to update image: {}", e))}));
|
||||||
// } else {
|
} else {
|
||||||
// image_updated = true
|
image_updated = true
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// Err(e) => return Err(format!("Failed to add image to blobstore: {}", e)),
|
Err(e) => {
|
||||||
// }
|
return Err(PeachWebError::Tilde(TildeError {message: (format!("Failed to add image to blob store: {}", e))}));
|
||||||
// } else {
|
}
|
||||||
// image_updated = false
|
}
|
||||||
// }
|
} else {
|
||||||
// }
|
image_updated = false
|
||||||
//
|
}
|
||||||
// if name_updated || description_updated || image_updated {
|
}
|
||||||
// Ok("Profile updated".to_string())
|
|
||||||
// } else {
|
if name_updated || description_updated || image_updated {
|
||||||
// // no updates were made but no errors were encountered either
|
Ok("Profile updated".to_string())
|
||||||
// Ok("Profile info unchanged".to_string())
|
} else {
|
||||||
// }
|
// no updates were made but no errors were encountered either
|
||||||
|
Ok("Profile info unchanged".to_string())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,8 +460,8 @@ pub async fn get_peer_info(key: &str) -> Result<HashMap<String, String>, Box<dyn
|
|||||||
|
|
||||||
// insert the public key of the peer into the info hashmap
|
// insert the public key of the peer into the info hashmap
|
||||||
peer_info.insert("id".to_string(), key.to_string());
|
peer_info.insert("id".to_string(), key.to_string());
|
||||||
// retrieve the profile image blob id for the given peer
|
// TODO: display profile photo blob
|
||||||
// TODO: blob support
|
// // retrieve the profile image blob id for the given peer
|
||||||
// if let Some(blob_id) = peer_info.get("image") {
|
// if let Some(blob_id) = peer_info.get("image") {
|
||||||
// // look-up the path for the image blob
|
// // look-up the path for the image blob
|
||||||
// if let Ok(blob_path) = blobs::get_blob_path(blob_id) {
|
// if let Ok(blob_path) = blobs::get_blob_path(blob_id) {
|
||||||
@ -586,15 +587,10 @@ pub fn publish_private_msg(text: String, recipients: Vec<String>) -> Result<Stri
|
|||||||
let mut sbot_client = init_sbot_client()
|
let mut sbot_client = init_sbot_client()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Err(PeachWebError::NotYetImplemented)
|
for recipient in &recipients {
|
||||||
// debug!("Publishing a new Scuttlebutt private message");
|
sbot_client.private_message(recipient, &text).await?;
|
||||||
// match sbot_client
|
}
|
||||||
// .publish_private(text.to_string(), recipients)
|
Ok("Published private message".to_string())
|
||||||
// .await
|
|
||||||
// {
|
|
||||||
// Ok(_) => Ok("Published private message".to_string()),
|
|
||||||
// Err(e) => Err(format!("Failed to publish private message: {}", e)),
|
|
||||||
// }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,28 +639,13 @@ pub async fn write_blob_to_store(image: BufferedFile) -> Result<String, PeachWeb
|
|||||||
// write file to temporary path
|
// write file to temporary path
|
||||||
fs::write(&temp_path, &image.data)?;
|
fs::write(&temp_path, &image.data)?;
|
||||||
|
|
||||||
// open the file and read it into a buffer
|
// create blob from file
|
||||||
let mut file = File::open(&temp_path)?;
|
let mut sbot_client = init_sbot_client().await?;
|
||||||
let mut buffer = Vec::new();
|
|
||||||
file.read_to_end(&mut buffer)?;
|
|
||||||
|
|
||||||
Err(PeachWebError::NotYetImplemented)
|
let blob_path = temp_path.to_str().ok_or("Error storing blob to disk").map_err(|e| PeachWebError::Tilde(TildeError {
|
||||||
// TODO: not yet implemented
|
message: format!("Error storing blob to disk: {}", e),
|
||||||
|
}))?;
|
||||||
|
let blob_id = sbot_client.store_blob(blob_path).await?;
|
||||||
|
|
||||||
// // hash the bytes representing the file
|
Ok(blob_id)
|
||||||
// let (hex_hash, blob_id) = blobs::hash_blob(&buffer)?;
|
|
||||||
//
|
|
||||||
// // define the blobstore path and blob filename
|
|
||||||
// let (blob_dir, blob_filename) = hex_hash.split_at(2);
|
|
||||||
// let go_ssb_path = get_go_ssb_path()?;
|
|
||||||
// let blobstore_sub_dir = format!("{}/blobs/sha256/{}", go_ssb_path, blob_dir);
|
|
||||||
//
|
|
||||||
// // create the blobstore sub-directory
|
|
||||||
// fs::create_dir_all(&blobstore_sub_dir)?;
|
|
||||||
//
|
|
||||||
// // copy the file to the blobstore
|
|
||||||
// let blob_path = format!("{}/{}", blobstore_sub_dir, blob_filename);
|
|
||||||
// fs::copy(temp_path, blob_path)?;
|
|
||||||
//
|
|
||||||
// Ok(blob_id)
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use std::fmt;
|
|||||||
/// all tilde client errors
|
/// all tilde client errors
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TildeError {
|
pub struct TildeError {
|
||||||
pub(crate) message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for TildeError {
|
impl fmt::Display for TildeError {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
pub use crate::error::TildeError;
|
pub use crate::error::TildeError;
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::{json, Value};
|
||||||
use std::process::{Command, exit};
|
use std::process::{Command, exit};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
@ -56,6 +56,16 @@ impl TildeClient {
|
|||||||
self.tilde_command_to_value(vec!["get_profile", "-i", key]).await
|
self.tilde_command_to_value(vec!["get_profile", "-i", key]).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn latest_sequence_number(&self) -> Result<String, TildeError> {
|
||||||
|
let key = self.whoami().await?;
|
||||||
|
// let num = self.run_tilde_command(vec!["get_sequence", "-i", &key])?.parse::<u64>().map_err(|e| TildeError {
|
||||||
|
// message: format!("Failed to parse u64 from sequence number: {}", e),
|
||||||
|
// })?;
|
||||||
|
let num = self.run_tilde_command(vec!["get_sequence", "-i", &key])?;
|
||||||
|
println!("NUM: {}", num);
|
||||||
|
Ok(num)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn is_following(&self, from_id: &str, to_id: &str) -> Result<bool, TildeError> {
|
pub async fn is_following(&self, from_id: &str, to_id: &str) -> Result<bool, TildeError> {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
@ -81,6 +91,45 @@ impl TildeClient {
|
|||||||
self.run_tilde_command(vec!["publish", "-u", ":admin", "-i", &key, "-c", &json_string])
|
self.run_tilde_command(vec!["publish", "-u", ":admin", "-i", &key, "-c", &json_string])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn publish_name(&self, name: &str) -> Result<String, TildeError> {
|
||||||
|
let key = self.whoami().await?;
|
||||||
|
let about_post = json!({
|
||||||
|
"type": "about",
|
||||||
|
"about": key,
|
||||||
|
"name": name
|
||||||
|
});
|
||||||
|
self.publish(about_post).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn publish_description(&self, description: &str) -> Result<String, TildeError> {
|
||||||
|
let key = self.whoami().await?;
|
||||||
|
let about_post = json!({
|
||||||
|
"type": "about",
|
||||||
|
"about": key,
|
||||||
|
"description": description
|
||||||
|
});
|
||||||
|
self.publish(about_post).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn publish_image(&self, image_blob_id: &str) -> Result<String, TildeError> {
|
||||||
|
let key = self.whoami().await?;
|
||||||
|
let about_post = json!({
|
||||||
|
"type": "about",
|
||||||
|
"about": key,
|
||||||
|
"image": image_blob_id
|
||||||
|
});
|
||||||
|
self.publish(about_post).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn store_blob(&self, blob_file_path: &str) -> Result<String, TildeError> {
|
||||||
|
self.run_tilde_command(vec!["store_blob", "-f", blob_file_path])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn private_message(&self, recipient_key: &str, message: &str) -> Result<String, TildeError> {
|
||||||
|
let self_key = self.whoami().await?;
|
||||||
|
self.run_tilde_command(vec!["private", "-u", ":admin", "-i", &self_key, "-r", recipient_key, "-t", message])
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create_invite(&self, num_uses: i32) -> Result<String, TildeError> {
|
pub async fn create_invite(&self, num_uses: i32) -> Result<String, TildeError> {
|
||||||
// TODO: look up ip/domain from config
|
// TODO: look up ip/domain from config
|
||||||
let key = self.whoami().await?;
|
let key = self.whoami().await?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user