use crate::Url;
use crate::storage::Storage;
use heed::types::{SerdeRmp, Str};
use heed::{Database, RoTxn};
use serde::{Deserialize, Serialize};
use std::error::Error;
use chrono::{DateTime, Utc};
#[derive(Debug, Serialize, Deserialize)]
pub struct TextNoteDraft<'a> {
#[serde(borrow)]
pub content: &'a str,
pub datetime_created: DateTime<Utc>,
pub datetime_expires: Option<DateTime<Utc>>,
pub datetime_autopublish: Option<DateTime<Utc>>,
pub attachments: Vec<&'a str>,
}
type DraftsDatabase<'a> = Database<Str, SerdeRmp<TextNoteDraft<'a>>>;
impl<'a> TextNoteDraft<'a> {
pub fn render_text(&self) -> String {
let mut body = self.content.to_string();
body.push('\n');
for url in self.attachments.iter() {
body.push_str(url);
body.push('\n');
}
body
}
}
const DB_NAME: &str = "note_drafts";
impl Storage {
fn drafts_db(
&self,
) -> Result<DraftsDatabase<'_>, Box<dyn Error + Send + Sync>> {
let mut rtxn = self.get_read_txn()?;
let dbo: Option<DraftsDatabase> =
self.env.open_database(&mut rtxn, Some(DB_NAME))?;
if dbo.is_some() {
Ok(dbo.unwrap())
} else {
Err(Box::from("Error opening nostr keys db"))
}
}
pub fn create_drafts_db(
&self,
) -> Result<DraftsDatabase<'_>, Box<dyn Error + Send + Sync>> {
let mut wtxn = self.env.write_txn()?;
let db: DraftsDatabase =
self.env.create_database(&mut wtxn, Some(DB_NAME))?;
wtxn.commit()?;
Ok(db)
}
pub fn draft_store(
&self,
name: &String,
content: &str,
) -> Result<(), Box<dyn Error>> {
if let Ok(db) = self.drafts_db() {
let mut wtxn = self.env.write_txn()?;
let draft = TextNoteDraft {
content,
datetime_created: Utc::now(),
datetime_expires: None,
datetime_autopublish: None,
attachments: Vec::new(),
};
db.put(&mut wtxn, name.as_str(), &draft)?;
wtxn.commit()?;
}
Ok(())
}
pub fn draft_attach<'c>(
&'c self,
rtxn: &'c mut RoTxn,
name: &String,
url: Url,
) -> Result<bool, Box<dyn Error>> {
if let Ok(db) = self.drafts_db() {
return match db.get(rtxn, name)? {
Some(mut draft) => {
let mut wtxn = self.env.write_txn()?;
draft.attachments.push(url.as_str());
db.put(&mut wtxn, name.as_str(), &draft)?;
wtxn.commit()?;
Ok(true)
}
None => Err(Box::from("Cannot get draft")),
};
}
Ok(false)
}
pub fn draft_get_content<'c>(
&'c self,
name: &String,
rtxn: &'c mut RoTxn,
) -> Result<&'c str, Box<dyn Error + Send + Sync>> {
match self.drafts_db()?.get(rtxn, name)? {
Some(draft) => Ok(draft.content),
None => Err(Box::from("Cannot get draft")),
}
}
pub fn draft_get<'c>(
&'c self,
name: &String,
rtxn: &'c mut RoTxn,
) -> Result<TextNoteDraft<'c>, Box<dyn Error + Send + Sync>> {
match self.drafts_db()?.get(rtxn, name)? {
Some(draft) => Ok(draft),
None => Err(Box::from("Cannot get draft")),
}
}
}