/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", image_folder: "priv/static",
fileserver_url: "http://localhost:4321", fileserver_url: "http://localhost:4321",
port: 4321, port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot", source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite: 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", image_folder: "priv/static",
fileserver_url: "http://localhost:4321", fileserver_url: "http://localhost:4321",
port: 4321, port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot", source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite: 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", image_folder: "priv/static",
fileserver_url: "http://localhost:4321", fileserver_url: "http://localhost:4321",
port: 4321, port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot", source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite: 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, config :nostrum,
token: System.get_env("DISCORD_TOKEN"), token: System.get_env("DISCORD_TOKEN"),
+3 -2
View File
@@ -8,6 +8,7 @@ config :plantid_discord_bot,
image_folder: "priv/static", image_folder: "priv/static",
fileserver_url: "http://localhost:4321", fileserver_url: "http://localhost:4321",
port: 4321, port: 4321,
source: "https://github.com/TheRealOwenRees/plantID_discordbot", source: "https://github.com/TheRealOwenRees/plantid-discord-bot",
invite: 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 defmodule PlantIdDiscordBot do
@moduledoc """ @moduledoc """
Documentation for `PlantidDiscordBot`. A Discord bot that identifies plants from photos of their organs.
""" """
@doc """ use Nostrum.Consumer
Hello world. alias Nostrum.Api
alias PlantIdDiscordBot.Cog
## Examples IO.inspect("Starting PlantIdDiscordBot")
iex> PlantidDiscordBot.hello() @global_application_commands [
:world {"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, []"}
]
""" # Starts the bot
def hello do def handle_event({:READY}) do
:world # 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
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. # Run "mix help compile.app" to learn about applications.
def application do def application do
[ [
extra_applications: [:logger] extra_applications: [:logger],
mod: {PlantIdDiscordBot.Application, []}
] ]
end 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 defmodule PlantIdDiscordBotTest do
use ExUnit.Case use ExUnit.Case
doctest PlantIdDiscordBot doctest PlantIdDiscordBot
test "greets the world" do
assert PlantIdDiscordBot.hello() == :world
end
end end
+140 -140
View File
@@ -1,143 +1,143 @@
ExUnit.start() # ExUnit.start()
defmodule PlantNetFixtures do # defmodule PlantNetFixtures do
def raw_response, do: plantnet_raw_response # def raw_response, do: plantnet_raw_response
def parsed_response, do: plantnet_parsed_response # def parsed_response, do: plantnet_parsed_response
end # end
plantnet_raw_response = # 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}" # "{\"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 = [ # plantnet_parsed_response = [
%{ # %{
"gbif" => %{"id" => "3021730"}, # "gbif" => %{"id" => "3021730"},
"gbif_url" => "https://www.gbif.org/species/3021730", # "gbif_url" => "https://www.gbif.org/species/3021730",
"iucn" => %{"category" => "DD", "id" => "172162"}, # "iucn" => %{"category" => "DD", "id" => "172162"},
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+cerasifera", # "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+cerasifera",
"powo" => %{"id" => "729568-1"}, # "powo" => %{"id" => "729568-1"},
"powo_url" => "https://powo.science.kew.org/taxon/729568-1", # "powo_url" => "https://powo.science.kew.org/taxon/729568-1",
"score" => 0.87871, # "score" => 0.87871,
"species" => %{ # "species" => %{
"commonNames" => ["Cherry plum, myrobalan", "Cherry Plum", "Purple-leaf Plum"], # "commonNames" => ["Cherry plum, myrobalan", "Cherry Plum", "Purple-leaf Plum"],
"family" => %{ # "family" => %{
"scientificName" => "Rosaceae", # "scientificName" => "Rosaceae",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae" # "scientificNameWithoutAuthor" => "Rosaceae"
}, # },
"genus" => %{ # "genus" => %{
"scientificName" => "Prunus", # "scientificName" => "Prunus",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus" # "scientificNameWithoutAuthor" => "Prunus"
}, # },
"scientificName" => "Prunus cerasifera Ehrh.", # "scientificName" => "Prunus cerasifera Ehrh.",
"scientificNameAuthorship" => "Ehrh.", # "scientificNameAuthorship" => "Ehrh.",
"scientificNameWithoutAuthor" => "Prunus cerasifera" # "scientificNameWithoutAuthor" => "Prunus cerasifera"
} # }
}, # },
%{ # %{
"gbif" => %{"id" => "3022465"}, # "gbif" => %{"id" => "3022465"},
"gbif_url" => "https://www.gbif.org/species/3022465", # "gbif_url" => "https://www.gbif.org/species/3022465",
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+cistena", # "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+cistena",
"powo" => %{"id" => "2959315-4"}, # "powo" => %{"id" => "2959315-4"},
"powo_url" => "https://powo.science.kew.org/taxon/2959315-4", # "powo_url" => "https://powo.science.kew.org/taxon/2959315-4",
"score" => 0.31668, # "score" => 0.31668,
"species" => %{ # "species" => %{
"commonNames" => [ # "commonNames" => [
"Dwarf red-leaf plum", # "Dwarf red-leaf plum",
"Purple-leaf sand cherry", # "Purple-leaf sand cherry",
"Purple-leaved sand cherry" # "Purple-leaved sand cherry"
], # ],
"family" => %{ # "family" => %{
"scientificName" => "Rosaceae", # "scientificName" => "Rosaceae",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae" # "scientificNameWithoutAuthor" => "Rosaceae"
}, # },
"genus" => %{ # "genus" => %{
"scientificName" => "Prunus", # "scientificName" => "Prunus",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus" # "scientificNameWithoutAuthor" => "Prunus"
}, # },
"scientificName" => "Prunus × cistena N.E.Hansen ex Koehne", # "scientificName" => "Prunus × cistena N.E.Hansen ex Koehne",
"scientificNameAuthorship" => "N.E.Hansen ex Koehne", # "scientificNameAuthorship" => "N.E.Hansen ex Koehne",
"scientificNameWithoutAuthor" => "Prunus × cistena" # "scientificNameWithoutAuthor" => "Prunus × cistena"
} # }
}, # },
%{ # %{
"gbif" => %{"id" => "3020955"}, # "gbif" => %{"id" => "3020955"},
"gbif_url" => "https://www.gbif.org/species/3020955", # "gbif_url" => "https://www.gbif.org/species/3020955",
"iucn" => %{"category" => "LC", "id" => "64127603"}, # "iucn" => %{"category" => "LC", "id" => "64127603"},
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+sargentii", # "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+sargentii",
"powo" => %{"id" => "730239-1"}, # "powo" => %{"id" => "730239-1"},
"powo_url" => "https://powo.science.kew.org/taxon/730239-1", # "powo_url" => "https://powo.science.kew.org/taxon/730239-1",
"score" => 0.01801, # "score" => 0.01801,
"species" => %{ # "species" => %{
"commonNames" => ["Sargent's cherry", "Northern Japanese hill cherry", "Sargents cherry"], # "commonNames" => ["Sargent's cherry", "Northern Japanese hill cherry", "Sargents cherry"],
"family" => %{ # "family" => %{
"scientificName" => "Rosaceae", # "scientificName" => "Rosaceae",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae" # "scientificNameWithoutAuthor" => "Rosaceae"
}, # },
"genus" => %{ # "genus" => %{
"scientificName" => "Prunus", # "scientificName" => "Prunus",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus" # "scientificNameWithoutAuthor" => "Prunus"
}, # },
"scientificName" => "Prunus sargentii Rehder", # "scientificName" => "Prunus sargentii Rehder",
"scientificNameAuthorship" => "Rehder", # "scientificNameAuthorship" => "Rehder",
"scientificNameWithoutAuthor" => "Prunus sargentii" # "scientificNameWithoutAuthor" => "Prunus sargentii"
} # }
}, # },
%{ # %{
"gbif" => %{"id" => "3021335"}, # "gbif" => %{"id" => "3021335"},
"gbif_url" => "https://www.gbif.org/species/3021335", # "gbif_url" => "https://www.gbif.org/species/3021335",
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+yedoensis", # "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+×+yedoensis",
"powo" => %{"id" => "30119904-2"}, # "powo" => %{"id" => "30119904-2"},
"powo_url" => "https://powo.science.kew.org/taxon/30119904-2", # "powo_url" => "https://powo.science.kew.org/taxon/30119904-2",
"score" => 0.00896, # "score" => 0.00896,
"species" => %{ # "species" => %{
"commonNames" => ["Yoshino cherry", "Hybrid cherry", "Korean flowering cherry"], # "commonNames" => ["Yoshino cherry", "Hybrid cherry", "Korean flowering cherry"],
"family" => %{ # "family" => %{
"scientificName" => "Rosaceae", # "scientificName" => "Rosaceae",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae" # "scientificNameWithoutAuthor" => "Rosaceae"
}, # },
"genus" => %{ # "genus" => %{
"scientificName" => "Prunus", # "scientificName" => "Prunus",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus" # "scientificNameWithoutAuthor" => "Prunus"
}, # },
"scientificName" => "Prunus × yedoensis Matsum.", # "scientificName" => "Prunus × yedoensis Matsum.",
"scientificNameAuthorship" => "Matsum.", # "scientificNameAuthorship" => "Matsum.",
"scientificNameWithoutAuthor" => "Prunus × yedoensis" # "scientificNameWithoutAuthor" => "Prunus × yedoensis"
} # }
}, # },
%{ # %{
"gbif" => %{"id" => "3022609"}, # "gbif" => %{"id" => "3022609"},
"gbif_url" => "https://www.gbif.org/species/3022609", # "gbif_url" => "https://www.gbif.org/species/3022609",
"iucn" => %{"category" => "LC", "id" => "217170511"}, # "iucn" => %{"category" => "LC", "id" => "217170511"},
"pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+serrulata", # "pfaf_url" => "https://pfaf.org/user/Plant.aspx?LatinName=/Prunus+serrulata",
"powo" => %{"id" => "730268-1"}, # "powo" => %{"id" => "730268-1"},
"powo_url" => "https://powo.science.kew.org/taxon/730268-1", # "powo_url" => "https://powo.science.kew.org/taxon/730268-1",
"score" => 0.00518, # "score" => 0.00518,
"species" => %{ # "species" => %{
"commonNames" => [ # "commonNames" => [
"Japanese flowering cherry", # "Japanese flowering cherry",
"Japanese flowering cherry Kwanzan", # "Japanese flowering cherry Kwanzan",
"Tibetan Cherry" # "Tibetan Cherry"
], # ],
"family" => %{ # "family" => %{
"scientificName" => "Rosaceae", # "scientificName" => "Rosaceae",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Rosaceae" # "scientificNameWithoutAuthor" => "Rosaceae"
}, # },
"genus" => %{ # "genus" => %{
"scientificName" => "Prunus", # "scientificName" => "Prunus",
"scientificNameAuthorship" => "", # "scientificNameAuthorship" => "",
"scientificNameWithoutAuthor" => "Prunus" # "scientificNameWithoutAuthor" => "Prunus"
}, # },
"scientificName" => "Prunus serrulata Lindl.", # "scientificName" => "Prunus serrulata Lindl.",
"scientificNameAuthorship" => "Lindl.", # "scientificNameAuthorship" => "Lindl.",
"scientificNameWithoutAuthor" => "Prunus serrulata" # "scientificNameWithoutAuthor" => "Prunus serrulata"
} # }
} # }
] # ]