Discord threads #16
@ -17,6 +17,7 @@ SERVER_REDIRECT_URI=http://127.0.0.1:3000/api/oauth/redirect
|
|||||||
DISCORD_CLIENT_ID=
|
DISCORD_CLIENT_ID=
|
||||||
DISCORD_CLIENT_SECRET=
|
DISCORD_CLIENT_SECRET=
|
||||||
DISCORD_USER_AGENT=
|
DISCORD_USER_AGENT=
|
||||||
|
DISCORD_BOT_TOKEN=
|
||||||
|
|
||||||
JWT_SECRET=aVerySecretJwtSigningSecret
|
JWT_SECRET=aVerySecretJwtSigningSecret
|
||||||
|
|
||||||
@ -29,4 +30,4 @@ REDIS_PORT=6379
|
|||||||
|
|
||||||
NEW_GAME_PINGABLE_ROLE_ID=1123232
|
NEW_GAME_PINGABLE_ROLE_ID=1123232
|
||||||
NEW_GAME_CHANNEL_WEBHOOK=https://discordapp.com/api/webhooks/
|
NEW_GAME_CHANNEL_WEBHOOK=https://discordapp.com/api/webhooks/
|
||||||
REMIND_MOVE_CHANNEL_WEBHOOK=https://discordapp.com/api/webhooks/
|
REMIND_MOVE_CHANNEL_ID=
|
||||||
|
@ -15,7 +15,7 @@ config :chessh, RateLimits,
|
|||||||
player_public_keys: 15,
|
player_public_keys: 15,
|
||||||
create_game_ms: 60 * 1000,
|
create_game_ms: 60 * 1000,
|
||||||
create_game_rate: 3,
|
create_game_rate: 3,
|
||||||
discord_notification_rate: 3,
|
discord_notification_rate: 30,
|
||||||
discord_notification_rate_ms: 1000
|
discord_notification_rate_ms: 1000
|
||||||
|
|
||||||
config :chessh, Web,
|
config :chessh, Web,
|
||||||
|
@ -5,8 +5,9 @@ config :chessh,
|
|||||||
|
|
||||||
config :chessh, DiscordNotifications,
|
config :chessh, DiscordNotifications,
|
||||||
looking_for_games_role_mention: "<@&#{System.get_env("NEW_GAME_PINGABLE_ROLE_ID")}>",
|
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"),
|
remind_move_channel_id: System.get_env("REMIND_MOVE_CHANNEL_ID"),
|
||||||
discord_new_game_notif_webhook: System.get_env("NEW_GAME_CHANNEL_WEBHOOK")
|
discord_bot_token: System.get_env("DISCORD_BOT_TOKEN"),
|
||||||
|
new_game_channel_id: System.get_env("NEW_GAME_CHANNEL_ID")
|
||||||
|
|
||||||
config :chessh, Web,
|
config :chessh, Web,
|
||||||
discord_client_id: System.get_env("DISCORD_CLIENT_ID"),
|
discord_client_id: System.get_env("DISCORD_CLIENT_ID"),
|
||||||
|
@ -50,9 +50,9 @@ defmodule Chessh.DiscordNotifier do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp send_notification({:move_reminder, game_id}) do
|
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)
|
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()
|
|> Keyword.values()
|
||||||
|
|
||||||
case Repo.get(Game, game_id) |> Repo.preload([:dark_player, :light_player]) do
|
case Repo.get(Game, game_id) |> Repo.preload([:dark_player, :light_player]) do
|
||||||
@ -62,13 +62,22 @@ defmodule Chessh.DiscordNotifier do
|
|||||||
turn: turn,
|
turn: turn,
|
||||||
updated_at: last_updated,
|
updated_at: last_updated,
|
||||||
moves: move_count,
|
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)
|
delta_t = NaiveDateTime.diff(NaiveDateTime.utc_now(), last_updated, :millisecond)
|
||||||
|
|
||||||
if delta_t >= min_delta_t do
|
if delta_t >= min_delta_t do
|
||||||
post_discord(
|
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})."
|
"<@#{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
|
end
|
||||||
@ -79,9 +88,9 @@ defmodule Chessh.DiscordNotifier do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp send_notification({:game_created, game_id}) do
|
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)
|
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()
|
|> Keyword.values()
|
||||||
|
|
||||||
case Repo.get(Game, game_id) do
|
case Repo.get(Game, game_id) do
|
||||||
@ -107,16 +116,16 @@ defmodule Chessh.DiscordNotifier do
|
|||||||
end
|
end
|
||||||
|
|
||||||
if message do
|
if message do
|
||||||
post_discord(discord_game_created_notif_webhook, message)
|
post_discord(new_game_channel_id, message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp post_discord(webhook, message) do
|
defp post_discord(channel_id, message) do
|
||||||
:httpc.request(
|
:httpc.request(
|
||||||
:post,
|
:post,
|
||||||
{
|
{
|
||||||
String.to_charlist(webhook),
|
'https://discord.com/api/channels/#{channel_id}/messages',
|
||||||
[],
|
[],
|
||||||
'application/json',
|
'application/json',
|
||||||
%{content: message} |> Jason.encode!() |> String.to_charlist()
|
%{content: message} |> Jason.encode!() |> String.to_charlist()
|
||||||
@ -125,4 +134,48 @@ defmodule Chessh.DiscordNotifier do
|
|||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
end
|
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
|
end
|
||||||
|
@ -15,6 +15,8 @@ defmodule Chessh.Game do
|
|||||||
belongs_to(:light_player, Player, foreign_key: :light_player_id)
|
belongs_to(:light_player, Player, foreign_key: :light_player_id)
|
||||||
belongs_to(:dark_player, Player, foreign_key: :dark_player_id)
|
belongs_to(:dark_player, Player, foreign_key: :dark_player_id)
|
||||||
|
|
||||||
|
field(:discord_thread_id, :string)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -28,7 +30,8 @@ defmodule Chessh.Game do
|
|||||||
:status,
|
:status,
|
||||||
:last_move,
|
:last_move,
|
||||||
:light_player_id,
|
:light_player_id,
|
||||||
:dark_player_id
|
:dark_player_id,
|
||||||
|
:discord_thread_id
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
defmodule Chessh.Repo.Migrations.AddDiscordThreadId do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user