Discord threads #16

Merged
Simponic merged 2 commits from discord-threads into main 2023-02-02 00:55:06 -05:00
5 changed files with 111 additions and 61 deletions
Showing only changes of commit 329291a076 - Show all commits

View File

@ -28,6 +28,6 @@ REACT_APP_SSH_PORT=42069
REDIS_HOST=localhost REDIS_HOST=localhost
REDIS_PORT=6379 REDIS_PORT=6379
NEW_GAME_PINGABLE_ROLE_ID=1123232 NEW_GAME_PINGABLE_ROLE_ID=10
NEW_GAME_CHANNEL_WEBHOOK=https://discordapp.com/api/webhooks/ REMIND_MOVE_CHANNEL_ID=91
REMIND_MOVE_CHANNEL_ID= NEW_GAME_CHANNEL_ID=91

View File

@ -24,8 +24,8 @@ config :chessh, Web,
discord_scope: "identify" discord_scope: "identify"
config :chessh, DiscordNotifications, config :chessh, DiscordNotifications,
game_move_notif_delay_ms: 3 * 60 * 1000, game_move_notif_delay_ms: 10 * 1000,
game_created_notif_delay_ms: 30 * 1000, game_created_notif_delay_ms: 10 * 1000,
reschedule_delay: 5 * 1000 reschedule_delay: 5 * 1000
config :joken, default_signer: "secret" config :joken, default_signer: "secret"

View File

