#simple-commits (sujeto a cambios)
1 messages · Page 1 of 1 (latest)
if let Some(scope) = scope {
if let Some(scopes) = &mut config.scopes {
if !scopes.exists(&scope) {
scopes.add_scope(scope);
if let Err(err) = config.update() {
eprintln!("{err}");
}
}
}
}
``` pq esto no me gusta?
dios como me encantaria borrar todo al carajo
y empezar de vuelta
JAWKDNAWJKNDA
pero vamos por partes
primero termino de agregar lo de los scopes
Pero que chucha
Que estas tratando de hacer?
ni idea
o sea
no se de donde lo saque
y por alguna razón no estaría encontrando como es que formateé los textos
wtf
interesante
me voy a clavar un cargo update
listo para romper el proyectop
xd?
:0
jajajajajaj
Un coso para generar el mensaje de cambios
Ok
Ya tienes el cambio de los scopes con descripcion?
Me fui a dormir estaba muy cansado
Joya, tranqui
Ya estaria desplegado uwu
pero
en la proxima release, nos movemos a https://github.com/wadackel/promptuity/
Promptuity is a library that provides interactive prompts. - wadackel/promptuity
Check!
simple-commit
A little CLI written in rust to improve your dirty commits into conventional ones.
Última Version: 1.0.2
Documentación: None
Repositorio: github:romancitodev/simple-commits
Página Web: None
@little horizon features pendientes?
lo del init y lo del -m o --message para automarizar pipelines
lo del body
lo del breaking change
-m pasa a ser -t de --title
porque las especificaciones dicen que el template es de esta forma
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
pero <description> seria el title del commit
y nos quedaria implementar el body
y el footer es lo mismo que el body pero se pueden implementar varios
fix(http): prevent racing of requests
Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.
Remove timeouts which were used to mitigate the racing issue but are
obsolete now.
Reviewed-by: Z
Refs: #123
asi se podria ver
// Load Local
// TODO: make recursive search root path
// The idea is find `.git` folder and use that as root path
if let Ok(cfg_content) = std::fs::read_to_string(&config_path) {
let mut l_config: SimpleCommitsConfig = toml::from_str(&cfg_content).unwrap();
config.merge(&mut l_config);
config.config = config_path;
}
para que carajo era esto @little horizon ?
https://stackoverflow.com/questions/71991935/how-to-make-a-default-subcommand-with-clap-and-derive encontre esto par el tema del init
match args.mode {
Some(Command::Init) => log::debug!("Init subcommand"),
_ => log::debug!("No sub command detected"),
}
te acordas de este error?
bueno, todo se resume en que el autocompleter se encargaba de eso
XDDD
y me estoy fijando exactamente el código que se encarga de parsear la config y parsear los ficheros
y me encuentro con esto...
let config_path = args.config.unwrap_or_else(|| {
let path = BaseDirs::new().unwrap().config_dir().join("sc");
// create directory if not exists
std::fs::create_dir_all(path.clone()).unwrap();
path.join("config.toml")
});
XDDDD
en resumen
es automatico
ya se crea solo
ndkjandkajnk
asi que el init es completamente al pedo
o sea
si pero no
porque si el usuario quiere configurar el archivo antes de ejecutar el comando por primera vez
vamos a tener que separar los pasos
por commands
osea
commands
| init
| some_config.rs
| default
| commit.rs
use std::{env::current_dir, path::PathBuf};
use directories::BaseDirs;
use merge2::Merge;
use super::SimpleCommitsConfig;
pub fn create_config() -> PathBuf {
let path = BaseDirs::new().unwrap().config_dir().join("sc");
let path = path.join("config.toml");
std::fs::create_dir_all(path.clone()).unwrap();
path
}
/// (Global, Local)
type ConfigPaths = (PathBuf, PathBuf);
pub fn get_config(path: Option<PathBuf>, config: &mut SimpleCommitsConfig) -> ConfigPaths {
let global_path = path.unwrap_or(create_config());
if let Ok(content) = std::fs::read_to_string(&global_path) {
let mut global_config: SimpleCommitsConfig = toml::from_str(&content).unwrap();
config.merge(&mut global_config);
}
let local_path = current_dir().expect("Weird error");
if let Ok(content) = std::fs::read_to_string(&local_path) {
let mut local_config: SimpleCommitsConfig = toml::from_str(&content).unwrap();
config.merge(&mut local_config);
}
(global_path, local_path)
}
yep
recien vuelvo de comprar unas cosas
Eso es para que no importa en que carpeta estes, siempre vaya al root del proyecto a buscar el sc.toml
bueno eso despues se implementa como patch
match args.mode {
Some(Command::Init) => {
helpers::create_config();
}
_ => {
let (config_path, local_path) = helpers::get_config(args.config, &mut config);
config.config = local_path;
config.merge(&mut args.sc_config);
}
}
mira que clean que me queda el get_config()
aunque estoy pensando en que deberia retornar un (Option<PathBuf>, PathBuf)
o mejor dicho
al reves
(PathBuf, Option<PathBuf>)
porque siempre va a existir una config global
pero capaz no hay config local
Y ESO ME HIZO ACORDAR
DE QUE EL INIT TE TIENE QUE DEJAR CONFIGURARLO DE MODO GLOBAL O LOCAL
ta joya
pub fn get_config() -> SimpleCommitsConfig {
let mut args = CliConfig::parse();
let mut config = SimpleCommitsConfig::default();
match args.mode {
Some(Command::Init(option)) => {
helpers::create_config(option);
log::trace!("option {option:?}");
}
_ => {
let (global_path, local_path) = helpers::get_config(args.config, &mut config);
if let Some(local_path) = local_path {
config.config = local_path;
} else {
config.config = global_path;
}
config.merge(&mut args.sc_config);
}
}
config
}
asi terminó
use std::{env::current_dir, path::PathBuf};
use directories::BaseDirs;
use merge2::Merge;
use super::{InitOptions, SimpleCommitsConfig};
pub fn create_config(option: InitOptions) -> PathBuf {
match option {
InitOptions::Global => {
let path = BaseDirs::new().unwrap().config_dir().join("sc");
let path = path.join("config.toml");
if !path.exists() {
std::fs::create_dir_all(path.clone()).unwrap();
}
path
}
InitOptions::Local => {
let path = current_dir()
.expect("The current dir must exists")
.join("sc.toml");
if !path.exists() {
std::fs::create_dir_all(path.clone()).unwrap();
}
path
}
}
}
/// (Global, Local)
type ConfigPaths = (PathBuf, Option<PathBuf>);
pub fn get_config(path: Option<PathBuf>, config: &mut SimpleCommitsConfig) -> ConfigPaths {
let global_path = path.unwrap_or(create_config(InitOptions::Global));
if let Ok(content) = std::fs::read_to_string(&global_path) {
let mut global_config: SimpleCommitsConfig = toml::from_str(&content).unwrap();
config.merge(&mut global_config);
}
let local_path = current_dir();
if let Ok(local_path_ok) = &local_path {
if let Ok(content) = std::fs::read_to_string(&local_path_ok) {
let mut local_config: SimpleCommitsConfig = toml::from_str(&content).unwrap();
config.merge(&mut local_config);
}
}
(global_path, local_path.ok())
}
y estos son los helpers
AL TOQUEEE
TERMINE LA FEATURE DEL INIT
SOY FELIZ
Y AHORA ME FUNCIONA DE FORMA GLOBAL
los saqué puramente del scope global
@zenith scarab Cuando saque la release, ya vas a poder usar sc init global | local dependiendo de donde te gustaría configurar los archivos!
asi que nada, capaz te puede interesar
acá está
me falló clippy
ya configure todo para mi helix XD
ok, se rompió
podemos sacar ideas de aca
estaria bueno que por ejemplo haya una flag que sea tipo
sc --predict
o ```
sc --ai
y que todo lo genere la AI
es posible que podamos usar ollama
agregué los proposal que pueden ser interesantes
me voy a dormir
ollama para local está joya, puede ser
Porque el hide?
ai? como seria? que la AI inspecciona tus cambios y propone un commit title basado en esos?
me da que yo podria hacer esa contrib si es asi
https://hub.docker.com/r/ollama/ollama se puede hacer que el servicio despliegue un docker
y saque la IA de ahi
oh bueno, tambien esta eso
Ufffffff
Yo dejaría que eso se configure en la cli o el manifest, porque hay gente que lo tiene en servidores privados o servidores en su casa
Pero gracias por el Docker, eso es mucho más fácil de usar
puede haber un fallback default
como "configure own ollama server" "use default server"
Aaaaa, messirve
@little horizon entonces asigno este proposal a @inner quiver ?
La idea sería que el programa parezca más único haciendo eso
O sea
Que se sienta como una CLI de verdad y que no se vea como por abajo hace en realidad un git commit
Seriamente pienso que si le metemos AI esto puede llegar a explotar en tendencia
lo empezaria a desarrollar el miercoles de la semana que viene
Tranqui, tampoco es algo urgente
Seee, no me da para hacerlo yo
Yo podría intentarlo pero fallaría en el intento
Yo me encargo de terminar lo del body y voy a ver como inferir los issues y demás
Hasta incluso ya dije, me gustaría cambiar un poco la arquitectura del CLI @little horizon
Porque siento que no estamos yendo por el camino correcto, se hace medio tedioso el hecho de crear pasos o como me pasó antes al momento de crear un sub comando
que body?
Sip
La descripción del commit
@little horizon
Y hacer lo del -m (ahora -t) para automatizar pipelines
El state es chiquito pero capaz en vez de hacer que el state tenga acceso a todo el proceso como tal, creo que deberíamos haber una clase CommitBuilder
Que lo único que haga es retornar un Commit(String) cuando se le haga .build()
Y que ese Commit(String) tenga el display para el commit entero
y de esta forma puede llegar a ser más extensible
genial
Me avisas cuando tengas eso
#[derive(Clone, Default, Debug)]
pub struct State {
pub commit: CommitBuilder,
pub action: Action,
}
#[allow(dead_code)]
#[derive(Clone, Debug, Default)]
pub enum Action {
#[default]
None,
DryRun(String),
Commit(String, Vec<String>),
}
``` @little horizon ASI ME GUSTA MAS
impl CommitBuilder {
pub fn set_r(&mut self, r#type: Option<String>) {
self.r#type = r#type;
}
pub fn set_scope(&mut self, scope: Option<String>) {
self.scope = scope;
}
pub fn set_emoji(&mut self, emoji: Option<String>) {
self.emoji = emoji;
}
pub fn set_title(&mut self, title: Option<String>) {
self.title = title;
}
pub fn set_description(&mut self, description: Option<String>) {
self.description = description;
}
pub fn set_footer(&mut self, footer: Option<String>) {
self.footer = footer;
}
pub fn build(self) -> Result<Commit, BuildError> {
let CommitBuilder { r#type, title, .. } = self;
if let None = r#type {
log::error!("Type of commit required");
return Err(BuildError::TypeRequired);
};
if let None = title {
log::error!("Title of the commit required");
return Err(BuildError::TitleRequired);
}
Ok(Commit {
r#type: r#type.unwrap(),
title,
..self
})
}
}
ASI SI ME GUSTAAAAAAAAA
Uuuu, ta joya
Me gustaaaa
banca porque creo que ando cookeando algo mejor
pub fn build(self) -> Result<Commit, BuildError> {
let CommitBuilder {
r#type,
title,
scope,
emoji,
description,
footer,
is_breaking_change,
breaking_change_message,
} = self;
if let None = r#type {
log::error!("Type of commit required");
return Err(BuildError::TypeRequired);
};
if let None = title {
log::error!("Title of the commit required");
return Err(BuildError::TitleRequired);
}
let r#type = r#type.unwrap();
let title = title.unwrap();
let scope = scope.map_or(String::new(), |s| format!(" ({s}) "));
let emoji = emoji.map_or(" ".to_owned(), |e| format!(" {e} "));
let description = description.unwrap_or("\n".to_owned());
let footer = footer.unwrap_or_default();
let exclamation = is_breaking_change.map_or(String::new(), |_| "!".to_owned());
let breaking_change_message =
breaking_change_message.map_or(String::new(), |m| format!("BREAKING CHANGE: {m}"));
let commit = format!(
"{type}{scope}{exclamation}:{emoji}{title}
{description}
{breaking_change_message}
{footer}
"
);
Ok(Commit(String::from(commit)))
}
NO MAN QUE RICO QUE SE VE
al menos el state ahora se redujo bastante y tiene una clase que le corresponde de mejora manera todo
- thanks for use this tool
+ thanks for using this tool
tenes razon
xd
- please report it to
+ please submit an issue at
Report it to no es una falta
Pero se ve mejor submit an issue
pub fn build(self) -> Result<Commit, BuildError> {
let CommitBuilder {
r#type,
title,
scope,
emoji,
description,
footer,
is_breaking_change,
breaking_change_message,
} = self;
if r#type.is_none() {
log::error!("Type of commit required");
return Err(BuildError::TypeRequired);
};
if title.is_none() {
log::error!("Title of the commit required");
return Err(BuildError::TitleRequired);
}
let r#type = r#type.unwrap();
let title = title.unwrap();
let scope = scope.map_or(String::new(), |s| format!("({s})"));
let emoji = emoji.map_or(" ".to_owned(), |e| format!(" {e} "));
let description = description.unwrap_or("\n".to_owned());
let footer = footer.unwrap_or_default();
let exclamation = is_breaking_change.map_or(String::new(), |_| "!".to_owned());
let breaking_change_message = breaking_change_message.map_or(String::new(), |m| {
format!("BREAKING CHANGE: {m}").trim().to_string()
});
let commit = format!(
"{type}{scope}{exclamation}:{emoji}{title}
{description}
{breaking_change_message}
{footer}
"
)
.trim()
.to_string();
Ok(Commit(commit))
}
``` @little horizon
AHORA SI QUE SE VE RICO CHABON
QUE LINDO SE VE MAS CHIQUITO AHORA ESTO LPM
@little horizon ya hice push
no es el gran commit la verdad'
pero al menos acomodé mucho más de lo que había
y di un paso más al refactor en donde se haga más cómodo el tema de los pasos y futuras actualizaciones que se le haga a la tool
lo que tiene de bueno este commit, es que ya está preparado para cuando haga los otros pasos que faltan
Joya, ahora miro
@little horizon se me estuvo ocurriendo algo que puede ser interesante para el trait Step
ahora lo armo
y tambien estuve acomodando archivos
Te quiero matar porque es algo que te dije al inicio 😠
pq no me gustaba como estaba acomoado
bueno flaco, quien queria la primera release?
Ta bien, lo acepto
struct App<T: Step> {
steps: Vec<T>
}
trait Step {
fn before_run(&self, ctx: Context) -> StepResult {};
fn on_run(&self, ctx: Context) -> StepResult;
fn after_run(&self, ctx: Context) -> StepResult {};
}
o sea
por ahi va la mano
nos sacamos el macro gen_steps de encima pq no ayuda en nada
y el trait Step se vuelve extremadamente extensible
y en el Context podriamos ponerle diferentes cosas
pub trait Step {
fn run(
&self,
prompt: &mut Promptuity<Stderr>,
state: &mut State,
config: &mut SimpleCommitsConfig,
) -> StepResult;
}
``` pq esto no me gusta en lo absoluto
No queda tan feo, si es mejor un contexto, pero es más complicado tratarlo
@little horizon, retomando la idea de ayer, sería mucho más tedioso si hago esto?
type StepResult = Result<Context, promptuity::Error>;
trait Step {
fn before_run(&self, ctx: Context) -> StepResult {};
fn on_run(&self, ctx: Context) -> StepResult;
fn after_run(&self, ctx: Context) -> StepResult {};
}
?
o sea
en vez de tener una &mut y todo lo que eso conlleva, intentar retornar el objeto directamente
Nop, no creo
Porque lo que podes hacer es que la funcion build de Context ya devuelva un result y asi no te queda feo el Step
como asi?
no entendi
@little horizon cuando puedas explicame esto
porq no lo entendi
ademas, hay un pequeño problemita
pq las estructuras internas del Context requieren de mutabilidad
claro pero
tipo
o sea
te entendi esa parte
porque asi funciona el CommitBuilder
como
Mutex no porfa
ya se
buenos días sergio
em, todavía no lo implementé pero era porque quería asegurarme de que me saliera el tema del context
joya, si necesitas ayuda me avisas
dale, posiblemente la necesite pero sigo investigando como recorcholis hacer un ctx EN DONDE PUEDA TENER 2 VARIABLES MUTABLES
https://rust-unofficial.github.io/patterns/patterns/structural/compose-structs.html esto capaz me pueda servir idk
A catalogue of Rust design patterns, anti-patterns and idioms
creo que voy a hacer que el Context tenga la siguiente estructura
pub struct Context<'ctx> {
pub prompt: Arc<Mutex<Promptuity<'ctx, Stderr>>>,
pub config: Arc<Mutex<SimpleCommitsConfig>>,
pub appdata: Arc<Mutex<AppData>>
}
y a la mierda todo
como me encanta buggear las cosas
usage of an Arc that is not Send and Sync
Arc<Mutex<Promptuity<'_, Stderr>>> is not Send and Sync as Mutex<Promptuity<'_, Stderr>> is neither Send nor Sync
if the Arc will not used be across threads replace it with an Rc
otherwise make Mutex<Promptuity<'_, Stderr>> Send and Sync or consider a wrapper type such as Mutex
for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync
#[warn(clippy::arc_with_non_send_sync)] on by default
A collection of lints to catch common mistakes and improve your Rust code.
lmao que pingo hice

No necesitas el Arc porque no usas multi hilo ni nada de eso
solo me queria ver mas senior
perdon
aunque ya tengo la clave
voy a hacer lo siguiente
Tenes estos cambios publicados?
no
efe
tengo los del principio
o sea
en los que todo esta ok
y funciona todo
con una mini refactorización
sobre las structs nomas
pero tengo una idea
mira
okeeey
a ver
struct Manager<S: CtxStep> {
prompt: P,
steps: Vec<Box<S>>,
ctx: Context
}
impl Manager {
pub fn with_step(&mut self, step) {
self.steps.push(step);
}
pub fn init(&mut self) {
for step in &self.steps {
step.run_with_ctx(&mut self.prompt, Context::from(&self.ctx))
}
}
}
idk
el problema es que
si necesito usar en este mismo ctx, una ref mutable del State y del SimpleCommitConfig
caigo en lo mismo
asi que voy a tener que vivir con el trait Step que teniamos desde un principio XD
pero
con la diff
Subí lo que tenés y le doy una revisada, me parece que estás sobreingenierizando
Con el que pasaste antes?
acabo de revertir todo XD
obvio
o sea
el Step va a pasar a tener todo lo que tenia el CtxStep
La idea del trair me gusta
lo unico que no me gusta del trait es eso
impl Step for _Step {
fn run(
&self,
p: &mut promptuity::Promptuity<std::io::Stderr>,
state: &mut crate::tui::State,
config: &mut SimpleCommitsConfig,
) -> StepResult {
esto mismo
que te obliga a tener 3 parametros tipados
lo que podria hacer
es abstraer los tipos
El problema?
idk
Ajá, podes hacer
trait Step {
type Prompt;
}
El resto si son tipos estáticos y eso que el prompt me parece que también es estático
🤔
esto me va a dar mas dolores de cabeza
mas que nada cuando necesite tipar el Vec
XD
mejor lo dejo todo como está
pusheo lo que necesito y fue
Jajajaja, metele
los pub(super) creo que no son necesarios
En general me gusta la PR
sip
@inner quiver cuando podrás empezar con lo de la IA?
la verdad no creo que pronto, mejor si la podeis asignar a otro
por que ando con menos tiempo de lo que pensaba
@little horizon estoy trabajando en un custom component que es literalmente un input pero estilo multi-line
que me está dando un dolor de cabeza terrible
y siento la lobotomía acercarse
pero bueno
Jajajajajaja
@supple turtle mira 👀
pucha
tengo que ver pq pasa
pero no tengo tiempo ultimamente
si lo podes testear vos cuando quieras...
dale dale
Ni vi el código pero así a ciegas tiene pinta de que le sobre la barra final
O al menos cosas así me pasaron alguna vez
Ya tiene una versión publicada
Y yo uso la versión de la rama principal
Está gooood
Nop, lo más probable es que estemos manejando mal el path
Tengo que revisar eso
Ya que Román anda sin tocar código 😔
yo ando demasiado ocupado estos días
literal
Después de usarlo un poco me pasaron un par de cosas
En la template del readme pone skip_emoji, me tiraba un panic y lo cambié por skip_emojis
Imagino que habrá cambiado en una actualización y es cambiarlo ahí también solamente
Y la primera vez que lo he ejecutado lo he hecho sin hacer el archivo de config, me preguntaba tipo de commit y luego me decía que tenía que hacer el archivo
Creo que sería un poco más amigable si tirara ese error primero
Cierto
Anotado, muchas gracias por tu colaboración y por usar la herramienta!
Te pediría (si queres) que armes la issue en github únicamente para que el repo tenga movimiento nomas
Pero igualmente ya está acá dicho y te leí
También es verdad
Ahora voy
A ti por hacerla
Muy chuli
He escrito un poco más casi que por no poner un issue de 2 líneas sinceramente
Muchas gracias
entro hilo
@little horizon recuerda que hice un cambio PR de simple-commits?
pues hubo un poblema
el otro dia funcionaba bien
pero despues yo actualize rust como 1.79
y volvi a probar otra vez nix profile install github:romancitodev/simple-commits
y me dieron errores
creo que no deberia
es esto
toca cambiarlo para que no repita eso
vere que puedo ahcer eso
el hash imagino
si, ya lo cambie para evitar eso
Cada vez que actualiza rustc o cargo se genera a un nuevo hash y te pide que cambies el hash manualmente.
no deberia eso
pero ya hice
diferente
podria mirar mi PR
y quiero que pruebe
si funciona o no
Puedes fijar una version, o no usar un toolchain file
ya subi a PR
que no debia eso
asi que lo cambie para evitar mas errores y manualmente hash
un amigo probo ese simple-commit recibio un error por el hash
antes estaba bien con ese simple me funcionaba bien hasta que actualice rustc o cargo recibi un error
el otro dia pense que era un hash, cambie el hash manualemnte y subi a pr pero volvio un error que probo de mi amigo
asi que decidi
para evitar mas errores
para lo que sepa mi amigo no usa rustc o cargo aun si recibe un error
ahora acepto la PR
👌🏻
@little horizon te hago una pregunta
me podrías recordar pq estamos usando promptuity?
pq estoy viendo que cliclack ya tiene las cosas que me gustaría tener
solo una
ni idea
tema tuyo creo
no afecta en los componentes que ya tenes?
si pero no
pq incluso es más facil la arquitectura
q se maneja con funciones internas ya
oooh, genial
pues nose, si gustas cambialo
dale, cuando tenga tiempo y ganas uwu
facilito @little horizon
ez
voy a ver si puedo aportar al código de la librería
has podido solucionar con el pinnetry-curses? pero bueno no se porque cerraste mi issues XD
YO, todavia sigo con el poblema usando pinnetry-curses
pinnetry curses?
que es eso?
una contraseña de gpg pero con una interfaz
para github
y gitlab
osea un permiso mi firmas
además la cerré como not planned o Won'tfix

@supple turtle tu coso no jala 0/5
Desde la rama main no jala
Tengo que revertir los commits
O
Tengo que pushear el rewrite entero
Que tengo hecho
el que hizo descargo cargo install --git <turepos>
y asi se ve esa foto
mejor romandev
cambialo los nombres de branch
para evitar mas errores
main -> Stable
dev (para desarrollar)
stable y dev en la branch
eso deberia servir eso
para que tu pueda desarrollar en dev
sin tocar stable
Main no es estable ni a palo JAJAAJAJ
Te voy a ser sincero, no me esperaba que nadie lo instale del main
Y la verdad tengo otras cosas que arreglar
por eso XDDD hay que evitarlo eso
tiene que cambiarlo las branch para que las personas/clientes instale stable no el main
XD
porque esa gente piensa que ese main jala bien XD
pero ellos no entiendes tus branch
Eso es mentira, es un estandard tener una rama main
Es como decir "voy a usar el metodo STEAL en http, ellos no entienden mis métodos"
Si pones releases nadie deberia, pero eso se debe especificar.
Otra mentira.
🤨
Para instalar son las releases, si quieres build propio clon a main y ya
si viniste decirme otra tonteria
si no lo entiende
no venga
Si sabes configurar proyectos buildear no debe costar nada.
na
tome la decision de que no voy a hacer eso
a bueno dale capy
hacer
ah vale :]
y no me corrigas cuando hablo pq se te entiende la mitad de las cosas y no te corrijo
salu2
.t :]
.t 🥳
@zenith scarab
Lo estaba revisando
Pero estaba todo bien