ol_rusty/src/commands/schedule.rs

159 lines
4.4 KiB
Rust
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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(())
}