From a8b1b811c54dc27b1ba21858b3d1cbd1c91f6fd1 Mon Sep 17 00:00:00 2001 From: dece Date: Wed, 6 Jul 2022 17:18:28 +0200 Subject: [PATCH] taxref: add function to get scientific name --- config.json.example | 2 +- edmond/plugins/taxref.py | 74 +++++++++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/config.json.example b/config.json.example index d775d6a..aaa5cc3 100644 --- a/config.json.example +++ b/config.json.example @@ -162,7 +162,7 @@ "snore_rate": 1.0 }, "taxref": { - "commands": ["taxref"], + "commands": ["taxref", "scientifize"], "not_found_reply": "Not found!", "reply": "{sci_name}, {fr_name}, {family}, {cd_nom}, {cd_ref}", "ambiguous_reply": "Ambiguous! It can be: ", diff --git a/edmond/plugins/taxref.py b/edmond/plugins/taxref.py index c5fff84..02a2d96 100644 --- a/edmond/plugins/taxref.py +++ b/edmond/plugins/taxref.py @@ -22,11 +22,20 @@ class TaxrefPlugin(Plugin): if not self.should_handle_command(event.arguments[0]): return False + # "taxref" if self.command.ident == self.config["commands"][0]: self.search_by_name(self.command.content, event.target) + # "scientifize" + if self.command.ident == self.config["commands"][1]: + self.find_scientific_name(self.command.content, event.target) return True def search_by_name(self, name, target): + """Get species data from a scientific name. + + Try to disambiguate the results by focusing on species only and their + scientific name. + """ name = name.lower() enc_name = urllib.parse.quote(name) url = ( @@ -66,7 +75,8 @@ class TaxrefPlugin(Plugin): if item["scientificName"].lower() == name ] if len(species_with_same_name) != 1: - self.show_ambiguous_reply(species_items, target) + reply = self.get_ambiguous_reply(species_items) + self.bot.say(target, reply) return item_to_use = species_with_same_name[0] @@ -80,9 +90,10 @@ class TaxrefPlugin(Plugin): ) self.bot.say(target, reply) - self.show_images(item_to_use, target) + if (images_reply := self.get_images_reply(item_to_use)): + self.bot.say(target, images_reply) - def show_ambiguous_reply(self, items, target): + def get_ambiguous_reply(self, items): """Show a reply with potential species.""" reply = self.config["ambiguous_reply"] append = "" @@ -92,25 +103,64 @@ class TaxrefPlugin(Plugin): reply += ", ".join(item["scientificName"] for item in items) if append: reply += append - self.bot.say(target, reply) + return reply - def show_images(self, item, target): - """If there are media available, show one!""" - m_url = item.get("_links", {}) .get("media", {}) .get("href") + def get_images_reply(self, item): + """If there are media available, return one in a message. + + Return a string with an URL to an image if one is available, or an + None if no image could be found or we encountered an error. + """ + m_url = item.get("_links", {}).get("media", {}).get("href") if not m_url: - return + return None response = requests.get(m_url) if response.status_code != 200: - self.signal_failure(target) - return + return None media_data = response.json() items = media_data.get("_embedded", {}).get("media", []) if not items: - return + return None random_item = random.choice(items) media_href = random_item.get("_links", {}).get("file", {}).get("href") if not media_href: + return None + return "📷 " + media_href + + def find_scientific_name(self, name, target): + """Find a corresponding scientific name for a vernacular name.""" + name = name.lower() + enc_name = urllib.parse.quote(name) + url = ( + f"{BASE_URL}/taxa/search?frenchVernacularNames={enc_name}" + "&page=1&size=100" + ) + response = requests.get(url) + if response.status_code != 200: + self.signal_failure(target) return - self.bot.say(target, "📷 " + media_href) + data = response.json() + items = data.get("_embedded", {}).get("taxa", []) + + if not items: + self.bot.say(target, self.config["not_found_reply"]) + return + + if len(items) == 1: + # Only one result: use it. + reply = items[0].get("scientificName") + else: + # More than one result? For simplicity sake, use the shrlok plugin + # if available or just show an ambiguous response. + if (shrlok := self.bot.get_plugin("shrlok")): + text = "\n".join( + f"{i['frenchVernacularName']} → {i['scientificName']}" + for i in items + ) + "\n" + reply = shrlok.post_text(text) + else: + reply = self.get_ambiguous_reply(items) + + self.bot.say(target, reply)