Etiqueta: programación

Telegram y el precio de la luz

Telegram y el precio de la luz

Desde hace ya un tiempo, llevo usando Telegram como principal aplicación de mensajería con mis conocidos. En esta, existen los llamados bots, que pueden implementarse por cualquiera a través de un API. Hace algún tiempo, intenté crear una librería para poder tratar con esos bots desde Java de una forma sencilla, pero lo dejé de lado por falta de tiempo, y por los constantes cambios que se van introduciendo por parte de Telegram. Por suerte no fui el único con esa idea, y alguien terminó llevándola a buen puerto, e incluso mejorándola. La librería se integra de una forma sencillísima con Spring Boot, para hacer un bot completamente funcional integrado en el ecosistema de Telegram.

Para crear un bot con esa librería, solo hay que usar el starter que incluye, y arrancarlo como una aplicación más de Spring. Lo necesario también, es obtener el token necesario de Telegram a través del BotFather que tiene, y que sirve para poder hacer las peticiones, que se debe añadir dentro de tu aplicación.

En su día, ya había creado algún bot por mi cuenta con mi propia librería anticuada, pero que también había abandonado, y ya llevaba dando vueltas a la cabeza el hacer uno nuevo, que realmente fuese útil. Y con mi situación actual, no terminó siendo difícil encontrar lo que necesitaba.

Como ya sabéis de mi anterior post, tengo un coche eléctrico, con el que estoy encantado. Para recargarlo, el 99% de las veces lo hago a través de la propia electricidad de mi casa, después de haber instalado un punto de carga en el garaje, y eso nos lleva hasta 2021. El precio de la luz como todos sabemos se disparó de manera desproporcionada, y la factura, incluso no siendo un consumidor excesivo, subió un riñón, y parte del otro. De hecho subió tanto, que ha habido un tiempo que no me compensaba cargar el coche en mi casa, porque me salía más caro, que irme a uno de los cargadores rápidos que hay cerca de mi casa.

Con todo esto, decidí que si iba a cargar el coche en casa, tendría que saber cuando hacerlo, para que mi factura no fuese una autentica aberración. Encontré una página web donde te dice que precio tiene la luz a cada hora del día, pero consultarla cada día, me parecía un poco engorroso. Esa página tira de un api público accesible para todos, que se puede consultar sin ningún problema, y al que le di un par de vueltas para ver como funcionaba.

Con mis ganas de volver a hacer un bot para Telegram, y mi necesidad de saber el precio de la luz cada día de forma rápida y sencilla, estaba claro lo que había que hacer: Un bot que te mandase cada día los precios de la luz de las horas de ese día, de forma automática. Con todo esto en mente, me puse manos a la obra, y en menos de un fin de semana ya lo tenia listo, y desplegado en un servidor propio que tengo desde hace siglos y un poco desaprovechado.

PrecioDeLaLuzBot

El código del bot es muy sencillo en si mismo: Obtiene desde el api público el precio de la luz para el día actual (Y el día siguiente también), y se lo guarda en una base de datos MariaDB. También almacena en la base de datos el ID de Telegram de todos los usuarios que se van uniendo al bot, para poder enviarle el mensaje con los precios de la luz. Una vez hecho esto, con un proceso programado a las 00:00 de cada noche, se crea el mensaje con los precios de ese día, y se le manda el mensaje formateado a todos los usuarios. Por supuesto si un usuario decide parar el bot, se le elimina del listado para que no se le mande más. Todo esto desplegado en un servidor a través de Docker (Como ya sabéis, no despliego ya nada que no se pueda hacer a través de Docker).

Desde que lo desplegué lo consulto todos los días, y en el momento de escribir este post, ya hay 70 personas que lo están usando, cosa que ya es más de lo que esperaba. Podéis acceder al bot vosotros mismos escaneando el QR de abajo, o pulsando directamente sobre el, para abrirlo directamente en Telegram.

Ansible: La automatización definitiva para servidores

El término ansible se usa en la literatura de ciencia ficción para describir un dispositivo hipotético de comunicación más rápida que la luz.

Ansible logo

Los creadores de la tecnología llamada Ansible, se basaron en este sistema para darle nombre, y aunque obviamente no hayan conseguido que vaya más rápido que la luz, si que esta tecnología consigue hacer muchísimo más simple la configuración remota de equipos.

