podping_api/podping/
api.rs

1use reqwest::Client;
2
3use crate::podping::OpPayload;
4
5use super::{
6    request::BlockId, HiveMessage, HiveOperation, HiveResponse, HiveResponseResult, Operations,
7    Transactions, HIVE_API,
8};
9
10/// Get operations for the current block
11/// We filter for notifications with the name `podping`
12pub async fn get_operations(
13    client: &Client,
14    block: &BlockId,
15) -> Result<Vec<Operations>, reqwest::Error> {
16    let transactions = get_transactions(client, block).await?;
17    tracing::debug!("Transactions: {transactions:?}, Block Id: {block:?}");
18
19    let mut operations = vec![];
20    for transaction in transactions {
21        for operation in transaction.operations {
22            for op in operation {
23                match op {
24                    HiveOperation::Operations(operation) => {
25                        if let Some(name) = &operation.id {
26                            // We only care about podping messages.
27                            // WARNING: The id names of podcast updates likely need to be expanded.
28                            let queries = vec!["podping", "pp_podcast", "pp_podcast_update"];
29
30                            if queries.contains(&name.as_str()) {
31                                operations.push(operation);
32                            }
33                        }
34                    }
35                    // We don't care about any of these messages.
36                    HiveOperation::String(_)
37                    | HiveOperation::Vote(_)
38                    | HiveOperation::Transfer(_)
39                    | HiveOperation::Transactions(_)
40                    | HiveOperation::Comment(_) => {}
41                }
42            }
43        }
44    }
45    Ok(operations)
46}
47
48pub async fn get_transactions(
49    client: &Client,
50    block: &BlockId,
51) -> Result<Vec<Transactions>, reqwest::Error> {
52    let hive_response = get_block(client, block).await?;
53    if let Some(HiveResponseResult::Block(block)) = &hive_response.result {
54        Ok(block.transactions.clone())
55    } else {
56        Ok(vec![])
57    }
58}
59
60/// Get information about the specified Block
61pub async fn get_block(client: &Client, block: &BlockId) -> Result<HiveResponse, reqwest::Error> {
62    let block_response = HiveMessage::get_block(block.get());
63    let resp = client
64        .post(HIVE_API)
65        .json(&block_response)
66        .send()
67        .await?
68        .text()
69        .await?;
70    // reqwest can't properly serialize the type into json,
71    // but serde_json can.
72    Ok(serde_json::from_str::<HiveResponse>(&resp).unwrap())
73}
74
75/// Extract Url's from the Operations
76/// TODO: Maybe move into a FROM impl?
77pub async fn get_payloads(operations: Vec<Operations>, _block: &BlockId) -> Vec<String> {
78    // Extract the updated uri's
79    let mut payloads = vec![];
80    for tr in operations {
81        let json_payload = serde_json::from_str::<OpPayload>(&tr.json.unwrap()).unwrap();
82        payloads = json_payload.iris;
83    }
84
85    payloads
86}
87
88/// Get the current head block number
89pub async fn get_head_block_number(client: &Client) -> Result<u64, reqwest::Error> {
90    let resp = client
91        .post(HIVE_API)
92        .json(&HiveMessage::get_dynamic_global_properties())
93        .send()
94        .await?
95        .json::<HiveResponse>()
96        .await?;
97    Ok(resp.get_head_block_number().unwrap())
98}