News Message

This commit is contained in:
Evann Regnault 2023-07-22 19:18:00 +02:00
parent 4cc3acc737
commit 3c4f45189a
6 changed files with 391 additions and 8 deletions

219
Cargo.lock generated
View file

@ -17,6 +17,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "android-tzdata" name = "android-tzdata"
version = "0.1.1" version = "0.1.1"
@ -92,6 +101,21 @@ version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "bit-set"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -343,6 +367,16 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "futf"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
dependencies = [
"mac",
"new_debug_unreachable",
]
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.28" version = "0.3.28"
@ -487,6 +521,20 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "html5ever"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
dependencies = [
"log",
"mac",
"markup5ever",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.9" version = "0.2.9"
@ -701,6 +749,38 @@ version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]]
name = "mac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "markup5ever"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
dependencies = [
"log",
"phf",
"phf_codegen",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
name = "markup5ever_rcdom"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9521dd6750f8e80ee6c53d65e2e4656d7de37064f3a7a5d2d11d05df93839c2"
dependencies = [
"html5ever",
"markup5ever",
"tendril",
"xml5ever",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.5.0"
@ -770,6 +850,12 @@ dependencies = [
"tempfile", "tempfile",
] ]
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -804,7 +890,9 @@ version = "1.1.3"
dependencies = [ dependencies = [
"levenshtein", "levenshtein",
"poise", "poise",
"regex",
"reqwest", "reqwest",
"select",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
@ -901,6 +989,44 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "phf"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
dependencies = [
"siphasher",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.9" version = "0.2.9"
@ -956,6 +1082,12 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.63" version = "1.0.63"
@ -1015,18 +1147,32 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.8.4" version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
dependencies = [ dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax", "regex-syntax",
] ]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.7.2" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
@ -1211,6 +1357,17 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "select"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f9da09dc3f4dfdb6374cbffff7a2cffcec316874d4429899eefdc97b3b94dcd"
dependencies = [
"bit-set",
"html5ever",
"markup5ever_rcdom",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.164" version = "1.0.164"
@ -1316,6 +1473,12 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.8" version = "0.4.8"
@ -1347,6 +1510,32 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "string_cache"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
dependencies = [
"new_debug_unreachable",
"once_cell",
"parking_lot",
"phf_shared",
"precomputed-hash",
"serde",
]
[[package]]
name = "string_cache_codegen"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
@ -1389,6 +1578,17 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "tendril"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0"
dependencies = [
"futf",
"mac",
"utf-8",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.40" version = "1.0.40"
@ -1954,3 +2154,14 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "xml5ever"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4034e1d05af98b51ad7214527730626f019682d797ba38b51689212118d8e650"
dependencies = [
"log",
"mac",
"markup5ever",
]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "obsessed-yanqing" name = "obsessed-yanqing"
version = "1.1.3" version = "1.2.0"
edition = "2021" edition = "2021"
authors = ["Evann Regnault"] authors = ["Evann Regnault"]
license = "MIT" license = "MIT"
@ -15,3 +15,5 @@ levenshtein = "1.0.5"
reqwest = "0.11.17" reqwest = "0.11.17"
serde = "1.0.160" serde = "1.0.160"
serde_path_to_error = "0.1.11" serde_path_to_error = "0.1.11"
select = "0.6.0"
regex = "1.9.1"

View file

@ -344,7 +344,7 @@ impl CharacterTab {
} }
} }
/// Displays your or another user's account creation date /// Search a character info
#[poise::command(slash_command, prefix_command)] #[poise::command(slash_command, prefix_command)]
pub async fn character( pub async fn character(
ctx: Context<'_>, ctx: Context<'_>,

166
src/commands/events.rs Normal file
View file

@ -0,0 +1,166 @@
use std::cmp::Ordering;
use regex::{Regex};
use select::document::Document;
use select::predicate::{Class, Name, Predicate};
use serenity::builder::CreateEmbed;
use serenity::model::channel::Channel;
use crate::data::{Context, Error};
pub async fn get_main_prydwen() -> String {
reqwest::get("https://www.prydwen.gg/star-rail/").await.expect("Cannot get Prydwen").text().await.expect("Cannot get data")
}
enum EventType {
CharacterBanner,
ConeBanner,
Memory,
Other,
}
struct BannerData {
five_stars: String,
four_stars: Vec<String>
}
struct Event {
name: String,
description: Option<(String, String)>,
time: Option<String>,
image: Option<String>,
banner_data: Option<BannerData>,
event_type: EventType
}
async fn get_events_from_document(doc: String) -> Vec<Event> {
let document = Document::from(doc.as_str());
let event_nodes = document.find(Class("event-tracker")).take(1).next();
let mut events : Vec<Event> = vec![];
if let Some(x) = event_nodes {
for event in x.find(Class("accordion-item")) {
let mut attributes = event.attr("class").expect("").split(' ');
if attributes.clone().count() != 2 {continue;}
let id = attributes.find(|p| !p.to_owned().eq("accordion-item")).expect("Error while getting other id");
let name = event.find(Class("event-name")).next().expect("Cannot find name").text();
let image_regex = Regex::new(r".accordion-item\.idofevent button\{background-color:#[0-9a-f]{6};background-image:url\((/static/.*?\.jpg)\)}".replace("idofevent", id).as_str()).expect("Cannot created REGEX");
let image = image_regex.captures(doc.as_str()).expect("Cannot scan document").get(1).map(|x| format!("https://www.prydwen.gg{}", x.as_str()));
let description = event.find(Class("description")).next().map(|x| {
let text = x.text();
let desc = text.split(": ").collect::<Vec<&str>>();
(desc.first().expect("").to_string(), desc.get(1).expect("").to_string())
});
let time = event.find(Class("time")).next().map(|x| x.text());
let event_type = match &description {
None => {
match event.find(Class("featured-characters")).next() {
None => EventType::ConeBanner,
Some(_) => EventType::CharacterBanner
}
}
Some(desc) => {
match desc.0.as_str() {
"Memory Turbulence" => EventType::Memory,
_ => EventType::Other
}
}
};
let five_stars = event.find(Class("rarity-5").descendant(Name("picture")).descendant(Name("img"))).next().map(|x| x.attr("alt").expect("No alt on five star image").to_string());
let four_stars = event.find(Class("rarity-4")).take(3).map(|four_stars_node| {
four_stars_node.find(Name("picture").descendant(Name("img"))).next().map(|x| x.attr("alt").expect("No alt on four star image").to_string()).expect("")
}).collect::<Vec<String>>();
let banner_data = match five_stars {
None => None,
Some(x) => match four_stars.len() {
3 => Some(BannerData { five_stars: x, four_stars}),
_ => None
}
};
events.push(Event {name, description, time, image, banner_data, event_type })
}
};
events
}
pub async fn create_events_embeds() -> Vec<CreateEmbed> {
let doc = get_main_prydwen().await;
let mut events = get_events_from_document(doc).await;
events.sort_by(|a, b| {
match (&a.event_type,&b.event_type) {
(EventType::CharacterBanner, EventType::ConeBanner) => Ordering::Less,
(EventType::CharacterBanner, EventType::Other) => Ordering::Less,
(EventType::CharacterBanner, EventType::Memory) => Ordering::Less,
(EventType::ConeBanner, EventType::Other) => Ordering::Less,
(EventType::ConeBanner, EventType::Memory) => Ordering::Less,
(EventType::Other, EventType::Memory) => Ordering::Less,
(EventType::Memory, EventType::Other) => Ordering::Greater,
(EventType::Memory, EventType::ConeBanner) => Ordering::Greater,
(EventType::Memory, EventType::CharacterBanner) => Ordering::Greater,
(EventType::Other, EventType::CharacterBanner) => Ordering::Greater,
(EventType::Other, EventType::ConeBanner) => Ordering::Greater,
(EventType::ConeBanner, EventType::CharacterBanner) => Ordering::Greater,
(_, _) => {Ordering::Equal}
}
});
events.into_iter().map(|event| {
let mut default = CreateEmbed::default();
let mut embed = default
.title(event.name);
if let Some(image) = event.image {
embed = embed.image(image);
}
if let Some(time) = event.time {
embed = embed.description(format!("Time remaining : {}", time));
}
if let Some(description) = event.description {
embed = embed.field(description.0, description.1, false);
}
if let Some(banner_infos) = event.banner_data {
embed = embed
.field("5 Stars", format!("- {}",banner_infos.five_stars), false)
.field("4 Stars", format!("- {}", banner_infos.four_stars.join("\n- ")), false);
}
embed.to_owned()
}).collect::<Vec<CreateEmbed>>()
}
/// Create a message that gets updated automatically
#[poise::command(slash_command, prefix_command)]
pub async fn create_event_message(
ctx: Context<'_>,
#[description = "Create Event Tab"] channel: Channel
) -> Result<(), Error> {
let embeds = create_events_embeds().await;
channel.id().send_message(ctx, |f| {
f.set_embeds(embeds)
}).await.unwrap();
let channel_name = channel.id().name(ctx).await.unwrap();
ctx.send(|f| {
f.embed(|e|{
e.title("Success !")
.description(format!("The event message has been created in #{}", channel_name))
}).ephemeral(true)
}).await.expect("TODO: panic message");
Ok(())
}

View file

@ -1 +1,4 @@
pub mod character; pub mod character;
pub mod events;

View file

@ -13,7 +13,8 @@ async fn main() {
.intents(GatewayIntents::non_privileged()) .intents(GatewayIntents::non_privileged())
.options(poise::FrameworkOptions { .options(poise::FrameworkOptions {
commands: vec![ commands: vec![
commands::character::character() commands::character::character(),
commands::events::create_event_message()
], ],
..Default::default() ..Default::default()
}) })