【Python】苦闘、丸3日。Google Cloud Function (コード実行環境）を使って、Twitterの自動リツイートを実装した話。

こんばんは！
表題の件ですが、こんなの簡単に出来るだろうと思っていたのですが、非常に嵌りました。
詰まったところを含めて、設定及びコードを公開します。
正直、かなり試行錯誤しました。間違っている所がありましたら、是非、御指摘ください。　私の苦難が皆様のお役に立てます様に。。。。


１．状況
一週間前に下記の記事を書きました。
ローカル環境で、Twitterのツイートを自動RetweetするBOTを、Pythonで構築しました。
⇒　[Python] Tweepyモジュールで、Tweeterのツイートを自動でretweetするBOTを超簡単に作成する方法　https://qiita.com/naiveprince0507/items/ea66eab7422fa8c682f5

自分のローカル環境では順調に動くのですが、当然ですが、PCの電源を落としたりすれば、プログラムが動かなくなります。これでは、BOTとしてはイマイチですよね。
と言う事で、クラウド環境で、このコードを、24時間/365日、動かし続けようと言うのが、今回のプロジェクトになります。

２．Google Cloud Functionについて。
Googleのサーバレス環境で構築します。（要は、PaaS環境です。）
尚、Googleでは、Cloud RunとCloud Functionと言う２種類のサーバレス環境が用意されております。
詳しい違いは下記サイトに書いておりますが、私の理解では、「簡単な関数（今回の様に、Pythonの単純なプログラムを動かす場合等）では、Cloud Functionを使い、コンテナ環境を構築し、複雑な処理をするプログラムを動かすなら、Cloud Runを使うべし。」と言う理解です。
https://cloud.google.com/blog/ja/topics/developers-practitioners/cloud-run-story-serverless-containers
今回は、Cloud Functionを使います。これは、AWSでは、Lambdaに相当します。（多分）


３．ローカルで動いているコード（「原文」と称する）

```.py
import tweepy
import time
from requests_oauthlib import OAuth1Session

CK = "Your Consumer Key"
CS = "Your Consumer Secret Key"
AT = "Your Access Token"
ATS = "Your Access Token secret"
twitter = OAuth1Session(CK, CS, AT, ATS)

def retweet(tweetId):
    url = "https://api.twitter.com/1.1/statuses/retweet/%s.json"%tweetId
    res = twitter.post(url) # retweet実行
    return res

def unretweet(tweetId):
    url = "https://api.twitter.com/1.1/statuses/unretweet/%s.json"%tweetId
    res = twitter.post(url) # unretweet実行
    return res

# リツイートしたいIDのリスト
#tweetIds = [line.strip() for line in open('retweetList.txt',encoding='utf-8')]

# リツイート履歴を保存する準備
retHist = {}

from time import time
def retweetProcess():
    ### 最後にリツイートした時間が最も遠いものを選ぶ ###
    # IDと時刻のペアをリスト化
    idTimes = [(tid,retHist[tid] if tid in retHist else 0) for tid in tweetIds]

    # 最後にリツイートした時刻でソート
    idTimes = [idt for idt in sorted(idTimes, key=lambda x:x[1])]

    # 最後にリツイートした時刻が最も古いツイートを選択
    tweetId = idTimes[0][0]

    # 一度解除してからretweet
    resUnrt = unretweet(tweetId)
    resRt = retweet(tweetId)

    # 処理内容を表示
    print(tweetId, resUnrt, resRt)

    # 現在の時刻で辞書の値を更新
    retHist[tweetId] = time()

from time import sleep
while True:
    sleep(60*15)  # これは15分毎にリツイートです。
    retweetProcess()
```




４. GCFで設定

Google Cloudにログオンして、GCFを設定します。
![0925x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/1465f43c-cf53-28aa-5dd0-5f583c648094.jpeg)

保存ボタンを押すと、「次へ」ボタンが出現します。
![0925y.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/e3246a53-844c-3d78-e22b-8659bf2761c3.jpeg)

「エントリーポイント」ですが、実行したい関数名(ここでは、retweetProcess)と一致させる必要があります。（ここで、丸１日詰まりました。）
![0925z.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/c540ec80-55e6-0bdb-4fb6-b8238d08a8d8.jpeg)


また、29行目のコードですが、３の「原文」では、引数不要でしたが、ここでは、"self"を入れないとエラーになります。（原因を調査中です。）
![0925c1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/c76cb426-47af-5879-d5ab-720071c68f25.jpeg)
![0925c5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/4ef77101-3db8-0942-6f84-4f31c56f32b2.jpeg)
で、この"Requirements.txt"とは何ぞやとの事ですが、ここをキチンと設定しないとエラーになります。（ここで、丸一日費やしました。）
ここに詳しいです。（要は、インストールするモジュールを列記する必要があります。）
https://qiita.com/sakusaku12/items/21083c73c8afa4f6c78d
![0925c2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/6eed0745-f1a4-8ccc-ac1b-a09164f7b99a.jpeg)
最後は、リツイートしたいTwitterのTweetIDを並べます。
![0925c3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/cecfba75-a2e4-404b-8e98-e833ca370e92.jpeg)

で、最終工程です。
トリガーを叩くと（URLサイトにアクセスすると）、プログラムが起動して、下記の画面が出る事を確認した。（正常な動作です。）
https://qiita.com/toshiaki_takase/items/ce65cd5582a80917b52f
![0925c4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/b0807b67-66b3-2ae9-0a97-8ce0ae250035.jpeg)

スケジューラーで、１時間に１回、上記URLを叩くように、Google Schedulerで設定します。（これは、超簡単）
![0925c6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/e5aa35cf-9d38-3c0b-8681-f9e42edae672.jpeg)


５．懸念点／継続調査事項
１）GCFのmain.pyの29行目のコードですが、３の「原文」では、引数不要だったが、GCFこには、"self"を入れないとエラーになる。（原因を調査中です。）

２）トリガーを叩くと（URLサイトにアクセスすると）、プログラムが起動して、下記の画面が出る事を確認した。（正常な動作です。）
（ただ、設定中に、下記サイトの様なアクセス権エラーが出たので、下記サイトの方法で解決したが、こんなにガバガバで良いのか？ 継続調査中）
https://qiita.com/toshiaki_takase/items/ce65cd5582a80917b52f
![0925c4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/b0807b67-66b3-2ae9-0a97-8ce0ae250035.jpeg)