@ -28,7 +28,7 @@ defmodule Chessh.DiscordNotifier do
case Hammer.check_rate_inc( case Hammer.check_rate_inc(
:redis, :redis,
"discord-webhook-message-rate", "discord-rate",
discord_notification_rate_ms, discord_notification_rate_ms,
discord_notification_rate, discord_notification_rate,
1 1
@ -65,15 +65,20 @@ defmodule Chessh.DiscordNotifier do
status: :continue, status: :continue,
discord_thread_id: discord_thread_id discord_thread_id: discord_thread_id
} = game -> } = game ->
delta_t = NaiveDateTime.diff(NaiveDateTime.utc_now(), last_updated, :millisecond)
game =
if is_nil(discord_thread_id) do if is_nil(discord_thread_id) do
{:ok, game} = {:ok, game} =
Game.changeset(game, %{ Game.changeset(game, %{
discord_thread_id: make_private_discord_thread_id(remind_move_channel_id, game) discord_thread_id: make_private_discord_thread_id(remind_move_channel_id, game)
}) })
|> Repo.update() |> Repo.update()
end
delta_t = NaiveDateTime.diff(NaiveDateTime.utc_now(), last_updated, :millisecond) game
else
game
end
if delta_t >= min_delta_t do if delta_t >= min_delta_t do
post_discord( post_discord(
@ -87,6 +92,26 @@ defmodule Chessh.DiscordNotifier do
end end
end end
defp send_notification({:cleanup_thread, game_id}) do
case Repo.get(Game, game_id) |> Repo.preload([:dark_player, :light_player]) do
%Game{
discord_thread_id: discord_thread_id,
status: status
} = game ->
if !is_nil(discord_thread_id) && status != :continue do
destroy_channel(discord_thread_id)
Game.changeset(game, %{
discord_thread_id: nil
})
|> Repo.update()
end
_ ->
nil
end
end
defp send_notification({:game_created, game_id}) do defp send_notification({:game_created, game_id}) do
[pingable_mention, new_game_channel_id] = [pingable_mention, new_game_channel_id] =
Application.get_env(:chessh, DiscordNotifications) Application.get_env(:chessh, DiscordNotifications)
@ -94,9 +119,6 @@ defmodule Chessh.DiscordNotifier do
|> Keyword.values() |> Keyword.values()
case Repo.get(Game, game_id) do case Repo.get(Game, game_id) do
nil ->
nil
game -> game ->
%Game{ %Game{
dark_player: dark_player, dark_player: dark_player,
@ -118,61 +140,80 @@ defmodule Chessh.DiscordNotifier do
if message do if message do
post_discord(new_game_channel_id, message) post_discord(new_game_channel_id, message)
end end
nil ->
nil
end
end
defp make_private_discord_thread_id(channel_id, %Game{
id: game_id,
dark_player: %Player{discord_id: dark_player_discord_id, username: dark_username},
light_player: %Player{discord_id: light_player_discord_id, username: light_username}
}) do
case make_discord_api_call(
:post,
"channels/#{channel_id}/threads",
%{
# Private thread
type: 12,
name: "Game #{game_id} - #{light_username} V #{dark_username}"
}
) do
{:ok, {_, _, body}} ->
%{"id" => thread_id} = Jason.decode!(body)
[light_player_discord_id, dark_player_discord_id]
|> Enum.map(fn id ->
make_discord_api_call(:put, 'channels/#{thread_id}/thread-members/#{id}')
end)
thread_id
_ ->
nil
end end
end end
defp post_discord(channel_id, message) do defp post_discord(channel_id, message) do
make_discord_api_call(:post, "channels/#{channel_id}/messages", %{content: message})
end
defp destroy_channel(channel_id) do
make_discord_api_call(:delete, "channels/#{channel_id}")
end
defp make_discord_api_call(method, route),
do:
:httpc.request( :httpc.request(
:post, method,
{ {
'https://discord.com/api/channels/#{channel_id}/messages', 'https://discord.com/api/#{route}',
[], [
'application/json', make_authorization_header()
%{content: message} |> Jason.encode!() |> String.to_charlist() ]
}, },
[], [],
[] []
) )
end
defp make_private_discord_thread_id(channel_id, %Game{ defp make_discord_api_call(method, route, body),
dark_player: %Player{discord_id: dark_player_discord_id}, do:
light_player: %Player{discord_id: light_player_discord_id}
}) do
%{"id" => thread_id} =
:httpc.request( :httpc.request(
:post, method,
{ {
'https://discord.com/api/channels/#{channel_id}/threads', 'https://discord.com/api/#{route}',
[ [
make_authorization_header() make_authorization_header()
], ],
'application/json', 'application/json',
%{ body
# Private thread
type: 12
}
|> Jason.encode!() |> Jason.encode!()
|> String.to_charlist() |> 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 defp make_authorization_header() do
bot_token = Application.get_env(:chessh, DiscordNotifications)[:discord_bot_token] bot_token = Application.get_env(:chessh, DiscordNotifications)[:discord_bot_token]

View File

@ -396,7 +396,7 @@ defmodule Chessh.SSH.Client.Game do
{:ok, status} -> {:ok, status} ->
{:ok, fen} = :binbo.get_fen(binbo_pid) {:ok, fen} = :binbo.get_fen(binbo_pid)
{:ok, _new_game} = {:ok, %Game{status: after_move_status}} =
game game
|> Game.changeset( |> Game.changeset(
Map.merge( Map.merge(
@ -413,11 +413,18 @@ defmodule Chessh.SSH.Client.Game do
:syn.publish(:games, {:game, game_id}, {:new_move, attempted_move}) :syn.publish(:games, {:game, game_id}, {:new_move, attempted_move})
if after_move_status == :continue do
GenServer.cast( GenServer.cast(
:discord_notifier, :discord_notifier,
{:schedule_notification, {:move_reminder, game_id}, {:schedule_notification, {:move_reminder, game_id},
Application.get_env(:chessh, DiscordNotifications)[:game_move_notif_delay_ms]} Application.get_env(:chessh, DiscordNotifications)[:game_move_notif_delay_ms]}
) )
else
GenServer.cast(
:discord_notifier,
{:schedule_notification, {:cleanup_thread, game_id}, 0}
)
end
_ -> _ ->
nil nil

View File

@ -2,6 +2,8 @@ defmodule Chessh.Repo.Migrations.AddDiscordThreadId do
use Ecto.Migration use Ecto.Migration
def change do def change do
alter table(:games) do
add(:discord_thread_id, :string, null: true)
end
end end
end end