Header Ads Widget

Ticker

6/recent/ticker-posts

Crea un bot meteorológico en Telegram usando Python


Telegram, una de las aplicaciones de mensajería más populares, es un poco más flexible que otras aplicaciones de chat populares como WhatsApp o Messenger de Facebook. Telegram es un servicio de mensajería instantánea multiplataforma que también admite videollamadas, VOIP y compartir archivos con tus amigos. Lanzado en 2013, Telegram ahora tiene más de 300 millones de usuarios activos.

Una de las mejores características de Telegram es almacenar mensajes en el servidor, no en su dispositivo local. La API de Telegram también está abierta para que los desarrolladores la aprovechen. Con las API adecuadas, puede potenciar sus chatbots con todo tipo de información interactiva basada en el chat, todo desde el entorno de chat de Telegram.

En este artículo, exploraremos cómo usar la API de Telegram para crear un chatbot que muestre su pronóstico del tiempo actual Repasaremos cómo obtener las credenciales de la API de Telegram, iniciar un bot, escribir un script para llamar a la API de OpenWeatherMap y codificar funciones en Python.

Requisitos previos:

  • Conocimientos básicos de Python
  • Cuenta de Telegram
  • Cuenta OpenWeather

Paso –1: Obtenga las credenciales de la API

Cubriremos cómo obtener las credenciales de la API de Telegram que puede obtener directamente desde su aplicación móvil, pero le sugiero que vaya a web.telegram.org e inicie un chat con este nombre de usuario BotFather.

Así que busque Bot Father y envíe este mensaje: /newbot

Una vez que presione enter, BotFather le hará esta pregunta:

“Muy bien, un nuevo bot. ¿Cómo lo vamos a llamar? Elija un nombre para su bot ".

Démosle el nombre de "WeatherBot"

A continuación, preguntará: “Bien. Ahora, elija un nombre de usuario para su bot. Debe terminar en botAsí, por ejemplo, TetrisBot o tetris_bot ".

Aquí tienes que asegurarte de que termine con "bot", así que dale un nombre. Por ejemplo, le estoy dando "geekyhumans_weather_bot".

Si tiene éxito, responderá con un mensaje como este:

Done! Congratulations on your new bot. You will find it at t.me/geekyhumans_weather_bot. You can now add a description, about section, and profile picture for your bot, see /help for a list of commands. By the way, when you've finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.

Use this token to access the HTTP API:
XXXXXXXXXXXXXXXXXXXX
Keep your token secure and store it safely, it can be used by anyone to control your bot.

For a description of the Bot API, see this page: https://core.telegram.org/bots/api

Ahora guarde sus credenciales de API en un lugar seguro. Usaremos esta clave para enviar mensajes.

Paso –3: Obtener las credenciales de la API meteorológica

En este tutorial, usaremos OpenWeatherMap API, una de las API meteorológicas más populares Regístrese con OpenWeatherMap aquí , cree su cuenta y verifique su correo electrónico.

Una vez hecho esto, inicie sesión en el sitio web y verá algo como esto:

Aquí haga clic en Claves API y copie su clave API desde allí.

Paso –3: Configuración del código:

Una vez que haya terminado con todas las tareas anteriores, configuremos nuestro proyecto ahora. Así que abre tu terminal y crea una nueva carpeta usando el siguiente comando:

mkdir telegram-api

Y luego abre la carpeta:

cd telegram-api

Ahora es el momento de instalar algunas dependencias. Entonces, en su terminal, pegue el siguiente código:

python3 -m pip install requests

Estamos instalando solicitudes aquí porque facilita mucho la realización de llamadas a la API.

Una vez hecho esto, cree un nuevo archivo telegram.pyy ábralo en su editor favorito. ¡Ahora es el momento de escribir código!

Comencemos con la importación de algunos módulos, así que pegue el siguiente código para importar los módulos:

import json 
import requests
import time
import urllib 
import logging
import signal
import sys

TOKEN = "API_KEY FOR TELEGRAM"
OWM_KEY = "OPEN WEATHER API KEY"
POLLING_TIMEOUT = None

Explicación del código:

Aquí estamos importando algunos módulos necesarios como jsonpara analizar el JSON, requestspara hacer llamadas API a Telegram y OpenWeatherAPI, timepara usar time.sleep()lo que ayudará en el sondeo, urllibpara analizar el texto codificado en URL.

Una vez hecho lo anterior, vamos a definir algunas funciones Lambda. ¿No conoces las funciones lambda? Bueno, son funciones anónimas que pueden tomar varios parámetros y solo una expresión.

# Lambda functions to parse updates from Telegram
def getText(update):            return update["message"]["text"]
def getLocation(update):        return update["message"]["location"]
def getChatId(update):          return update["message"]["chat"]["id"]
def getUpId(update):            return int(update["update_id"])
def getResult(updates):         return updates["result"]

# # Lambda functions to parse weather responses
def getDesc(w):                 return w["weather"][0]["description"]
def getTemp(w):                 return w["main"]["temp"]
def getCity(w):                 return w["name"]
logger = logging.getLogger("weather-telegram")
logger.setLevel(logging.DEBUG)

