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