Buenas tardes, hoy me gustaría compartir con ustedes los problemas y sus soluciones inusuales que se encontraron al escribir pequeños proyectos de TI. Debo decir de inmediato que el artículo es para aquellos que están un poco versados en el desarrollo de telegramas para bots, bases de datos, SQL y el lenguaje de programación Python.
Todo el proyecto está publicado en github, el enlace estará al final del artículo.

Problema principal
Inicialmente, quería escribir para mí un simple contador de calorías de bot de telegramas, que recibe un número del usuario y devuelve cuántas calorías quedan a la normalidad durante el día. Es decir, debe almacenar aproximadamente un par de variables para cada usuario.
Al final, tuvo que elegir una forma de almacenar estos datos.
- Opción: variables globales , memoria de acceso aleatorio. La opción es inmediatamente un fracaso, porque cuando el programa falla, perdemos todo
- Opción: escribir en un archivo en el disco. Podría funcionar para tal proyecto, pero planeé implementar un bot en heroku, que borra todos los datos del disco todos los días. Entonces esta opción no encajaba
- Opción: hojas de cálculo de Google . Inicialmente, quería pensar en esta opción, pero comencé a comprender y me di cuenta de que había un límite en la cantidad de consultas a la tabla, y para comenzar a usar la tabla, debe escribir un montón de líneas de código y descubrir su no tan simple api
- La opción es una base de datos . Sí, esta es la mejor opción en todo. Pero para tal proyecto, incluso es divertido de usar. Además, la implementación y el soporte de una base de datos en un servidor de terceros costará un centavo.
Como resultado, ninguna de estas opciones surgió. Por supuesto, hay docenas de otras formas, pero me gustaría que fuera gratis, rápido y con un mínimo de código.
Solución
La idea es muy simple, para el almacenamiento de datos usaremos la base de datos sqllite en la memoria, ya que está integrada en python 3 y haremos una copia de seguridad de nuestra tabla en los servidores de Telegram con un pequeño intervalo (aproximadamente cada 30 segundos) y una copia de seguridad cuando se cierre el proceso del programa.
Si el servidor falla, entonces, en la primera solicitud, descargaremos automáticamente nuestra tabla desde el servidor de Telegram y restauraremos los datos a sqllite.
Puede usar cualquier otro en la base de datos de memoria como desee.
Pros
- Rendimiento : debido al trabajo con datos en la memoria principal, la velocidad de ejecución del programa es aún más rápida que cuando se usa la base de datos en un servidor de terceros (la velocidad y los gráficos de prueba estarán al final)
- Gratis : no es necesario comprar servidores de terceros para bases de datos y todos los datos se almacenan como una copia de seguridad de forma gratuita en los servidores de Telegram
- Relativamente confiable : si el servidor falla por razones desconocidas, entonces perdemos los datos máximos durante los últimos 30 segundos (tiempo de intervalo de respaldo), para un prototipo que funcione o un proyecto pequeño será suficiente.
- Costos mínimos al cambiar a una base de datos normal: debe reemplazar los datos de conexión, eliminar el código de respaldo y transferir los datos de la tabla del respaldo a una nueva base de datos.
Contras
- Falta de escala horizontal
- Necesita dos cuentas en Telegram (una para el administrador y la otra para probar al usuario)
- El servidor no funcionará en Rusia debido a bloqueos
- En los comentarios, creo que encontrarás una docena de otros matices.
Hora de cagar
Vamos a escribir un simple clicker y ejecutar pruebas de velocidad.
El bot se escribirá en el lenguaje de programación python utilizando una biblioteca asíncrona de interacción con el aiograma de telegrama api.
Lo primero que debe hacer es completar la configuración del bot, no le diré cómo obtener un token de BotFather, ya hay cientos de artículos sobre este tema.
También necesitamos una segunda cuenta en un telegrama para el administrador, en la que se guardarán nuestras copias de seguridad.
Para obtener admin_id y config_id, necesitamos iniciar el bot desde la cuenta de administrador y escribir "admin" en el bot, después de lo cual creará la primera copia de seguridad y escribirá su admin_id, config_id. Reemplace e inicie el bot nuevamente.
Así que ahora veamos la lógica principal del bot
Si el bot recibe un mensaje con la palabra "admin", entonces creamos una tabla de usuario con el siguiente modelo de datos:
- chatid: usuario de identificación de chat único
- nombre - nombre de usuario
- clic - número de clics
- estado: el valor de la máquina de estado no se usa en este proyecto, pero no puede prescindir de otros más complejos
Agregue un usuario de prueba y envíe el documento al servidor de Telegram con nuestra tabla. También enviamos admin_id y config_id al administrador en forma de mensajes. Después de recibir ID, este código debe comentarse.
Lógica de usuario
En primer lugar, tratamos de obtener de la base de datos en memoria los datos del usuario que envió el mensaje. Si detectamos un error, cargue los datos de la copia de seguridad del servidor Telergam, complete nuestra base de datos con los datos de la copia de seguridad e intente nuevamente encontrar al usuario.
Si encontramos al usuario en la base de datos, procesamos los botones:
- Al hacer clic en "Hacer clic", actualizamos el número de clics para este usuario
- Cuando hace clic en "Calificación", mostramos una lista de quince personas que tienen la mayor cantidad de clics.
Si no encontró al usuario, escríbale un error.
Escribamos la lógica para el registro de usuarios
Estamos tratando de encontrar al usuario en la base de datos, si no está allí, agregue una nueva fila a la tabla y haga una copia de seguridad.
Si detectamos un error, cargamos la última copia de seguridad, completamos la tabla y repetimos el intento de registro.
sql_select = "SELECT * FROM users where chatid={}".format(message.chat.id) sql_insert = "INSERT INTO users VALUES ({}, '{}', {},{})".format(message.chat.id,message.chat.first_name, 0, 0) try: cursor.execute(sql_select) data = cursor.fetchone() if data is None: cursor.execute(sql_insert) conn.commit() await save_data() except Exception: data = await get_data() cursor.execute("CREATE TABLE users (chatid INTEGER , name TEXT, click INTEGER, state INTEGER)") cursor.executemany("INSERT INTO users VALUES (?,?,?,?)", data) conn.commit() cursor.execute(sql_select) data = cursor.fetchone() if data is None: cursor.execute(sql_insert) conn.commit() await save_data()
Entonces, bueno, y lo más interesante.
Guardar y recuperar datos del servidor Telergam
Descargamos todos los datos de la tabla de usuarios, traducimos el diccionario en una cadena y modificamos nuestro archivo, que se almacena en los servidores de Telegram.
Para obtener una copia de seguridad, debemos reenviar el mensaje con el archivo del administrador al administrador. Luego obtenga la ruta al archivo, lea los datos por url y devuelva la copia de seguridad completa.
Bueno, eso es casi todo, solo queda escribir un temporizador para hacer copias de seguridad y probar el bot.
Cree un hilo que ejecute nuestro método save_data () cada 30 segundos.
def timer_start(): threading.Timer(30.0, timer_start).start() try: asyncio.run_coroutine_threadsafe(save_data(),bot.loop) except Exception as exc: pass
Bueno, en el programa principal, iniciamos el temporizador y el propio bot.
Entonces, el código parece estar ordenado, aquí está el enlace del borrador de trabajo a github .
Como correr
- Descargue el proyecto desde github. Comenzamos el proyecto en cualquier entorno de desarrollo para python (por ejemplo: PyCharm).
- El entorno de desarrollo cargará automáticamente las bibliotecas necesarias del archivo de requisitos.
- Reemplazar token de BotFather en main.py

