rust_v4v/
boostagram.rs

1use serde::{Deserialize, Deserializer, Serialize};
2use serde_json;
3
4use crate::Error;
5
6use base64::{engine::general_purpose, Engine as _};
7
8pub mod builder;
9
10pub fn from_b64(b64: &str) -> Result<Boostagram, Error> {
11    let json_raw = general_purpose::STANDARD.decode(b64)?;
12    serde_json::from_slice(&json_raw).map_err(Error::from)
13}
14
15pub fn from_json(json: &str) -> Result<Boostagram, Error> {
16    serde_json::from_str(json).map_err(Error::from)
17}
18
19#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
20pub enum Action {
21    #[serde(rename = "stream")]
22    Stream,
23    #[serde(rename = "boost")]
24    Boost,
25    #[serde(rename = "lsat")]
26    Lsat,
27    #[serde(rename = "auto")]
28    Auto,
29    #[serde(other)]
30    Unknown,
31}
32
33#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
34pub struct Boostagram {
35    pub podcast: Option<String>,
36
37    #[serde(rename = "feedID")]
38    pub feed_id: Option<usize>,
39
40    pub url: Option<String>,
41
42    pub guid: Option<String>,
43
44    pub episode: Option<String>,
45
46    #[serde(rename = "itemID")]
47    #[serde(deserialize_with = "deserialize_item_id")]
48    #[serde(default)]
49    pub item_id: Option<usize>,
50
51    pub episode_guid: Option<String>,
52
53    pub time: Option<String>,
54
55    pub ts: Option<usize>,
56
57    pub action: Option<Action>,
58
59    pub app_name: Option<String>,
60
61    pub app_version: Option<String>,
62
63    pub boost_link: Option<String>,
64
65    pub message: Option<String>,
66
67    pub name: Option<String>,
68
69    pub sender_name: Option<String>,
70
71    pub sender_id: Option<String>,
72
73    pub signature: Option<String>,
74
75    pub speed: Option<String>,
76
77    pub uuid: Option<String>,
78
79    //can't be larger for the lightning network
80    pub value_msat_total: Option<u64>,
81
82    pub reply_address: Option<String>,
83
84    //TODO why string?
85    pub reply_custom_key: Option<usize>,
86
87    pub reply_custom_value: Option<String>,
88}
89
90fn deserialize_item_id<'de, D>(d: D) -> Result<Option<usize>, D::Error>
91where
92    D: Deserializer<'de>,
93{
94    Deserialize::deserialize(d).or(Ok(Option::None))
95}
96
97impl Boostagram {
98    pub fn to_b64(&self) -> Result<String, Error> {
99        let json = serde_json::to_vec(self)?;
100        Ok(general_purpose::STANDARD.encode(json))
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn test_from_fountain_invoice() {
110        let boost_raw = "eyJhcHBfbmFtZSI6IkZvdW50YWluIiwidmFsdWVfbXNhdF90b3RhbCI6MTAwMDAwLCJuYW1lIjoiQWxieSBUZXN0IFVzZXIgUFVUIiwicG9kY2FzdCI6IlRlc3QgUG9kY2FzdCBBbmNob3IiLCJmZWVkSUQiOjYwMTU2NzEsImFjdGlvbiI6ImJvb3N0Iiwic2VuZGVyX2lkIjoiblNpcTdpZDc4SkFkSDl1WTFwSXkiLCJzZW5kZXJfbmFtZSI6IkBhbHdpbl9jb25zaGF4IiwibWVzc2FnZSI6InRlc3QiLCJpdGVtSUQiOiIxNDkzNDE1NDMwOSIsImJvb3N0X2xpbmsiOiJodHRwczovL2ZvdW50YWluLmZtL2VwaXNvZGUvMTQ5MzQxNTQzMDkiLCJlcGlzb2RlIjoidGhpcyBpcyBhIHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgdmVyeSB2ZXJ5IHZlcnkgbG9uZyBlcGlzb2RlIG5hbWUhISEiLCJ0cyI6MzI5LCJ0aW1lIjoiMDA6MDU6MjkifQ==";
111
112        let result = from_b64(boost_raw);
113
114        dbg!(&result);
115
116        assert!(result.is_ok());
117
118        let boostagram = result.unwrap();
119
120        assert_eq!(boostagram.item_id, None);
121    }
122}