エンジニアリング

へたれエンジニアがTwitterで不穏なつぶやきがあったらサイレンを鳴らしてみた(CloudFunctions GCP python)

どーもヘタレエンジニアまる です。

サービス運営とかやっている時にシステムアラートがなってないのに何故か止まっていた!みたいな事たま〜にありますよね(いや、ログ設計ちゃんとしろよというツッコミは認めます・・・笑)

そういう時に役立つのはTwitterです。ということでソーシャルアラートを鳴らしてみることをしてみました。

DIYの第1弾は監視カメラを作りました、興味があればそちらもどうぞ。

Raspberry Piを使った格安監視カメラシステムを作った!実家に帰省してます。今回は片手に「Raspberry Pi」を携えております・・・・・ 田舎の古民家に監視カメラを設置しよう 実...

第二弾は手抜きシステム

自分が投資したい株式投資銘柄をスクリーニングツールから抽出→メール通知させてみた。手抜き感炸裂のseleniumとjenkinsで!どーもヘタレエンジニア まる です。 最近スノーボードなどでお金を使いすぎていることもありちょっと財テクを日曜大工的にやってみよう第2弾...

第三弾はLineBot

LINEのbotを使って家庭の家事業務を円滑にすることをGCPのCloud Functions を使ってやってみた(python3)どーもヘタレエンジニアまる です。 我が家は共働き家庭でして家事分担でよく揉めます、ケンカになることもしばしば。 ということ...

ルンバさんハックはこんなこともやってます

(へたれエンジニアの引っ越し)新しいラグを買ったらルンバが動かなくなった・・・引っ越しシリーズです (へたれエンジニアの引っ越し)物件を探す時に面倒なのでチャット不動産を試してみた (へたれエンジニアの引っ...
Arduinoでルンバのバーチャルウォールを作ってみたどーもヘタレエンジニアまる です。 夏休み真っ盛りですが、僕は実家への帰省くらいであまり遊びに出かけてません。溶けますからね。。 ...

システム概要

今回のシステムはこんな感じです

  1. 10分に1回APIを叩く
  2. APIではTwitter上で指定キーワードで10分以内のツイートを取得します
  3. 2件以上あったらtrueをjsonに返します
  4. trueが帰ってきたらパトランプとけたたましいサイレンがブラウザ上でなります

動画は以下をお借りしました(動画にサイレン音を付与させていただきローカル実行しており、再配布してません今回のサンプルコードにも添付してません)

APIを作ってみましょう

TwitterのAPIを叩くための事前設定はググってください 完了したところから始めます。

今回は、GCPのCloud FunctionsでAPIを作成します

twitter-reaction.py

from requests_oauthlib import OAuth1Session
import json
import datetime
from pytz import timezone
import flask



def main(request):
    ck = "Twitterのコンシューマキー"
    cs = "Twitterのコンシューマーシークレット"
    at = "Twitterのアクセストークン"
    ats = "Twitterのアクセスシークレット"
    twitter = OAuth1Session(ck, cs, at, ats)

    #twitterの検索用のAPI
    url = "https://api.twitter.com/1.1/search/tweets.json"

    #GCPだとUTC標準時になってしまうためタイムゾーンを日本に設定した上で本日日付を取得
    dt = datetime.datetime.now(timezone('Asia/Tokyo'))
    #10分前算出
    dt2 = dt + datetime.timedelta(minutes=-10)

    #検索条件をリツイートを除いて設定 コードが動いた時間から10分前以降のツイートを取得
    #retweetは除く JSTをつけることで日本時間で検索が出来る
    #TwitterAPIにおいては時分秒はAPIリファレンス上では検索出来ることは書いてないが可能
    query = '検索ワード1 検索ワード2 exclude:retweets since:' + dt.strftime('%Y-%m-%d') + "_" + dt2.strftime('%H:%M:%S') + "_JST"

    params = {
                'q' : query,
                'count': 3
    }

    str = ""
    res = twitter.get(url, params = params)


    if res.status_code == 200:
        res = json.loads(res.text)

        #デバッグ用にツイートログ出力
        for line in res['statuses']:
            print(line['text'])
            print(line['created_at'])

        #sutatusesが2件以上あったら検索にひっかかっているということ
        #headerにはCORS対策でAccess-Control-Allow-Originをallにしている
        if len(res['statuses']) > 1:

            response = flask.jsonify(result="true")
            #
            response.headers.set('Access-Control-Allow-Origin', '*')
            response.headers.set('Access-Control-Allow-Methods', 'GET, POST')
            return response

        else:
            response = flask.jsonify(result="false")
            response.headers.set('Access-Control-Allow-Origin', '*')
            response.headers.set('Access-Control-Allow-Methods', 'GET, POST')
            return response

    else:
        return "エラー"

requirement.txt

# Function dependencies, for example:
# package>=version
requests-oauthlib
flask

ポイントは以下3点

  1. GCPだとUTC標準時になってしまうためタイムゾーンを日本に設定した上で本日日付を取得
  2. TwitterAPIにおいては時分秒はAPIリファレンス上では検索出来ることは書いてないが可能なので設定した上で_JSTをつけて日本時間にする
  3. CORS対策でAccess-Control-Allow-Originをallにしている

これで出来ました

フロント画面を作ってみましょう

index.html

<!DOCTYPE HTML>
<html lang="ja-JP">
<head>
  <meta charset="UTF-8">
</head>
<body>


<h1 id="status_mohji">現在Twitter上でXXXXXXは平穏です</h1>
<video controls id="myVideo" width="400px" height="224px">
  <source src="./ramp1.mp4"  type="video/mp4" width="400px" height="224px">
</video>

<script type="text/javascript" src="./main.js"></script>

</body>

main.js

//10分に1回ブラウザを自動リロードさせる
const timer = 600000
window.addEventListener('load',function(){
  setInterval('location.reload()',timer)
})


window.onload = function(){
  //リクエスト変数
  var req = new XMLHttpRequest();
  req.open("GET", "CloudFunctionsのURL", true);
  req.send("");
  req.onreadystatechange = function() {
  var video = document.getElementById("myVideo");
  var str = document.getElementById("status_mohji");
  if (req.readyState == 4) { // 通信の完了時
    if (req.status == 200) { // 通信の成功時
      json = req.responseText;
      twitter = JSON.parse(json);
      console.log(json);
      if (twitter.result == "true") {
        video.play();
        str.textContent = "TwitterでXXXにおいて問題が起きています!";
      } else {
        str.textContent = "現在Twitter上でXXXXは平穏です";
      }
    }
  }else{
  }
  }
};

ポイントは以下2点

  1. ブラウザは10分に1回リロードさせている
  2. GCPへjsからコールしてきてjsonを取得{result:true or false}

これでやってみたんですが GoogleChromeのみ音声が鳴らないです、こちらChromeの仕様が変わってしまって突如音がなるということはGoogle先生的には駄目になってしまったみたいです。つれないねぇ・・・・・・

参考:Google Chromeで動画が再生されない

とまぁこんな感じで

結構カンタンにソーシャルアラートを作ることが出来ました。

サーバーレスで気軽に作れるので気軽度高いですよね。

今度はこれをArduinoなどを使って本物のパドランプをまわしてみたいと思います。

みなさんも楽しいアラートライフをお送りください(楽しいのか??はおいておきましょう)