- Comenzamos el proyecto
- Desde la segunda cuenta, haga clic / iniciar y escriba la palabra "admin"
- Apague el proyecto y complete admin_id y config_id en el archivo main.py
- Iniciamos el proyecto y desde la cuenta de usuario presionamos inicio
- Ganancia
Pruebas y gráficos
Las pruebas se realizaron en servidores heroku con características de instancia mínimas. Por lo tanto, podemos suponer que todas las pruebas se realizaron en condiciones más o menos iguales.
Los gráficos están hechos de muestras de ~ 100 solicitudes-respuestas. Y se presenta el promedio de la muestra.
PostgreSQL en Amazon RDS con características mínimas se utilizó como base de datos en un servidor de terceros.

Con un millón de usuarios, el tiempo de respaldo se convierte en un problema.

El tamaño de la copia de seguridad depende completamente de su modelo de datos, en mi caso, con un millón de usuarios, se obtuvo un archivo de datos con 21 megabytes.

Conclusión
Este método de almacenamiento de datos tiene sentido para proyectos de hasta un millón de usuarios. Es decir, para un prototipo o una startup personal, este método tiene derecho a la vida.
Como resultado, obtuvimos un clicker totalmente independiente, independiente de las bases de datos remotas.
Aquí está el proyecto descrito anteriormente desplegado en heroku: @Clicker_fast_bot
También implementé un proyecto más complejo con esta ideología: @Random_friend_bot
La imagen de una sala de chat y chat de dos personas, pero solo en un telegrama.
Está buscando comunicación dentro de un radio de 100 km de una persona del sexo opuesto y se da cuenta de una conversación cerrada con un nuevo interlocutor.
Si es interesante, puedo descartar el código fuente del proyecto. Además, si este tema es relevante, en el próximo artículo puedo describir la creación de la API Rest sin bases de datos externas. Esa es una pila de django-sqllite-Telegram.
Estaré encantado de cualquier crítica, ¡gracias por su atención!