Skip to content

Commit

Permalink
feat: ahora se guarda el estado de noticias_automaticas y si estaba p…
Browse files Browse the repository at this point in the history
…rendido, al revivir el bot se setean automaticamente; otros cambios menores
  • Loading branch information
SBen-IV committed May 1, 2023
1 parent c5f4db4 commit c2f12ff
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,4 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/

noticias.json
*.json
5 changes: 3 additions & 2 deletions connectors/fiuba_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

from entities.noticia import Noticia


class FiubaWeb(ABC):

@abstractclassmethod
def obtener_noticias(self, n: int = 1) -> list:
pass

@abstractclassmethod
def obtener_noticias_nuevas(self, ultima_noticia: Noticia) -> list:
pass
pass
11 changes: 6 additions & 5 deletions connectors/silk.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
INICIO_TITULO = 8
MAX_NOTICIAS = 16


class Silk(FiubaWeb):
def __init__(self):
self.logger = logging.getLogger(__class__.__name__)
Expand All @@ -31,7 +32,7 @@ def obtener_noticias(self, n_noticias: int = 1) -> list:
noticias.append(self.obtener_noticia(uri))

return noticias

def obtener_noticia(self, uri: str) -> Noticia:
url = DOMINIO + uri
self.logger.info("Obteniendo noticia de {url}".format(url=url))
Expand All @@ -50,28 +51,28 @@ def obtener_noticia(self, uri: str) -> Noticia:
titulo = soup.title.get_text()[INICIO_TITULO:]

return Noticia(titulo, descripcion, fecha, url)

def obtener_noticias_nuevas(self, ultima_noticia: Noticia) -> list:
uris_noticias = self.__obtener_uri_noticias()

noticias_nuevas = []

for uri in uris_noticias[:MAX_NOTICIAS]:
noticia = self.obtener_noticia(uri)

if noticia.fecha > ultima_noticia.fecha:
noticias_nuevas.append(noticia)
else:
break

return noticias_nuevas

def __obtener_uri_noticias(self) -> list:
page = requests.get(LINK_NOTICIAS)
soup = BeautifulSoup(page.content, 'html.parser')

return list(map(lambda x: x.get('href'), soup.select(".noticia > a")))

def __validar_cantidad(self, n_noticias: int) -> None:
if n_noticias <= 0:
raise CantidadNoticiasNegativaException(n_noticias)
Expand Down
41 changes: 28 additions & 13 deletions controllers/jjjameson.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,28 @@
from connectors.fiuba_web import FiubaWeb
from view.imprenta import Imprenta
from repositories.noticias_repository import NoticiasRepository
from repositories.estado_repository import EstadoRepository
from error_handler import logging
from exceptions.cantidad_noticias_exception import CantidadNoticiasNoEsNumeroException


ID_CANAL_NOTICIAS = os.getenv('ID_CANAL_NOTICIAS')
INTERVALO_MENSAJES_AUTOMATICOS = 3*60*60 # En segundos
INTERVALO_MENSAJES_AUTOMATICOS = 3*60*60 # En segundos


class JJJameson:
def __init__(self, fiuba_web: FiubaWeb, repo: NoticiasRepository, imprenta: Imprenta):
def __init__(self, fiuba_web: FiubaWeb, noticias_repo: NoticiasRepository, estado_repo: EstadoRepository, imprenta: Imprenta, job_queue, bot):
self.fiuba_web = fiuba_web
self.repo = repo
self.repo = noticias_repo
self.estado_repo = estado_repo
self.imprenta = imprenta
self.noticias_automaticas = False
self.job = None
self.noticias_automaticas = self.estado_repo.noticias_automaticas()

if self.noticias_automaticas:
self.__activar_noticias_automaticas(job_queue, bot.get_chat(ID_CANAL_NOTICIAS))
else:
self.job = None

self.logger = logging.getLogger(__class__.__name__)

def conseguir_noticias(self, update: Update, context: CallbackContext):
Expand All @@ -39,29 +47,33 @@ def conseguir_noticias(self, update: Update, context: CallbackContext):
self.logger.warn("Cantidad de noticias no es número {arg}".format(arg=context.args[0]))
raise CantidadNoticiasNoEsNumeroException(arg=context.args[0])