# Cities for weather requests
cities = ["London", "Brasov"]
def sigHandler(signal, frame):
    logger.info("SIGINT received. Exiting... Bye bye")
    sys.exit(0)

Explicación del código:

Hemos definido muchas funciones Lambda y cada función se utiliza para devolver datos diferentes. Por ejemplo, getText()se usa para obtener el texto del mensaje en Telegram, getLocation()se usa para devolver la ubicación del mensaje, getChatId()se usa para devolver la identificación de chat del mensaje, getUpIddevuelve la identificación de actualización, getResultdevuelve el resultado.

Del mismo modo, hay funciones Lambda para la API del tiempo como, getDesc()devolver la descripción del tiempo, getTemp()devolver la temperatura, getCitydevolverá la ciudad.

También hemos definido una lista de ciudades que aparecerán por defecto en Telegram.

Hasta ahora, hemos creado la clave API e inicializado todas las funciones. Ahora profundicemos en la funcionalidad principal.

Paso –4: Definición de todas las funciones:

Ahora definiremos todas las funciones que usaremos para nuestro Weather Bot. Así que pega el siguiente código:

# Configure file and console logging
def configLogging():
    # Create file logger and set level to DEBUG
    # Mode = write -> clear existing log file
    handler = logging.FileHandler("run.log", mode="w")
    handler.setLevel(logging.DEBUG)
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    # Create console handler and set level to INFO
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)
    formatter = logging.Formatter("[%(levelname)s] - %(message)s")
    ch.setFormatter(formatter)
    logger.addHandler(ch)

def parseConfig():
    global URL, URL_OWM, POLLING_TIMEOUT
    URL = "https://api.telegram.org/bot{}/".format(TOKEN)
    URL_OWM = "http://api.openweathermap.org/data/2.5/weather?appid={}&units=metric".format(OWM_KEY)
    POLLING_TIMEOUT

Explicación del código:

Aquí estamos definiendo nuestro registrador, este registrará cualquier error, acceso, con el mensaje y. Creará un archivo run.logy guardará todos y cada uno de los registros allí de forma formateada. He aquí un ejemplo:

2020-12-13 02:56:36,450 - INFO - Getting updates
2020-12-13 02:56:36,450 t - DEBUG - URL: https://api.telegram.org/bot1482273391:XXXXXXX/getUpdates?timeout=None
2020-12-13 02:56:41,082 - DEBUG - {'keyboard': [[{'text': 'London'}], [{'text': 'Brasov'}], [{'text': 'Share location', 'request_location': True}]], 'one_time_keyboard': True}

Ahora vamos a definir tres funciones más, makeRequest()getUpdates()buildkeyboard()buildCitiesKeyboard()Así que pega el siguiente código en el mismo archivo:

# Make a request to Telegram bot and get JSON response
def makeRequest(url):
    logger.debug("URL: %s" % url)
    r = requests.get(url)
    resp = json.loads(r.content.decode("utf8"))
    return resp

# Return all the updates with ID > offset
# (Updates list is kept by Telegram for 24h)
def getUpdates(offset=None):
    url = URL + "getUpdates?timeout=%s" % POLLING_TIMEOUT
    logger.info("Getting updates") 
    if offset:
        url += "&offset={}".format(offset)
    js = makeRequest(url)
    return js

# Build a one-time keyboard for on-screen options
def buildKeyboard(items):
    keyboard = [[{"text":item}] for item in items]
    replyKeyboard = {"keyboard":keyboard, "one_time_keyboard": True}
    logger.debug(replyKeyboard)
    return json.dumps(replyKeyboard)

def buildCitiesKeyboard():
    keyboard = [[{"text": c}] for c in cities]
    keyboard.append([{"text": "Share location", "request_location": True}])
    replyKeyboard = {"keyboard": keyboard, "one_time_keyboard": True}
    logger.debug(replyKeyboard)
    return json.dumps(replyKeyboard)

Explicación del código:

La función makeResuest()es una especie de función universal en la que solo tenemos que pasar la URL, y hará una GETsolicitud y devolverá la respuesta en JSON. La función getUpdates()devuelve las actualizaciones para el registrador con tiempo de espera de sondeo. También hemos definido dos funciones más, buildKeyboard()buildCitiesKeyboard(), que crearán un teclado personalizado, que le mostraremos más adelante en este tutorial.

Ahora agregaremos algunas funciones más relacionadas con Weather API y Telegram API. Así que agregue el siguiente código:

# Query OWM for the weather for place or coords
def getWeather(place):
    if isinstance(place, dict):     # coordinates provided
        lat, lon = place["latitude"], place["longitude"]
        url = URL_OWM + "&lat=%f&lon=%f&cnt=1" % (lat, lon)
        logger.info("Requesting weather: " + url)
        js = makeRequest(url)
        logger.debug(js)
        return u"%s \N{DEGREE SIGN}C, %s in %s" % (getTemp(js), getDesc(js), getCity(js))
    else:                           # place name provided 
        # make req
        url = URL_OWM + "&q={}".format(place)
        logger.info("Requesting weather: " + url)
        js = makeRequest(url)
        logger.debug(js)
        return u"%s \N{DEGREE SIGN}C, %s in %s" % (getTemp(js), getDesc(js), getCity(js))

