Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rust_rest_api"
version = "0.3.0"
version = "0.4.0"
edition = "2024"
license = "MIT"
authors = ["Habibi-Dev"]
Expand Down
7 changes: 4 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::core::config::Config;
use crate::jobs::{cache_flush::CacheFlushJob, coin_sync::CoinSyncJob};
use crate::jobs::cache_flush::CacheFlushJob;
use crate::jobs::tgju_sync::TgjuSyncJob;
use crate::server;
use crate::services::{cache::StatsCache, routes::Routes};
use crate::state::{self, APP_STATE, AppState};
Expand Down Expand Up @@ -48,9 +49,9 @@ async fn setup_database() -> Result<sea_orm::DatabaseConnection> {

fn start_background_jobs(cache: &Arc<StatsCache>) -> Result<()> {
let flush_job = CacheFlushJob::new(Arc::clone(cache));
let coin_job = CoinSyncJob::new();
let tgju_job = TgjuSyncJob::new();

crate::services::jobs::FlushJob::start(vec![flush_job.into_task(), coin_job.into_task()], None);
crate::services::jobs::FlushJob::start(vec![flush_job.into_task(), tgju_job.into_task()], None);

Ok(())
}
Expand Down
36 changes: 0 additions & 36 deletions src/jobs/coin_sync.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/jobs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod cache_flush;
pub mod coin_sync;
pub mod tgju_sync;

use std::{future::Future, pin::Pin, sync::Arc};

Expand Down
36 changes: 36 additions & 0 deletions src/jobs/tgju_sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::jobs::JobTask;
use crate::request::request_handler;
use crate::state::APP_STATE;
use std::sync::Arc;

pub struct TgjuSyncJob;

impl TgjuSyncJob {
pub fn new() -> Self {
Self
}

pub fn into_task(self) -> JobTask {
Arc::new(|| {
Box::pin(async {
if let Err(e) = tgju_sync().await {
eprintln!("Gold sync job failed: {}", e);
}
})
})
}
}

async fn tgju_sync() -> Result<(), Box<dyn std::error::Error>> {
let service = request_handler::RequestHandler::new();
let tg = service.tgju_typed().await?;

let state = APP_STATE.get().ok_or("Application state not available")?;

state
.financial_rates_tx
.send(tg)
.map_err(|_| "Failed to send golds to channel")?;

Ok(())
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod entities;
mod jobs;
mod middleware;
mod repository;
mod request;
mod server;
mod services;
mod state;
Expand Down
1 change: 1 addition & 0 deletions src/request/data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

3 changes: 3 additions & 0 deletions src/request/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod data;
pub mod request_handler;
pub mod tgju_data;
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
use crate::services::coin_ir::data::{ApiResponse, CoinData};
use crate::request::tgju_data::{ApiResponse, TgjuData};
use reqwest::Client;
use uuid::Uuid;

pub struct RequestCoinIr {
pub struct RequestHandler {
client: Client,
}

impl RequestCoinIr {
impl RequestHandler {
pub fn new() -> Self {
let client = Client::builder()
.use_rustls_tls()
.timeout(std::time::Duration::from_secs(10))
.build()
.expect("reqwest client build failed");
.expect("reqwest client [RequestGold] build failed");
Self { client }
}

pub async fn start(&self) -> Result<ApiResponse, reqwest::Error> {
let uuid = Uuid::new_v4();
let url = format!("https://call1.tgju.org/ajax.json?rev={}", uuid);
let url = format!("https://call3.tgju.org/ajax.json?rev={}", uuid);
let resp = self
.client
.get(url)
Expand All @@ -31,8 +31,8 @@ impl RequestCoinIr {
Ok(api)
}

pub async fn coins_typed(&self) -> Result<CoinData, reqwest::Error> {
pub async fn tgju_typed(&self) -> Result<TgjuData, reqwest::Error> {
let api = self.start().await?;
Ok(CoinData::from(&api.current))
Ok(TgjuData::from(&api.current))
}
}
100 changes: 100 additions & 0 deletions src/request/tgju_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use crate::utility::de_num_opt;
use chrono::Utc;
use chrono_tz::Tz;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize)]
pub struct Info {
pub current: Option<u64>,
pub highest: Option<u64>,
pub lowest: Option<u64>,
pub updated_at: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct TgjuData {
pub gold_18_750: Option<Info>,
pub gold_18_740: Option<Info>,
pub gold_24: Option<Info>,
pub mesghal: Option<Info>,
pub used_gold: Option<Info>,
pub emami: Option<Info>,
pub bahar: Option<Info>,
pub nim: Option<Info>,
pub rob: Option<Info>,
pub gerami: Option<Info>,
pub price_dollar_rl: Option<Info>,
pub price_eur: Option<Info>,
pub price_aed: Option<Info>,
pub price_gbp: Option<Info>,
pub price_try: Option<Info>,
pub crypto_bitcoin_irr: Option<Info>,
pub crypto_ethereum_irr: Option<Info>,
pub crypto_binance_coin_irr: Option<Info>,
pub crypto_ripple_irr: Option<Info>,
pub crypto_usd_coin_irr: Option<Info>,
pub crypto_dogecoin_irr: Option<Info>,
pub crypto_tron_irr: Option<Info>,
pub sync_at: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct ApiResponse {
pub current: HashMap<String, Quote>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Quote {
#[serde(deserialize_with = "de_num_opt")]
pub p: Option<u64>,
#[serde(deserialize_with = "de_num_opt")]
pub h: Option<u64>,
#[serde(deserialize_with = "de_num_opt")]
pub l: Option<u64>,
pub ts: Option<String>,
}

impl From<&HashMap<String, Quote>> for TgjuData {
fn from(m: &HashMap<String, Quote>) -> Self {
let info = Self::info(m);
let tz: Tz = "Asia/Tehran".parse().unwrap_or(chrono_tz::UTC);
Self {
gold_18_750: Some(info("geram18")),
gold_18_740: Some(info("gold_740k")),
gold_24: Some(info("geram24")),
mesghal: Some(info("mesghal")),
used_gold: Some(info("gold_mini_size")),
emami: Some(info("sekee")),
bahar: Some(info("sekeb")),
nim: Some(info("nim")),
rob: Some(info("rob")),
gerami: Some(info("gerami")),
price_dollar_rl: Some(info("price_dollar_rl")),
price_eur: Some(info("price_eur")),
price_aed: Some(info("price_aed")),
price_gbp: Some(info("price_gbp")),
price_try: Some(info("price_try")),
crypto_bitcoin_irr: Some(info("crypto-bitcoin-irr")),
crypto_ethereum_irr: Some(info("crypto-ethereum-irr")),
crypto_binance_coin_irr: Some(info("crypto-binance-coin-irr")),
crypto_ripple_irr: Some(info("crypto-ripple-irr")),
crypto_usd_coin_irr: Some(info("crypto-usd-coin-irr")),
crypto_dogecoin_irr: Some(info("crypto-dogecoin-irr")),
crypto_tron_irr: Some(info("crypto-tron-irr")),
sync_at: Some(Utc::now().with_timezone(&tz).to_rfc3339()),
}
}
}

impl TgjuData {
pub fn info<'a>(m: &'a HashMap<String, Quote>) -> impl Fn(&str) -> Info + 'a {
move |k: &str| {
let q = m.get(k);
Info {
current: q.and_then(|q| q.p),
highest: q.and_then(|q| q.h),
lowest: q.and_then(|q| q.l),
updated_at: q.and_then(|q| q.ts.clone()),
}
}
}
}
66 changes: 0 additions & 66 deletions src/services/coin_ir/data.rs

This file was deleted.

4 changes: 0 additions & 4 deletions src/services/coin_ir/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
pub(crate) mod data;
pub mod helper;
pub mod request;
mod response;

use crate::services::coin_ir::response::response_coin;
use axum::routing::{MethodRouter, get};
pub use helper::de_num_opt;

pub fn routers_list() -> Vec<(&'static str, MethodRouter)> {
Vec::from([("/ir", get(response_coin))])
Expand Down
12 changes: 11 additions & 1 deletion src/services/coin_ir/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@ use serde_json::json;

pub async fn response_coin() -> Json<ApiResponse<serde_json::Value>> {
let state = APP_STATE.get();
let payload = json!(state.unwrap().coin_rx.borrow().clone());
let data = state.unwrap().financial_rates_rx.borrow().clone();

let payload = json!({
"emami": data.emami,
"gerami": data.gerami,
"bahar": data.bahar,
"nim": data.nim,
"rob": data.rob,
"source": "tgju.org",
"sync_at": data.sync_at,
});

Json(ApiResponse::success(payload))
}
8 changes: 8 additions & 0 deletions src/services/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mod response;

use crate::services::crypto::response::response_crypto_ir;
use axum::routing::{MethodRouter, get};

pub fn routers_list() -> Vec<(&'static str, MethodRouter)> {
Vec::from([("/ir", get(response_crypto_ir))])
}
Loading