Ansible se basa en el más que probado protocolo SSH, con el cual se pueden ejecutar ordenes remotas mediante un terminal introduciendo comandos. Además se han abstraído estos comandos (Llamados tasks en Ansible), para que no tengan que escribirse como tal, y que escribiendo un trozo de código en formato yml, Ansible lo traduzca a comandos Linux. Lo bueno de Ansible, es que no hay que instalar en servidor nada más que un servidor de SSH, y listo, Ansible funcionará perfectamente, ya que en realidad no ejecuta en servidor, sino en la máquina cliente que ataca esos servidores, por eso desde la máquina donde se lance la ejecución, si que debe tener Ansible instalado.

Inventarios

El inventario en Ansible no es mas que un archivo de texto plano, donde se definen los hosts a los que podemos atacar. Un fichero de inventario podría tener el siguiente aspecto

mail.example.com

[webservers]
foo.example.com
bar.example.com

[dbservers]
one.example.com
two.example.com
three.example.com

Se puede ver, que tiene una dirección por defecto como mail.example.com, y ademas mediante corchetes, se pueden crear grupos de máquinas como en este caso [webservers] o [dbservers], por si queremos ejecutar los mismos comandos directamente contra varios servidores de una sola vez.

A su vez, Ansible tiene unos posibles hosts donde ejecutar estos comandos. Estos hosts no son mas que configuraciones de conexión a los servidores donde se tiene que ejecutar los tasks. Se puede tener un solo host, o varios a la vez donde ejecutarse. Por supuesto, se debe tener el acceso correspondiente a cada máquina, ya sea via usuario y contraseña (Nada recomendable), o mediante una clave publica/privada que se haya instalado en el servidor donde se ejecutarán las tareas.

tareas

Un ejemplo básico de una tarea Ansible, en la que se copia un fichero de un directorio local, a uno remoto en el servidor sería este

- name: example copying file with owner and permissions
  copy:
    src: /srv/myfiles/foo.conf
    dest: /etc/foo.conf
    owner: foo
    group: foo
    mode: 0644

Los elementos son los siguientes:

  • name: Nombre de la tarea a ejecutar que la identifica de forma unica
  • copy: etiqueta que identifica el comando de la tarea. En este caso el tipo copy sirve para copiar archivos en servidor.
    • src: Fichero local a subir en nuestro servidor
    • dest: Ruta donde se dejará el fichero a subir. Se puede poner un nombre distinto al original si queremos renombrarlo.
    • owner: Propietario del fichero que se pondrá al subirlo.
    • group: Grupo del fichero que se pondrá al subirlo.
    • mode: Permisos en formato octal, que se le darán al fichero en servidor.

Como podéis ver es un formato yml muy claro, y fácilmente entendible. Por supuesto existen muchos mas tipos de tareas en Ansible que se traducirán a comandos ssh automáticamente cuando se ejecuten. Los ficheros que agrupan estas tareas, se les denomina en Ansible, playbooks, ya que pueden contener varias tareas a ejecutar.

ejecución

Una vez creado nuestro primero playbook, ya podremos ejecutarlo. Una ejemplo de ejecución seria este

ansible-playbook -i hosts.cfg -l webservers myPlaybookFile.yml

Este comando usa un fichero hosts.cfg (El del ejemplo escrito arriba), y un fichero de playbook llamado myPlaybookFile.yml donde se encuentran las tareas a ejecutar. Al ejecutar este comando, subirá a los hosts definidos dentro del grupo webservers (Con el argumento -l nombregrupo se indica que se quiere ejecutar contra un grupo de hosts) del ficheros hosts.cfg, el fichero que se indica en la tarea copy de nuestro fichero myPlaybookFile.yml.

Variables

La gran mayoria de veces las tareas que necesitamos ejecutar deben ser parametrizadas, ya que seguramente cambien con el tiempo. Para eso pueden usarse variables que puedan cogerse desde el mismo fichero de playbook, una fuente externa como un fichero de variables, o como parámetros dentro del propio comando de ejecución.

Para usar variables dentro de una tarea se debe poner el nombre de la variable dentro de dobles llaves {{ nombre_variable }}.

Un ejemplo dentro de una tarea podria ser el siguiente

- name: example copying file with owner and permissions
  copy:
    src: /srv/myfiles/{{ file_name }}
    dest: /etc/{{ file_name }}
    owner: foo
    group: foo
    mode: 0644

Y el comando a ejecutar pasándole la variable file_name

ansible-playbook -i hosts.cfg -l webservers myPlaybookFile.yml --extra-vars "file_name=ficherodeprueba.txt"

Con el parámetro –extra-vars (Aunque también vale con -e) se le pueden pasar variables extras que después se usen dentro de los playbooks.

Módulos

