Split youmubot-osu

This commit is contained in:
Natsu Kagami 2020-02-05 17:25:34 -05:00
parent 03be1a4acc
commit aec9cd130d
15 changed files with 108 additions and 86 deletions

8
Cargo.lock generated
View file

@ -1679,10 +1679,7 @@ version = "0.1.0"
dependencies = [
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serenity 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1710,10 +1707,15 @@ version = "0.1.0"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
"serenity 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"youmubot-db 0.1.0",
"youmubot-prelude 0.1.0",
]
[[package]]

View file

@ -12,6 +12,12 @@ chrono = "0.4.10"
reqwest = "0.10.1"
serde = { version = "1.0", features = ["derive"] }
bitflags = "1"
rayon = "1.1"
lazy_static = "1"
regex = "1"
youmubot-db = { path = "../youmubot-db" }
youmubot-prelude = { path = "../youmubot-prelude" }
[dev-dependencies]
serde_json = "1"

View file

@ -1,16 +1,16 @@
use super::{embeds::score_embed, BeatmapWithMode};
use crate::db::{OsuSavedUsers, OsuUser};
use super::db::{OsuSavedUsers, OsuUser};
use super::{embeds::score_embed, BeatmapWithMode, OsuClient};
use crate::{
models::{Mode, Score},
request::{BeatmapRequestKind, UserID},
Client as Osu,
};
use rayon::prelude::*;
use serenity::{
framework::standard::{CommandError as Error, CommandResult},
http::Http,
model::id::{ChannelId, UserId},
};
use youmubot_osu::{
models::{Mode, Score},
request::{BeatmapRequestKind, UserID},
Client as Osu,
};
use youmubot_prelude::*;
/// Announce osu! top scores.

View file

@ -1,5 +1,5 @@
use super::db::OsuLastBeatmap;
use super::BeatmapWithMode;
use crate::db::OsuLastBeatmap;
use serenity::{
framework::standard::{CommandError as Error, CommandResult},
model::id::ChannelId,

View file

@ -0,0 +1,22 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serenity::{
model::id::{ChannelId, UserId},
};
use std::collections::HashMap;
use youmubot_db::{DB};
use crate::models::{Beatmap, Mode};
/// Save the user IDs.
pub type OsuSavedUsers = DB<HashMap<UserId, OsuUser>>;
/// Save each channel's last requested beatmap.
pub type OsuLastBeatmap = DB<HashMap<ChannelId, (Beatmap, Mode)>>;
/// An osu! saved user.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct OsuUser {
pub id: u64,
pub last_update: DateTime<Utc>,
}

View file

