mirror of
https://github.com/scsibug/nostr-rs-relay.git
synced 2024-11-22 00:59:07 -05:00
wip: regex condition parsing
This commit is contained in:
parent
b3fe03279b
commit
e7f67c8e36
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -1042,11 +1042,11 @@ dependencies = [
|
||||||
"r2d2",
|
"r2d2",
|
||||||
"r2d2_sqlite",
|
"r2d2_sqlite",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
|
"regex",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"secp256k1",
|
"secp256k1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
|
@ -1767,18 +1767,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_urlencoded"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
|
||||||
dependencies = [
|
|
||||||
"form_urlencoded",
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
|
|
@ -32,7 +32,7 @@ http = { version = "0.2" }
|
||||||
parse_duration = "2"
|
parse_duration = "2"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
const_format = "0.2.28"
|
const_format = "0.2.28"
|
||||||
serde_urlencoded = "0.7"
|
regex = "1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
//! Event parsing and validation
|
//! Event parsing and validation
|
||||||
//use crate::error::Error::*;
|
use crate::error::Error;
|
||||||
//use crate::error::Result;
|
use crate::error::Result;
|
||||||
//use crate::utils::unix_time;
|
//use crate::utils::unix_time;
|
||||||
//use bitcoin_hashes::{sha256, Hash};
|
//use bitcoin_hashes::{sha256, Hash};
|
||||||
//use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
use regex::Regex;
|
||||||
//use secp256k1::{schnorr, Secp256k1, VerifyOnly, XOnlyPublicKey};
|
//use secp256k1::{schnorr, Secp256k1, VerifyOnly, XOnlyPublicKey};
|
||||||
use serde::{Deserializer, Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
//use serde_json::value::Value;
|
//use serde_json::value::Value;
|
||||||
//use serde_json::Number;
|
//use serde_json::Number;
|
||||||
//use std::collections::HashMap;
|
//use std::collections::HashMap;
|
||||||
|
@ -58,35 +59,11 @@ pub enum Value {
|
||||||
Number(u64),
|
Number(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, PartialEq, Eq, Debug, Clone)]
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
|
||||||
pub struct ConditionQuery {
|
pub struct ConditionQuery {
|
||||||
pub(crate) conditions: Vec<Condition>,
|
pub(crate) conditions: Vec<Condition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'de> Deserialize<'de> for ConditionQuery {
|
|
||||||
fn deserialize<D>(d: D) -> Result<ConditionQuery, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
// recv'd is an array of pairs.
|
|
||||||
let _recvd: Value = d.deserialize_seq
|
|
||||||
let cond_list = recvd.as_object().ok_or_else(|| {
|
|
||||||
serde::de::Error::invalid_type(
|
|
||||||
Unexpected::Other("reqfilter is not an object"),
|
|
||||||
&"a json object",
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// all valid conditions will be put into this vec
|
|
||||||
let conditions : Vec<Condition> = vec![];
|
|
||||||
// loop through the parsed value, and identify if they are
|
|
||||||
// known attributes. unknown attributes will trigger failure,
|
|
||||||
// since we can't respect those restrictions.
|
|
||||||
Ok(ConditionQuery{conditions})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parsed delegation statement
|
/// Parsed delegation statement
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
|
||||||
pub struct Delegation {
|
pub struct Delegation {
|
||||||
|
@ -95,6 +72,7 @@ pub struct Delegation {
|
||||||
pub(crate) signature: String,
|
pub(crate) signature: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Parsed delegation condition
|
/// Parsed delegation condition
|
||||||
/// see https://github.com/nostr-protocol/nips/pull/28#pullrequestreview-1084903800
|
/// see https://github.com/nostr-protocol/nips/pull/28#pullrequestreview-1084903800
|
||||||
/// An example complex condition would be: kind=1,2,3&created_at<1665265999
|
/// An example complex condition would be: kind=1,2,3&created_at<1665265999
|
||||||
|
@ -105,6 +83,36 @@ pub struct Condition {
|
||||||
pub(crate) values: Vec<Value>,
|
pub(crate) values: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn str_to_condition(cs: &str) -> Option<Condition> {
|
||||||
|
// a condition is a string (alphanum+underscore), an operator (<>=!), and values (num+comma)
|
||||||
|
lazy_static! {
|
||||||
|
static ref RE: Regex = Regex::new("([[:word:]])([<>=!]+)([,[[:digit:]]]+))").unwrap();
|
||||||
|
}
|
||||||
|
// match against the regex
|
||||||
|
let caps = RE.captures(cs)?;
|
||||||
|
let _field =caps.get(0)?;
|
||||||
|
Some(Condition {field: Field::Kind, operator: Operator::LessThan, values: vec![]})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Parse a condition query from a string slice
|
||||||
|
impl TryFrom<&str> for ConditionQuery {
|
||||||
|
type Error = Error;
|
||||||
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
|
// split the string with '&'
|
||||||
|
let conds = value.split('&');
|
||||||
|
// parse each individual condition
|
||||||
|
for c in conds.into_iter() {
|
||||||
|
str_to_condition(c).ok_or(Error::DelegationParseError)?;
|
||||||
|
}
|
||||||
|
Ok(ConditionQuery{conditions: vec![]})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -114,6 +122,5 @@ mod tests {
|
||||||
fn parse_empty() {
|
fn parse_empty() {
|
||||||
// given an empty condition query, produce an empty vector
|
// given an empty condition query, produce an empty vector
|
||||||
assert_eq!(Delegation::from(""), vec![]);
|
assert_eq!(Delegation::from(""), vec![]);
|
||||||
assert_eq!(serde_urlencoded::from_str::<Vec<(String, String)>>(""), vec![]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,8 @@ pub enum Error {
|
||||||
HyperError(hyper::Error),
|
HyperError(hyper::Error),
|
||||||
#[error("Hex encoding error")]
|
#[error("Hex encoding error")]
|
||||||
HexError(hex::FromHexError),
|
HexError(hex::FromHexError),
|
||||||
|
#[error("Delegation parse error")]
|
||||||
|
DelegationParseError,
|
||||||
#[error("Unknown/Undocumented")]
|
#[error("Unknown/Undocumented")]
|
||||||
UnknownError,
|
UnknownError,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user