diff --git a/config/dev.exs b/config/dev.exs index 9125d78..c13ddff 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -2,6 +2,7 @@ import Config config :plantid_discord_bot, api: Nostrum.Api, + guild: Nostrum.Cache.GuildCache, port: 4321 config :plantid_discord_bot, :environment, :dev diff --git a/config/prod.exs b/config/prod.exs index 6790285..e3bca64 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -2,6 +2,7 @@ import Config config :plantid_discord_bot, api: Nostrum.Api, + guild: Nostrum.Cache.GuildCache, port: 4000 config :plantid_discord_bot, :environment, :prod diff --git a/config/test.exs b/config/test.exs index 1e67483..df7ec08 100644 --- a/config/test.exs +++ b/config/test.exs @@ -2,6 +2,7 @@ import Config config :plantid_discord_bot, api: PlantIdDiscordBotTest.Mocks.Nostrum.Api, + guild: PlantIdDiscordBotTest.Mocks.Guild, port: 4321 config :plantid_discord_bot, :environment, :test diff --git a/lib/commands.ex b/lib/commands.ex index 040082b..f0e921c 100644 --- a/lib/commands.ex +++ b/lib/commands.ex @@ -35,43 +35,6 @@ defmodule PlantIdDiscordBot.Consumer.Commands do name: "servers", description: "All servers that this bot belongs to", options: [] - }, - %{ - name: "id", - description: "ID a plant from up to 5 images", - options: [ - %{ - # Attachment type - type: 11, - name: "image1", - description: "The image to identify", - required: true - }, - %{ - type: 11, - name: "image2", - description: "The image to identify", - required: false - }, - %{ - type: 11, - name: "image3", - description: "The image to identify", - required: false - }, - %{ - type: 11, - name: "image4", - description: "The image to identify", - required: false - }, - %{ - type: 11, - name: "image5", - description: "The image to identify", - required: false - } - ] } ] end diff --git a/lib/plantid_discord_bot.ex b/lib/plantid_discord_bot.ex index 2acfd90..b513c47 100644 --- a/lib/plantid_discord_bot.ex +++ b/lib/plantid_discord_bot.ex @@ -22,7 +22,6 @@ defmodule PlantIdDiscordBot.Consumer do "stats" -> Cog.Info.stats(interaction) "status" -> Cog.Info.status(interaction) "servers" -> Cog.Info.servers(interaction) - "id" -> Cog.PlantNet.id(interaction) end end diff --git a/lib/plantid_discord_bot/cogs/plantnet.ex b/lib/plantid_discord_bot/cogs/plantnet.ex deleted file mode 100644 index a8f0d72..0000000 --- a/lib/plantid_discord_bot/cogs/plantnet.ex +++ /dev/null @@ -1,169 +0,0 @@ -defmodule PlantIdDiscordBot.Cog.PlantNet do - require Logger - use Nostrum.Consumer - alias Nostrum.Api - alias Nostrum.Cache.GuildCache - alias PlantIdDiscordBot.RateLimiter - alias PlantIdDiscordBot.PlantNet.Parser - alias PlantIdDiscordBot.FileServer.File - alias PlantIdDiscordBot.Metrics - - @api Application.compile_env(:plantid_discord_bot, :api) - @plantnet_api_base_url Application.compile_env(:plantid_discord_bot, :plantnet_api_base_url) - @max_results Application.compile_env(:plantid_discord_bot, :max_results) - - @doc """ - Process /id application command. - """ - def id(interaction) do - case RateLimiter.check_limit(interaction.guild_id) do - {:limit_exceeded, _} -> - @api.create_interaction_response(interaction, %{ - type: 4, - data: %{ - content: - "This server has exceeded its allowed requests in 24 hours. Please try again tomorrow." - } - }) - - {:ok, _} -> - do_identification(interaction) - end - end - - defp do_identification(interaction) do - @api.create_interaction_response(interaction, %{ - type: 5, - data: %{ - content: "Processing..." - } - }) - - attachment_urls = get_attachment_urls(interaction) - original_images = get_original_images(attachment_urls) - - saved_images = - try do - File.download_and_save_files!(attachment_urls) - rescue - e in ArgumentError -> - Api.create_followup_message(interaction.application_id, interaction.token, %{ - content: e.message - }) - - nil - end - - if saved_images do - try do - prepare_images(saved_images) - |> build_query_uri() - |> get_response(interaction, original_images) - rescue - e -> - Logger.error(Exception.format(:error, e, __STACKTRACE__)) - - Api.create_followup_message(interaction.application_id, interaction.token, %{ - content: "An error occurred. This error has been logged." - }) - after - cleanup_saved_images(saved_images) - end - end - end - - defp get_attachment_urls(interaction) do - interaction.data.resolved.attachments - |> Map.values() - |> Enum.map(& &1.url) - end - - @spec get_original_images([String.t()]) :: String.t() - defp get_original_images(attachment_urls), do: Enum.join(attachment_urls, "\n") - - defp prepare_images(saved_images) do - case Application.get_env(:plantid_discord_bot, :environment) do - :test -> - PlantIdDiscordBotTest.Mocks.PlantNet.Images.images() - - :dev -> - PlantIdDiscordBotTest.Mocks.PlantNet.Images.images() - - _ -> - Enum.map(saved_images, fn {:ok, filename} -> - "#{Application.get_env(:plantid_discord_bot, :fileserver_url)}/#{filename}" - end) - end - end - - @spec build_query_uri([String.t()]) :: String.t() - defp build_query_uri(image_filenames) do - URI.parse( - "#{@plantnet_api_base_url}/identify/all?api-key=#{Application.get_env(:plantid_discord_bot, :plantnet_api_key)}" - ) - |> URI.append_query("images=#{Enum.join(image_filenames, "&images=")}") - |> URI.append_query("nb-results=#{@max_results}") - |> URI.append_query("type=kt") - |> URI.to_string() - end - - @spec get_response(String.t(), Nostrum.Interaction.t(), String.t()) :: :ok - defp get_response(query_uri, interaction, original_images) do - case HTTPoison.get(query_uri) do - {:ok, %HTTPoison.Response{status_code: 200, body: body}} -> - response_message = Parser.parse(body) - - guild_id = interaction.guild_id - {:ok, %{name: guild_name}} = GuildCache.get(guild_id) - - RateLimiter.increase_counter(guild_id) - Metrics.increase_request_count(guild_id, guild_name) - - Api.create_followup_message(interaction.application_id, interaction.token, %{ - content: response_message <> "\n#{original_images}" - }) - - {:ok, %HTTPoison.Response{status_code: 400, body: body}} -> - Logger.error(""" - Malformed request sent to the PlantNet Api from PlantIdDiscordBot.Cog.PlantNet.do_identification - Query URI: #{query_uri} - Status Code: 400 - Response Body: #{String.slice(body, 0..500)}... (truncated) - """) - - Api.create_followup_message(interaction.application_id, interaction.token, %{ - content: "Bad Request. This error has been logged." - }) - - {:ok, %HTTPoison.Response{status_code: 404}} -> - guild_id = interaction.guild_id - {:ok, %{name: guild_name}} = GuildCache.get(guild_id) - - RateLimiter.increase_counter(guild_id) - Metrics.increase_request_count(guild_id, guild_name) - - Api.create_followup_message(interaction.application_id, interaction.token, %{ - content: "Species Not Found" - }) - - {:ok, %HTTPoison.Response{status_code: 429}} -> - Logger.warning("Request limit exceeded for the PlantNet API") - - Api.create_followup_message(interaction.application_id, interaction.token, %{ - content: "Too Many Requests" - }) - - {_, _} -> - Logger.error("Internal server error when contacting the PlantNet API") - - Api.create_followup_message(interaction.application_id, interaction.token, %{ - content: "Internal Server Error" - }) - end - end - - defp cleanup_saved_images(saved_images) do - Enum.map(saved_images, fn {:ok, filename} -> filename end) - |> File.delete_files!() - end -end diff --git a/lib/plantid_discord_bot/cogs/plantnet_message.ex b/lib/plantid_discord_bot/cogs/plantnet_message.ex index b17c6d0..a86c1a6 100644 --- a/lib/plantid_discord_bot/cogs/plantnet_message.ex +++ b/lib/plantid_discord_bot/cogs/plantnet_message.ex @@ -3,10 +3,11 @@ defmodule PlantIdDiscordBot.Cog.PlantNetMessage do use Nostrum.Consumer alias Nostrum.Api - alias PlantIdDiscordBot.{Guild, RateLimiter, Metrics, FileServer.File, PlantNet.Parser} + alias PlantIdDiscordBot.{Guild, RateLimiter, Metrics} + alias PlantIdDiscordBot.PlantNet.Parser + alias PlantIdDiscordBot.FileServer.File - # TODO reintroduce mocks - # @api Application.compile_env(:plantid_discord_bot, :api) + # @guild Application.compile_env(:plantid_discord_bot, :guild) @plantnet_api_base_url Application.compile_env(:plantid_discord_bot, :plantnet_api_base_url) @max_results Application.compile_env(:plantid_discord_bot, :max_results) diff --git a/test/guild_test.exs b/test/guild_test.exs new file mode 100644 index 0000000..ec4cda7 --- /dev/null +++ b/test/guild_test.exs @@ -0,0 +1,3 @@ +defmodule PlantIdDiscordBotTest.Guild do + use ExUnit.Case +end