取得に失敗しました

2021年度 入部

Twitter GitHub YouTube

sasigume

await 寝る().then(白紙=>提出(白紙))

自己紹介

浪人中にどうしてもTypeScriptを書きたくなって色々やってたら情電数理落ちました。機シスですが機械はわかりません。
🏇349242177

自己紹介画像

取得に失敗しました

この人が書いた記事

プログラミング Polygon
プログラミング

Minecraftでプレイヤーの参加をツイートするbotの作り方

こんにちはさしぐめです。初投稿の今回はマインクラフトとTypeScriptを使ったbotについて書こうと思います。 Twitterアプリを申請する Developer PortalでTwitterアプリの申請をしましょう。この時、botとして使いたいアカウントで申請するのがベストです。 間違えてメインアカで申請しちゃった場合は、OAuth1.0aを使ってサブアカのトークンを発行しましょう。(手順は割愛) また、アプリの権限はRead & Write にします(DM権限は使いません)。 APIを用意する Webhookの受け皿にはCloud Functions for Firebase (実質GCP)を使います。 Herokuでもいいんですが、個人的に ログが見やすいサーバーレスかつ応答が早いFirestore等と連携できる外出先で確認できるアプリがある という理由で選びました。 https://firebase.google.com/pricing/ なお、従量制プランを選択する必要があり、処理時間と回数が膨大になると請求される可能性もありますのでご注意ください。 ステップ1: 認証情報を用意 Firebaseプロジェクトを用意して、開発環境を用意します。ここの手順は日々変わるので割愛します。 また、Cloud Functions for Firebaseでは.env ではなくCLIで一つづつ環境変数を設定していきます。 後述するWebhookプラグインはリクエストのヘッダーをカスタマイズできません。仕方なくbodyでパスフレーズを送って認証します。 まずはオレオレパスフレーズを作ります。OAuthでもなんでもないただのパスワードなので、個人用途以外で使わないでください。$ cd functions/ # 32桁のオレオレパスフレーズを生成 $ openssl rand -base64 32 # configに登録 $ firebase functions:config:set minecraft.auth="(オレオレパスフレーズ)" もっといい生成方法があったら教えてください>< アプリの申請が通ると以下のキーが手に入ります。これらを全部コンフィグに登録します。コンシューマキーコンシューマシークレットユーザのトークンユーザのシークレット $ firebase functions:config:set twitter.key="(コンシューマキー)" $ firebase functions:config:set twitter.secret="(コンシューマシークレット)" $ firebase functions:config:set minecraft.auth=(ユーザのトークン)" $ firebase functions:config:set minecraft.auth="(ユーザのシークレット)" # エミュレータ用ファイルを生成 $ firebase functions:config:get > .runtimeconfig.json {   "twitter": {     "user_secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",     "user_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",     "key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",     "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"   }, "minecraft": {     "auth": "(オレオレパスフレーズ)"   } }.runtimeconfig.json がこんな感じになります。これがローカルでテストする時の環境変数代わりになります。 functions/models/AdminConfig.d.tsexport interface AdminConfig {   twitter: {     key: string;     secret: string;     user_token: string;     user_secret: string;   };   minecraft: {     auth: string;   }; }TypeScriptの場合、こんな感じで型を作っておくと自動補完が楽です。 ステップ3: APIのエンドポイントを用意 さあいよいよAPIを作ります。 $ npm i twitter-api-clienttwitter-api-client というライブラリを使います。 FirebaseなのでFirebaseが用意しているfunctions.https.onRequest を使いますが、別にexpressでもいいです。 functions/src/twitter/post.tsimport * as functions from 'firebase-functions'; import { AdminConfig } from '../models/adminConfig'; const config = functions.config() as AdminConfig; import { TwitterClient } from 'twitter-api-client'; const client = new TwitterClient({ apiKey: config.twitter.key, apiSecret: config.twitter.secret, accessToken: config.twitter.user_token, accessTokenSecret: config.twitter.user_secret, }); const post = functions.region('asia-northeast1').https.onRequest(async (request, response) => { if (request.method !== 'POST') { response.status(405).json({ message: `POSTメソッドを使ってください`, }); return; } const body: { // マイクラサーバーのplugins/SimpleWebhooks/config.ymlで内容は定義してある tweet?: string; // コンフィグで定義 auth?: string; // テスト用 test?: boolean; } = request.body;   functions.logger.debug(`Received body: ${JSON.stringify(body)}`); if (Object.keys(body).length == 0) { response.status(400).json({ message: `bodyはJSONオブジェクトにしてください`, }); return; } if (body.auth !== config.minecraft.auth) { response.status(401).json({ message: `認証できませんでした`, }); return; } let tweet = body.tweet; if (!tweet) { response.status(422).json({ message: `ツイート本文を指定してください`, }); return; } // testがtrueならツイートはしない if (body.test) { response.status(200).json({ message: `テスト成功`,       ...body,     }); return; } // 以下、Twitter APIと通信する try { await client.tweets .statusesUpdate({ status: tweet, }) .then(async (apiResponse) => { // https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-update         // レスポンスにcreated_atがあればツイート成功 if (apiResponse.created_at) { response.status(200).json({ message: `ツイート成功`, ...apiResponse }); functions.logger.info(`Successfully tweeted: ${tweet}`); } else { response.status(500).json( apiResponse ?? { message: `Twitter APIからの応答がありませんでした`, } ); } }) .catch((e) => { response.status(500).json({ message: `Twitter API呼び出し中のエラー: ${JSON.stringify(e)}`, }); }); return; } catch (e) { response.status(500).json({ message: `その他のエラー: ${JSON.stringify(e)}`, }); } return; }); export default post; ステップ3: フォルダにまとめる expressならこんなことしなくて良いですが、Firebaseの書き方だとこうやってエンドポイントを整理します。 functions/src/index.tsconst twitter = require('./twitter'); exports.twitter = twitter; functions/src/twitter/index.tsexport { default as post } from './post'; こうすることで、エンドポイントが /twitter-post になります。 ステップ4: テストとデプロイ $ npm run serve Firebaseのエミュレータが立ち上がり、 http://localhost:5001/(プロジェクト名)/asia-northeast1/twitter-post でテスト可能になります。 curl --location --request POST 'http://localhost:5001/(プロジェクト名)/asia-northeast1/twitter-post' \ --header 'Content-Type: application/json' \ --data-raw '{     "tweet": "テストツイート",     "auth": "(オレオレパスフレーズ)",     "test": true }' こんな感じのリクエストを送ればテストできます。 $ npm run deploy デプロイすると https://asia-northeast1-(プロジェクト名).cloudfunctions.net/twitter-post にAPIが公開されます。 マイクラサーバー側の設定 あとはマイクラサーバーからWebhookを送るだけです。 Webhookプラグインを入れる https://github.com/Akenland/SimpleWebhooks SimpleWebhooks プラグインを使います。PaperMCの1.16.5で動作を確認しました。 プラグインの設定 $ vi plugins/SimpleWebhooks/config.yml config.yml webhooks:   join:     twitter-join:       url: https://asia-northeast1-(プロジェクト名).cloudfunctions.net/twitter-post       json:         tweet: "{PLAYER_DISPLAYNAME}が{SERVER_MOTD}に参加しました!"         auth: "(オレオレパスフレーズ)" こんな感じで、URLと送信するJSONを設定してください。YAMLマジで苦手。 豆知識: Cyberduckなら、サーバー上のファイルをローカルのように編集できます。宗教的こだわりがない場合は例えばVSCodeで開いて編集しましょう。 動作確認 YAMLを保存したら、マイクラサーバー側でwebhookをリロードします。 > webhooks reload サーバー再起動の必要はなく、このコマンドを実行するだけです。 プレイヤーが参加すると、Firebaseの管理画面にログが出るはずです。 .sasigumeが自由にサバイバル!に参加しました!#mc_asobinon 参加方法はこちら→ https://t.co/N1cU2977TQ— アソビノン - 誰でも編集できる攻略サイト (@asobinon) July 23, 2021 うちのサーバーではこんな感じでツイートしています。 --- 以上、マイクラサーバーと連携するbotの作り方でした。

> 内容を見る