Ansible tienes unas tareas básicas que prácticamente pueden ejecutar en cualquier servidor Linux, sin embargo, estas son ampliables y pueden añadírsele módulos adicionales para poder manejar determinadas partes del host destino, como por ej. docker.

En la página web de Ansible tenéis todos los módulos disponibles que se pueden instalar para poder ampliar su funcionalidad.


Con esto espero haberos dado una idea aproximada de la potencia de Ansible, ya que para mi es imprescindible en estos momento, porque mis backups automatizados de servidores están hechos sobre Ansible, y en un futuro lo usaré para configuración completa de servidores nuevos.

Concepto de orientación a objetos

Probablemente el concepto que más me costó comprender cuando empecé a programar fue la orientación a objetos. El primer día de programación, van y me sueltan tan tranquilamente la definición estándar: Un objeto es una instancia de una clase. Ajam… si… muy bien… No se vosotros pero yo me quedé exactamente igual que estaba. Para mi en ese momento, una clase no era más que un archivo con cierto formato, donde yo ponía ordenes, y al compilarlas se ejecutaban una detrás de otra. Pero claro, eso se queda muy lejos de lo que es realmente programar.

Tardé bastante tiempo en entender claramente el significado de que era un objeto, y cómo usarlo. Y estoy seguro de que no he sido el único que ha estado tan perdido en este sentido. Pero un día, no se muy bien cómo, me di cuenta de que era, y cómo funcionaba. Fue un flash instantáneo que me vino a la mente, y de repente todo cobró sentido. Era un concepto tan simple que no sabía como había podido no entenderlo. Bueno, si lo se: Me estaban metiendo tantas cosas nuevas en la cabeza, que comprender en profundidad todo, era casi imposible. Pero a partir de ese momento todo fue viento en popa.

Por eso hoy, os voy a intentar enseñar cómo comprendí la orientación a objetos, y que siempre uso de ejemplo cada vez que intento explicarle a un alumno mío, que no tiene ni idea de que es un objeto.

Voy a dar por hecho que sabéis los conceptos de clase (Al menos con saber, burdamente explicado, que es un fichero donde se mete código y se ejecuta, suficiente), el de función o método (Definición simple: Una forma de agrupar instrucciones para hacer más legible el código), y la de variables (Esta lo siento, pero si no sabes lo que es una variable es que estás en el día 0 de aprender a programar xD), para explicaros la forma de entender la orientación a objetos

Esto es una clase

Clase coche
A partir de ahora, para vosotros esta clase es intocable, el código que escribáis en ella, NO PODÉIS EJECUTARLO. Hay formas de hacerlo obviamente (El concepto de static me costó comprenderlo bastante más, y no voy a meterme ahora con ello), pero por ahora para tener las cosas claras, ese código es intocable.
La cosa es que necesitamos ejecutar código de esa clase, y acceder a la variable que hay en ella para cambiarla, o ver que valor tiene. Aquí es cuando entra el concepto de objeto. Mi propia definición de objeto: Un objeto, es una copia usable de una clase. Dicho así, suena casi tan raro como la definición original de objeto, así que vamos a desarrollarlo un poco.
Para poder usar ese código hacemos una copia de nuestra clase:
Clase cocheClase coche
 
 
 
 
 
 
 
Hasta aquí todo bien, ya tenemos nuestra copia usable. La cosa es que, en esta copia, para vosotros, no es visible su código realmente, solo podrás hacer cosas con el, pero no ver las instrucciones que ejecuta. Por lo cual podría resumirse en que ahora mismo tienes esto:

CLASE   –   OBJECTO

Clase coche

 
 
 
 
 
 
 
Esta es la mejor imagen para definir un objeto, porque literalmente ES un objeto: Una cosa con la que podemos hacer algo.
Ahora a ese objeto le podemos decir que haga cosas. En nuestro caso, tenemos un objeto de la clase coche por lo cual podemos llamar a los métodos que tiene:

LLAMADA AL MéTODO/función ARRANCAR DEL OBJETO

Por supuesto, podemos crear tanto objetos como queramos. Podemos tener un array de esos objetos por ej:

Objecto cocheObjecto cocheObjecto coche

Y podemos decirle al segundo solamente que arranque.

Objecto cochearrancarObjecto cocheObjecto coche

Así es como lo veo yo, y al menos a mi me sirvió para captar de forma crucial el concepto de objeto, y por ahora, parece que mis alumnos también consiguen captarlo y entenderlo, por lo cual, algo de bueno tiene que tener verlo así.

Espero que a vosotros también os sirva para entenderlo si estáis empezando. Y si tenéis que enseñarle a alguien este concepto, tener una idea de cómo simplificar el proceso para que lo aprendan.