added team command, added game command, added about command
added request module, added nfl module, among other items
This commit is contained in:
commit
031b2be817
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
.env
|
2715
Cargo.lock
generated
Normal file
2715
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "ball-bot"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
serenity = { version = "0.12.2", features = [
|
||||
"client",
|
||||
"gateway",
|
||||
"rustls_backend",
|
||||
"model",
|
||||
"collector",
|
||||
] }
|
||||
tokio = { version = "1.41.0", features = ["macros", "rt-multi-thread"] }
|
||||
reqwest = { version = "0.12.9", features = ["json", "rustls-tls"] }
|
||||
tracing = "0.1.40"
|
||||
dotenvy = "0.15.7"
|
||||
rand = "0.8.5"
|
||||
chrono = { version = "0.4.38" }
|
||||
serde = "1.0.214"
|
||||
serde_json = "1.0.132"
|
||||
serde_derive = "1.0.214"
|
61
flake.lock
Normal file
61
flake.lock
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-schemas": {
|
||||
"locked": {
|
||||
"lastModified": 1721999734,
|
||||
"narHash": "sha256-G5CxYeJVm4lcEtaO87LKzOsVnWeTcHGKbKxNamNWgOw=",
|
||||
"rev": "0a5c42297d870156d9c57d8f99e476b738dcd982",
|
||||
"revCount": 75,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/DeterminateSystems/flake-schemas/0.1.5/0190ef2f-61e0-794b-ba14-e82f225e55e6/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%2A"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1730741070,
|
||||
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
|
||||
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
|
||||
"revCount": 636376,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2405.636376%2Brev-d063c1dd113c91ab27959ba540c0d9753409edf3/0192facb-0ae2-71fe-ba33-5b04923dc511/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://flakehub.com/f/NixOS/nixpkgs/%2A"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-schemas": "flake-schemas",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730860036,
|
||||
"narHash": "sha256-u0sfA4B65Q9cRO3xpIkQ4nldB8isfdIb3rWtsnRZ+Iw=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "b8eb3aeb21629cbe14968a5e3b1cbaefb0d1b260",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
64
flake.nix
Normal file
64
flake.nix
Normal file
@ -0,0 +1,64 @@
|
||||
# This flake was initially generated by fh, the CLI for FlakeHub (version 0.1.16)
|
||||
{
|
||||
description = "Discord bot for viewing football statistics, teams, team members, and more!";
|
||||
|
||||
inputs = {
|
||||
flake-schemas.url = "https://flakehub.com/f/DeterminateSystems/flake-schemas/*";
|
||||
|
||||
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/*";
|
||||
|
||||
rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
flake-schemas,
|
||||
nixpkgs,
|
||||
rust-overlay,
|
||||
}: let
|
||||
overlays = [
|
||||
rust-overlay.overlays.default
|
||||
(final: prev: {
|
||||
rustToolchain = final.rust-bin.stable.latest.default.override {extensions = ["rust-src"];};
|
||||
})
|
||||
];
|
||||
|
||||
supportedSystems = ["x86_64-linux" "aarch64-darwin" "aarch64-linux"];
|
||||
forEachSupportedSystem = f:
|
||||
nixpkgs.lib.genAttrs supportedSystems (system:
|
||||
f {
|
||||
pkgs = import nixpkgs {inherit overlays system;};
|
||||
});
|
||||
in {
|
||||
schemas = flake-schemas.schemas;
|
||||
|
||||
devShells = forEachSupportedSystem ({pkgs}: {
|
||||
default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
rustToolchain
|
||||
cargo-bloat
|
||||
cargo-edit
|
||||
cargo-outdated
|
||||
cargo-udeps
|
||||
cargo-watch
|
||||
rust-analyzer
|
||||
curl
|
||||
git
|
||||
jq
|
||||
wget
|
||||
pkg-config-unwrapped
|
||||
openssl.dev
|
||||
];
|
||||
|
||||
env = {
|
||||
RUST_BACKTRACE = "1";
|
||||
RUST_SRC_PATH = "${pkgs.rustToolchain}/lib/rustlib/src/rust/library";
|
||||
PKG_CONFIG_PATH = "${pkgs.openssl.dev}/lib/pkgconfig";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
16
src/commands/about.rs
Normal file
16
src/commands/about.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use serenity::builder::CreateCommand;
|
||||
use serenity::model::application::ResolvedOption;
|
||||
|
||||
pub async fn run(options: &[ResolvedOption<'_>]) -> String {
|
||||
r#"
|
||||
A Discord bot that gathers information about NFL games, teams, conferences, and more!
|
||||
Designed, developed, and maintained by Wyatt J. Miller
|
||||
Copyright 2024, all rights reserved
|
||||
Got a feature request? Found a bug? Wanna punch me in the face? Email ballbot@wyattjmiller.com
|
||||
"#
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn register() -> CreateCommand {
|
||||
CreateCommand::new("about").description("Get information about this bot")
|
||||
}
|
0
src/commands/conference.rs
Normal file
0
src/commands/conference.rs
Normal file
106
src/commands/game.rs
Normal file
106
src/commands/game.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use crate::{
|
||||
types,
|
||||
util::{junk, nfl, request},
|
||||
};
|
||||
|
||||
use serenity::builder::{CreateCommand, CreateCommandOption};
|
||||
use serenity::model::application::{CommandOptionType, ResolvedOption, ResolvedValue};
|
||||
|
||||
pub async fn run(options: &[ResolvedOption<'_>]) -> String {
|
||||
if let Some(ResolvedOption {
|
||||
value: ResolvedValue::String(team),
|
||||
..
|
||||
}) = options.first()
|
||||
{
|
||||
let teams = nfl::nfl_teams();
|
||||
let team_id = match junk::find_team_key(&teams, team.to_lowercase().as_str()) {
|
||||
Some(t) => t,
|
||||
None => return junk::get_random_insult(),
|
||||
};
|
||||
let req = request::Request::new();
|
||||
let tmp_url = format!("{:}/nfl/teams/{:}", req.base_url, team_id);
|
||||
let tmp_result = req
|
||||
.request_url::<types::team::TeamResponse>(&tmp_url)
|
||||
.await
|
||||
.unwrap();
|
||||
let event_id = tmp_result.team.next_event[0].id.clone();
|
||||
let url = format!("{:}/nfl/scoreboard/{:}", req.base_url, event_id);
|
||||
let result = req
|
||||
.request_url::<types::event::EventResponse>(&url)
|
||||
.await
|
||||
.unwrap();
|
||||
let game = result.competitions[0].clone();
|
||||
|
||||
let event_title = format!("{:} ({:})", result.name, result.short_name); // needed
|
||||
let event_date = format!(
|
||||
"<t:{:}:R>",
|
||||
junk::flexible_to_epoch_seconds(result.date.as_str()).unwrap()
|
||||
); // needed
|
||||
let clock = result.status.display_clock.clone();
|
||||
let quarter = result.status.period.to_string().clone();
|
||||
let venue = game.venue.full_name.clone();
|
||||
let team_home = game
|
||||
.competitors
|
||||
.iter()
|
||||
.find(|t| t.home_away == "home")
|
||||
.unwrap();
|
||||
let team_away = game
|
||||
.competitors
|
||||
.iter()
|
||||
.find(|t| t.home_away == "away")
|
||||
.unwrap();
|
||||
let home_team = team_home.team.display_name.clone();
|
||||
let away_team = team_away.team.display_name.clone();
|
||||
let home_team_score = team_home.score.clone();
|
||||
let away_team_score = team_away.score.clone();
|
||||
|
||||
let discord_response = GameDiscordResponse {
|
||||
event_title,
|
||||
home_team,
|
||||
home_team_score,
|
||||
away_team,
|
||||
away_team_score,
|
||||
venue,
|
||||
event_date,
|
||||
clock,
|
||||
quarter,
|
||||
};
|
||||
discord_response.format()
|
||||
} else {
|
||||
junk::get_random_insult()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register() -> CreateCommand {
|
||||
CreateCommand::new("game")
|
||||
.description("Get the next game's information by specifying a team name")
|
||||
.add_option(
|
||||
CreateCommandOption::new(
|
||||
CommandOptionType::String,
|
||||
"team",
|
||||
"The team to query to get team's game info",
|
||||
)
|
||||
.required(true),
|
||||
)
|
||||
}
|
||||
|
||||
pub struct GameDiscordResponse {
|
||||
pub event_title: String,
|
||||
pub home_team: String,
|
||||
pub home_team_score: String,
|
||||
pub away_team: String,
|
||||
pub away_team_score: String,
|
||||
pub venue: String,
|
||||
pub event_date: String,
|
||||
pub clock: String,
|
||||
pub quarter: String,
|
||||
}
|
||||
|
||||
impl GameDiscordResponse {
|
||||
pub fn format(&self) -> String {
|
||||
format!(
|
||||
"\n## {:}\nGame Date: {:}\nHome Team: {:}\nHome Team Score: {:}\nAway Team: {:}\nAway Team Score: {:}\nVenue: {:}\nClock: {:}\nQuarter: {:}",
|
||||
self.event_title, self.event_date, self.home_team, self.home_team_score, self.away_team, self.away_team_score, self.venue, self.clock, self.quarter
|
||||
)
|
||||
}
|
||||
}
|
3
src/commands/mod.rs
Normal file
3
src/commands/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod about;
|
||||
pub mod game;
|
||||
pub mod team;
|
69
src/commands/team.rs
Normal file
69
src/commands/team.rs
Normal file
@ -0,0 +1,69 @@
|
||||
use crate::{
|
||||
types,
|
||||
util::{junk, nfl, request},
|
||||
};
|
||||
|
||||
use serenity::builder::{CreateCommand, CreateCommandOption};
|
||||
use serenity::model::application::{CommandOptionType, ResolvedOption, ResolvedValue};
|
||||
|
||||
pub async fn run(options: &[ResolvedOption<'_>]) -> String {
|
||||
if let Some(ResolvedOption {
|
||||
value: ResolvedValue::String(team),
|
||||
..
|
||||
}) = options.first()
|
||||
{
|
||||
let teams = nfl::nfl_teams();
|
||||
let team_id = match junk::find_team_key(&teams, team.to_lowercase().as_str()) {
|
||||
Some(t) => t,
|
||||
None => return junk::get_random_insult(),
|
||||
};
|
||||
let req = request::Request::new();
|
||||
let url = format!("{:}/nfl/teams/{:?}", req.base_url, team_id);
|
||||
let results = req
|
||||
.request_url::<types::team::TeamResponse>(&url)
|
||||
.await
|
||||
.unwrap();
|
||||
let team_name = results.team.display_name;
|
||||
let record = results.team.record.items[1].summary.clone();
|
||||
let next_event = results.team.next_event[0].name.clone();
|
||||
let game_date_raw = results.team.next_event[0].date.clone();
|
||||
let game_date = junk::flexible_to_epoch_seconds(game_date_raw.as_str()).unwrap();
|
||||
let standing = results.team.standing_summary;
|
||||
let discord_response = TeamDiscordResponse {
|
||||
team_name,
|
||||
record,
|
||||
next_event,
|
||||
game_date: format!("<t:{:}:R>", game_date),
|
||||
standing,
|
||||
};
|
||||
discord_response.format()
|
||||
} else {
|
||||
junk::get_random_insult()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register() -> CreateCommand {
|
||||
CreateCommand::new("team")
|
||||
.description("Get team members for current season")
|
||||
.add_option(
|
||||
CreateCommandOption::new(CommandOptionType::String, "team", "The team to query")
|
||||
.required(true),
|
||||
)
|
||||
}
|
||||
|
||||
pub struct TeamDiscordResponse {
|
||||
pub team_name: String,
|
||||
pub record: String,
|
||||
pub next_event: String,
|
||||
pub game_date: String,
|
||||
pub standing: String,
|
||||
}
|
||||
|
||||
impl TeamDiscordResponse {
|
||||
pub fn format(&self) -> String {
|
||||
format!(
|
||||
"## {:}\nSeason Record (W-L): {:}\nNext Game: {:}\nNext Game Date: {:}\nStanding: {:}",
|
||||
self.team_name, self.record, self.next_event, self.game_date, self.standing
|
||||
)
|
||||
}
|
||||
}
|
11
src/config.rs
Normal file
11
src/config.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Configuration {
|
||||
env: Result<PathBuf, dotenvy::Error>,
|
||||
}
|
||||
|
||||
pub fn config() -> Configuration {
|
||||
Configuration {
|
||||
env: dotenvy::dotenv(),
|
||||
}
|
||||
}
|
82
src/main.rs
Normal file
82
src/main.rs
Normal file
@ -0,0 +1,82 @@
|
||||
mod commands;
|
||||
mod config;
|
||||
mod types;
|
||||
mod util;
|
||||
|
||||
use std::env;
|
||||
|
||||
use serenity::async_trait;
|
||||
use serenity::builder::{CreateInteractionResponse, CreateInteractionResponseMessage};
|
||||
use serenity::model::application::Interaction;
|
||||
use serenity::model::gateway::Ready;
|
||||
use serenity::model::id::GuildId;
|
||||
use serenity::prelude::*;
|
||||
|
||||
struct Handler;
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
||||
if let Interaction::Command(command) = interaction {
|
||||
println!("Received command interaction: {command:#?}");
|
||||
|
||||
let content = match command.data.name.as_str() {
|
||||
"team" => Some(commands::team::run(&command.data.options()).await),
|
||||
"about" => Some(commands::about::run(&command.data.options()).await),
|
||||
"game" => Some(commands::game::run(&command.data.options()).await),
|
||||
_ => Some("not implemented :(".to_string()),
|
||||
};
|
||||
|
||||
if let Some(content) = content {
|
||||
let data = CreateInteractionResponseMessage::new().content(content);
|
||||
let builder = CreateInteractionResponse::Message(data);
|
||||
if let Err(why) = command.create_response(&ctx.http, builder).await {
|
||||
println!("Cannot respond to slash command: {why}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
||||
println!("{} is connected!", ready.user.name);
|
||||
|
||||
let guild_id = GuildId::new(
|
||||
env::var("GUILD_ID")
|
||||
.expect("Expected GUILD_ID in environment")
|
||||
.parse()
|
||||
.expect("GUILD_ID must be an integer"),
|
||||
);
|
||||
|
||||
let commands = guild_id
|
||||
.set_commands(
|
||||
&ctx.http,
|
||||
vec![
|
||||
commands::team::register(),
|
||||
commands::about::register(),
|
||||
commands::game::register(),
|
||||
], // TODO: register commands here
|
||||
)
|
||||
.await;
|
||||
|
||||
println!("Registered guild slash commands: {commands:#?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// setting up configuration
|
||||
let _ = config::config();
|
||||
|
||||
// setting up the discord bot
|
||||
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");
|
||||
|
||||
// setting up the discord client
|
||||
let mut client = Client::builder(token, GatewayIntents::empty())
|
||||
.event_handler(Handler)
|
||||
.await
|
||||
.expect("Error creating client");
|
||||
|
||||
if let Err(why) = client.start().await {
|
||||
println!("Client error: {why:?}");
|
||||
}
|
||||
}
|
327
src/types/event.rs
Normal file
327
src/types/event.rs
Normal file
@ -0,0 +1,327 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EventResponse {
|
||||
pub id: String,
|
||||
pub uid: String,
|
||||
pub date: String,
|
||||
pub name: String,
|
||||
pub short_name: String,
|
||||
pub season: Season,
|
||||
pub week: Week,
|
||||
pub competitions: Vec<Competition>,
|
||||
pub links: Vec<Link3>,
|
||||
pub status: Status2,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Season {
|
||||
pub year: i64,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: i64,
|
||||
pub slug: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Week {
|
||||
pub number: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Competition {
|
||||
pub id: String,
|
||||
pub uid: String,
|
||||
pub date: String,
|
||||
pub attendance: i64,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: Type,
|
||||
pub time_valid: bool,
|
||||
pub neutral_site: bool,
|
||||
pub conference_competition: bool,
|
||||
pub play_by_play_available: bool,
|
||||
pub recent: bool,
|
||||
pub venue: Venue,
|
||||
pub competitors: Vec<Competitor>,
|
||||
pub notes: Vec<Value>,
|
||||
pub status: Status,
|
||||
pub broadcasts: Vec<Broadcast>,
|
||||
pub leaders: Vec<Leader>,
|
||||
pub format: Format,
|
||||
pub start_date: String,
|
||||
pub broadcast: String,
|
||||
pub geo_broadcasts: Vec<GeoBroadcast>,
|
||||
pub highlights: Vec<Value>,
|
||||
pub headlines: Option<Vec<Headline>>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Type {
|
||||
pub id: String,
|
||||
pub abbreviation: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Venue {
|
||||
pub id: String,
|
||||
pub full_name: String,
|
||||
pub address: Address,
|
||||
pub indoor: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Address {
|
||||
pub city: String,
|
||||
pub state: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Competitor {
|
||||
pub id: String,
|
||||
pub uid: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
pub order: i64,
|
||||
pub home_away: String,
|
||||
pub winner: Option<bool>,
|
||||
pub team: Team,
|
||||
pub score: String,
|
||||
pub linescores: Option<Vec<Linescore>>,
|
||||
pub statistics: Vec<Value>,
|
||||
pub records: Vec<Record>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Team {
|
||||
pub id: String,
|
||||
pub uid: String,
|
||||
pub location: String,
|
||||
pub name: String,
|
||||
pub abbreviation: String,
|
||||
pub display_name: String,
|
||||
pub short_display_name: String,
|
||||
pub color: String,
|
||||
pub alternate_color: String,
|
||||
pub is_active: bool,
|
||||
pub venue: Venue2,
|
||||
pub links: Vec<Link>,
|
||||
pub logo: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Venue2 {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Link {
|
||||
pub rel: Vec<String>,
|
||||
pub href: String,
|
||||
pub text: String,
|
||||
pub is_external: bool,
|
||||
pub is_premium: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Linescore {
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Record {
|
||||
pub name: String,
|
||||
pub abbreviation: Option<String>,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
pub summary: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Status {
|
||||
pub clock: f64,
|
||||
pub display_clock: String,
|
||||
pub period: i64,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: Type2,
|
||||
#[serde(rename = "isTBDFlex")]
|
||||
pub is_tbdflex: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Type2 {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub state: String,
|
||||
pub completed: bool,
|
||||
pub description: String,
|
||||
pub detail: String,
|
||||
pub short_detail: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Broadcast {
|
||||
pub market: String,
|
||||
pub names: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Leader {
|
||||
pub name: String,
|
||||
pub display_name: String,
|
||||
pub short_display_name: String,
|
||||
pub abbreviation: String,
|
||||
pub leaders: Vec<Leader2>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Leader2 {
|
||||
pub display_value: String,
|
||||
pub value: f64,
|
||||
pub athlete: Athlete,
|
||||
pub team: Team3,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Athlete {
|
||||
pub id: String,
|
||||
pub full_name: String,
|
||||
pub display_name: String,
|
||||
pub short_name: String,
|
||||
pub links: Vec<Link2>,
|
||||
pub headshot: String,
|
||||
pub jersey: String,
|
||||
pub position: Position,
|
||||
pub team: Team2,
|
||||
pub active: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Link2 {
|
||||
pub rel: Vec<String>,
|
||||
pub href: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Position {
|
||||
pub abbreviation: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Team2 {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Team3 {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Format {
|
||||
pub regulation: Regulation,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Regulation {
|
||||
pub periods: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GeoBroadcast {
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: Type3,
|
||||
pub market: Market,
|
||||
pub media: Media,
|
||||
pub lang: String,
|
||||
pub region: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Type3 {
|
||||
pub id: String,
|
||||
pub short_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Market {
|
||||
pub id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Media {
|
||||
pub short_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Headline {
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
pub description: String,
|
||||
pub short_link_text: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Link3 {
|
||||
pub language: String,
|
||||
pub rel: Vec<String>,
|
||||
pub href: String,
|
||||
pub text: String,
|
||||
pub short_text: String,
|
||||
pub is_external: bool,
|
||||
pub is_premium: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Status2 {
|
||||
pub clock: f64,
|
||||
pub display_clock: String,
|
||||
pub period: i64,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: Type4,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Type4 {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub state: String,
|
||||
pub completed: bool,
|
||||
pub description: String,
|
||||
pub detail: String,
|
||||
pub short_detail: String,
|
||||
}
|
3
src/types/mod.rs
Normal file
3
src/types/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod event;
|
||||
pub mod score;
|
||||
pub mod team;
|
19
src/types/score.rs
Normal file
19
src/types/score.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ScoreResponse {
|
||||
#[serde(rename = "$ref")]
|
||||
pub ref_field: String,
|
||||
pub value: f64,
|
||||
pub display_value: String,
|
||||
pub winner: bool,
|
||||
pub source: ScoreSource,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ScoreSource {
|
||||
pub id: String,
|
||||
pub description: String,
|
||||
}
|
367
src/types/team.rs
Normal file
367
src/types/team.rs
Normal file
@ -0,0 +1,367 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamResponse {
|
||||
pub team: Team,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Team {
|
||||
pub id: String,
|
||||
pub uid: String,
|
||||
pub slug: String,
|
||||
pub location: String,
|
||||
pub name: String,
|
||||
pub nickname: String,
|
||||
pub abbreviation: String,
|
||||
pub display_name: String,
|
||||
pub short_display_name: String,
|
||||
pub color: String,
|
||||
pub alternate_color: String,
|
||||
pub is_active: bool,
|
||||
pub logos: Vec<Logo>,
|
||||
pub record: TeamRecord,
|
||||
pub groups: TeamGroups,
|
||||
pub links: Vec<TeamLink>,
|
||||
pub franchise: TeamFranchise,
|
||||
// #[serde(rename = "nextEvent")]
|
||||
pub next_event: Vec<NextEvent>,
|
||||
pub standing_summary: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Logo {
|
||||
pub href: String,
|
||||
pub width: i64,
|
||||
pub height: i64,
|
||||
pub alt: String,
|
||||
pub rel: Vec<String>,
|
||||
pub last_updated: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamRecord {
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Item {
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
pub summary: String,
|
||||
pub stats: Vec<Stat>,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Stat {
|
||||
pub name: String,
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamGroups {
|
||||
pub id: String,
|
||||
pub parent: Parent,
|
||||
pub is_conference: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Parent {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamLink {
|
||||
pub language: String,
|
||||
pub rel: Vec<String>,
|
||||
pub href: String,
|
||||
pub text: String,
|
||||
pub short_text: String,
|
||||
pub is_external: bool,
|
||||
pub is_premium: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamFranchise {
|
||||
#[serde(rename = "$ref")]
|
||||
pub ref_field: String,
|
||||
pub id: String,
|
||||
pub uid: String,
|
||||
pub slug: String,
|
||||
pub location: String,
|
||||
pub name: String,
|
||||
pub nickname: String,
|
||||
pub abbreviation: String,
|
||||
pub display_name: String,
|
||||
pub short_display_name: String,
|
||||
pub color: String,
|
||||
pub is_active: bool,
|
||||
pub venue: TeamVenue,
|
||||
pub team: Team2,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamVenue {
|
||||
#[serde(rename = "$ref")]
|
||||
pub ref_field: String,
|
||||
pub id: String,
|
||||
pub full_name: String,
|
||||
pub address: TeamAddress,
|
||||
pub grass: bool,
|
||||
pub indoor: bool,
|
||||
pub images: Vec<TeamImage>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamAddress {
|
||||
pub city: String,
|
||||
pub state: String,
|
||||
pub zip_code: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamImage {
|
||||
pub href: String,
|
||||
pub width: i64,
|
||||
pub height: i64,
|
||||
pub alt: String,
|
||||
pub rel: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Team2 {
|
||||
#[serde(rename = "$ref")]
|
||||
pub ref_field: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct NextEvent {
|
||||
pub id: String,
|
||||
pub date: String,
|
||||
pub name: String,
|
||||
pub short_name: String,
|
||||
pub season: TeamSeason,
|
||||
pub season_type: TeamSeasonType,
|
||||
pub week: TeamWeek,
|
||||
pub time_valid: bool,
|
||||
pub competitions: Vec<TeamCompetition>,
|
||||
pub links: Vec<TeamLink4>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamSeason {
|
||||
pub year: i64,
|
||||
pub display_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamSeasonType {
|
||||
pub id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: i64,
|
||||
pub name: String,
|
||||
pub abbreviation: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamWeek {
|
||||
pub number: i64,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamCompetition {
|
||||
pub id: String,
|
||||
pub date: String,
|
||||
pub attendance: i64,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: TeamType,
|
||||
pub time_valid: bool,
|
||||
pub neutral_site: bool,
|
||||
pub boxscore_available: bool,
|
||||
pub tickets_available: bool,
|
||||
pub venue: TeamVenue2,
|
||||
pub competitors: Vec<TeamCompetitor>,
|
||||
pub notes: Vec<Value>,
|
||||
pub broadcasts: Vec<Broadcast>,
|
||||
pub tickets: Vec<Ticket>,
|
||||
pub status: TeamStatus,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamType {
|
||||
pub id: String,
|
||||
pub text: String,
|
||||
pub abbreviation: String,
|
||||
pub slug: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamVenue2 {
|
||||
pub full_name: String,
|
||||
pub address: TeamAddress2,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamAddress2 {
|
||||
pub city: String,
|
||||
pub state: String,
|
||||
pub zip_code: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamCompetitor {
|
||||
pub id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
pub order: i64,
|
||||
pub home_away: String,
|
||||
pub team: Team3,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Team3 {
|
||||
pub id: String,
|
||||
pub location: String,
|
||||
pub nickname: String,
|
||||
pub abbreviation: String,
|
||||
pub display_name: String,
|
||||
pub short_display_name: String,
|
||||
pub logos: Vec<Logo2>,
|
||||
pub links: Vec<TeamLink2>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Logo2 {
|
||||
pub href: String,
|
||||
pub width: i64,
|
||||
pub height: i64,
|
||||
pub alt: String,
|
||||
pub rel: Vec<String>,
|
||||
pub last_updated: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamLink2 {
|
||||
pub rel: Vec<String>,
|
||||
pub href: String,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Broadcast {
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: Type2,
|
||||
pub market: Market,
|
||||
pub media: Media,
|
||||
pub lang: String,
|
||||
pub region: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Type2 {
|
||||
pub id: String,
|
||||
pub short_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Market {
|
||||
pub id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Media {
|
||||
pub short_name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Ticket {
|
||||
pub id: String,
|
||||
pub summary: String,
|
||||
pub description: String,
|
||||
pub max_price: f64,
|
||||
pub starting_price: f64,
|
||||
pub number_available: i64,
|
||||
pub total_postings: i64,
|
||||
pub links: Vec<TeamLink3>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamLink3 {
|
||||
pub rel: Vec<String>,
|
||||
pub href: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamStatus {
|
||||
pub clock: f64,
|
||||
pub display_clock: String,
|
||||
pub period: i64,
|
||||
#[serde(rename = "type")]
|
||||
pub type_field: TeamType3,
|
||||
#[serde(rename = "isTBDFlex")]
|
||||
pub is_tbdflex: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamType3 {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub state: String,
|
||||
pub completed: bool,
|
||||
pub description: String,
|
||||
pub detail: String,
|
||||
pub short_detail: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TeamLink4 {
|
||||
pub language: String,
|
||||
pub rel: Vec<String>,
|
||||
pub href: String,
|
||||
pub text: String,
|
||||
pub short_text: String,
|
||||
pub is_external: bool,
|
||||
pub is_premium: bool,
|
||||
}
|
0
src/util/discord.rs
Normal file
0
src/util/discord.rs
Normal file
59
src/util/junk.rs
Normal file
59
src/util/junk.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use chrono::prelude::*;
|
||||
use chrono::DateTime;
|
||||
use rand::seq::SliceRandom;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn find_team_key(teams: &HashMap<u32, &str>, team_name: &str) -> Option<u32> {
|
||||
teams
|
||||
.iter()
|
||||
.find(|(_k, &v)| v == team_name)
|
||||
.map(|(&k, _v)| k)
|
||||
}
|
||||
|
||||
pub fn find_team_name<'a>(teams: &HashMap<u32, &'a str>, identifier: u32) -> Option<&'a str> {
|
||||
teams
|
||||
.iter()
|
||||
.find(|(&k, _v)| k == identifier)
|
||||
.map(|(_k, &v)| v)
|
||||
}
|
||||
|
||||
pub fn get_random_insult() -> String {
|
||||
let insults = get_insults();
|
||||
let result = insults.choose(&mut rand::thread_rng()).unwrap();
|
||||
result.to_owned().to_string()
|
||||
}
|
||||
|
||||
fn get_insults<'a>() -> Vec<&'a str> {
|
||||
Vec::from([
|
||||
"You football bro?",
|
||||
"Somebody ought to throw pigskin in your face!",
|
||||
"Who are you, Ian?",
|
||||
"Your football expertise is about as useful as a screen door on a submarine!",
|
||||
"You must think a wide receiver is someone who shovels food into their face!",
|
||||
])
|
||||
}
|
||||
|
||||
pub fn flexible_to_epoch_seconds(time: &str) -> Result<i64, Box<dyn std::error::Error>> {
|
||||
let normalized = normalize_rfc_time(time);
|
||||
match DateTime::parse_from_rfc3339(&normalized) {
|
||||
Ok(dt) => Ok(dt.timestamp()),
|
||||
Err(_) => {
|
||||
let datetime = if time.ends_with('Z') {
|
||||
NaiveDateTime::parse_from_str(&time[..time.len() - 1], "%Y-%m-%dT%H:%M")?
|
||||
} else {
|
||||
NaiveDateTime::parse_from_str(time, "%Y-%m-%dT%H:%M")?
|
||||
};
|
||||
|
||||
Ok(datetime.and_utc().timestamp())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_rfc_time(time: &str) -> String {
|
||||
if time.ends_with('Z') && time.matches(':').count() == 1 {
|
||||
let len = time.len();
|
||||
format!("{}:00{}", &time[..len - 1], &time[len - 1..])
|
||||
} else {
|
||||
time.to_string()
|
||||
}
|
||||
}
|
4
src/util/mod.rs
Normal file
4
src/util/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub mod discord;
|
||||
pub mod junk;
|
||||
pub mod nfl;
|
||||
pub mod request;
|
42
src/util/nfl.rs
Normal file
42
src/util/nfl.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn nfl_teams<'a>() -> HashMap<u32, &'a str> {
|
||||
HashMap::from([
|
||||
(1, "falcons"),
|
||||
(2, "bills"),
|
||||
(3, "bears"),
|
||||
(4, "bengals"),
|
||||
(5, "browns"),
|
||||
(6, "cowboys"),
|
||||
(7, "broncos"),
|
||||
(8, "lions"),
|
||||
(9, "packers"),
|
||||
(10, "titans"),
|
||||
(11, "colts"),
|
||||
(12, "chiefs"),
|
||||
(13, "raiders"),
|
||||
(14, "rams"),
|
||||
(15, "dolphins"),
|
||||
(16, "vikings"),
|
||||
(17, "patriots"),
|
||||
(18, "saints"),
|
||||
(19, "giants"),
|
||||
(20, "jets"),
|
||||
(21, "eagles"),
|
||||
(22, "cardinals"),
|
||||
(23, "steelers"),
|
||||
(24, "chargers"),
|
||||
(25, "49ers"),
|
||||
(26, "seahawks"),
|
||||
(27, "buccaneers"),
|
||||
(28, "commanders"),
|
||||
(29, "panthers"),
|
||||
(30, "jaguars"),
|
||||
(33, "ravens"),
|
||||
(34, "texans"),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn nfl_conferences<'a>() -> HashMap<u32, &'a str> {
|
||||
HashMap::from([])
|
||||
}
|
54
src/util/request.rs
Normal file
54
src/util/request.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use reqwest::StatusCode;
|
||||
|
||||
pub struct Request<'a> {
|
||||
pub base_url: &'a str,
|
||||
pub full_url: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Request<'a> {
|
||||
pub fn new() -> Self {
|
||||
Request {
|
||||
base_url: "https://site.api.espn.com/apis/site/v2/sports/football",
|
||||
full_url: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base_url(&self) -> &str {
|
||||
self.base_url
|
||||
}
|
||||
|
||||
pub fn set_base_url(&mut self, base_url: &'a str) {
|
||||
self.base_url = base_url;
|
||||
}
|
||||
|
||||
pub async fn request_url<T>(&self, url: &String) -> Result<T, Box<dyn std::error::Error>>
|
||||
where
|
||||
T: for<'de> serde::Deserialize<'de>,
|
||||
{
|
||||
println!("{}", url);
|
||||
let api_result = match reqwest::get(url).await {
|
||||
Ok(r) => r,
|
||||
Err(e) => return Err(Box::new(e)),
|
||||
};
|
||||
match api_result.status() {
|
||||
StatusCode::OK => {
|
||||
let json = api_result.json::<T>();
|
||||
let json_result = match json.await {
|
||||
Ok(j) => j,
|
||||
Err(e) => return Err(Box::new(e)),
|
||||
};
|
||||
Ok(json_result)
|
||||
}
|
||||
status => Err(Box::new(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("Unexpected status code: {}", status),
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RequestOptions {
|
||||
team_id: Option<u32>,
|
||||
event_id: Option<u32>,
|
||||
year: Option<u32>,
|
||||
}
|
Loading…
Reference in New Issue
Block a user