[PYTHON] Créez une application qui informe LINE de la météo tous les matins

introduction

J'ai un enfant de 2 ans, donc je regarde E-tele tous les matins, mais le temps ne sort pas sur E-tele. Je change de canal vers des programmes d'information juste pour vérifier la météo, donc je vais créer une application simple qui récupère la météo de l'API météo et la pousse vers LINE. C'est une période de meurtre de fin d'année Bien sûr dans le domaine libre

Constitution

 2019-12-26 14.41.32.png

Je n'ai jamais utilisé d'actions GitHub, donc je l'essaye Cependant, comme je n'utilise que la fonction cron, je pense que la fonction de déclenchement GAS est plus facile et meilleure si c'est tout.

Créer un compte de développeur LINE et enregistrer une application

Créé à partir d'ici https://developers.line.biz/ja/services/messaging-api

De plus, comme il existe un code QR de l'application enregistré sur l'écran de gestion de LINE Developer, enregistrez-le en tant qu'ami.

Créez un compte pour l'API météo

Permettez-moi d'utiliser l'API OpenWeatherMap

Créez un compte à partir d'ici https://home.openweathermap.org/users/sign_up

Code pour obtenir la météo et le pousser sur LINE

import os
import json
import pandas as pd
from dotenv import load_dotenv
from urllib.request import urlopen
from datetime import datetime
from pytz import timezone
from linebot import LineBotApi
from linebot.models import TextSendMessage


def get_weather_icon(icon_str):
    if icon_str == "01d" or icon_str == "01n":
        return "☀️"
    elif (
        icon_str == "02d"
        or icon_str == "02n"
        or icon_str == "03d"
        or icon_str == "03n"
        or icon_str == "04d"
        or icon_str == "04n"
    ):
        return "☁️"
    elif (
        icon_str == "09d" or icon_str == "09n" or icon_str == "10d" or icon_str == "10n"
    ):
        return "☂️"
    elif icon_str == "11d" or icon_str == "11n":
        return "⚡️"
    elif icon_str == "13d" or icon_str == "13n":
        return "☃️"
    else:
        return ""


def send_to_line(df):
    texts = []
    for k, v in df:
        texts.append(f"【{k}】")
        for _, d in v.iterrows():
            texts.append(
                f"{d['time']}Temps{get_weather_icon(d['icon'])} {d['temp']}(℃) {d['rain']}(mm/3h)"
            )
        texts.append("")

    line_bot = LineBotApi(os.getenv("LINE_ACCESS_TOKEN"))
    line_bot.push_message(
        os.getenv("LINE_USER_ID"), TextSendMessage(text="\n".join(texts))
    )


def main():
    url = "http://api.openweathermap.org/data/2.5/forecast"
    id = os.getenv("OWM_PLACE_ID")
    api_key = os.getenv("OWM_API_KEY")

    res = urlopen(f"{url}?id={id}&appid={api_key}&lang=ja&units=metric").read()
    res_json = json.loads(res)

    arr_rj = []
    for rj in res_json["list"]:
        conv_rj = {}
        timestamp = timezone("Asia/Tokyo").localize(datetime.fromtimestamp(rj["dt"]))
        conv_rj["date"] = timestamp.strftime("%m/%d %a")
        conv_rj["time"] = timestamp.strftime("%H")
        conv_rj["description"] = rj["weather"][0]["description"]
        conv_rj["icon"] = rj["weather"][0]["icon"]
        conv_rj["temp"] = round(rj["main"]["temp"])
        conv_rj["rain"] = round(rj["rain"]["3h"], 1) if "rain" in rj else 0
        arr_rj.append(conv_rj)

    send_to_line(pd.DataFrame(arr_rj).groupby("date"))


load_dotenv()
main()

Lorsque vous exécutez le code ci-dessus, l'application que vous avez enregistrée précédemment sera notifiée comme suit

 2019-12-25 15.30.35.png