@ -1,8 +1,8 @@
use super::BeatmapWithMode;
use crate::commands::args::Duration;
use crate::models::{Beatmap, Mode, Rank, Score, User};
use chrono::Utc;
use serenity::{builder::CreateEmbed, utils::MessageBuilder};
use youmubot_osu::models::{Beatmap, Mode, Rank, Score, User};
use youmubot_prelude::*;
fn format_mode(actual: Mode, original: Mode) -> String {
if actual == original {

View file

@ -1,3 +1,8 @@
use super::OsuClient;
use crate::{
models::{Beatmap, Mode},
request::BeatmapRequestKind,
};
use lazy_static::lazy_static;
use regex::Regex;
use serenity::{
@ -6,10 +11,6 @@ use serenity::{
model::channel::Message,
utils::MessageBuilder,
};
use youmubot_osu::{
models::{Beatmap, Mode},
request::BeatmapRequestKind,
};
use youmubot_prelude::*;
use super::embeds::{beatmap_embed, beatmapset_embed};

View file

@ -1,4 +1,8 @@
use crate::db::{OsuSavedUsers, OsuUser};
use crate::{
models::{Beatmap, Mode, User},
request::{BeatmapRequestKind, UserID},
Client as OsuHttpClient,
};
use serenity::{
framework::standard::{
macros::{command, group},
@ -8,21 +12,59 @@ use serenity::{
utils::MessageBuilder,
};
use std::str::FromStr;
use youmubot_osu::{
models::{Beatmap, Mode, User},
request::{BeatmapRequestKind, UserID},
};
use youmubot_prelude::*;
mod announcer;
mod cache;
mod db;
pub(crate) mod embeds;
mod hook;
pub use announcer::OsuAnnouncer;
use db::OsuUser;
use db::{OsuLastBeatmap, OsuSavedUsers};
use embeds::{beatmap_embed, score_embed, user_embed};
pub use hook::hook;
/// The osu! client.
pub(crate) struct OsuClient;
impl TypeMapKey for OsuClient {
type Value = OsuHttpClient;
}
/// Sets up the osu! command handling section.
///
/// This automatically enables:
/// - Related databases
/// - An announcer system (that will eventually be revamped)
/// - The osu! API client.
///
/// This does NOT automatically enable:
/// - Commands on the "osu" prefix
/// - Hooks. Hooks are completely opt-in.
///
pub fn setup(
path: &std::path::Path,
client: &serenity::client::Client,
data: &mut ShareMap,
) -> CommandResult {
// Databases
OsuSavedUsers::insert_into(&mut *data, &path.join("osu_saved_users.yaml"))?;
OsuLastBeatmap::insert_into(&mut *data, &path.join("last_beatmaps.yaml"))?;
// API client
let http_client = data.get_cloned::<HTTPClient>();
data.insert::<OsuClient>(OsuHttpClient::new(
http_client,
std::env::var("OSU_API_KEY").expect("Please set OSU_API_KEY as osu! api key."),
));
// Announcer
OsuAnnouncer::scan(&client, std::time::Duration::from_secs(300));
Ok(())
}
#[group]
#[prefix = "osu"]
#[description = "osu! related commands."]

View file

@ -1,5 +1,5 @@
pub mod discord;
pub mod models;
pub mod request;
#[cfg(test)]

View file

@ -18,13 +18,6 @@ impl TypeMapKey for HTTPClient {
type Value = reqwest::blocking::Client;
}
/// The osu! client.
// pub(crate) struct OsuClient;
// impl TypeMapKey for OsuClient {
// type Value = OsuHttpClient;
// }
/// The TypeMap trait that allows TypeMaps to quickly get a clonable item.
pub trait GetCloned {
/// Gets an item from the store, cloned.

View file

@ -9,6 +9,5 @@ pub fn setup_prelude(db_path: &Path, data: &mut ShareMap, _: &mut StandardFramew
crate::announcer::AnnouncerChannels::insert_into(data, db_path.join("announcers.yaml"))
.expect("Announcers DB set up");
data.insert::<crate::HTTPClient>(reqwest::blocking::Client::new())
.expect("Should be able to insert");
data.insert::<crate::HTTPClient>(reqwest::blocking::Client::new());
}

View file

@ -14,10 +14,7 @@ chrono = "0.4.9"
rand = "0.7.2"
static_assertions = "1.1.0"
reqwest = "0.10.1"
regex = "1"
lazy_static = "1"
youmubot-osu = { path = "../youmubot-osu" }
rayon = "1.1"
youmubot-db = { path = "../youmubot-db" }
youmubot-prelude = { path = "../youmubot-prelude" }

View file

@ -10,14 +10,10 @@ use youmubot_prelude::*;
pub mod admin;
pub mod community;
pub mod fun;
pub mod osu;
pub use admin::ADMIN_GROUP;
pub use community::COMMUNITY_GROUP;
pub use fun::FUN_GROUP;
pub use osu::OSU_GROUP;
pub use announcer::Announcer;
// A help command
#[help]

View file

@ -1,37 +1,21 @@
use chrono::{DateTime, Utc};
use dotenv::var;
use serde::{Deserialize, Serialize};
use serenity::{
client::Client,
framework::standard::CommandError as Error,
model::id::{ChannelId, RoleId, UserId},
model::id::{RoleId, UserId},
};
use std::collections::HashMap;
use std::path::PathBuf;
use std::path::Path;
use youmubot_db::{GuildMap, DB};
use youmubot_osu::models::{Beatmap, Mode};
use youmubot_prelude::*;
/// A list of SoftBans for all servers.
pub type SoftBans = DB<GuildMap<ServerSoftBans>>;
/// Save the user IDs.
pub type OsuSavedUsers = DB<HashMap<UserId, OsuUser>>;
/// Save each channel's last requested beatmap.
pub type OsuLastBeatmap = DB<HashMap<ChannelId, (Beatmap, Mode)>>;
/// Sets up all databases in the client.
pub fn setup_db(client: &mut Client) -> Result<(), Error> {
let path: PathBuf = var("DBPATH").map(|v| PathBuf::from(v)).unwrap_or_else(|e| {
println!("No DBPATH set up ({:?}), using `/data`", e);
PathBuf::from("data")
});
let mut data = client.data.write();
pub fn setup_db(path: &Path, data: &mut ShareMap) -> Result<(), Error> {
SoftBans::insert_into(&mut *data, &path.join("soft_bans.yaml"))?;
OsuSavedUsers::insert_into(&mut *data, &path.join("osu_saved_users.yaml"))?;
OsuLastBeatmap::insert_into(&mut *data, &path.join("last_beatmaps.yaml"))?;
// AnnouncerChannels::insert_into(&mut *data, &path.join("announcers.yaml"))?;
Ok(())
}
@ -62,10 +46,3 @@ pub struct ImplementedSoftBans {
/// List of all to-unban people.
pub periodical_bans: HashMap<UserId, DateTime<Utc>>,
}
/// An osu! saved user.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct OsuUser {
pub id: u64,
pub last_update: DateTime<Utc>,
}

View file

@ -4,15 +4,13 @@ use serenity::{
framework::standard::{DispatchError, StandardFramework},
model::{channel::Message, gateway},
};
use youmubot_osu::Client as OsuApiClient;
use youmubot_osu::discord::{setup as setup_osu, OSU_GROUP};
use youmubot_prelude::*;
mod commands;
mod db;
use commands::osu::OsuAnnouncer;
const MESSAGE_HOOKS: [fn(&mut Context, &Message) -> (); 1] = [commands::osu::hook];
const MESSAGE_HOOKS: [fn(&mut Context, &Message) -> (); 1] = [youmubot_osu::discord::hook];
struct Handler;
@ -53,26 +51,15 @@ fn main() {
std::path::PathBuf::from("data")
});
youmubot_prelude::setup::setup_prelude(&db_path, &mut data, &mut fw);
}
// Setup initial data
db::setup_db(&mut client).expect("Setup db should succeed");
// Setup shared instances of things
{
let mut data = client.data.write();
let http_client = data.get_cloned::<HTTPClient>();
data.insert::<OsuClient>(OsuApiClient::new(
http_client.clone(),
var("OSU_API_KEY").expect("Please set OSU_API_KEY as osu! api key."),
));
// Setup initial data
db::setup_db(&db_path, &mut data).expect("Setup db should succeed");
// osu!
setup_osu(&db_path, &client, &mut data).expect("osu! is initialized");
}
// Create handler threads
std::thread::spawn(commands::admin::watch_soft_bans(&mut client));
// Announcers
OsuAnnouncer::scan(&client, std::time::Duration::from_secs(300));
println!("Starting...");
if let Err(v) = client.start() {
panic!(v)
@ -150,5 +137,5 @@ fn setup_framework(client: &Client) -> StandardFramework {
.group(&commands::ADMIN_GROUP)
.group(&commands::FUN_GROUP)
.group(&commands::COMMUNITY_GROUP)
.group(&commands::OSU_GROUP)
.group(&OSU_GROUP)
}