diff --git a/Cargo.lock b/Cargo.lock index dc44b9f..2deca46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2013,7 +2013,7 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "payphone" -version = "4.4.31" +version = "4.4.32" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 516777b..7f51cfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "payphone" -version = "4.4.31" +version = "4.4.32" edition = "2024" default-run = "payphone" diff --git a/src/framework/bot.rs b/src/framework/bot.rs index 948165f..bf32e69 100644 --- a/src/framework/bot.rs +++ b/src/framework/bot.rs @@ -334,6 +334,8 @@ where .resource_types(resource_types) .build(); + let (gateway_tx, mut gateway_rx) = tokio::sync::mpsc::unbounded_channel(); + let runtime = Arc::new(Runtime { http, app, @@ -342,6 +344,9 @@ where prefixes: bot.prefixes.clone(), commands: bot.commands.clone(), cache, + gateway_tx, + shard_number: bot.shard.number(), + shard_total: bot.shard.total(), }); for task in bot.tasks.clone() { @@ -372,120 +377,125 @@ where let mut gateway = Shard::with_config(bot.shard, config); loop { - if let Some(Ok(event)) = gateway.next_event(EventTypeFlags::all()).await { - let task_rt = runtime.clone(); - let task_bot = bot.clone(); + tokio::select! { + Some(Ok(event)) = gateway.next_event(EventTypeFlags::all()) => { + let task_rt = runtime.clone(); + let task_bot = bot.clone(); - tokio::spawn(async move { - task_rt.cache.update(&event); + tokio::spawn(async move { + task_rt.cache.update(&event); - match event { - Event::Ready(event) => { - for handler in &task_bot.on_ready_handlers { - handler - .on_ready(&event, task_rt.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on ready for {handler:?}! {e:?}") - ) - .bye(); + match event { + Event::Ready(event) => { + for handler in &task_bot.on_ready_handlers { + handler + .on_ready(&event, task_rt.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on ready for {handler:?}! {e:?}") + ) + .bye(); + } } - } - Event::GatewayReconnect => { - for handler in &task_bot.on_reconnect_handlers { - handler - .on_reconnect(task_rt.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on reconnect for {handler:?}! {e:?}") - ) - .bye(); + Event::GatewayReconnect => { + for handler in &task_bot.on_reconnect_handlers { + handler + .on_reconnect(task_rt.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on reconnect for {handler:?}! {e:?}") + ) + .bye(); + } } - } - Event::InteractionCreate(interaction) => { - for handler in &task_bot.on_interaction_handlers { - handler - .on_interaction(&interaction, task_rt.clone(), task_bot.extras.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on interaction for {handler:?}! {e:?}") - ) - .bye(); + Event::InteractionCreate(interaction) => { + for handler in &task_bot.on_interaction_handlers { + handler + .on_interaction(&interaction, task_rt.clone(), task_bot.extras.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on interaction for {handler:?}! {e:?}") + ) + .bye(); + } } - } - Event::MessageCreate(message) => { - for handler in &task_bot.on_message_handlers { - log::trace!("Running {handler:?}"); + Event::MessageCreate(message) => { + for handler in &task_bot.on_message_handlers { + log::trace!("Running {handler:?}"); - handler - .on_message(&message, task_rt.clone(), task_bot.extras.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on message for {handler:?}! {e:?}") - ) - .bye(); + handler + .on_message(&message, task_rt.clone(), task_bot.extras.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on message for {handler:?}! {e:?}") + ) + .bye(); + } + } + Event::MessageUpdate(message) => { + for handler in &task_bot.on_message_edit_handlers { + handler + .on_message_edit(&message, task_rt.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on message edit for {handler:?}! {e:?}") + ) + .bye(); + } + } + Event::MessageDelete(message) => { + for handler in &task_bot.on_message_delete_handlers { + handler + .on_message_delete(&message, task_rt.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on message delete for {handler:?}! {e:?}") + ) + .bye(); + } + } + Event::GuildCreate(guild) => { + for handler in &task_bot.on_server_create_handlers { + handler + .on_server_create(&guild, task_rt.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on server create for {handler:?}! {e:?}") + ) + .bye(); + } + } + Event::GuildUpdate(guild) => { + for handler in &task_bot.on_server_update_handlers { + handler + .on_server_update(&guild, task_rt.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on server update for {handler:?}! {e:?}") + ) + .bye(); + } + } + Event::GuildDelete(guild) => { + for handler in &task_bot.on_server_delete_handlers { + handler + .on_server_delete(&guild, task_rt.clone()) + .await + .inspect_err( + |e| log::error!("An error occurred while handling on server delete for {handler:?}! {e:?}") + ) + .bye(); + } + } + _ => { + log::trace!("Unhandled event {:?} received", event.kind()); } } - Event::MessageUpdate(message) => { - for handler in &task_bot.on_message_edit_handlers { - handler - .on_message_edit(&message, task_rt.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on message edit for {handler:?}! {e:?}") - ) - .bye(); - } - } - Event::MessageDelete(message) => { - for handler in &task_bot.on_message_delete_handlers { - handler - .on_message_delete(&message, task_rt.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on message delete for {handler:?}! {e:?}") - ) - .bye(); - } - } - Event::GuildCreate(guild) => { - for handler in &task_bot.on_server_create_handlers { - handler - .on_server_create(&guild, task_rt.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on server create for {handler:?}! {e:?}") - ) - .bye(); - } - } - Event::GuildUpdate(guild) => { - for handler in &task_bot.on_server_update_handlers { - handler - .on_server_update(&guild, task_rt.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on server update for {handler:?}! {e:?}") - ) - .bye(); - } - } - Event::GuildDelete(guild) => { - for handler in &task_bot.on_server_delete_handlers { - handler - .on_server_delete(&guild, task_rt.clone()) - .await - .inspect_err( - |e| log::error!("An error occurred while handling on server delete for {handler:?}! {e:?}") - ) - .bye(); - } - } - _ => { - log::trace!("Unhandled event {:?} received", event.kind()); - } - } - }); + }); + } + Some(json) = gateway_rx.recv() => { + gateway.send(json) + } } } } diff --git a/src/framework/runtime.rs b/src/framework/runtime.rs index 212f7a4..57727eb 100644 --- a/src/framework/runtime.rs +++ b/src/framework/runtime.rs @@ -19,6 +19,7 @@ use std::sync::Arc; +use tokio::sync::mpsc::UnboundedSender; use twilight_cache_inmemory::InMemoryCache; use twilight_http::Client; use twilight_model::oauth::Application; @@ -48,6 +49,12 @@ pub struct Runtime { pub state: Arc, pub cache: InMemoryCache, + + /// Used to send messages through the gateway. + pub gateway_tx: UnboundedSender, + + pub shard_number: u32, + pub shard_total: u32, } impl Runtime { diff --git a/src/groups/about/mod.rs b/src/groups/about/mod.rs index 8d675fb..5ac75f9 100644 --- a/src/groups/about/mod.rs +++ b/src/groups/about/mod.rs @@ -1,3 +1,4 @@ pub mod commands; pub mod components; pub mod embeds; +pub mod tasks; diff --git a/src/groups/about/tasks.rs b/src/groups/about/tasks.rs new file mode 100644 index 0000000..1e41485 --- /dev/null +++ b/src/groups/about/tasks.rs @@ -0,0 +1,262 @@ +use async_trait::async_trait; +use rand::{Rng, SeedableRng}; +use rand_chacha::ChaCha20Rng; +use twilight_model::gateway::{ + payload::outgoing::update_presence::UpdatePresencePayload, + presence::{Activity, ActivityType, Status}, +}; + +use crate::{ + extras::Extras, + framework::{runtime::Runtime, tasks::Task}, + state::State, +}; + +#[derive(Debug)] +pub struct UpdatePresenceTask; + +#[async_trait] +impl Task for UpdatePresenceTask { + fn delay(&self) -> std::time::Duration { + std::time::Duration::from_secs(120) + } + + async fn run(&self, rt: &Runtime) -> anyhow::Result<()> { + let presences = vec![ + "Billie Jean is not my lover", + "Baby vamo' a buscar una excusa para vernos", + "Vi que estaba sola y que queria bellaquear", + "Esto es real gangsta love", + "Dice que está acompañada, pero sé que en el fondo ella se encuentra sola", + "Conmigo todo eso ignora, bailando se van las horas", + "Me dice 'I wanna know you more', pero no logro entenderte", + "Tiene una amiga que le traduce, ella sola se lo introduce", + "Y aunque intentara olvidarte, mi boca no lo haría", + "Qué más da si besarte es tan fácil", + "Quería olvidarte, no lo logré, pero casi", + "Tú no me dejas en paz, de mi mente no te vas", + "No me busque' en Instagram, mami, búscame en casa", + "Dime dónde tú está', que yo por ti cojo un vuelo, y a Yonaguni le llego", + "Masivo, we run the world (da-ddy)", + "Vamos cógele el ritmo, cintura, rodilla al piso", + "Oh-eh-oh, mano arriba, no la dejes caer", + "Y esto está como, como pa, como pa, como pa rumbiar, pa pasarla caliente, con toda mi gente", + "Nos favorece el sol, tu bronceado y el calor", + "Porque hoy hace caloooor, hace un re caloooor", + "Tan bonita como tu, tan bonita y sola", + "Te he visto antes, te pareces al amor de mi vida", + "Tú está' como pa' mete-, pa' meterte el cora'", + "Whine up, whine up, whine up, mami baila, baila-a", + "Esto es pa que baile'-e'-e', mueve la cintura y dale pa'l suelo", + "Para todo' eso' amore que, que fueron obligados a ser separados", + "Dime ¿Cómo le explico a mi destino que ya no estás ahí?", + "Eres la niña de mis ojos, tú, eres todo lo que quiero yo", + "Las tentacione' así como tú merecen pecado' como yo", + "Ay, tienes la magia, tú sí tienes una vainita que a mí me encanta, me enloquece", + "Ay tú no me dices que sí, que sí que sí que sí", + "Si tú me dices ahorita que me quieres a tu la'o que lindo sería", + "La gente me dice que ya es muy obvio que ya se me nota", + "Si tú supieras que por ti me muero, que yo te quiero", + "Si tú supieras lo que te esperado, que yo te amo", + "Y me dijeron que te vieron sola ¿Por qué estás sola?", + "Ella está recién soltera, de hace poquito", + "El pelo se lo suelta, el vestido cortito", + "Si yo no te escribo, tú no me escribe'", + "Negra, rara vez te vi bien tando con aquel", + "Te estoy viendo de hace un tiempo, 'toy esperando el momento, ma', no paro de pensarte, ¿qué le voy a hacer?", + "Antes que te vayas dame un beso", + "C'mon (Oh oh oh oh oh oh), Daddy (Oh oh oh oh oh oh)", + "Y el día está soleao, te quiero de mi lao", + "Baby, te vo'a dar una vuelta por la playita", + "Aquella noche que volviste, llorando me convenciste", + "Malo, malo, pero malo", + "Goin' deep in with me for no reason", + "It ain't no problem, it's cool to do it in the night", + "You give me your love, but it's borrowed", + "Y no colme la paciencia si no quieres tu demencia", + "Tengo su criptonita, y para sus mujeres les tengo una vitamina", + "Sólo somos tú y yo", + "Llegó el tiempo de los dos", + "De verdad tienes lo que me gusta a mí", + "Al ritmo y al movimiento, le ponemos sentimiento", + "Tú eres hielo, yo soy fuego, vamo' a ver quién se va a quemar", + "Bailando así pidiendo más y más calor", + "Rumba pa' que tú abuses, BUM!", + "Nueva temporada ya empezó, dale play", + "Sonido del bajo, Bizarrap, suena el bass", + "Si me preguntan, a nadie yo le debo", + "Ahora estoy buscando algo más, una razón para volverme a enamorar (puede que seas tú)", + "Quiero una chica, quiero una gyal", + "Que-que-que no diga que no, que no, que no, que no, que no, que", + "Me monté en un barco, he cruzado el mar, he subido el río", + "Le digo hola, ella me dice goodbye", + "Si yo le salgo por la izquierda, se va pa' la derecha", + "No se lo que le pasa, conmigo ella no quiere bailar", + "Yo quería decirle que me encanta", + "Una varita diseño su cuerpo", + "Y la verdad, si está mas buena, explota", + "Baby yo llevo tiempo deseandote aquí", + "Tiraré la casa por la ventana", + "Y no te importa cuantos caigan por error", + "Presiento que tu siempre vas y vienes", + "Presiento que serás de esos errores que estoy dispuesto a cometer", + "Podré vivir sin escuchar tu voz", + "Bebé, me enteré que con ella peleaste", + "Y a estas alturas no importa si estás con él", + "La luna llena alumbrandote", + "Cuando te vi, supe que iba a pasar", + "Que me gustas mucho con bastante", + "En la radio, tu song favorito", + "Como mango y limón, saborearte", + "Tú eres la dulce fruta que mi paladar añora", + "Esa cara de ternura sé que esconde una atrevida", + "Teresa es una asesina, que cuando camina la ven y dicen oooh", + "Y no le importa si el novio le corta, se corta una botella y se va para el club", + "Essa novinha é terrorista, é especialista", + "Olha o que ela faz num baile funk com as amiga", + "Cara de doncella, pero mas bestia que bella", + "Si me avisa en cinco estoy, porque sabe como soy", + "Su gato no le da, entonces me llama y voy", + "Se te nota que quieres de mi boca", + "Si hay rumba no quiero mas na'", + "Yo lo que vine es a pasarla bien", + "Ella no e' tuya, te vendió sueño, ey, dice que no tiene dueño", + "Te está haciendo lucir mal, manito; yo que tú, ruedo", + "Los besos no se dan, se roban", + "Yo tengo tu amor, I got your love", + "Como ríe la vida si tus ojos negros me quieren mirar", + "El día que me quieras la rosa que engalana se vestirá de fiesta con su mejor color", + "Luciérnagas curiosas que verán que eres mi consuelo", + "DANZA KUDUROOOOOO", + "La mano arriba, cintura sola, da media vuelta, danza kuduro", + "¿Quién puede domar la fuerza del mal que se mete por tus vena'?", + "¿Quién puede parar eso que al bailar descontrola tu cadera?", + "Hey DJ, póngale la música que le gusta", + "Y cómo hago con mi mente pa' decirle que los momentos que tuvimos se quedan en la nada", + "No necesito quejas, sino contención", + "Cómo hago pa' mentirme diciéndome que no quiero verte aunque extrañe tu cara", + "Y no puedo sacarte de mi mente, y no quiero hablar con otra gente", + "Y si tengo que escoger, me quedo, me quedo contigo", + "Y si yo vuelvo a San Juan, yo bailo, yo bailo contigo", + "Y si te tengo que olvidar, tú sabe' que no va a pasar", + "Contigo desde Alaska hasta Buenos Aires", + "There on the subway, I nearly had a breakdown", + "Tú no fuiste la primera, tampoco serás la última", + "He giving me that good shit, that make me not quit", + "Oh, he give it to me everyday, everyday, everyday", + "You just want attention, you don't want my heart", + "Maybe you just hate the thought of me with someone new", + "Y la vi, que va a ser, una hermosa lucifer", + "Y es que este amor es azul como el mar azul", + "Como de tu mirada nació mi ilusión", + "Fue una mañana que yo te encontré, cuando la brisa besaba tu dulce piel", + "Tus ojos tristes que al ver adoré, la noche que yo te amé, azul", + "Hoy miro al cielo y en ti puedo ver, la estrella que siempre soñé (azul)", + "Eres la niña que siempre busqué, azul", + "Es tu inocencia que quiero entender", + "Y con la lluvia pintada de azul, por siempre serás solo tú", + "Azul como el lucero de nuestra pasión", + "I heard the music through the walls", + "I felt you here before I even saw your face", + "Though we can't get higher", + "But we keep going up, going up, going up, going up, going up", + "They could describe everything with one single word", + "Eres lo primero que yo pienso cuando alguien me dice 'pide un deseo'", + "Tengamos algo sin mentiras", + "Y ya sé que estás aburrida de promesas incumplidas", + "Quiero que tu seas mi princesa", + "I wanna let my hair down while I'm staring down your face", + "Que lindo que te queda ese look bronceado", + "Si tú me bailas así yo me muero de amor", + "Boy, don't make me choose", + "We can share one seat", + "I think you wanna uh", + "I think you know what this is", + "Pretty blue streetlights", + "In a room full of people I look at you", + "Somos dos desconocidos que se quieren conocer muy bien", + "Frequentemos nuestros cuerpos para ver que tal nos va", + "Nena, yo quiero con usted ser caballero", + "Deja que pase, pues que pase, lo que tenga que pasar", + "Todo casual, nada ideal, medio eventual, casi ilegal", + "Mami, long time sin saber de ti", + "Un brindis, vasitos arriba, y tú te pones loquita, mamita", + "Estoy ansioso por estar solos tú y yo", + "Good girl, I know you want it", + "I know you want it, you're a good girl (oh yeah)", + "Baby, it's in your nature (meow)", + "The way you grab me, must wanna get nasty", + "What do they make dreams for?", + "Ella sale por deporte, por la' noches", + "Sé muy dentro que yo sin ti estoy mejor", + "Oye, escucha lo que tengo que decir", + "Que sea así nomá y en no má' de seis tomas", + "Ya no me seduce la que se produce toda", + "Creo que me aburre lo que hoy produce la moda", + "Tu sonrisa rota me trastorna todavía", + "Vuelvo por necesidad de algo real y recíproco", + "Yo lo sentí en un segundo, me enamoré de primero", + "Tú te quedaste callada, y yo te dije te quiero", + "Imaginando de esos besos tuyos, porque no tengo de esos besos tuyos", + "Y mientras me enamoraba dijiste que había un tercero", + "Y aunque sé bien que si no hay otra voy a buscarte en otra boca", + "Como te extraño nena, no sabés", + "Me siento fuerte y débil a la vez", + "Quizá eso sea el amor", + "Dímelo si el cabrón no vale la pena y lo borramos de la escena", + "Confiesalo", + "Seeing you tonight, it's a bad idea, right?", + "You know what would be really fucking cool on this? Sabrina", + "She was covered in leather and gold", + "Little Miss Perfect sitting at the train stop", + "She's, somewhere, somewhere, somewhere in Brooklyn", + "Before I got her name, along came a train", + "Next stop, Brooklyn", + "Y si te invito a una copa, y me acerco a tu boca", + "Y si te robo un besito, a ver, ¿te enojas conmigo?", + "Una aventura es más divertida si huele a peligro", + "That's when the taxi man turned on the radio and a Jay-Z song was on", + "I'm nodding my head like, yeah, moving my hips like, yeah", + "Yeah, it's a party in the U.S.A.", + "Just shoot for the stars if it feels right", + "And aim for my heart if you feel like it", + "You say I'm a kid, my ego is big, I don't give a shit", + "Cuando se apaga la luz", + "Annie, are you ok?", + "Will you tell us that you're ok?", + ]; + + let mut rng = ChaCha20Rng::from_os_rng(); + let index = rng.random_range(0..presences.len()); + + rt.gateway_tx + .send(serde_json::to_string(&UpdatePresencePayload::new( + vec![Activity { + application_id: None, + assets: None, + buttons: vec![], + created_at: None, + details: None, + emoji: None, + flags: None, + id: None, + instance: None, + kind: ActivityType::Listening, + name: format!( + "p.help - '{}' - {}/{}", + presences[index], rt.shard_number, rt.shard_total + ), + party: None, + secrets: None, + state: None, + timestamps: None, + url: None, + }], + false, + None, + Status::Online, + )?)?)?; + + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index c53e4f6..bc98053 100644 --- a/src/main.rs +++ b/src/main.rs @@ -138,7 +138,7 @@ use crate::{ groups::{ about::{ commands::{HelpCommand, TetoCommand}, - components::HelpGoBackButton, + components::HelpGoBackButton, tasks::UpdatePresenceTask, }, calls::{ commands::{ @@ -192,7 +192,7 @@ pub async fn main() { shard, redis_urls, bot_owner_id, - topgg_token + topgg_token, } => { start( token, @@ -202,7 +202,7 @@ pub async fn main() { shard.into(), redis_urls, bot_owner_id, - topgg_token + topgg_token, ) .await; } @@ -325,32 +325,7 @@ async fn start( .on_server_create(ServerCreateHandler) .on_server_update(ServerUpdateHandler) .on_server_delete(ServerDeleteHandler) - .presence( - UpdatePresencePayload::new( - vec![Activity { - application_id: None, - assets: None, - buttons: vec![], - created_at: None, - details: None, - emoji: None, - flags: None, - id: None, - instance: None, - kind: ActivityType::Listening, - name: format!("p.help - {}/{}", shard.number() + 1, shard.total()), - party: None, - secrets: None, - state: None, - timestamps: None, - url: None, - }], - false, - None, - Status::Online, - ) - .expect("Could not set bot presence since the parameters passed were invalid"), - ); + .task(UpdatePresenceTask); if let Some(topgg_token) = topgg_token { bot = bot.topgg_token(topgg_token);