# Send URL-encoded message to chat id
def sendMessage(text, chatId, interface=None):
    text = text.encode('utf-8', 'strict')                                                       
    text = urllib.parse.quote_plus(text)
    url = URL + "sendMessage?text={}&chat_id={}&parse_mode=Markdown".format(text, chatId)
    if interface:
        url += "&reply_markup={}".format(interface)
    requests.get(url)

# Get the ID of the last available update
def getLastUpdateId(updates):
    ids = []
    for update in getResult(updates):
        ids.append(getUpId(update))
    return max(ids)

Explicación del código:

Aquí hemos definido tres funciones más:, getWeather()que toma la longitud y latitud de la ubicación actual y luego realiza la solicitud a la API del clima y devuelve la temperatura, la descripción y la ciudad. La función sendMessages()analiza el mensaje en url-encodedformato y llama a la API de Telegram, luego envía el mensaje a Telegram. La función getLastUpdatedID()devuelve el id del último mensaje; estamos haciendo esto para que nuestro bot no se confunda con los mensajes más antiguos mientras busca un mensaje nuevo.

Ahora vamos a agregar dos últimas funciones, y luego nuestro bot está listo. Entonces agregue estas dos funciones:

# Keep track of conversation states: 'weatherReq'
chats = {}

# Echo all messages back
def handleUpdates(updates):
    for update in getResult(updates):
        chatId = getChatId(update)
        try:
            text = getText(update)
        except Exception as e:
            logger.error("No text field in update. Try to get location")
            loc = getLocation(update)
            # Was weather previously requested?
            if (chatId in chats) and (chats[chatId] == "weatherReq"):
                logger.info("Weather requested for %s in chat id %d" % (str(loc), chatId))
                # Send weather to chat id and clear state
                sendMessage(getWeather(loc), chatId)
                del chats[chatId]
            continue

        if text == "/weather":
            keyboard = buildCitiesKeyboard()
            chats[chatId] = "weatherReq"
            sendMessage("Select a city", chatId, keyboard)
        elif text == "/start":
            sendMessage("Cahn's Axiom: When all else fails, read the instructions", chatId)
        elif text.startswith("/"):
            logger.warning("Invalid command %s" % text)    
            continue
        elif (text in cities) and (chatId in chats) and (chats[chatId] == "weatherReq"):
            logger.info("Weather requested for %s" % text)
            # Send weather to chat id and clear state
            sendMessage(getWeather(text), chatId)
            del chats[chatId]
        else:
            keyboard = buildKeyboard(["/weather"])
            sendMessage("I learn new things every day but for now you can ask me about the weather.", chatId, keyboard)

def main():
    # Set up file and console loggers
    configLogging()



    # Get tokens and keys
    parseConfig()
 
    # Intercept Ctrl-C SIGINT 
    signal.signal(signal.SIGINT, sigHandler) 
 
    # Main loop
    last_update_id = None
    while True:
        updates = getUpdates(last_update_id)
        if len(getResult(updates)) > 0:
            last_update_id = getLastUpdateId(updates) + 1
            handleUpdates(updates)
        time.sleep(0.5)

if __name__ == "__main__":
    main()

Explicación del código:

Hemos definido una función handleUpdates()que maneja todo el procesamiento. Llama getResult()para obtener la identificación del último mensaje. Si hay un mensaje nuevo, llamará getText()para recibir el texto del mensaje. Comprueba si la ciudad se registró anteriormente en el pasado. En caso afirmativo, simplemente realizará una llamada a la API y devolverá la información meteorológica. Si coincide con la /weathercadena, devolverá el teclado personalizado. Al seleccionar la ciudad, realizará la llamada API y devolverá la información meteorológica. Si no hay texto en el mensaje, intentará obtener la ubicación actual y luego intentará realizar la llamada a la API según la ubicación.

También tenemos la main()función. Esto llamará a las otras funciones en la secuencia correcta y se ejecutará de forma predeterminada.

Ahora que hemos completado la parte de codificación, podemos seguir adelante con la parte de prueba.

Paso –5: Probar nuestro bot:

Ejecutemos el código para que en su terminal ejecute el siguiente código:

python3 telegram.py

Y luego, abra su aplicación de Telegram y busque el nombre de usuario que eligió para el bot. Ahora toca el bot y escribe /weatherTe mostrará algo como esto:

Desde aquí, puede seleccionar cualquier ciudad predefinida o compartir su propia ubicación. Vayamos a Brasov, y devolverá el clima actual:

Ultimas palabras:

Hemos creado con éxito el Telegram Weather Bot. La API de Telegram puede hacer mucho más que devolver el clima actual. Incluso puede crear un bot que pueda devolver los precios de las acciones actuales o cualquier cosa que desee. Puede intentar explorar la API e intentar implementar nuevas funcionalidades utilizando la API.

Publicar un comentario

0 Comentarios