技術書典16でChatGPT本を出します!(ここをクリック)

【Python】Mastodonにトランジット月の運行を流すBOTを作った

Q.なんで作ったの?
A.月の運行やルナリターンのタイミングを知りたかったので

ということで作ったやつは下記のリンクになります。

月星座BOT (@moonbot@ariesmc21.com) – 相戸ゆづなの新放牧地

目次

作ったプログラム

長いので折りたたんでます
import swisseph as swe  
import datetime  
from mastodon import Mastodon  

mastodon = Mastodon(  
    client_id='クライアントID',  
    client_secret='シークレットキー',  
    access_token="アクセストークン",  
    api_base_url="ドメイン"  
)  


def calculate_moon_position(date: datetime.date, time: datetime.time, timezone: int):  
    # 日付をUTC・ユリウス暦に変換  
    utc = swe.utc_time_zone(date.year, date.month, date.day, time.hour, time.minute, time.second, timezone)  
    jul = swe.utc_to_jd(*utc)  

    # 月の位置を計算  
    moon_calc = swe.calc(jul[0], 1)  
    return moon_calc  


def time_word_calc(now: datetime.time):  
    if now < datetime.time(12, 0, 0):  
        time = datetime.time(11, 59, 0)  
        word = "午前"  

    else:  
        time = datetime.time(23, 59, 0)  
        word = "午後"  
    return time, word  


def determine_moon_sign(moon: int):  
    # 星座  
    zodiac_sign = (  
        "牡羊座", "牡牛座", "双子座", "蟹座", "獅子座", "乙女座", "天秤座", "蠍座", "射手座", "山羊座", "水瓶座",  
        "魚座")  

    # 星座判定(360度の円を12等分している。1つの星座につき30度)  
    idx = int(moon // 30)  
    if idx < 0 or idx > 11:  
        raise ValueError(f"moon は360以下の整数である必要がある: {moon}")  # エラーで原因が分かるようにする  
    return zodiac_sign[idx]  


def check_moon_sign(start: int, end: int, today: datetime.date, time: str):  
    date_format = '%Y年%m月%d日'  
    date = datetime.datetime.strftime(today, date_format)  

    if start == end:  
        mastodon.status_post(status=f"{date}{time}の月星座ニュースです。\n今後12時間、{start}になります。")  
        print(f"{date}{time}の月星座ニュースです。\n今後12時間、{start}になります。")  

    else:  
        mastodon.status_post(status=f"{date}{time}の月星座ニュースです。\n今後12時間以内に{start}から{end}に変わります。")  
        print(f"{date}{time}の月星座ニュースです。\n今後12時間以内に{start}から{end}に変わります。")  


def main():  
    # 日付・タイムゾーン入力  
    today_date = datetime.date.today()  
    now_time = datetime.datetime.now().time()  
    timezone_offset = 9  

    end_time, time_word = time_word_calc(now_time)  

    # 日付計算  
    start_moon = calculate_moon_position(today_date, now_time, timezone_offset)  
    end_moon = calculate_moon_position(today_date, end_time, timezone_offset)  

    # 月星座チェック  
    start_moon_sign = determine_moon_sign(start_moon[0][0])  
    end_moon_sign = determine_moon_sign(end_moon[0][0])  
    check_moon_sign(start_moon_sign, end_moon_sign, today_date, time_word)  


if __name__ == '__main__':  
    main()

大まかな流れ

  1. Pythonライブラリー「swisseph」を入れる
  2. 現時刻(+09:00)をUTC・ユリウス日に変換
  3. 現時刻と12時間後の月星座の位置を取得・星座設定
  4. 月星座が変わるかの判定→出力文章を設定
  5. 4で設定した文章をMastodonにトゥート
  6. 作ったプログラムをVPSにアップロード・cronの設定

詳しい話

1.Pythonライブラリ「swisseph」を入れる

pip install pyswisseph

計算が大変だったので、ライブラリを入れました。こんなニッチなライブラリーがあるんですね……!

このライブラリは惑星の位置計算以外にもできるみたいですが、私はまだ理解してない。もうしばらくドキュメントとにらめっこします。

2.現時刻(+09:00)をUTC・ユリウス日に変換

現時刻(時報は0:10と12:10に動かしてます)をUTCにし、そこからさらにユリウス日に変更します。2つの処理はswissephにあるので、関数を呼び出して使っています。

なお、位置による誤差は考慮していません。処理の方法がわからなかったのと、それやったら複雑になる予感がしたので……(未熟者)

3.月星座の位置を取得・星座の設定

ユリウス暦を用いて月の位置を計算します。とはいっても、swisseph任せですが。

この時、取得する月の位置は「0~360の数値」で出てきます。「0~29」は牡羊座、「30~59」は牡牛座といった感じです。そのため、位置を取得した後に星座の文字列を確認する必要があります。

ということで「月の位置を12で割って、割った数値から星座リストから文字列を取得」する形をとりました。

4.月星座が変わるかの判定→出力文章を設定

現時刻と12時間後の月星座を取得したら、月星座が一致してるか確認します。一致してたら「今後12時間〇〇座になります」という文章で、一致してなかったら「〇〇座から△△座に変わります」という文章にします。

5.4で設定した文章をMastodonにトゥート

Mastodonの設定→開発で各種キーを取得し、Pythonに埋め込みます。埋め込んだあとに実行して投稿されたかどうか確認します。

6.VPSにアップロード・cronの設定

完成したらVPSにプログラムをアップロードします。この時に「swisseph」もpipで入れておきます。

大まかな流れは下記の記事後半と同じなので、リンクを掲載しておきますね。

今後の方針

  • 関数・変数の見直すこと
  • 月星座以外の惑星の動き(逆行含む)
  • 星座の移動トゥをリアルタイムにしたい

星座が移動するタイミングでトゥートしたいところですが、これは難しいかも。特定の時刻から惑星位置を取得できますが、特定の惑星位置から時刻を計算することは難しそうな感じがしたので……。

まあできたところで、VPS側の設定が煩雑・下手したら新規契約する必要が出てくるので難しいんですけれども。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次