def __activar_noticias_automaticas(self, job_queue, chat):
self.job = job_queue.run_repeating(self.conseguir_noticias_automatico, INTERVALO_MENSAJES_AUTOMATICOS, context=chat)

def activar_noticias_automaticas(self, update: Update, context: CallbackContext):
if self.noticias_automaticas == False:
self.job = context.job_queue.run_repeating(self.conseguir_noticias_automatico, INTERVALO_MENSAJES_AUTOMATICOS, context=context.bot.get_chat(ID_CANAL_NOTICIAS))
if not self.noticias_automaticas:
self.__activar_noticias_automaticas(context.job_queue, context.bot.get_chat(ID_CANAL_NOTICIAS))
self.noticias_automaticas = True
self.logger.info("Se activaron las noticias automaticas.")
self.estado_repo.guardar(self.noticias_automaticas)
self.logger.info("Se activaron las noticias automáticas.")
update.effective_chat.send_message("Se activaron las noticias automáticas.")
else:
update.effective_chat.send_message("Las noticias automáticas ya estan activadas.")

update.effective_chat.send_message("Las noticias automáticas ya están activadas.")

def desactivar_noticias_automaticas(self, update: Update, _: CallbackContext):
if self.noticias_automaticas == True:
if self.noticias_automaticas:
self.job.schedule_removal()
self.noticias_automaticas = False
self.estado_repo.guardar(self.noticias_automaticas)
self.logger.info("Se desactivaron las noticias automáticas.")
update.effective_chat.send_message("Se desactivaron las noticias automáticas.")
else:
update.effective_chat.send_message("Las noticias automáticas no estan activadas.")
update.effective_chat.send_message("Las noticias automáticas no están activadas.")

def conseguir_noticias_automatico(self, context: CallbackContext):
ultima_noticia_guardada = self.repo.ultima_noticia()
self.logger.info("Fecha de última noticia {titulo} es {fecha}.".format(titulo=ultima_noticia_guardada.titulo, fecha=ultima_noticia_guardada.fecha))

nuevas_noticias = self.fiuba_web.obtener_noticias_nuevas(ultima_noticia_guardada)

if len(nuevas_noticias) > 0:
Expand All @@ -70,3 +82,6 @@ def conseguir_noticias_automatico(self, context: CallbackContext):
self.imprenta.enviar_noticias(context.job.context, nuevas_noticias, 30)
else:
self.logger.info("No hay noticias nuevas.")

def estado(self, update: Update, _: CallbackContext):
update.effective_chat.send_message("Noticias automáticas: {noticias_automaticas}".format(noticias_automaticas=self.noticias_automaticas))
7 changes: 5 additions & 2 deletions exceptions/cantidad_noticias_exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ def __init__(self, message) -> None:
self.message = message
super().__init__(self.message)


class CantidadNoticiasNoEsNumeroException(CantidadNoticiasException):
def __init__(self, arg = "") -> None:
def __init__(self, arg="") -> None:
self.message = "No creo que '{arg}' sea un número.".format(arg=arg)
super().__init__(self.message)



class CantidadNoticiasNegativaException(CantidadNoticiasException):
def __init__(self, arg) -> None:
self.message = "¿Cómo puedo conseguir {arg} noticias?".format(arg=arg)
super().__init__(self.message)


class CantidadNoticiasMaximaException(CantidadNoticiasException):
def __init__(self, arg) -> None:
self.message = "¿Quieres que consiga {arg} noticias? Aumentame el sueldo.".format(arg=arg)
Expand Down
9 changes: 6 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from connectors.silk import Silk
from view.threats_and_menaces import ThreatsAndMenaces
from repositories.noticias_repository import NoticiasRepository
from repositories.estado_repository import EstadoRepository
from error_handler import error_handler, logging
from telegram.ext import Updater, Filters, CommandHandler
from dotenv import load_dotenv
Expand All @@ -13,28 +14,30 @@

