From 154efce2b91c0702a76a1ca776dc4ff66b2d6d91 Mon Sep 17 00:00:00 2001 From: metalalchemist <37036927+metalalchemist@users.noreply.github.com> Date: Mon, 2 May 2022 02:12:24 -0700 Subject: [PATCH] corregidos muchos bugs menores --- VeTube.py | 116 +++++++++++++++++++++++-------------------- changelog.txt | 16 ++++++ doc/es/readme.md | 33 ++++++++---- sounds/abrirchat.mp3 | Bin 0 -> 12141 bytes sounds/msj.mp3 | Bin 0 -> 1462 bytes sounds/orilla.mp3 | Bin 0 -> 6896 bytes 6 files changed, 99 insertions(+), 66 deletions(-) create mode 100644 changelog.txt create mode 100644 sounds/abrirchat.mp3 create mode 100644 sounds/msj.mp3 create mode 100644 sounds/orilla.mp3 diff --git a/VeTube.py b/VeTube.py index 7052435..775e7a0 100644 --- a/VeTube.py +++ b/VeTube.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: -*- -import pytchat, json,wx,threading,keyboard,time,gettext,webbrowser +import pytchat, json,wx,threading,keyboard,gettext,webbrowser,urllib.request from playsound import playsound from os import path from accessible_output2.outputs import auto, sapi5 @@ -18,18 +18,20 @@ sapy=True todos=True sonidos=True +version=1.2 idiomas = [] miembros=[] +favoritos=[] leer=sapi5.SAPI5() lector=auto.Auto() lista=leer.list_voices() t = gettext.translation('VeTube', 'locales',fallback=True,) _ = t.gettext def asignarBuffer(): - if mensajes==0 : buffer=100 - elif mensajes==1 : buffer=300 - elif mensajes==2 : buffer=500 - elif mensajes==3 : buffer=1000 + if mensajes==0 : buffer=100 + elif mensajes==1 : buffer=300 + elif mensajes==2 : buffer=500 + elif mensajes==3 : buffer=1000 def asignarConfiguracion(): global voz,tono,volume,speed,configchat,sapy,mensajes,sonidos,buffer voz=0 @@ -81,13 +83,14 @@ def __init__(self, *args, **kwds): self.contarmiembros=0 self.contador=0 self.dentro=False + self.msg="" self.hilo1 = threading.Thread(target=self.capturarTeclas) self.hilo1.daemon = True self.hilo1.start() kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) self.donar = wx.Dialog(self, wx.ID_ANY, _("información")) - dlg = wx.MessageDialog(self.donar, _(u"Con tu apoyo contribuyes a que este programa siga siendo gratuito. ¿Te unes a nuestra causa?"), _(u"Atención:"), wx.YES_NO | wx.ICON_ASTERISK) + dlg = wx.MessageDialog(self.donar, _("Con tu apoyo contribuyes a que este programa siga siendo gratuito. ¿Te unes a nuestra causa?"), _(u"Atención:"), wx.YES_NO | wx.ICON_ASTERISK) dlg.SetYesNoLabels(_("&Aceptar"), _("&Cancelar")) if dlg.ShowModal()==wx.ID_YES: webbrowser.open('https://www.paypal.com/donate/?hosted_button_id=5ZV23UDDJ4C5U') @@ -101,14 +104,11 @@ def __init__(self, *args, **kwds): self.menu_1 = wx.Button(self.panel_1, wx.ID_ANY, _(u"&Más opciones")) self.menu_1.Bind(wx.EVT_BUTTON, self.opcionesMenu) self.menu_1.SetToolTip(_(u"Pulse alt para abrir el menú")) - self.notebook_1 = wx.Notebook(self.panel_1, wx.ID_ANY) sizer_1.Add(self.notebook_1, 1, wx.EXPAND, 0) self.tap_1 = wx.Panel(self.notebook_1, wx.ID_ANY) self.notebook_1.AddPage(self.tap_1, _("Inicio")) - sizer_2 = wx.BoxSizer(wx.VERTICAL) - self.label_1 = wx.StaticText(self.tap_1, wx.ID_ANY, _("Escriba o pegue una URL de youtube"), style=wx.ALIGN_CENTER_HORIZONTAL) sizer_2.Add(self.label_1, 0, 0, 0) self.text_ctrl_1 = wx.TextCtrl(self.tap_1, wx.ID_ANY, "", style=wx.TE_AUTO_URL | wx.TE_CENTRE | wx.TE_PROCESS_ENTER) @@ -126,7 +126,6 @@ def __init__(self, *args, **kwds): self.button_2.Disable() sizer_2.Add(self.button_2, 0, 0, 0) self.tap_1.SetSizer(sizer_2) - self.panel_1.SetSizer(sizer_1) self.Layout() self.Maximize() @@ -136,12 +135,17 @@ def __init__(self, *args, **kwds): def opcionesMenu(self, event): self.menu = wx.Menu() self.opciones = wx.Menu() - + self.ayuda = wx.Menu() self.menu.AppendSubMenu(self.opciones, _(u"&Opciones")) self.opcion_1 = self.opciones.Append(wx.ID_ANY, _(u"Configuración")) self.Bind(wx.EVT_MENU, self.appConfiguracion, self.opcion_1) self.opcion_2 = self.opciones.Append(wx.ID_ANY, _(u"Restablecer los ajustes")) self.Bind(wx.EVT_MENU, self.restaurar, self.opcion_2) + self.menu.AppendSubMenu(self.ayuda, _("&Ayuda")) + self.apoyo = self.ayuda.Append(wx.ID_ANY, _(u"Únete a nuestra &causa")) + self.Bind(wx.EVT_MENU, self.donativo, self.apoyo) + self.itemPageMain = self.ayuda.Append(wx.ID_ANY, _(u"&Visita nuestra página de github")) + self.Bind(wx.EVT_MENU, self.pageMain, self.itemPageMain) self.acercade = self.menu.Append(wx.ID_ANY, _(u"Acerca de")) self.Bind(wx.EVT_MENU, self.infoApp, self.acercade) self.salir = self.menu.Append(wx.ID_EXIT) @@ -149,22 +153,20 @@ def opcionesMenu(self, event): position = self.menu_1.GetPosition() self.PopupMenu(self.menu, position) pass - + def pageMain(self, evt): webbrowser.open('https://github.com/metalalchemist/VeTube') + def donativo(self, evt): webbrowser.open('https://www.paypal.com/donate/?hosted_button_id=5ZV23UDDJ4C5U') def appConfiguracion(self, event): self.dialogo_2 = wx.Dialog(self, wx.ID_ANY, _("Configuración")) - sizer_5 = wx.BoxSizer(wx.VERTICAL) labelConfic = wx.StaticText(self.dialogo_2, -1, _("Categorías")) sizer_5.Add(labelConfic, 1, wx.EXPAND, 0) self.tree_1 = wx.Treebook(self.dialogo_2, wx.ID_ANY) sizer_5.Add(self.tree_1, 1, wx.EXPAND, 0) - self.treeItem_1 = wx.Panel(self.tree_1, wx.ID_ANY) self.tree_1.AddPage(self.treeItem_1, _("General")) sizer_4 = wx.BoxSizer(wx.HORIZONTAL) box_1 = wx.StaticBox(self.treeItem_1, -1, _("Opciones de la app")) boxSizer_1 = wx.StaticBoxSizer(box_1,wx.VERTICAL) - label_7 = wx.StaticText(self.treeItem_1, wx.ID_ANY, _("Modalidad del chat: ")) boxSizer_1.Add(label_7) self.choice_3 = wx.Choice(self.treeItem_1, wx.ID_ANY, choices=[_("Todos los chats"), _("solo chats de miembros y donativos.")]) @@ -182,7 +184,6 @@ def appConfiguracion(self, event): self.check_2.Bind(wx.EVT_CHECKBOX, self.reproducirSonidos) boxSizer_1.Add(self.check_2) sizer_4.Add(boxSizer_1, 0, 0, 0) - self.treeItem_2 = wx.Panel(self.tree_1, wx.ID_ANY) self.tree_1.AddPage(self.treeItem_2, _("Voz")) sizer_6 = wx.BoxSizer(wx.HORIZONTAL) @@ -192,32 +193,24 @@ def appConfiguracion(self, event): self.check_1.SetValue(sapy) self.check_1.Bind(wx.EVT_CHECKBOX, self.checar) boxSizer_2.Add(self.check_1) - label_6 = wx.StaticText(self.treeItem_2, wx.ID_ANY, _("Voz: ")) boxSizer_2 .Add(label_6) - self.choice_2 = wx.Choice(self.treeItem_2, wx.ID_ANY, choices=lista) self.choice_2.SetSelection(voz) self.choice_2.Bind(wx.EVT_CHOICE, self.cambiarVoz) boxSizer_2 .Add(self.choice_2) - label_8 = wx.StaticText(self.treeItem_2, wx.ID_ANY, _("Tono: ")) boxSizer_2 .Add(label_8) - self.slider_1 = wx.Slider(self.treeItem_2, wx.ID_ANY, tono+10, 0, 20) self.slider_1.Bind(wx.EVT_SLIDER, self.cambiarTono) boxSizer_2 .Add(self.slider_1) - label_9 = wx.StaticText(self.treeItem_2, wx.ID_ANY, _("Volumen: ")) boxSizer_2 .Add(label_9) - self.slider_2 = wx.Slider(self.treeItem_2, wx.ID_ANY, volume, 0, 100) self.slider_2.Bind(wx.EVT_SLIDER, self.cambiarVolumen) boxSizer_2 .Add(self.slider_2) - label_10 = wx.StaticText(self.treeItem_2, wx.ID_ANY, _("Velocidad: ")) boxSizer_2 .Add(label_10) - self.slider_3 = wx.Slider(self.treeItem_2, wx.ID_ANY, speed+10, 0, 20) self.slider_3.Bind(wx.EVT_SLIDER, self.cambiarVelocidad) boxSizer_2 .Add(self.slider_3) @@ -225,14 +218,11 @@ def appConfiguracion(self, event): self.boton_prueva.Bind(wx.EVT_BUTTON, self.reproducirPrueva) boxSizer_2.Add(self.boton_prueva) sizer_6.Add(boxSizer_2, 0, 0, 0) - self.button_cansel = wx.Button(self.dialogo_2, wx.ID_CLOSE, _("&Cancelar")) sizer_5.Add(self.button_cansel, 0, 0, 0) - self.button_6 = wx.Button(self.dialogo_2, wx.ID_ANY, _("&Aceptar")) self.button_6.Bind(wx.EVT_BUTTON, self.guardar) sizer_5.Add(self.button_6, 0, 0, 0) - self.treeItem_1.SetSizer(sizer_4) self.treeItem_2.SetSizer(sizer_6) self.dialogo_2.SetSizer(sizer_5) @@ -241,12 +231,10 @@ def appConfiguracion(self, event): self.dialogo_2.ShowModal() self.dialogo_2.Destroy() # Fin de la ventana de configuración - def reproducirPrueva(self, event): - if leer.silence(): leer.silence() - else: leer.speak(_("Hola, soy la voz que te acompañará de ahora en adelante a leer los mensajes de tus canales favoritos.")) - def infoApp(self, event): - wx.MessageBox(_("Creadores del proyecto:")+"\nCésar Verástegui & Johan G.\n"+_("Descripción:\n Lee en voz alta los mensajes de los directos en youtube, ajusta tus preferencias como quieras y disfruta más tus canales favoritos."), _("Información"), wx.ICON_INFORMATION) + leer.silence() + leer.speak(_("Hola, soy la voz que te acompañará de ahora en adelante a leer los mensajes de tus canales favoritos.")) + def infoApp(self, event): wx.MessageBox(_("Creadores del proyecto:")+"\nCésar Verástegui & Johan G.\n"+_("Descripción:\n Lee en voz alta los mensajes de los directos en youtube, ajusta tus preferencias como quieras y disfruta más tus canales favoritos."), _("Información"), wx.ICON_INFORMATION) def cambiarVelocidad(self, event): global speed value=self.slider_3.GetValue()-10 @@ -278,9 +266,14 @@ def acceder(self, event): wx.MessageBox(_("No se puede acceder porque el campo de texto está vacío, debe escribir algo."), "error.", wx.ICON_ERROR) self.text_ctrl_1.SetFocus() else: + if 'studio' in self.text_ctrl_1.GetValue(): + pag=self.text_ctrl_1.GetValue() + pag=pag.split("/") + pag=pag[-2] + self.text_ctrl_1.SetValue("https://www.youtube.com/watch?v="+pag) try: chat = ChatDownloader().get_chat(self.text_ctrl_1.GetValue()) - except: - wx.MessageBox(_("¡Parece que el enlace al cual está intentando acceder no es un enlace válido."), "error.", wx.ICON_ERROR) + except Exception as e: + wx.MessageBox(_("¡Parece que el enlace al cual está intentando acceder no es un enlace válido."+str(e)), "error.", wx.ICON_ERROR) return try: self.contador=0 @@ -310,10 +303,12 @@ def acceder(self, event): sizer_mensaje_1.Fit(self.dialog_mensaje) self.dialog_mensaje.Centre() self.dialog_mensaje.SetEscapeId(self.button_mensaje_detener.GetId()) + if sonidos: playsound("sounds/abrirchat.mp3",False) leer.speak(_("Ingresando al chat.")) self.hilo2 = threading.Thread(target=self.iniciarChat) self.hilo2.daemon = True self.hilo2.start() + if not self.hilo1.is_alive(): self.hilo1.start() self.dialog_mensaje.ShowModal() except Exception as e: wx.MessageBox(_("¡Parece que el enlace al cual está intentando acceder no es un enlace válido."), "error.", wx.ICON_ERROR) @@ -399,59 +394,64 @@ def elementoAnterior(self): if self.list_box_1.GetCount() <= 0: lector.speak(_("no hay elementos en el historial")) else: if self.contador>0: self.contador-=1 - lector.speak(self.list_box_1.GetString(self.contador)) + self.msg=(self.list_box_1.GetString(self.contador)) + lector.speak(self.msg) else: if len(miembros) <= 0: lector.speak(_("no hay elementos en el historial")) else: if self.contarmiembros>0: self.contarmiembros-=1 - lector.speak(miembros[self.contarmiembros]) + self.msg=(miembros[self.contarmiembros]) + lector.speak(self.msg) + if sonidos: self.reproducirMsg() def elementoSiguiente(self): if self.dentro: if todos: if self.list_box_1.GetCount() <= 0: lector.speak(_("no hay elementos en el historial")) else: if self.contador0 and todos: return self.list_box_1.GetString(self.contador) elif todos==False and len(miembros)>0: return miembros[self.contarmiembros] @@ -500,6 +499,13 @@ def mostrarMensaje(self): my_dialog.Centre() my_dialog.SetEscapeId(cancelar.GetId()) my_dialog.ShowModal() + def reproducirMsg(self): + if todos: + if self.contador==0 or self.contador==self.list_box_1.GetCount()-1: playsound("sounds/orilla.mp3",False) + else: playsound("sounds/msj.mp3",False) + else: + if self.contarmiembros==0 or self.contarmiembros==len(miembros)-1: playsound("sounds/orilla.mp3",False) + else: playsound("sounds/msj.mp3",False) class MyApp(wx.App): def OnInit(self): self.frame = MyFrame(None, wx.ID_ANY, "") diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..50603cd --- /dev/null +++ b/changelog.txt @@ -0,0 +1,16 @@ +V1.2 +corregido el que la interfaz se congelara al momento de ingresar al chat. +corregido el no poder ir al inicio del chat en la lista principal. +agregado sonidos al navegar por el chat y al llegar al borde, gracias Glein +Agregamos un sonido para indicar que se a ingresado al chat. gracias Johan G. +Agregado el fácil acceso a nuestra página de github para poder colaborar con nosotros desde github, así como también una opción de apoyo en la sección de ayuda. gracias Johan G +Ahora el mensaje se copia de manera precisa. +VeTube ahora reconoce un link de YouTube Studio cuando es en vivo, por lo cual ya no es necesario sacar el link de youtube +*** +v1.1 +agregado diálogo para el chat aparte, gracias Johan G +Agregado poder mostrar el mensaje en un cuadro de texto. +Ahora VeTube reconoce cuando un enlace no está en vivo para hebitar la creación del chat. +*** +v1.0 +primera versión del proyecto \ No newline at end of file diff --git a/doc/es/readme.md b/doc/es/readme.md index 9bc0da7..11eaef9 100644 --- a/doc/es/readme.md +++ b/doc/es/readme.md @@ -1,6 +1,6 @@ # vetube Lee y gestiona de manera accesible el chat de youtube en tus propios directos o en los de tus creadores favoritos. -[demostración del producto en funcionamiento](https://www.youtube.com/c/4everzyanya/) +[demostración del producto en funcionamiento](https://youtu.be/4XawJoBymPs) ## Características - Modo automático: Lee los mensajes de chat en tiempo real utilizando la voz sapy5 - Interfaz invisible: Gestiona los chats desde cualquier ventana utilizando simples comandos de teclado. Es necesario tener un lector de pantalla activo. @@ -38,21 +38,32 @@ Lee y gestiona de manera accesible el chat de youtube en tus propios directos o | Reproducir mensaje seleccionado | espacio | | borrar mensaje seleccionado | suprimir | -Con tu apoyo contribuyes a que este programa siga en crecimiento -[¿Te unes a nuestra causa?](https://www.paypal.com/donate/?hosted_button_id=5ZV23UDDJ4C5U) ## futuras actualizaciones: -- He agregado para futuras actualizaciones próximas el poder traducir facilmente la aplicación a otros idiomas. +He agregado para futuras actualizaciones próximas +- el poder traducir facilmente la aplicación a otros idiomas. - Posibbilidad de mostrar información de la persona que está chateando desde la interfaz invisible: - El usuario es moderador? - Nombre del canal del usuario - Entre muchas cosas mas. -Se que gracias a ustedes esta aplicación seguirá mejorando y cada una de sus ideas y colaboraciones serán bienvenidas a este proyecto que iremos construyendo entre todos. # agradecimientos: Agradesco a: -[4everzyanya](https://www.youtube.com/c/4everzyanya/) -principal tester del proyecto. -[Johan G](https://github.com/JohanAnim) el cual me ayudó ha crear la interfaz gráfica para el proyecto y a corregir ciertos bugs menores. -Y a todos y cada uno de ustedes por sus futuras ideas y alimentar el proyecto constantemente. -Si gustas reportarme bugs, ideas o simplemente escribirme puedes hacerlo en: -cesar.verastegui17@gmail.com \ No newline at end of file + +[4everzyanya](https://www.youtube.com/c/4everzyanya/), + +Principal tester del proyecto. + +[Johan G](https://github.com/JohanAnim), + +Quien ayudó ha crear la interfaz gráfica para el proyecto y a corregir ciertos bugs menores. + +Se que gracias a ustedes esta aplicación seguirá mejorando y cada una de sus ideas y colaboraciones serán bienvenidas a este proyecto que iremos construyendo entre todos. + +Para ideas, bugs y sugerencias Puedes escribirme a +cesar.verastegui17@gmail.com +## Links de descarga. +Con tu apoyo contribuyes a que este programa siga en crecimiento. + +[¿Te unes a nuestra causa?](https://www.paypal.com/donate/?hosted_button_id=5ZV23UDDJ4C5U) + +[Descarga el programa desde aquí](https://github.com/metalalchemist/VeTube/files/8586368/VeTube.zip) \ No newline at end of file diff --git a/sounds/abrirchat.mp3 b/sounds/abrirchat.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..796ba2dd537655510ef3b3dc9720663031d4ffa1 GIT binary patch literal 12141 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 literal 0 HcmV?d00001 diff --git a/sounds/orilla.mp3 b/sounds/orilla.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4076dc399fe1b7ef6a87c9d89df5ba52603ab4c9 GIT binary patch literal 6896 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