4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

闘魂Elixir ── 2022-12-31 大晦日ハッカソン2022 をElixirで楽しむ!(元氣と闘魂を毎朝投稿(とうこん闘魂)する!)

Last updated at Posted at 2022-12-31

$\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}

完成品

スクリーンショット 2022-12-31 14.49.16.png

毎朝08:30にイベント情報が届きます。
ちなみに、私が主催する「autoracex または闘魂ex」は毎日もくもく会をエンジョイしています。

設計書(指示書)

image.png

ポイントは、

$\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

mix.exs
  defp deps do
    [
      {:req, "~> 0.3.3"}
    ]
  end

外部のHexは、HTTPクライアントReqを使いました。
mix deps.getで依存関係を解決します。

lib/binta/connpass.ex

connpass API イベントサーチAPIを呼び出すモジュールです。

lib/binta/connpass.ex
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にメッセージを投稿(とうこん闘魂)するモジュールです。

lib/binta/slack.ex
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を設定して読み出して使うようにします。

config/config.exs
import Config

config :binta, slack_incoming_webhook_url: System.get_env("BINTA_SLACK_INCOMING_WEBHOOK_URL")

lib/binta/inoki.ex

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

上記で部品は揃いました。
上記を組み合わせてひとつなぎのものにしたものです。

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で動かすことにしてみました。

test/binta_test.exs
defmodule BintaTest do
  use ExUnit.Case
  doctest Binta

  test "run" do
    Binta.run()
    assert true == true
  end
end

.github/workflows/test.yml

.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に設定した環境変数を読み出せるようになりました。
なにかのヒントになるかもしれませんので設定画面のスクリーンショットを貼っておきます。

スクリーンショット 2022-12-31 16.14.57.png

mix test

GitHub Actions Workflows上でのmix testの動かし方は、@mnishiguchi さんの記事を参考にしました。
ありがとうーーーーッ!!! ございます。

schedule イベントを使うと、スケジュールした時刻にワークフローをトリガーできます

GitHub Actions Workflowsでのcron Likeな指定は以下をご参照ください。

That's all!!!
完成です。:tada::tada::tada::tada::tada::tada::tada::tada::tada::tada:

スクリーンショット 2022-12-31 14.49.16.png

動かし方

念の為、ローカルマシンでの動かし方を書いておきます。
Incoming Web Hook URLの取得方法は下記のドキュメントをご参照ください。

CMD
export BINTA_SLACK_INCOMING_WEBHOOK_URL="https://hooks.slack.com/services/supersecret"

iex -S mix
iex> Binta.run()

または

CMD
mix test

mix testでテスト以外のことを動かすのは当然ながら非推奨です。私はダメだなとおもいながら、やっています。相当たちが悪いわけです。


Twitter

Twitterに制作過程をつぶやきました。
これでだいたいのことが思い出せます。

09:43 参加表明

09:45 制作意図を表明

10:28 設計完了

コード作成

コードはさらさらさらっと書きました。
コードを書くうえで一番悩んだのはプロジェクト名です。
bintaにしました。
毎朝、朝一に猪木さんから闘魂ビンタをいただくイメージです。

GitHub Actions Workflowsの設定に悩み続ける

コードはできたので次は実行環境の構築です。
毎朝08:30にSlackチャンネルへメッセージを投稿(とうこん闘魂)したいわけです。

GitHub Actions Workflowsを使うことにしました。

環境変数がうまく読みだせませんでした。いろいろ試行錯誤を繰り返しました。いつものことです。あの.ymlの書き方はよくわかりません。カンで書いています。

14:47 GitHub Actions Workflows上で動作するようになる :tada::tada::tada:

16:45 報告書という名の後片付け

その後Advent Of Code Day 5を楽しみました


さいごに

この記事では、大晦日ハッカソン2022に参加して制作した作品のことを書きました。
来年のことを言うと鬼に笑われると申しますが、もっと積極的に鬼といっしょになって笑おうではありませんか!
元氣があればなんでもできる!
また来年の12-31にお会いしましょう!
よいお年を!

闘魂とは、 「己に打ち克つこと、そして闘いを通じて己の魂を磨いていくことである」 との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。

$\huge{1、2、3 ぁっダー!}$



$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
$\huge{1、2、3 ぁっダー!}$

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?