mirror of
https://github.com/TheRealOwenRees/plantid-discord-bot.git
synced 2026-07-22 20:16:57 +00:00
refactoring of modules
This commit is contained in:
+2
-2
@@ -17,8 +17,8 @@ config :nostrum,
|
|||||||
config :plantid_discord_bot, PlantIdDiscordBot.Scheduler,
|
config :plantid_discord_bot, PlantIdDiscordBot.Scheduler,
|
||||||
jobs: [
|
jobs: [
|
||||||
{"@daily", {PlantIdDiscordBot.RateLimiter, :reset_counters, []}},
|
{"@daily", {PlantIdDiscordBot.RateLimiter, :reset_counters, []}},
|
||||||
{"@hourly", {PlantIdDiscordBot.Metrics, :write, []}},
|
{"@hourly", {PlantIdDiscordBot.Metrics, :backup, []}},
|
||||||
{"0 8 * * *", {PlantIdDiscordBot.Metrics.Message, :start, []}}
|
{"0 8 * * *", {PlantIdDiscordBot.Metrics.Message, :send, []}}
|
||||||
]
|
]
|
||||||
|
|
||||||
import_config "#{config_env()}.exs"
|
import_config "#{config_env()}.exs"
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ defmodule PlantIdDiscordBot.Application do
|
|||||||
PlantIdDiscordBot.ProcessRegistry,
|
PlantIdDiscordBot.ProcessRegistry,
|
||||||
PlantIdDiscordBot.Consumer,
|
PlantIdDiscordBot.Consumer,
|
||||||
PlantIdDiscordBot.RateLimiter,
|
PlantIdDiscordBot.RateLimiter,
|
||||||
{PlantIdDiscordBot.Metrics, []},
|
{PlantIdDiscordBot.Metrics.Requests, []},
|
||||||
PlantIdDiscordBot.Scheduler,
|
PlantIdDiscordBot.Scheduler,
|
||||||
{Plug.Cowboy,
|
{Plug.Cowboy,
|
||||||
scheme: :http,
|
scheme: :http,
|
||||||
|
|||||||
+7
-94
@@ -1,101 +1,14 @@
|
|||||||
defmodule PlantIdDiscordBot.Metrics do
|
defmodule PlantIdDiscordBot.Metrics do
|
||||||
use Agent
|
alias PlantIdDiscordBot.Metrics.Requests
|
||||||
alias PlantIdDiscordBot.Metrics
|
|
||||||
|
|
||||||
@file_path "priv/metrics"
|
def backup() do
|
||||||
|
Requests.write()
|
||||||
defstruct [
|
|
||||||
:guild_id,
|
|
||||||
:guild_name,
|
|
||||||
:first_request_at,
|
|
||||||
:last_request_at,
|
|
||||||
:total_requests
|
|
||||||
]
|
|
||||||
|
|
||||||
def start_link(_opts) do
|
|
||||||
initial_state =
|
|
||||||
case File.exists?(Path.join(@file_path, "requests")) do
|
|
||||||
true -> read()
|
|
||||||
false -> %{}
|
|
||||||
end
|
|
||||||
|
|
||||||
Agent.start_link(fn -> initial_state end, name: via_tuple(:metrics))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp via_tuple(key) do
|
def increase_request_count(guild_id, guild_name) do
|
||||||
PlantIdDiscordBot.ProcessRegistry.via_tuple({__MODULE__, key})
|
Requests.put(guild_id, guild_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_pid do
|
def requests(guild_id), do: Requests.get(guild_id)
|
||||||
[{pid, _value}] = Registry.lookup(PlantIdDiscordBot.ProcessRegistry, {__MODULE__, :metrics})
|
def requests(), do: Requests.get_all()
|
||||||
pid
|
|
||||||
end
|
|
||||||
|
|
||||||
def get(key) do
|
|
||||||
get_pid()
|
|
||||||
|> Agent.get(&Map.get(&1, key))
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_all() do
|
|
||||||
get_pid()
|
|
||||||
|> Agent.get(& &1)
|
|
||||||
end
|
|
||||||
|
|
||||||
def put(guild_id, guild_name) do
|
|
||||||
get_pid()
|
|
||||||
|> Agent.update(fn state ->
|
|
||||||
case Map.get(state, guild_id) do
|
|
||||||
nil ->
|
|
||||||
Map.put(state, guild_id, %Metrics{
|
|
||||||
guild_id: guild_id,
|
|
||||||
guild_name: guild_name,
|
|
||||||
first_request_at: DateTime.utc_now(),
|
|
||||||
last_request_at: DateTime.utc_now(),
|
|
||||||
total_requests: 1
|
|
||||||
})
|
|
||||||
|
|
||||||
existing ->
|
|
||||||
Map.put(state, guild_id, %Metrics{
|
|
||||||
existing
|
|
||||||
| last_request_at: DateTime.utc_now(),
|
|
||||||
total_requests: existing.total_requests + 1
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Reset metrics state and remove the saved file from disk.
|
|
||||||
"""
|
|
||||||
def reset() do
|
|
||||||
get_pid()
|
|
||||||
|> Agent.update(fn _ -> %{} end)
|
|
||||||
|
|
||||||
file = Path.join(@file_path, "requests")
|
|
||||||
|
|
||||||
if File.exists?(file) do
|
|
||||||
File.rm!(Path.join(@file_path, "requests"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Write the current state to disk. To be consumed by a CRON job.
|
|
||||||
"""
|
|
||||||
def write() do
|
|
||||||
File.mkdir_p!("priv/metrics")
|
|
||||||
|
|
||||||
data =
|
|
||||||
get_all()
|
|
||||||
|> :erlang.term_to_binary()
|
|
||||||
|
|
||||||
File.write!(Path.join(@file_path, "requests"), data)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Read the state from disk. To be loaded into state on process start.
|
|
||||||
"""
|
|
||||||
def read() do
|
|
||||||
File.read!(Path.join(@file_path, "requests"))
|
|
||||||
|> :erlang.binary_to_term()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
+6
-11
@@ -1,11 +1,11 @@
|
|||||||
defmodule PlantIdDiscordBot.Metrics.Message do
|
defmodule PlantIdDiscordBot.Metrics.Message do
|
||||||
def start() do
|
def send() do
|
||||||
PlantIdDiscordBot.Metrics.get_all()
|
PlantIdDiscordBot.Metrics.requests()
|
||||||
|> format_message()
|
|> format_message()
|
||||||
|> send_message()
|
|> do_send_message()
|
||||||
end
|
end
|
||||||
|
|
||||||
def format_message(data) do
|
defp format_message(data) do
|
||||||
embeds =
|
embeds =
|
||||||
Enum.map(data, fn {guild_id, metrics} ->
|
Enum.map(data, fn {guild_id, metrics} ->
|
||||||
first_request_at =
|
first_request_at =
|
||||||
@@ -30,15 +30,10 @@ defmodule PlantIdDiscordBot.Metrics.Message do
|
|||||||
%{embeds: embeds}
|
%{embeds: embeds}
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_message(data) do
|
defp do_send_message(data) do
|
||||||
webhook_url = Application.get_env(:plantid_discord_bot, :metrics_webhook_url)
|
webhook_url = Application.get_env(:plantid_discord_bot, :metrics_webhook_url)
|
||||||
|
|
||||||
body = Jason.encode!(data)
|
body = Jason.encode!(data)
|
||||||
|
headers = [{"Content-Type", "application/json"}]
|
||||||
headers = [
|
|
||||||
{"Content-Type", "application/json"}
|
|
||||||
]
|
|
||||||
|
|
||||||
HTTPoison.post!(webhook_url, body, headers)
|
HTTPoison.post!(webhook_url, body, headers)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
defmodule PlantIdDiscordBot.Metrics.Requests do
|
||||||
|
use Agent
|
||||||
|
alias PlantIdDiscordBot.Metrics.Requests
|
||||||
|
alias PlantIdDiscordBot.ProcessRegistry
|
||||||
|
|
||||||
|
@file_path "priv/metrics"
|
||||||
|
|
||||||
|
defstruct [
|
||||||
|
:guild_id,
|
||||||
|
:guild_name,
|
||||||
|
:first_request_at,
|
||||||
|
:last_request_at,
|
||||||
|
:total_requests
|
||||||
|
]
|
||||||
|
|
||||||
|
def start_link(_opts) do
|
||||||
|
initial_state =
|
||||||
|
case File.exists?(Path.join(@file_path, "requests")) do
|
||||||
|
true -> read()
|
||||||
|
false -> %{}
|
||||||
|
end
|
||||||
|
|
||||||
|
Agent.start_link(fn -> initial_state end, name: via_tuple(:requests))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp via_tuple(key) do
|
||||||
|
ProcessRegistry.via_tuple({__MODULE__, key})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_pid do
|
||||||
|
[{pid, _value}] = Registry.lookup(ProcessRegistry, {__MODULE__, :requests})
|
||||||
|
pid
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(key) do
|
||||||
|
get_pid()
|
||||||
|
|> Agent.get(&Map.get(&1, key))
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_all() do
|
||||||
|
get_pid()
|
||||||
|
|> Agent.get(& &1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def put(guild_id, guild_name) do
|
||||||
|
get_pid()
|
||||||
|
|> Agent.update(fn state ->
|
||||||
|
case Map.get(state, guild_id) do
|
||||||
|
nil ->
|
||||||
|
request_time = DateTime.utc_now()
|
||||||
|
|
||||||
|
Map.put(state, guild_id, %Requests{
|
||||||
|
guild_id: guild_id,
|
||||||
|
guild_name: guild_name,
|
||||||
|
first_request_at: request_time,
|
||||||
|
last_request_at: request_time,
|
||||||
|
total_requests: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
existing ->
|
||||||
|
Map.put(state, guild_id, %Requests{
|
||||||
|
existing
|
||||||
|
| last_request_at: DateTime.utc_now(),
|
||||||
|
total_requests: existing.total_requests + 1
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Reset metrics state and remove the saved file from disk.
|
||||||
|
"""
|
||||||
|
def reset() do
|
||||||
|
get_pid()
|
||||||
|
|> Agent.update(fn _ -> %{} end)
|
||||||
|
|
||||||
|
file = Path.join(@file_path, "requests")
|
||||||
|
|
||||||
|
if File.exists?(file) do
|
||||||
|
File.rm!(Path.join(@file_path, "requests"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Write the current state to disk. To be consumed by a CRON job.
|
||||||
|
"""
|
||||||
|
def write() do
|
||||||
|
File.mkdir_p!("priv/metrics")
|
||||||
|
|
||||||
|
data =
|
||||||
|
get_all()
|
||||||
|
|> :erlang.term_to_binary()
|
||||||
|
|
||||||
|
File.write!(Path.join(@file_path, "requests"), data)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Read the state from disk. To be loaded into state on process start.
|
||||||
|
"""
|
||||||
|
def read() do
|
||||||
|
File.read!(Path.join(@file_path, "requests"))
|
||||||
|
|> :erlang.binary_to_term()
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -117,7 +117,7 @@ defmodule PlantIdDiscordBot.Cog.PlantNet do
|
|||||||
{:ok, %{name: guild_name}} = GuildCache.get(guild_id)
|
{:ok, %{name: guild_name}} = GuildCache.get(guild_id)
|
||||||
|
|
||||||
RateLimiter.increase_counter(guild_id)
|
RateLimiter.increase_counter(guild_id)
|
||||||
Metrics.put(guild_id, guild_name)
|
Metrics.increase_request_count(guild_id, guild_name)
|
||||||
|
|
||||||
Api.create_followup_message(interaction.application_id, interaction.token, %{
|
Api.create_followup_message(interaction.application_id, interaction.token, %{
|
||||||
content: response_message <> "\n#{original_images}"
|
content: response_message <> "\n#{original_images}"
|
||||||
@@ -140,7 +140,7 @@ defmodule PlantIdDiscordBot.Cog.PlantNet do
|
|||||||
{:ok, %{name: guild_name}} = GuildCache.get(guild_id)
|
{:ok, %{name: guild_name}} = GuildCache.get(guild_id)
|
||||||
|
|
||||||
RateLimiter.increase_counter(guild_id)
|
RateLimiter.increase_counter(guild_id)
|
||||||
Metrics.put(guild_id, guild_name)
|
Metrics.increase_request_count(guild_id, guild_name)
|
||||||
|
|
||||||
Api.create_followup_message(interaction.application_id, interaction.token, %{
|
Api.create_followup_message(interaction.application_id, interaction.token, %{
|
||||||
content: "Species Not Found"
|
content: "Species Not Found"
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ defmodule PlantIdDiscordBot.Cog.PlantNetMessage do
|
|||||||
response_message = Parser.parse(body)
|
response_message = Parser.parse(body)
|
||||||
|
|
||||||
RateLimiter.increase_counter(guild_id)
|
RateLimiter.increase_counter(guild_id)
|
||||||
Metrics.put(guild_id, guild_name)
|
Metrics.increase_request_count(guild_id, guild_name)
|
||||||
|
|
||||||
# Nostrum.Api.create_message/2 is deprecated but the new function is not available in v0.10 of the library
|
# Nostrum.Api.create_message/2 is deprecated but the new function is not available in v0.10 of the library
|
||||||
# Nostrum.Api.message/2 will be the new function
|
# Nostrum.Api.message/2 will be the new function
|
||||||
@@ -99,7 +99,7 @@ defmodule PlantIdDiscordBot.Cog.PlantNetMessage do
|
|||||||
|
|
||||||
{:ok, %HTTPoison.Response{status_code: 404}} ->
|
{:ok, %HTTPoison.Response{status_code: 404}} ->
|
||||||
RateLimiter.increase_counter(guild_id)
|
RateLimiter.increase_counter(guild_id)
|
||||||
Metrics.put(guild_id, guild_name)
|
Metrics.increase_request_count(guild_id, guild_name)
|
||||||
|
|
||||||
Api.create_message(message.channel_id,
|
Api.create_message(message.channel_id,
|
||||||
content: "Species Not Found",
|
content: "Species Not Found",
|
||||||
|
|||||||
Reference in New Issue
Block a user