logger = logging.getLogger('main')


def main():
updater = Updater(token=os.getenv('BOT_TOKEN'), use_context=True)

bot = updater.bot.get_me()

logger.info("Iniciando {full_name} (@{username}).".format(full_name=bot.full_name, username=bot.username))

jameson = JJJameson(Silk(), NoticiasRepository(), ThreatsAndMenaces())
jameson = JJJameson(Silk(), NoticiasRepository(), EstadoRepository(), ThreatsAndMenaces(), updater.job_queue, updater.bot)
filtro = Filters.chat(chat_id=int(os.getenv('ID_GRUPO_NOTICIAS')))

updater.dispatcher.add_handler(CommandHandler('noticias', jameson.conseguir_noticias, filtro))
updater.dispatcher.add_handler(CommandHandler('empezar', jameson.activar_noticias_automaticas, filtro))
updater.dispatcher.add_handler(CommandHandler('terminar', jameson.desactivar_noticias_automaticas, filtro))
updater.dispatcher.add_handler(CommandHandler('estado', jameson.estado, filtro))
updater.dispatcher.add_error_handler(error_handler)

try:
updater.start_polling()
logger.info("Iniciado, esperando por comandos...")

updater.idle()
except Exception as e:
logger.error(e.__cause__)


main()
main()
30 changes: 30 additions & 0 deletions repositories/estado_repository.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os
import json

ESTADO_DEFAULT_JSON = {
"noticias_automaticas": False
}


class EstadoRepository:
def __init__(self, path: str = "estado.json"):
if not os.path.exists(path):
with open(path, "w", encoding='utf-8') as f:
json.dump(ESTADO_DEFAULT_JSON, f, indent=4)

self.path = path

def noticias_automaticas(self) -> bool:
estado = {}
with open(self.path, 'r', encoding='utf-8') as f:
estado = json.load(f)

return estado.get("noticias_automaticas", False)

def guardar(self, noticias_automaticas) -> None:
estado = {
"noticias_automaticas": noticias_automaticas
}

with open(self.path, "w", encoding='utf-8') as f:
json.dump(estado, f, indent=4)
11 changes: 6 additions & 5 deletions repositories/noticias_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from entities.noticia import Noticia
from error_handler import logging


class NoticiasRepository:
def __init__(self, path: str = "noticias.json"):
if os.path.exists(path) == False:
if not os.path.exists(path):
f = open(path, "w")
f.close()
self.path = path
Expand All @@ -18,7 +19,7 @@ def ultima_noticia(self) -> Noticia:

with open(self.path, 'r', encoding='utf-8') as f:
ultima_noticia_json = json.load(f)

return self.__json_to_object(ultima_noticia_json)

def guardar(self, noticia: Noticia) -> Noticia:
Expand All @@ -28,7 +29,7 @@ def guardar(self, noticia: Noticia) -> Noticia:
json.dump(noticia_json, f, indent=4)

self.logger.info("Guardada {noticia}.".format(noticia=noticia_json))

return noticia

def __object_to_json(self, noticia: Noticia) -> dict:
Expand All @@ -40,7 +41,7 @@ def __object_to_json(self, noticia: Noticia) -> dict:
}

return noticia_json

def __json_to_object(self, noticia_json: dict) -> Noticia:
fecha = datetime.strptime(noticia_json['fecha'], "%Y-%m-%d %H:%M")
return Noticia(noticia_json['titulo'], noticia_json['descripcion'], fecha, noticia_json['url'])
return Noticia(noticia_json['titulo'], noticia_json['descripcion'], fecha, noticia_json['url'])
1 change: 1 addition & 0 deletions view/threats_and_menaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
MAS_INFORMACION = emojize(":information: Más información")
FORMATO_MENSAJE = "<b>{titulo}</b>\n\n{descripcion}\n\n<a href=\"{url}\">{texto_url}</a>\n"


class ThreatsAndMenaces(Imprenta):
def __init__(self):
self.logger = logging.getLogger(__class__.__name__)
Expand Down

0 comments on commit c2f12ff

Please sign in to comment.