$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
$\huge{闘魂とは己に打ち克つこと、}$
$\huge{そして闘いを通じて己の魂を磨いていく}$
$\huge{ことだとおもいます}$
はじめに
闘魂とElixirが出会いました。
闘魂 meets Elixir.です。
Elixir meets 闘魂.でもよいです。
本日2022-12-31(土)は、毎年恒例大晦日ハッカソン2022が開催されました。
今年も参加しました。
elixir.jp Slackの「#autoracex」にイベント情報を投稿(とうこん闘魂)するボットをつくります。
たまに気が向いたときに自分で手動で行っています。それをボットに任せてみようというわけです。
iex> "Elixir" |> String.graphemes() |> Enum.frequencies()
%{"E" => 1, "i" => 2, "l" => 1, "r" => 1, "x" => 1}
完成品
毎朝08:30にイベント情報が届きます。
ちなみに、私が主催する「autoracex または闘魂ex」は毎日もくもく会をエンジョイしています。
設計書(指示書)
ポイントは、
$\huge{元氣}$
と
$\huge{闘魂}$
を毎朝Slackに投稿(とうこん闘魂)することです。
ちなみに指示書と言えば、私が真っ先に思い出すのは
この話です。指示書そのものはすごいものだとおもいます。私が指示書という単語を使うときにイメージしているものはコレです。
ソースコード
GitHubに投稿(とうこん闘魂)しておきます。
| バージョン | |
|---|---|
| elixir | 1.14.2-otp-25 |
| erlang | 25.2 |
ソースコードの説明
ポイントとなる部分を説明します。
プロジェクトの作成
mix new binta --sup
--supオプションは付けなくてもよかったかも。実行環境をどうするか見えていなかったのでとりあえずTo generate an app with a supervision tree and an application callbackで作りました。
mix.exs
defp deps do
[
{:req, "~> 0.3.3"}
]
end
外部のHexは、HTTPクライアントReqを使いました。
mix deps.getで依存関係を解決します。
lib/binta/connpass.ex
connpass API イベントサーチAPIを呼び出すモジュールです。
defmodule Binta.Connpass do
@moduledoc false
def event_now do
utc_today = Date.utc_today()
ym =
"#{utc_today.year}#{utc_today.month |> Integer.to_string() |> String.pad_leading(2, "0")}"
%{ym: ym, series_id: 11144}
|> run()
|> handle_response()
|> Enum.filter(fn %{"started_at" => started_at, "ended_at" => ended_at} ->
{:ok, start, _} = DateTime.from_iso8601(started_at)
{:ok, ending, _} = DateTime.from_iso8601(ended_at)
utc_now = DateTime.utc_now()
DateTime.compare(start, utc_now) in [:lt, :eq] and
DateTime.compare(utc_now, ending) in [:lt, :eq]
end)
|> Enum.at(0)
end
def run(query) do
Req.get("https://connpass.com/api/v1/event/?#{URI.encode_query(query)}")
end
defp handle_response({:error, _}), do: []
defp handle_response({:ok, %{body: %{"events" => events}}}), do: events
end
Binta.Connpass.event_now/0関数は、現在開催中の「autoracex または闘魂ex」コミュニティイベントを取得するように早すぎる最適化をしています。
コード中11144は「autoracex または闘魂ex」のことを指します。
@koga1020 さんのExConnpassを参考にしました。ありがとうーーーーッ!!! ございます。
こちらを使おうかともおもったのですが、先に入れたReqと依存関係の解決がうまくいかなかったので、どうせHTTP GETだけだし、雑に自分で書きました。
lib/binta/slack.ex
Slackにメッセージを投稿(とうこん闘魂)するモジュールです。
defmodule Binta.Slack do
@moduledoc false
def post(message) do
Req.post(url(), json: %{text: message})
end
defp url, do: Application.get_env(:binta, :slack_incoming_webhook_url)
end
メッセージを投稿(とうこん闘魂)するためのSlackの設定やURLの取得方法は下記のドキュメントをご参照ください。
config/config.exs
環境変数BINTA_SLACK_INCOMING_WEBHOOK_URLにSlack Incoming WebhookのURLを設定して読み出して使うようにします。
import Config
config :binta, slack_incoming_webhook_url: System.get_env("BINTA_SLACK_INCOMING_WEBHOOK_URL")
lib/binta/inoki.ex
defmodule Binta.Inoki do
@moduledoc false
# TODO 将来猪木さんAI
@messages [
"闘魂とは己に打ち克つこと、そして闘いを通じて己の魂を磨いていくことだとおもいます",
"元氣ですかーーーーッ!!! 元氣があればなんでもできる!",
"イーチ、ニィー、サン、ぁッ ダー!!!"
]
def build_message do
message = Enum.random(@messages)
":fire::toukon: *#{message}* :inoki: :toukon::fire:"
end
end
将来はAI技術を取り込んで、猪木さんが話しているかのようにしたいです。
元氣があればなんでもできる!
lib/binta.ex
上記で部品は揃いました。
上記を組み合わせてひとつなぎのものにしたものです。
defmodule Binta do
@moduledoc """
Documentation for `Binta`.
"""
@doc """
post https://autoracex.connpass.com/ event to #autoracex channel on elixir.jp Slack
"""
def run do
event_now()
|> build_message()
|> post_message()
end
defp post_message(:error), do: :error
defp post_message(message) do
Binta.Slack.post(message)
end
defp build_message(:error), do: :error
defp build_message(event_now) do
Binta.Inoki.build_message()
|> Kernel.<>("\n\n\n")
|> Kernel.<>(event_now)
|> Kernel.<>(
"\n\nThis bot is https://github.com/TORIFUKUKaiou/binta .\nThanks for GitHub Actions workflows & William Henry \"Bill\" Gates III."
)
end
defp event_now do
case Binta.Connpass.event_now() do
%{
"title" => title,
"event_url" => event_url,
"accepted" => accepted,
"started_at" => started_at,
"ended_at" => ended_at
} ->
"""
*#{title}*
#{started_at} 〜 #{ended_at}
参加人数: #{accepted}人
#{event_url}
"""
_ ->
:error
end
end
end
test/binta_test.exs
testじゃなくてもいいのですが、GitHub Actions Workflowsはハマりがちになるのはわかりきっているので、mix testで動かすことにしてみました。
defmodule BintaTest do
use ExUnit.Case
doctest Binta
test "run" do
Binta.run()
assert true == true
end
end
.github/workflows/test.yml
name: test
on:
workflow_dispatch:
schedule:
- cron: '30 23 * * *'
jobs:
test:
runs-on: ubuntu-22.04
environment:
name: secrets
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
otp-version: '25.2'
elixir-version: '1.14.2'
- run: mix deps.get
- run: mix test
env:
BINTA_SLACK_INCOMING_WEBHOOK_URL: ${{ secrets.BINTA_SLACK_INCOMING_WEBHOOK_URL }}
カンで書きました。
environment:
name: secrets
この記述がポイントだったのかもしれません。よくわかりません。とにかく上記でGitHubに設定した環境変数を読み出せるようになりました。
なにかのヒントになるかもしれませんので設定画面のスクリーンショットを貼っておきます。
mix test
GitHub Actions Workflows上でのmix testの動かし方は、@mnishiguchi さんの記事を参考にしました。
ありがとうーーーーッ!!! ございます。
schedule イベントを使うと、スケジュールした時刻にワークフローをトリガーできます
GitHub Actions Workflowsでのcron Likeな指定は以下をご参照ください。
That's all!!!
完成です。![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
動かし方
念の為、ローカルマシンでの動かし方を書いておきます。
Incoming Web Hook URLの取得方法は下記のドキュメントをご参照ください。
export BINTA_SLACK_INCOMING_WEBHOOK_URL="https://hooks.slack.com/services/supersecret"
iex -S mix
iex> Binta.run()
または
mix test
mix testでテスト以外のことを動かすのは当然ながら非推奨です。私はダメだなとおもいながら、やっています。相当たちが悪いわけです。
Twitterに制作過程をつぶやきました。
これでだいたいのことが思い出せます。
09:43 参加表明
#大晦日ハッカソン
— TORIFUKU Kaiou (@torifukukaiou) December 31, 2022
Twitterに投稿(とうこん 闘魂)された「井大晦日ハッカソン」付きメッセージをとにかく「いいね」するボットを設置、イゴかしはじめました。#autoracex
09:45 制作意図を表明
#大晦日ハッカソン
— TORIFUKU Kaiou (@torifukukaiou) December 31, 2022
connpass に毎日登録しているもくもく会の開催通知をSlackチャンネルに投稿(とうこん闘魂する)ボットを作ります。「おもに」二人で令和の巌流島決戦をしているだけですので通知はいらないのですが自分の行動は極力ボットに任せたいとおもっています。#autoracex
10:28 設計完了
#大晦日ハッカソン
— TORIFUKU Kaiou (@torifukukaiou) December 31, 2022
設計図、指示書 pic.twitter.com/SLEAXWDhX1
コード作成
コードはさらさらさらっと書きました。
コードを書くうえで一番悩んだのはプロジェクト名です。
bintaにしました。
毎朝、朝一に猪木さんから闘魂ビンタをいただくイメージです。
GitHub Actions Workflowsの設定に悩み続ける
コードはできたので次は実行環境の構築です。
毎朝08:30にSlackチャンネルへメッセージを投稿(とうこん闘魂)したいわけです。
GitHub Actions Workflowsを使うことにしました。
環境変数がうまく読みだせませんでした。いろいろ試行錯誤を繰り返しました。いつものことです。あの.ymlの書き方はよくわかりません。カンで書いています。
14:47 GitHub Actions Workflows上で動作するようになる 

#大晦日ハッカソン
— TORIFUKU Kaiou (@torifukukaiou) December 31, 2022
完成しました!
毎朝 08:30 に届くはずです。
次はQiitaに作成記録を残しておきます。#autoracex pic.twitter.com/LV8qiK9kcO
16:45 報告書という名の後片付け
#大晦日ハッカソン
— TORIFUKU Kaiou (@torifukukaiou) December 31, 2022
闘魂Elixir ── 2022-12-31 大晦日ハッカソン2022 をElixirで楽しむ!(元氣と闘魂を毎朝投稿(とうこん闘魂)する!) https://t.co/i7bWp1BvvB #Qiita
完成🎉
元氣があればなんでもできる!
また来年の12-31にお会いしましょう!
よいお年を!#autoracex #MyElixirStatus
その後Advent Of Code Day 5を楽しみました
#大晦日ハッカソン
— TORIFUKU Kaiou (@torifukukaiou) December 31, 2022
I've completed "Supply Stacks" - Day 5 - Advent of Code 2022 https://t.co/EnXouUid0U #AdventOfCode https://t.co/NDw4NFgd6nhttps://t.co/LnDP7TX4rxhttps://t.co/xVsVNZXrf7#MyElixirStatus
さいごに
この記事では、大晦日ハッカソン2022に参加して制作した作品のことを書きました。
来年のことを言うと鬼に笑われると申しますが、もっと積極的に鬼といっしょになって笑おうではありませんか!
元氣があればなんでもできる!
また来年の12-31にお会いしましょう!
よいお年を!
闘魂とは、 「己に打ち克つこと、そして闘いを通じて己の魂を磨いていくことである」 との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。
$\huge{1、2、3 ぁっダー!}$
$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
$\huge{1、2、3 ぁっダー!}$



