159 lines
4.4 KiB
Rust
159 lines
4.4 KiB
Rust
use crate::{commands::utils, Context, Error};
|
||
use cached::proc_macro::cached;
|
||
use chrono::{DateTime, Utc};
|
||
use log::{warn};
|
||
use reqwest::header::AUTHORIZATION;
|
||
use serde::Deserialize;
|
||
|
||
#[derive(Deserialize, Clone)]
|
||
struct MSReq {
|
||
containers: Vec<MSEvent>,
|
||
#[serde(rename = "eventTitle")]
|
||
event_title: String,
|
||
}
|
||
|
||
#[derive(Deserialize, Clone)]
|
||
struct MSEvent {
|
||
id: String,
|
||
// #[serde(rename = "longDescription")]
|
||
// description: String,
|
||
// country: String,
|
||
metadata: MSMetadata,
|
||
}
|
||
|
||
impl MSEvent {
|
||
fn get_title(&self) -> String {
|
||
let title = &self.metadata.attributes.series.replace("FORMULA", "F");
|
||
format!("**{}: {}**", title, self.metadata.brief)
|
||
// format!("", sport=self.content.format.sport, title=self.content.title, synopsis=self.content.synopsis, start=self.times.start.timestamp(), end=self.times.end.timestamp(), desc=self.content.description, id=self.system.product_key)
|
||
}
|
||
|
||
fn get_value(&self, high_tier: bool) -> String {
|
||
let link = if high_tier {
|
||
format!("[{id}](https://morningstreams.com/hightier/f1/session/{id})\n", id=self.id)
|
||
} else {
|
||
"".to_string()
|
||
};
|
||
format!("{link}Start: <t:{start}:R>\nEnd: <t:{end}:R>", link=link, start=self.metadata.attributes.start.timestamp(), end=self.metadata.attributes.end.timestamp())
|
||
}
|
||
}
|
||
|
||
#[derive(Deserialize, Clone)]
|
||
struct MSMetadata {
|
||
// id: String,
|
||
// system: System,
|
||
#[serde(rename="emfAttributes")]
|
||
attributes: EmfAttributes,
|
||
#[serde(rename="titleBrief")]
|
||
brief: String,
|
||
// #[serde(rename="Series")]
|
||
// series: String,
|
||
}
|
||
|
||
|
||
#[derive(Deserialize, Clone)]
|
||
struct EmfAttributes {
|
||
#[serde(with = "ms_date")]
|
||
#[serde(rename="sessionStartDate")]
|
||
start: DateTime<Utc>,
|
||
#[serde(with = "ms_date")]
|
||
#[serde(rename="sessionEndDate")]
|
||
end: DateTime<Utc>,
|
||
#[serde(rename="Series")]
|
||
series: String,
|
||
}
|
||
|
||
|
||
|
||
|
||
mod ms_date {
|
||
use chrono::{DateTime, Utc, NaiveDateTime};
|
||
use serde::{self, Deserialize, Deserializer};
|
||
|
||
pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
|
||
where
|
||
D: Deserializer<'de>,
|
||
{
|
||
let n = i64::deserialize(deserializer)?/1000;
|
||
// let s = String::deserialize(deserializer)?;
|
||
|
||
Ok(DateTime::from_utc(NaiveDateTime::from_timestamp(n, 0), Utc))
|
||
|
||
|
||
}
|
||
}
|
||
|
||
|
||
#[cached(time = 3600)]
|
||
async fn get_schedule() -> Option<MSReq> {
|
||
let token = super::super::SETTINGS
|
||
.read()
|
||
.unwrap()
|
||
.get_table("morningstreams")
|
||
.unwrap()
|
||
.get("token")
|
||
.expect("Config error, please set the morningstreams[token] value")
|
||
.clone()
|
||
.into_string()
|
||
.expect("Config error, please make sure morningstreams[token] is a string");
|
||
let client = reqwest::Client::new();
|
||
let req = client
|
||
.get(format!(
|
||
"https://api.morningstreams.com/api/hightier/f1/next-event"
|
||
))
|
||
.header(AUTHORIZATION, token)
|
||
.send()
|
||
.await;
|
||
|
||
let result: Option<MSReq> = match req {
|
||
Err(e) => {
|
||
warn!("Error getting Viaplay schedule {}", e);
|
||
None
|
||
}
|
||
Ok(req) if req.status().as_u16() == 404 => {
|
||
warn!("404 on getting VP events");
|
||
None
|
||
}
|
||
Ok(req) if req.status().as_u16() == 200 => {
|
||
let data = req.json::<MSReq>().await;
|
||
match data {
|
||
Ok(d) => Some(d),
|
||
Err(e) => {
|
||
warn!("Error getting Viaplay schedule {}", e);
|
||
None
|
||
}
|
||
}
|
||
}
|
||
Ok(req) => {
|
||
warn!(
|
||
"Unhandled status when parsing viaplay request {}",
|
||
req.status()
|
||
);
|
||
None
|
||
}
|
||
};
|
||
result
|
||
}
|
||
|
||
#[poise::command(slash_command)]
|
||
pub async fn schedule(
|
||
ctx: Context<'_>,
|
||
) -> Result<(), Error> {
|
||
let events: Option<MSReq> = get_schedule().await;
|
||
let ht: bool = utils::high_tier(ctx).await;
|
||
match events {
|
||
None => {ctx.say("Error on fetching events :(").await?;},
|
||
Some(evs) => {
|
||
ctx.send(|b| {b.embed(|e| {
|
||
e.title(format!("F1 schedule: {}", evs.event_title));
|
||
for event in evs.containers {
|
||
e.field(event.get_title(), event.get_value(ht), true);
|
||
};
|
||
e
|
||
})}).await?;
|
||
}
|
||
};
|
||
|
||
Ok(())
|
||
|
||
} |