[PYTHON] [Google Photo & Slack Photo Bot] Une histoire sur la création d'un bot qui acquiert une photo dans Google Photo et l'envoie à Slack.

Préface

«Je voulais devenir ingénieur en développement à l'automne de ma deuxième année d'université, alors j'ai commencé l'auto-apprentissage en programmation. --J'ai rejoint l'entreprise en août 2017 en tant qu'ingénieur serveur. Nous développons avec Rails. ――Pour la première fois, j'ai développé en Python. ――Depuis que je suis un débutant en programmation, j'ai lu Qiita et j'ai toujours voulu écrire un article facile à comprendre, donc je vais l'écrire d'une manière facile à comprendre. (Ce sera plus long, mais j'espère que vous comprenez.) Ici, je vais écrire sur les API et les modules que j'utilise. ―― Tout le code est publié sur github et l'url est collée, donc si vous voulez voir le code, veuillez le déplacer vers le bas.

Pourquoi j'ai décidé d'écrire un article

--Un jour, sur le canal aléatoire de slack, une entreprise qui travaille comme stagiaire pour le développement PHP jusqu'en juillet 2017. --CEO "Je pensais, mais s'il y a un robot qui tire au hasard une photo de google photo par jour et la jette à #random, il semble qu'il va augmenter. @CTO @CTO @CTO @CTO @CTO @CTO Vous êtes occupé, non? --CTO "CS n'a pas d'autre choix que de le faire lol" «Je regardais ce slack" Ah ..., je peux y arriver? "

De cette façon, j'ai décidé de faire un bot photo, mais je pensais que c'était difficile ... à ce moment, il y a encore un long chemin à parcourir. Je suis souvent coincé, alors j'ai décidé d'écrire un article. (La raison d'écrire en Python est que je voulais étudier parce que c'était un langage que je n'avais jamais écrit personnellement, car le CTO aime Python lol)

objectif

Comme le montre l'image ci-dessous, appelez le bot appelé gallery, entrez gallery, puis laissez l'image s'écouler.

Regardons le traitement un par un.

procédure

  1. Créez un utilisateur de bot dans Slack
  2. Installez la bibliothèque Bot implémentée en Python
  3. Installez le module gdata
  4. Authentification Google Auth (obtention de photos à partir de Google Photo)
  5. Publiez du texte et des photos sur Slack à l'aide de Rtmbot et de l'API Slack.

Environnement de développement

--Python 2.7 (Préparer l'environnement de développement avec pyenv)

1. Créez un utilisateur Bot dans Slack

Tout d'abord, créez un utilisateur Bot sur la page Slack Apps. Celui écrit en rectangle rouge est un jeton de bot, alors copiez-le ailleurs. スクリーンショット 2019-06-22 12.44.19.png

2. Installez la bibliothèque Bot implémentée en Python

Installez la bibliothèque de gestion de bot open source via pip (https://github.com/slackapi/python-rtmbot)

$ pip install rtmbot 

Après cela, créez rtmbot.conf et modifiez-le comme indiqué ci-dessous.

rtmbot.conf


# Add the following to rtmbot.conf
 DEBUG: True # make this False in production

 # 1.Veuillez écrire ici le jeton du Bot créé à l'époque.
 SLACK_TOKEN: "xoxb-11111111111-222222222222222"

  #Écrivez le chemin du Bot ici.(Entre les noms des répertoires/ne pas,.Écrivons.)
 ACTIVE_PLUGINS:
     - plugins.google_photo_to_slack.GooglePhotoToSlackBot

3. Installez le module gdata

$ pip install gdata

4. Authentification Google OAuth (obtention de photos à partir de Google Photo)

Ici, nous allons vous expliquer comment utiliser l'authentification Google OAuth 2.0.

Tableau de bord Google Cloud Platform-> Utiliser les API Google-> Identifiants, client OAuth2.0 Créez un ID et téléchargez son fichier json secret. Sélectionnez "Autre" comme type.

スクリーンショット 2017-08-11 20.19.37.png

À mesure que le nombre de fichiers a augmenté, la structure des répertoires est la suivante. Pour l'instant, vous n'avez rien à écrire sur le contenu de credentials.dat.

rtmbot
├── photo-gallery.json
├── credentials.dat
├── plugins
│   ├── __init__.py
│   └── google_photo_to_slack.py
├── rtmbot.conf
└── rtmbot.log

Tout d'abord, pour confirmer votre connexion, écrivez quelque chose comme ce qui suit. Si l'un des modules répertoriés dans le fichier ci-dessous n'est pas installé, installez-le.

google_photo_to_slack.py


#!/usr/bin/python2.7
 
# module ----  
import os
import webbrowser
from datetime import datetime, timedelta
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
import gdata.photos.service
import gdata.media
import gdata.geo
import httplib2
import json
import urllib2
 
# Google Authetication
def OAuth2Login(client_secrets, credential_store, email):
    scope='https://picasaweb.google.com/data/'
    user_agent='picasawebuploader'
    storage = Storage(credential_store)
    credentials = storage.get()
 
    if credentials is None or credentials.invalid:
        flow = flow_from_clientsecrets(client_secrets, scope=scope, redirect_uri='urn:ietf:wg:oauth:2.0:oob')
        uri = flow.step1_get_authorize_url()
        webbrowser.open(uri)
        code = raw_input('Enter the authentication code: ').strip()
        credentials = flow.step2_exchange(code)
        storage.put(credentials)
 
    if (credentials.token_expiry - datetime.utcnow()) < timedelta(minutes=5):
        http = httplib2.Http()
        http = credentials.authorize(http)
        credentials.refresh(http)
 
    gd_client = gdata.photos.service.PhotosService(source=user_agent,
                                               email=email,
                                               additional_headers={'Authorization' : 'Bearer %s' % credentials.access_token})
    return gd_client
 

# main ----- 
if __name__ == '__main__':
    email = os.environ['EMAIL']
    confDir = os.path.abspath(os.path.dirname(__file__))
    client_secrets = os.path.join(confDir, 'photo-gallery.json') 
    credential_store = os.path.join(confDir, 'credentials.dat') 
    gd_client = OAuth2Login(client_secrets, credential_store, email)
 
    albums = gd_client.GetUserFeed()
    for album in albums.entry:
        print 'Album: %s (%s)' % (album.title.text, album.numphotos.text)
 
        photos = gd_client.GetFeed('/data/feed/api/user/default/albumid/%s?kind=photo' % (album.gphoto_id.text))
        for photo in photos.entry:
            print(photo.title.text)
            f = open(photo.title.text, 'w')
            f.write(urllib2.urlopen(photo.content.src).read())
            f.close()

Et quand je lance le fichier ci-dessus,

$ python google_photo_to_slack.py

Comme indiqué ci-dessous, le navigateur affichera une page de photos et la console vous demandera de saisir le code d'authentification affiché dans le navigateur.

Enter the authentication code: 

Entrez le code d'authentification affiché sur le navigateur pour terminer la connexion.

encore une fois,

$ python google_photo_to_slack.py 

Si vous exécutez, toutes les photos de google photo seront téléchargées.

5. Publiez du texte et des photos sur Slack à l'aide de Rtmbot et de l'API Slack.

Modifiez le fichier Google PhotoToSlack ci-dessus comme ci-dessous.

GooglePhotoToSlackBot.py


class GooglePhotoToSlackBot (Plugin):
    MEDIA_ARR = []
    RANDOM_NUMBER = 0
    EMAIL = os.version['EMAIL']
    CHANNEL_POST = ''
    SLACK_BOT_TOKEN = os.version['SLACK_BOT_TOKEN']

    PLUGIN_CHILD_DIRECTORY = os.path.abspath(os.path.dirname(__file__))
    PLUGIN_DIRECTORY = os.path.abspath(
        os.path.join(PLUGIN_CHILD_DIRECTORY, os.pardir)
    )
    RTMBOT_DIRECTORY = os.path.abspath(
        os.path.join(PLUGIN_DIRECTORY, os.pardir)
    )
    CLIENT_SECRETS = os.path.join(RTMBOT_DIRECTORY, os.version['SECRET_JSON'])
    CREDENTIAL_STORE = os.path.join(
        RTMBOT_DIRECTORY, os.version['CREDENTIAL_DAT']
    )

    def process_message(self, data):
        feedback_pattern = re.compile(
            #Ici, entrez l'id du bot commençant par U affiché dans l'api de la liste des utilisateurs slack
            r'.*<@UAAAAAAA.*(gallery).*', re.DOTALL | re.IGNORECASE
        )

        if not (re.match(feedback_pattern, data['text'])):
            return

        self.CHANNEL_POST = data['channel']

        message = u"L'image d'aujourd'hui/Je télécharge la vidéo! S'il te plaît attend un moment!"
        message += "Pour les vidéos, le téléchargement peut prendre un certain temps."
        response = self.slack_client.api_call(
            "chat.postMessage",
            channel=self.CHANNEL_POST,
            text=message,
            link_names=1,
            as_user=True
        )

        self.fetch_all_media()
        self.post_random_media()

    def oauth_login(self, client_secrets, credential_store, email):
        scope = 'https://picasaweb.google.com/data/'
        user_agent = 'picasawebuploader'
        storage = Storage(credential_store)
        credentials = storage.get()
        now_time = datetime.utcnow()

        if credentials is None or credentials.invalid:
            flow = flow_from_clientsecrets(
                client_secrets,
                scope=scope,
                redirect_uri='urn:ietf:wg:oauth:2.0:oob'
            )
            uri = flow.step1_get_authorize_url()
            webbrowser.open(uri)
            code = raw_input('Enter the authentication code: ').strip()
            credentials = flow.step2_exchange(code)
            storage.put(credentials)

        if (credentials.token_expiry - now_time) < timedelta(minutes=5):
            http = httplib2.Http()
            http = credentials.authorize(http)
            credentials.refresh(http)

        gd_client = gdata.photos.service.PhotosService(
            source=user_agent,
            email=email,
            additional_headers={
                'Authorization': 'Bearer %s' % credentials.access_token
            }
        )

        return gd_client

    def fetch_all_media(self):
        gd_client = self.oauth_login(
            self.CLIENT_SECRETS,
            self.CREDENTIAL_STORE,
            self.EMAIL
        )

        albums = gd_client.GetUserFeed()
        for album in albums.entry:
            medias = gd_client.GetFeed(
                '/data/feed/api/user/default/albumid/%s' %
                (album.gphoto_id.text)
            )
            for media in medias.entry:
                self.MEDIA_ARR.append(media)

    def get_random_number_in_array(self, arr):
        max_length = len(arr)
        return random.randint(0, max_length)
               
    def post_random_media(self):
        self.RANDOM_NUMBER = self.get_random_number_in_array(self.MEDIA_ARR)
        media_object = self.MEDIA_ARR[self.RANDOM_NUMBER]
        media_file = open(media_object.title.text, 'wb')
        media_file.write(response.content)
        media_file.close()
        media_path = self.RTMBOT_DIRECTORY + "/" + media_object.title.text

        with open(media_path, 'rb') as f:
            param = {
                'token': self.SLACK_BOT_TOKEN,
                'channels': self.CHANNEL_POST,
                'title': u'Today\'s ' + media
            }
            r = requests.post(
                "https://slack.com/api/files.upload",
                params = param,
                files = {'file': f}
            )

Ensuite, dans le répertoire rtmbot, entrez la commande rtmbot pour lancer le serveur rtmbot. Ensuite, dans Slack, saisissez @gallery. (N'importe quelle chaîne convient.)

$ rtmbot

Téléchargez l'image / vidéo d'aujourd'hui dans le code ci-dessus! S'il te plaît attend un moment! Si la photo coule dans le mou, le bot photo est terminé !!

Tous les codes

J'ai posté sur github avec diverses fonctions (comme la suppression de photos pour que les photos téléchargées ne soient pas accumulées), j'espère donc que vous pourrez le voir si vous êtes intéressé. https://github.com/romukey/PythonAlgorithm/blob/master/google_gallery/plugins/google_photo_to_slack.py

Référencé

Documentation de l'API Web Picasa https://developers.google.com/picasa-web/docs/1.0/developers_guide_python

Comment se connecter à Google OAuth https://stackoverflow.com/questions/30474269/using-google-picasa-api-with-python

Recommended Posts

[Google Photo & Slack Photo Bot] Une histoire sur la création d'un bot qui acquiert une photo dans Google Photo et l'envoie à Slack.
Une histoire reliant Slack et la feuille de calcul Google
L'histoire de la création de Botonyan qui renvoie le contenu de Google Docs en réponse à un mot-clé spécifique sur Slack
Une histoire d'essais et d'erreurs essayant de créer un groupe d'utilisateurs dynamique dans Slack
Une histoire qui reflète l'activité Discord dans Slack Status
Une histoire sur la façon de spécifier un chemin relatif en python.
Une histoire sur tout, de la collecte de données au développement d'IA et à la publication d'applications Web en Python (3. développement d'IA)
L'histoire de la création d'un Bot qui affiche les membres actifs dans un canal spécifique de Slack avec Python
Une histoire sur une erreur de construction dans une bibliothèque partagée qui fait référence à libusb
Ecrire un programme qui abuse du programme et envoie 100 e-mails
Comment créer un bot slack
Créez un bot qui publie sur Slack le nombre de personnes positives pour le nouveau virus corona à Tokyo
Une histoire sur la création d'un programme qui augmentera le nombre d'abonnés Instagram de 0 à 700 en une semaine
Une histoire d'essayer d'exécuter JavaScripthon sur Windows et d'abandonner.
L'histoire de l'abandon d'essayer de se connecter à MySQL en utilisant Heroku
Une histoire sur Python pop and append
Une histoire d'essayer d'installer uwsgi sur une instance EC2 et d'échouer
L'histoire de la fabrication d'une boîte qui interconnecte la mémoire AL de Pepper et MQTT
L'histoire de la création d'un Line Bot qui nous raconte le calendrier de la programmation du concours
En Python, j'ai créé un LINE Bot qui envoie des informations sur le pollen à partir des informations de localisation.
J'ai essayé de créer un chargeur de démarrage x86 qui peut démarrer vmlinux avec Rust
Je veux un bot Slack qui calcule et me dit le salaire d'un emploi à temps partiel à partir du calendrier de Google Agenda!