Comme il existe de nombreux processus qui traitent les messages, c'est plutôt long si vous ne regardez que le code, mais si vous ne traitez que l'acquisition des informations météorologiques et poussez sur LINE, ce sera comme suit J'utilise python-dotenv pour définir des informations sécurisées telles que des jetons dans des variables d'environnement.

Obtenez des informations météorologiques (format JSON) à partir de l'API OpenWeatherMap


def main():
    url = "http://api.openweathermap.org/data/2.5/forecast"
    id = os.getenv("OWM_PLACE_ID")
    api_key = os.getenv("OWM_API_KEY")

    res = urlopen(f"{url}?id={id}&appid={api_key}&lang=ja&units=metric").read()
    ...

Cette fois, je voulais juste connaître la météo uniquement là où j'habite, j'ai donc passé l'ID de la zone où j'habite directement au paramètre ʻid. Vous pouvez vérifier l'ID de la région en téléchargeant city.list.json.gz depuis [ici](http://bulk.openweathermap.org/sample/). En plus de ʻid, il est également possible de spécifier lat (latitude), lon (longitudinal) et zip (code postal) comme paramètres pour obtenir le résultat (l'application que j'ai créée cette fois le prend en charge. N'est pas) Vous pouvez vérifier l'API_KEY depuis ici

Envoyer un message à LINE


