use super::vars as SPVars;
use crate::err::LDError;
use crate::niri::ToNamedNode;
use derive_builder::Builder;
use language::Language;
use nostr::{EventId, PublicKey, Timestamp};
use oxigraph::model::*;
use std::time::Duration;
pub fn subl(
varname: &str,
literal: Literal,
) -> Result<(Variable, Term), LDError> {
Ok((
Variable::new(varname).map_err(|_| LDError::SubstitutionError)?,
literal.into(),
))
}
pub fn subnn(
varname: &str,
nn: NamedNode,
) -> Result<(Variable, Term), LDError> {
Ok((
Variable::new(varname).map_err(|_| LDError::SubstitutionError)?,
nn.into(),
))
}
#[derive(Builder, Debug, Default)]
#[builder(default)]
pub struct QuerySubs {
#[builder(setter(strip_option))]
event_id: Option<EventId>,
#[builder(setter(strip_option))]
replies_to_event_id: Option<EventId>,
#[builder(setter(strip_option))]
in_forum: Option<EventId>,
#[builder(setter(strip_option))]
since: Option<Duration>,
#[builder(setter(strip_option))]
author: Option<PublicKey>,
#[builder(setter(strip_option))]
identity_nip21: Option<PublicKey>,
#[builder(setter(strip_option))]
lang: Option<Language>,
#[builder(setter(strip_option))]
hashtag: Option<String>,
#[builder(setter(strip_option))]
only_followees: Option<i16>,
}
impl QuerySubs {
#[deprecated]
pub fn subs(&self) -> Result<Vec<(Variable, Term)>, LDError> {
let mut subs_v = Vec::new();
if let Some(id) = self.event_id {
subs_v.push(subl(SPVars::EVENT_ID, id.to_hex().into())?);
}
Ok(subs_v)
}
pub fn subs_with_ckey(
&self,
) -> Result<(Vec<(Variable, Term)>, String), LDError> {
let mut cache_key = String::new();
let mut subs_v = Vec::new();
if let Some(pk) = self.identity_nip21 {
subs_v.push(subnn("identity_nip21", pk.named_node().unwrap())?);
}
if let Some(id) = self.event_id {
subs_v.push(subl(SPVars::EVENT_ID, id.to_hex().into())?);
cache_key.push_str(&format!("ev_{}", id.to_hex()));
}
if let Some(ev_id) = self.replies_to_event_id {
subs_v.push(subl("e_tag_value", Literal::from(ev_id.to_hex()))?);
subs_v.push(subl("filter_e_tag", Literal::from(1))?);
cache_key.push_str(&format!("_etag_{}", ev_id.to_hex()));
} else {
subs_v.push(subl("filter_e_tag", Literal::from(0))?);
}
if let Some(since_dur) = self.since {
let created_since = Timestamp::now() - since_dur;
subs_v.push(subl(
"created_at_since",
Literal::from(created_since.as_u64()),
)?);
cache_key.push_str(&format!("since_{}", since_dur.as_secs()));
}
if let Some(ref hashtag) = self.hashtag {
subs_v.push(subl("query_hashtag", Literal::from(hashtag.clone()))?);
cache_key.push_str(&format!("_ht{}", hashtag));
}
if let Some(lang) = self.lang {
let lang_tag = lang.as_tag();
subs_v.push(subl(
"lang_tag_filter",
Literal::from(lang_tag.to_string()),
)?);
} else {
subs_v.push(subl("lang_tag_filter", Literal::from(""))?);
}
if let Some(event_id) = &self.in_forum {
subs_v.push(subl("f_tag_value", Literal::from(event_id.to_hex()))?);
subs_v.push(subl("filter_f_tag", Literal::from(1))?);
cache_key.push_str(&format!("_ftag_{}", event_id.to_hex()));
} else {
subs_v.push(subl("filter_f_tag", Literal::from(0))?);
}
if let Some(only_f) = self.only_followees {
subs_v.push(subl("only_followees", Literal::from(only_f))?);
}
Ok((subs_v, cache_key))
}
}
#[test]
fn test_subs() -> Result<(), LDError> {
let (_, _) = QuerySubsBuilder::default()
.event_id(EventId::parse("5d35413cad64e6c4e9cd9788b1d82b935744a36582239d753cd4dadca045580a").unwrap())
.lang(Language::EnGb)
.build().map_err(|_| LDError::EventBuildError)?
.subs_with_ckey()?;
Ok(())
}