From fcabcdb5cb463f15d036169317f77bd7b2043ac8 Mon Sep 17 00:00:00 2001 From: Logan Hunt Date: Wed, 1 Feb 2023 18:23:23 -0700 Subject: [PATCH] Add initial support for discord threads --- .env.example | 3 +- config/config.exs | 2 +- config/runtime.exs | 5 +- lib/chessh/discord/notifier.ex | 73 ++++++++++++++++--- lib/chessh/schema/game.ex | 5 +- .../20230202004927_add_discord_thread_id.exs | 7 ++ 6 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 priv/repo/migrations/20230202004927_add_discord_thread_id.exs diff --git a/.env.example b/.env.example index 51168fc..11ca42e 100644 --- a/.env.example +++ b/.env.example @@ -17,6 +17,7 @@ SERVER_REDIRECT_URI=http://127.0.0.1:3000/api/oauth/redirect DISCORD_CLIENT_ID= DISCORD_CLIENT_SECRET= DISCORD_USER_AGENT= +DISCORD_BOT_TOKEN= JWT_SECRET=aVerySecretJwtSigningSecret @@ -29,4 +30,4 @@ REDIS_PORT=6379 NEW_GAME_PINGABLE_ROLE_ID=1123232 NEW_GAME_CHANNEL_WEBHOOK=https://discordapp.com/api/webhooks/ -REMIND_MOVE_CHANNEL_WEBHOOK=https://discordapp.com/api/webhooks/ \ No newline at end of file +REMIND_MOVE_CHANNEL_ID= diff --git a/config/config.exs b/config/config.exs index e732049..2c08a17 100644 --- a/config/config.exs +++ b/config/config.exs @@ -15,7 +15,7 @@ config :chessh, RateLimits, player_public_keys: 15, create_game_ms: 60 * 1000, create_game_rate: 3, - discord_notification_rate: 3, + discord_notification_rate: 30, discord_notification_rate_ms: 1000 config :chessh, Web, diff --git a/config/runtime.exs b/config/runtime.exs index 684e48e..5da6d47 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -5,8 +5,9 @@ config :chessh, config :chessh, DiscordNotifications, looking_for_games_role_mention: "<@&#{System.get_env("NEW_GAME_PINGABLE_ROLE_ID")}>", - discord_game_move_notif_webhook: System.get_env("REMIND_MOVE_CHANNEL_WEBHOOK"), - discord_new_game_notif_webhook: System.get_env("NEW_GAME_CHANNEL_WEBHOOK") + remind_move_channel_id: System.get_env("REMIND_MOVE_CHANNEL_ID"), + discord_bot_token: System.get_env("DISCORD_BOT_TOKEN"), + new_game_channel_id: System.get_env("NEW_GAME_CHANNEL_ID") config :chessh, Web, discord_client_id: System.get_env("DISCORD_CLIENT_ID"), diff --git a/lib/chessh/discord/notifier.ex b/lib/chessh/discord/notifier.ex index 6d7bd46..c19495c 100644 --- a/lib/chessh/discord/notifier.ex +++ b/lib/chessh/discord/notifier.ex @@ -50,9 +50,9 @@ defmodule Chessh.DiscordNotifier do end defp send_notification({:move_reminder, game_id}) do - [min_delta_t, discord_game_move_notif_webhook] = + [min_delta_t, remind_move_channel_id] = Application.get_env(:chessh, DiscordNotifications) - |> Keyword.take([:game_move_notif_delay_ms, :discord_game_move_notif_webhook]) + |> Keyword.take([:game_move_notif_delay_ms, :remind_move_channel_id]) |> Keyword.values() case Repo.get(Game, game_id) |> Repo.preload([:dark_player, :light_player]) do @@ -62,13 +62,22 @@ defmodule Chessh.DiscordNotifier do turn: turn, updated_at: last_updated, moves: move_count, - status: :continue - } -> + status: :continue, + discord_thread_id: discord_thread_id + } = game -> + if is_nil(discord_thread_id) do + {:ok, game} = + Game.changeset(game, %{ + discord_thread_id: make_private_discord_thread_id(remind_move_channel_id, game) + }) + |> Repo.update() + end + delta_t = NaiveDateTime.diff(NaiveDateTime.utc_now(), last_updated, :millisecond) if delta_t >= min_delta_t do post_discord( - discord_game_move_notif_webhook, + game.discord_thread_id, "<@#{if turn == :light, do: light_player_discord_id, else: dark_player_discord_id}> it is your move in Game #{game_id} (move #{move_count})." ) end @@ -79,9 +88,9 @@ defmodule Chessh.DiscordNotifier do end defp send_notification({:game_created, game_id}) do - [pingable_mention, discord_game_created_notif_webhook] = + [pingable_mention, new_game_channel_id] = Application.get_env(:chessh, DiscordNotifications) - |> Keyword.take([:looking_for_games_role_mention, :discord_new_game_notif_webhook]) + |> Keyword.take([:looking_for_games_role_mention, :new_game_channel_id]) |> Keyword.values() case Repo.get(Game, game_id) do @@ -107,16 +116,16 @@ defmodule Chessh.DiscordNotifier do end if message do - post_discord(discord_game_created_notif_webhook, message) + post_discord(new_game_channel_id, message) end end end - defp post_discord(webhook, message) do + defp post_discord(channel_id, message) do :httpc.request( :post, { - String.to_charlist(webhook), + 'https://discord.com/api/channels/#{channel_id}/messages', [], 'application/json', %{content: message} |> Jason.encode!() |> String.to_charlist() @@ -125,4 +134,48 @@ defmodule Chessh.DiscordNotifier do [] ) end + + defp make_private_discord_thread_id(channel_id, %Game{ + dark_player: %Player{discord_id: dark_player_discord_id}, + light_player: %Player{discord_id: light_player_discord_id} + }) do + %{"id" => thread_id} = + :httpc.request( + :post, + { + 'https://discord.com/api/channels/#{channel_id}/threads', + [ + make_authorization_header() + ], + 'application/json', + %{ + # Private thread + type: 12 + } + |> Jason.encode!() + |> String.to_charlist() + }, + [], + [] + ) + |> Jason.decode!() + + [light_player_discord_id, dark_player_discord_id] + |> Enum.map(fn id -> + :httpc.request( + :post, + { + 'https://discord.com/api/channels/#{thread_id}/thread-members/#{id}', + [] + } + ) + end) + + thread_id + end + + defp make_authorization_header() do + bot_token = Application.get_env(:chessh, DiscordNotifications)[:discord_bot_token] + {'Authorization', 'Bot #{bot_token}'} + end end diff --git a/lib/chessh/schema/game.ex b/lib/chessh/schema/game.ex index b7893f1..55b9ea4 100644 --- a/lib/chessh/schema/game.ex +++ b/lib/chessh/schema/game.ex @@ -15,6 +15,8 @@ defmodule Chessh.Game do belongs_to(:light_player, Player, foreign_key: :light_player_id) belongs_to(:dark_player, Player, foreign_key: :dark_player_id) + field(:discord_thread_id, :string) + timestamps() end @@ -28,7 +30,8 @@ defmodule Chessh.Game do :status, :last_move, :light_player_id, - :dark_player_id + :dark_player_id, + :discord_thread_id ]) end end diff --git a/priv/repo/migrations/20230202004927_add_discord_thread_id.exs b/priv/repo/migrations/20230202004927_add_discord_thread_id.exs new file mode 100644 index 0000000..fadb8f1 --- /dev/null +++ b/priv/repo/migrations/20230202004927_add_discord_thread_id.exs @@ -0,0 +1,7 @@ +defmodule Chessh.Repo.Migrations.AddDiscordThreadId do + use Ecto.Migration + + def change do + + end +end