/source application command with test

This commit is contained in:
Owen
2024-12-13 23:02:23 +01:00
parent 1c4d0fb8af
commit 5975458407
12 changed files with 233 additions and 162 deletions
+3 -2
View File
@@ -8,6 +8,7 @@ config :plantid_discord_bot,
image_folder: "priv/static",
fileserver_url: "http://localhost:4321",
port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot",
source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite:
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot"
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot",
api: Nostrum.Api
+3 -2
View File
@@ -8,6 +8,7 @@ config :plantid_discord_bot,
image_folder: "priv/static",
fileserver_url: "http://localhost:4321",
port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot",
source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite:
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot"
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot",
api: Nostrum.Api
+3 -2
View File
@@ -8,9 +8,10 @@ config :plantid_discord_bot,
image_folder: "priv/static",
fileserver_url: "http://localhost:4321",
port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot",
source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite:
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot"
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot",
api: Nostrum.Api
config :nostrum,
token: System.get_env("DISCORD_TOKEN"),
+3 -2
View File
@@ -8,6 +8,7 @@ config :plantid_discord_bot,
image_folder: "priv/static",
fileserver_url: "http://localhost:4321",
port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot",
source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite:
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot"
"https://discord.com/api/oauth2/authorize?client_id=948227126094598204&permissions=19520&scope=bot",
api: PlantIdDiscordBotTest.Mocks.Nostrum.Api
+15
View File
@@ -0,0 +1,15 @@
defmodule PlantIdDiscordBot.Application do
use Application
@port Application.compile_env(:plantid_discord_bot, :port)
@impl true
def start(_type, _args) do
children = [
PlantIdDiscordBot
]
opts = [strategy: :one_for_one, name: PlantIdDiscordBot.Supervisor]
Supervisor.start_link(children, opts)
end
end
+7
View File
@@ -0,0 +1,7 @@
defmodule PlantIdDiscordBotTest.Mocks.Nostrum.Api do
@moduledoc """
Mocks the Nostrum.Api module.
"""
def create_interaction_response(_interaction, response), do: {:ok, response}
end
+28 -9
View File
@@ -1,18 +1,37 @@
defmodule PlantIdDiscordBot do
@moduledoc """
Documentation for `PlantidDiscordBot`.
A Discord bot that identifies plants from photos of their organs.
"""
@doc """
Hello world.
use Nostrum.Consumer
alias Nostrum.Api
alias PlantIdDiscordBot.Cog
## Examples
IO.inspect("Starting PlantIdDiscordBot")
iex> PlantidDiscordBot.hello()
:world
@global_application_commands [
{"servers", "All servers that this bot belongs to, []"},
{"invite", "Invite link for this bot, []"},
{"source", "Link to the source code for this bot, []"},
{"info", "Information about this bot, []"},
{"stats", "Statistics about this bot, []"},
{"help", "Help information for this bot, []"},
{"status", "API Status, []"},
{"id", "ID a plant from up to 5 images, []"}
]
"""
def hello do
:world
# Starts the bot
def handle_event({:READY}) do
# mock function depending on the environment
Api.create_global_application_command(@global_application_commands)
# TODO fix, not working
Api.update_status(:online, "Guess the Plant|/help")
# TODO remove in prod
Api.create_guild_application_command(1_002_507_312_159_797_318, @global_application_commands)
end
# Handle /source command
def handle_event({:INTERACTION_CREATE, %{data: %{name: "source"}} = interaction, _ws_state}) do
Cog.Info.source(interaction)
end
end
+13
View File
@@ -0,0 +1,13 @@
defmodule PlantIdDiscordBot.Cog.Info do
use Nostrum.Consumer
@api Application.compile_env(:plantid_discord_bot, :api)
@source Application.compile_env(:plantid_discord_bot, :source)
@doc """
Sends a link to the source code for this bot.
"""
def source(interaction) do
@api.create_interaction_response(interaction, %{type: 4, data: %{content: @source}})
end
end
+2 -1
View File
@@ -14,7 +14,8 @@ defmodule PlantidDiscordBot.MixProject do
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
extra_applications: [:logger],
mod: {PlantIdDiscordBot.Application, []}
]
end
+16
View File
@@ -0,0 +1,16 @@
defmodule PlantIdDiscordBotTest.Cog.Source do
use ExUnit.Case
@source Application.compile_env(:plantid_discord_bot, :source)
test "source" do
interaction = %{data: %{name: "source"}}
expected_response = %{
type: 4,
data: %{content: @source}
}
assert PlantIdDiscordBot.Cog.Info.source(interaction) == {:ok, expected_response}
end
end
-4
View File
@@ -1,8 +1,4 @@
defmodule PlantIdDiscordBotTest do
use ExUnit.Case
doctest PlantIdDiscordBot
test "greets the world" do
assert PlantIdDiscordBot.hello() == :world
end
end
+140 -140
View File
@@ -1,143 +1,143 @@
ExUnit.start()
# ExUnit.start()
defmodule PlantNetFixtures do
def raw_response, do: plantnet_raw_response
def parsed_response, do: plantnet_parsed_response
end
# defmodule PlantNetFixtures do
# def raw_response, do: plantnet_raw_response
# def parsed_response, do: plantnet_parsed_response
# end
plantnet_raw_response =
"{\"query\":{\"project\":\"all\",\"images\":[\"https://upload.wikimedia.org/wikipedia/commons/f/ff/Prunus_cerasifera_A.jpg\",\"https://le-jardin-de-pascal.com/2195113-large_default/prunus-cerasifera-atropurpurea-prunier-myrobolan-nigra.jpg\"],\"organs\":[\"auto\",\"auto\"],\"includeRelatedImages\":false,\"noReject\":false},\"language\":\"en\",\"preferedReferential\":\"k-world-flora\",\"bestMatch\":\"Prunus cerasifera Ehrh.\",\"results\":[{\"score\":0.87871,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus cerasifera\",\"scientificNameAuthorship\":\"Ehrh.\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Cherry plum, myrobalan\",\"Cherry Plum\",\"Purple-leaf Plum\"],\"scientificName\":\"Prunus cerasifera Ehrh.\"},\"gbif\":{\"id\":\"3021730\"},\"powo\":{\"id\":\"729568-1\"},\"iucn\":{\"id\":\"172162\",\"category\":\"DD\"}},{\"score\":0.31668,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus × cistena\",\"scientificNameAuthorship\":\"N.E.Hansen ex Koehne\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Dwarf red-leaf plum\",\"Purple-leaf sand cherry\",\"Purple-leaved sand cherry\"],\"scientificName\":\"Prunus × cistena N.E.Hansen ex Koehne\"},\"gbif\":{\"id\":\"3022465\"},\"powo\":{\"id\":\"2959315-4\"}},{\"score\":0.01801,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus sargentii\",\"scientificNameAuthorship\":\"Rehder\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Sargent's cherry\",\"Northern Japanese hill cherry\",\"Sargents cherry\"],\"scientificName\":\"Prunus sargentii Rehder\"},\"gbif\":{\"id\":\"3020955\"},\"powo\":{\"id\":\"730239-1\"},\"iucn\":{\"id\":\"64127603\",\"category\":\"LC\"}},{\"score\":0.00896,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus × yedoensis\",\"scientificNameAuthorship\":\"Matsum.\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Yoshino cherry\",\"Hybrid cherry\",\"Korean flowering cherry\"],\"scientificName\":\"Prunus × yedoensis Matsum.\"},\"gbif\":{\"id\":\"3021335\"},\"powo\":{\"id\":\"30119904-2\"}},{\"score\":0.00518,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus serrulata\",\"scientificNameAuthorship\":\"Lindl.\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Japanese flowering cherry\",\"Japanese flowering cherry Kwanzan\",\"Tibetan Cherry\"],\"scientificName\":\"Prunus serrulata Lindl.\"},\"gbif\":{\"id\":\"3022609\"},\"powo\":{\"id\":\"730268-1\"},\"iucn\":{\"id\":\"217170511\",\"category\":\"LC\"}}],\"version\":\"2024-11-19 (7.3)\",\"remainingIdentificationRequests\":488}"
# plantnet_raw_response =
# "{\"query\":{\"project\":\"all\",\"images\":[\"https://upload.wikimedia.org/wikipedia/commons/f/ff/Prunus_cerasifera_A.jpg\",\"https://le-jardin-de-pascal.com/2195113-large_default/prunus-cerasifera-atropurpurea-prunier-myrobolan-nigra.jpg\"],\"organs\":[\"auto\",\"auto\"],\"includeRelatedImages\":false,\"noReject\":false},\"language\":\"en\",\"preferedReferential\":\"k-world-flora\",\"bestMatch\":\"Prunus cerasifera Ehrh.\",\"results\":[{\"score\":0.87871,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus cerasifera\",\"scientificNameAuthorship\":\"Ehrh.\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Cherry plum, myrobalan\",\"Cherry Plum\",\"Purple-leaf Plum\"],\"scientificName\":\"Prunus cerasifera Ehrh.\"},\"gbif\":{\"id\":\"3021730\"},\"powo\":{\"id\":\"729568-1\"},\"iucn\":{\"id\":\"172162\",\"category\":\"DD\"}},{\"score\":0.31668,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus × cistena\",\"scientificNameAuthorship\":\"N.E.Hansen ex Koehne\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Dwarf red-leaf plum\",\"Purple-leaf sand cherry\",\"Purple-leaved sand cherry\"],\"scientificName\":\"Prunus × cistena N.E.Hansen ex Koehne\"},\"gbif\":{\"id\":\"3022465\"},\"powo\":{\"id\":\"2959315-4\"}},{\"score\":0.01801,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus sargentii\",\"scientificNameAuthorship\":\"Rehder\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Sargent's cherry\",\"Northern Japanese hill cherry\",\"Sargents cherry\"],\"scientificName\":\"Prunus sargentii Rehder\"},\"gbif\":{\"id\":\"3020955\"},\"powo\":{\"id\":\"730239-1\"},\"iucn\":{\"id\":\"64127603\",\"category\":\"LC\"}},{\"score\":0.00896,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus × yedoensis\",\"scientificNameAuthorship\":\"Matsum.\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Yoshino cherry\",\"Hybrid cherry\",\"Korean flowering cherry\"],\"scientificName\":\"Prunus × yedoensis Matsum.\"},\"gbif\":{\"id\":\"3021335\"},\"powo\":{\"id\":\"30119904-2\"}},{\"score\":0.00518,\"species\":{\"scientificNameWithoutAuthor\":\"Prunus serrulata\",\"scientificNameAuthorship\":\"Lindl.\",\"genus\":{\"scientificNameWithoutAuthor\":\"Prunus\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Prunus\"},\"family\":{\"scientificNameWithoutAuthor\":\"Rosaceae\",\"scientificNameAuthorship\":\"\",\"scientificName\":\"Rosaceae\"},\"commonNames\":[\"Japanese flowering cherry\",\"Japanese flowering cherry Kwanzan\",\"Tibetan Cherry\"],\"scientificName\":\"Prunus serrulata Lindl.\"},\"gbif\":{\"id\":\"3022609\"},\"powo\":{\"id\":\"730268-1\"},\"iucn\":{\"id\":\"217170511\",\"category\":\"LC\"}}],\"version\":\"2024-11-19 (7.3)\",\"remainingIdentificationRequests\":488}"
plantnet_parsed_response = [
%{
"gbif" => %{"id" => "3021730"},
"gbif_url" => "https://www.gbif.org/species/3021730",
"iucn" => %{"category" => "DD", "id" => "172162"},
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+cerasifera",
"powo" => %{"id" => "729568-1"},
"powo_url" => "https://powo.science.kew.org/taxon/729568-1",
"score" => 0.87871,
"species" => %{
"commonNames" => ["Cherry plum, myrobalan", "Cherry Plum", "Purple-leaf Plum"],
"family" => %{
"scientificName" => "Rosaceae",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae"
},
"genus" => %{
"scientificName" => "Prunus",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus"
},
"scientificName" => "Prunus cerasifera Ehrh.",
"scientificNameAuthorship" => "Ehrh.",
"scientificNameWithoutAuthor" => "Prunus cerasifera"
}
},
%{
"gbif" => %{"id" => "3022465"},
"gbif_url" => "https://www.gbif.org/species/3022465",
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+cistena",
"powo" => %{"id" => "2959315-4"},
"powo_url" => "https://powo.science.kew.org/taxon/2959315-4",
"score" => 0.31668,
"species" => %{
"commonNames" => [
"Dwarf red-leaf plum",
"Purple-leaf sand cherry",
"Purple-leaved sand cherry"
],
"family" => %{
"scientificName" => "Rosaceae",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae"
},
"genus" => %{
"scientificName" => "Prunus",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus"
},
"scientificName" => "Prunus × cistena N.E.Hansen ex Koehne",
"scientificNameAuthorship" => "N.E.Hansen ex Koehne",
"scientificNameWithoutAuthor" => "Prunus × cistena"
}
},
%{
"gbif" => %{"id" => "3020955"},
"gbif_url" => "https://www.gbif.org/species/3020955",
"iucn" => %{"category" => "LC", "id" => "64127603"},
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+sargentii",
"powo" => %{"id" => "730239-1"},
"powo_url" => "https://powo.science.kew.org/taxon/730239-1",
"score" => 0.01801,
"species" => %{
"commonNames" => ["Sargent's cherry", "Northern Japanese hill cherry", "Sargents cherry"],
"family" => %{
"scientificName" => "Rosaceae",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae"
},
"genus" => %{
"scientificName" => "Prunus",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus"
},
"scientificName" => "Prunus sargentii Rehder",
"scientificNameAuthorship" => "Rehder",
"scientificNameWithoutAuthor" => "Prunus sargentii"
}
},
%{
"gbif" => %{"id" => "3021335"},
"gbif_url" => "https://www.gbif.org/species/3021335",
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+yedoensis",
"powo" => %{"id" => "30119904-2"},
"powo_url" => "https://powo.science.kew.org/taxon/30119904-2",
"score" => 0.00896,
"species" => %{
"commonNames" => ["Yoshino cherry", "Hybrid cherry", "Korean flowering cherry"],
"family" => %{
"scientificName" => "Rosaceae",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae"
},
"genus" => %{
"scientificName" => "Prunus",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus"
},
"scientificName" => "Prunus × yedoensis Matsum.",
"scientificNameAuthorship" => "Matsum.",
"scientificNameWithoutAuthor" => "Prunus × yedoensis"
}
},
%{
"gbif" => %{"id" => "3022609"},
"gbif_url" => "https://www.gbif.org/species/3022609",
"iucn" => %{"category" => "LC", "id" => "217170511"},
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+serrulata",
"powo" => %{"id" => "730268-1"},
"powo_url" => "https://powo.science.kew.org/taxon/730268-1",
"score" => 0.00518,
"species" => %{
"commonNames" => [
"Japanese flowering cherry",
"Japanese flowering cherry Kwanzan",
"Tibetan Cherry"
],
"family" => %{
"scientificName" => "Rosaceae",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae"
},
"genus" => %{
"scientificName" => "Prunus",
"scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus"
},
"scientificName" => "Prunus serrulata Lindl.",
"scientificNameAuthorship" => "Lindl.",
"scientificNameWithoutAuthor" => "Prunus serrulata"
}
}
]
# plantnet_parsed_response = [
# %{
# "gbif" => %{"id" => "3021730"},
# "gbif_url" => "https://www.gbif.org/species/3021730",
# "iucn" => %{"category" => "DD", "id" => "172162"},
# "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+cerasifera",
# "powo" => %{"id" => "729568-1"},
# "powo_url" => "https://powo.science.kew.org/taxon/729568-1",
# "score" => 0.87871,
# "species" => %{
# "commonNames" => ["Cherry plum, myrobalan", "Cherry Plum", "Purple-leaf Plum"],
# "family" => %{
# "scientificName" => "Rosaceae",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Rosaceae"
# },
# "genus" => %{
# "scientificName" => "Prunus",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Prunus"
# },
# "scientificName" => "Prunus cerasifera Ehrh.",
# "scientificNameAuthorship" => "Ehrh.",
# "scientificNameWithoutAuthor" => "Prunus cerasifera"
# }
# },
# %{
# "gbif" => %{"id" => "3022465"},
# "gbif_url" => "https://www.gbif.org/species/3022465",
# "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+cistena",
# "powo" => %{"id" => "2959315-4"},
# "powo_url" => "https://powo.science.kew.org/taxon/2959315-4",
# "score" => 0.31668,
# "species" => %{
# "commonNames" => [
# "Dwarf red-leaf plum",
# "Purple-leaf sand cherry",
# "Purple-leaved sand cherry"
# ],
# "family" => %{
# "scientificName" => "Rosaceae",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Rosaceae"
# },
# "genus" => %{
# "scientificName" => "Prunus",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Prunus"
# },
# "scientificName" => "Prunus × cistena N.E.Hansen ex Koehne",
# "scientificNameAuthorship" => "N.E.Hansen ex Koehne",
# "scientificNameWithoutAuthor" => "Prunus × cistena"
# }
# },
# %{
# "gbif" => %{"id" => "3020955"},
# "gbif_url" => "https://www.gbif.org/species/3020955",
# "iucn" => %{"category" => "LC", "id" => "64127603"},
# "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+sargentii",
# "powo" => %{"id" => "730239-1"},
# "powo_url" => "https://powo.science.kew.org/taxon/730239-1",
# "score" => 0.01801,
# "species" => %{
# "commonNames" => ["Sargent's cherry", "Northern Japanese hill cherry", "Sargents cherry"],
# "family" => %{
# "scientificName" => "Rosaceae",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Rosaceae"
# },
# "genus" => %{
# "scientificName" => "Prunus",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Prunus"
# },
# "scientificName" => "Prunus sargentii Rehder",
# "scientificNameAuthorship" => "Rehder",
# "scientificNameWithoutAuthor" => "Prunus sargentii"
# }
# },
# %{
# "gbif" => %{"id" => "3021335"},
# "gbif_url" => "https://www.gbif.org/species/3021335",
# "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+yedoensis",
# "powo" => %{"id" => "30119904-2"},
# "powo_url" => "https://powo.science.kew.org/taxon/30119904-2",
# "score" => 0.00896,
# "species" => %{
# "commonNames" => ["Yoshino cherry", "Hybrid cherry", "Korean flowering cherry"],
# "family" => %{
# "scientificName" => "Rosaceae",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Rosaceae"
# },
# "genus" => %{
# "scientificName" => "Prunus",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Prunus"
# },
# "scientificName" => "Prunus × yedoensis Matsum.",
# "scientificNameAuthorship" => "Matsum.",
# "scientificNameWithoutAuthor" => "Prunus × yedoensis"
# }
# },
# %{
# "gbif" => %{"id" => "3022609"},
# "gbif_url" => "https://www.gbif.org/species/3022609",
# "iucn" => %{"category" => "LC", "id" => "217170511"},
# "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+serrulata",
# "powo" => %{"id" => "730268-1"},
# "powo_url" => "https://powo.science.kew.org/taxon/730268-1",
# "score" => 0.00518,
# "species" => %{
# "commonNames" => [
# "Japanese flowering cherry",
# "Japanese flowering cherry Kwanzan",
# "Tibetan Cherry"
# ],
# "family" => %{
# "scientificName" => "Rosaceae",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Rosaceae"
# },
# "genus" => %{
# "scientificName" => "Prunus",
# "scientificNameAuthorship" => "",
# "scientificNameWithoutAuthor" => "Prunus"
# },
# "scientificName" => "Prunus serrulata Lindl.",
# "scientificNameAuthorship" => "Lindl.",
# "scientificNameWithoutAuthor" => "Prunus serrulata"
# }
# }
# ]