2017年9月8日金曜日

TwitterとPythonでRaspberry Piを再起動する

Python用Twitter APIラッパーTweepyでツイートを取得してみた(Python3でTwitterのデータを取得する)が、このときに取得したのは過去のツイート。Twitter APIにはリアルタイムにツイートを取得できるStreaming APIがあり、Tweepyでもそれを利用できる。例えば、スマホから自分宛にTwitterのダイレクトメッセージを送ると、そのメッセージをRaspberry Piでリアルタイムに受け取ることができる。この機能を利用して、Twitterを使ってRaspberry Piを再起動してみる。


環境


Raspberry PiとRaspbian Jessie。



事前準備


Twitter APIの利用に必要なAPIキーとトークン、それにTweepyのインストールについてはPython3でTwitterのデータを取得するを参照。


コーディング


TweepyでStreaming APIを使うサンプルコードはStreaming With Tweepyにあり、ツイートを取得するならサンプルの方法で問題ないが、ダイレクトメッセージを受け取るにはon_statusではなくon_dataメソッドを使う。自分宛てにダイレクトメッセージで再起動コマンドを送り、Raspberry Piでコマンドを受信したら再起動する。

import os
import json
import tweepy

# Twitter APIの認証情報
# Twitterの開発者向けのページで取得したキーとトークンを使う
CONSUMER_KEY = 'Consumer Key'
CONSUMER_SECRET = 'Consumer Secret'
ACCESS_TOKEN = 'Access Token'
ACCESS_TOKEN_SECRET = 'Access Token Secret'

class MyStreamListener(tweepy.StreamListener):
    """
    Streaming APIで取得したデータを処理するクラス
    """

    """
    def on_status(self, status):
        #on_statusでツイートは取得できるが、Direct Messageはできない
        print('@{} {}'.format(status.author.screen_name, status.text))
    """

    def on_data(self, status):
        # Direct Messageはon_dataでないと取得できない

        # Direct Messageのみを処理する
        if 'direct_message' in status:
            # JSONから辞書型に変換
            dm = json.loads(status)['direct_message']

            # 送信者と受信者の一致をチェック
            # 他人からのDirect Messageに反応しないようにするため
            if dm['sender_screen_name'] == dm['recipient_screen_name']:
                print('DM: {} from @{}'.format(dm['text'], dm['sender_screen_name']))

                # rebootを受信したら再起動する
                if dm['text'] == 'reboot':

                    # Direct Messageを送信
                    api = tweepy.API(auth)
                    api.send_direct_message(screen_name=dm['sender_screen_name'], text='The system is going down for reboot!')

                    # OSを再起動
                    os.system('sudo reboot')

    def on_error(self, status_code):

        # Twitter APIの使用制限を超えた場合
        if status_code == 420:
            print('Error code: {}'.format(status_code))
            # Falseを返すとstreamを切断する
            return False

    def on_timeout(self):
        print('Timeout')
        # Trueを返すとstreamを切断しない
        return True

# 認証情報の設定
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

# Streamオブジェクトの作成
stream = tweepy.Stream(auth, MyStreamListener())

# User Streamを取得
stream.userstream()


Twitterからコマンドを送ってRaspberry Piを再起動してみる


上記コードをRaspberry PiのPython3で実行し、スマホのTwitterから自分宛に「reboot」と送信する。すると、Raspberry Piから「The system is going down for reboot!」というダイレクトメッセージが送信され、Raspberry Piが再起動する。



注意事項


User Streamの取得方法は、今後Streaming APIからAccount Activity APIに変わるらしい(Streaming APIs)。Tweepyが対応するかは不明なので、しばらくしたらTweepyを使わない方法を考える必要があるかもしれない。


バックグランド実行


ターミナルから実行した場合、ターミナルを閉じるとPython3のプロセスが終了してしまう。nohupコマンドを使うとターミナルが閉じても実行し続けることができる。



おまけ


Raspberry PiとPython3でPCを起動するにあるWOL用のマジックパケットを送信するPythonコードを使うと、Twitterのダイレクトメッセージを使ってRaspberry PiからPCを起動させることもできる。

0 件のコメント:

コメントを投稿