def send_to_line(df):
    ...
    line_bot = LineBotApi(os.getenv("LINE_ACCESS_TOKEN"))
    line_bot.push_message(
        os.getenv("LINE_USER_ID"), TextSendMessage(text="Hello")

LINE_ACCESS_TOKEN peut être émis à partir de l'écran de gestion de LINE Developer Vous pouvez également vérifier LINE_USER_ID à partir du même écran de gestion.

Comment envoyer un message à plusieurs personnes (Ajouté le 28/12/2019)

Au moment de la rédaction de cet article, je pensais que tous ceux qui auraient enregistré l'application météo créée en tant qu'ami seraient informés du message, mais avec la méthode ci-dessus, je serai le seul informé du message. (Je suis désolé, je l'ai fait sans vérifier du tout cette zone.)

Rédigez une procédure à envoyer à des personnes autres que vous Pour envoyer à quelqu'un d'autre que vous-même, il vous suffit de connaître le UserID de l'expéditeur, mais c'est un peu gênant à savoir.

Lorsqu'une personne qui souhaite connaître l'ID utilisateur «enregistre une application en tant qu'ami», Line envoie une demande de publication à la fonction de rappel préparée ici et la confirme dans cette fonction. Je pense qu'il y a plusieurs façons, mais j'écrirai comme je l'ai fait ci-dessous

Préparer une fonction de rappel

Fabriqué avec du GAZ

var SLACK_ACCESS_TOKEN = ''

function doPost(e) {
  SlackApp.create(SLACK_ACCESS_TOKEN).postMessage(
    '#event-line',
    JSON.stringify(e),
    { username: 'kurosame-gas' }
  )
}

Vous pouvez également le vérifier avec console.log (e), mais comme il est difficile d'ouvrir GAS et de le vérifier à chaque fois, j'informe Slack. ʻE` contient des informations telles que l'ID utilisateur

Obtenir l'URL du Webhook

Vous pouvez publier en tant qu'API Web à partir de Publier-> Déployer en tant qu'application Web à partir de l'écran GAS. À ce stade, la plage de divulgation doit être «tout le monde (y compris anonyme)» Notez l'URL de l'application telle qu'elle apparaîtra à l'écran lorsque vous la publiez.

Paramètres d'URL du webhook

Il peut être défini sur l'écran de gestion de LINE Developer comme suit

 2019-12-28 23.14.45.png Ce n'est pas grave si vous exécutez Verify et obtenez SUCCESS

En passant, veuillez également définir ce qui suit sur Désactivé sur le même écran

 2019-12-28 23.16.18.png

Contrôle de fonctionnement

Si vous envoyez un personnage sur l'écran de discussion de l'application Line créée et que les informations telles que le personnage et votre ID utilisateur arrivent à Slack, l'opération réussit. De plus, si quelqu'un d'autre enregistre votre application en tant qu'ami, Slack sera averti afin que vous puissiez obtenir l'ID utilisateur de cette personne.

Code modifié pour passer de Python à LINE

#Changer avant
line_bot.push_message(
    os.getenv("LINE_USER_ID"), TextSendMessage(text="\n".join(texts))
)

#Après le changement
line_bot.multicast(
    os.getenv("LINE_USER_ID").split(","), TextSendMessage(text="\n".join(texts))
)

Définissez UserID pour LINE_USER_ID séparés par des virgules.

Courir régulièrement

Utilisez la fonction cron de GitHub Actions pour définir la météo afin de vous avertir chaque matin à 7 heures du matin Vous trouverez ci-dessous le fichier yaml chargé par Actions Vous pouvez utiliser les actions GitHub simplement en plaçant les fichiers suivants dans le répertoire .github / workflows sur le répertoire racine.

name: Weather

on:
  schedule:
    - cron: '00 22 * * *' # UTC

jobs:
  weather:
    name: Run weather
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Setup Python
        uses: actions/setup-python@v1
        with:
          python-version: 3.7
      - name: Install Pipenv
        uses: dschep/install-pipenv-action@v1
      - name: Install dependencies
        run: pipenv sync
      - name: Run weather
        env:
          OWM_PLACE_ID: ${{ secrets.OWM_PLACE_ID }}
          OWM_API_KEY: ${{ secrets.OWM_API_KEY }}
          LINE_ACCESS_TOKEN: ${{ secrets.LINE_ACCESS_TOKEN }}
          LINE_USER_ID: ${{ secrets.LINE_USER_ID }}
        run: pipenv run python3 ./bots/weather.py

Puisque nous utilisons des variables d'environnement dans notre code Python, nous devons les rendre disponibles sur le serveur Actions. Vous pouvez définir des variables d'environnement qui peuvent être utilisées dans des actions à partir de l'onglet Paramètres-> Secrets dans le référentiel GitHub. Et comme mentionné ci-dessus, nous utilisons le contexte secrets pour permettre aux coureurs d'utiliser des variables d'environnement.

Après l'avoir utilisé, j'étais un peu inquiet que le timing de l'exécution du Workflow soit environ 5 à 6 minutes plus tard que l'heure spécifiée par cron.

à la fin

Ma femme utilise généralement LINE, il semble donc que cette application sera utilisée. (Lorsque j'ai utilisé l'application mémo qui peut être utilisée sur Slack auparavant, il était difficile de démarrer Slack et j'ai arrêté de l'utiliser)

Le code implémenté cette fois-ci est donné ci-dessous https://github.com/kurosame/bots-python

Recommended Posts

Créez une application qui informe LINE de la météo tous les matins
LINE Bot qui vous informe des stocks d'intérêt
J'ai créé une application avec Lambda qui notifie LINE de "j'aime" à l'aide de l'API Qiita.
Créez une application qui devine les étudiants avec Python
Avec LINEBot, j'ai fait une application qui m'informe de "l'heure du bus"
Créez une application qui fonctionne bien avec les rapports des utilisateurs à l'aide de l'API COTOHA
Comment créer un article à partir de la ligne de commande
Créez une application qui devine les étudiants avec la version python-GUI
Créons une application qui authentifie OIDC avec Azure AD
J'ai créé un robot Line qui devine le sexe et l'âge d'une personne à partir de l'image
J'ai fait un bot mou qui m'informe de la température
(Python) J'ai créé une application de Trello qui notifie périodiquement le relâchement des tâches sur le point d'expirer.
Une extension de l'application de peinture Kivy
Déploiement Heroku de la première application Django à laquelle les débutants sont accros
Comment créer un wrapper qui préserve la signature de la fonction à envelopper
[Python] J'ai créé une application qui télécharge automatiquement le fichier audio de chaque mot utilisé pour l'application d'étude d'anglais.
Créez une application simple qui intègre l'API Fetch pour les requêtes Ajax dans Flask et expliquez-la rapidement.
Création d'un bot Slack qui confirme et notifie à AWS Lambda la date d'expiration d'un certificat SSL