Source code for inatcog.search
"""Module to search iNat site."""
from dronefly.core.formatters.constants import WWW_BASE_URL
from dronefly.core.formatters.generic import format_taxon_name, format_user_name
from pyinaturalist.models import Place, Project, Taxon, User
from .utils import get_home
[docs]def get_place(result):
"""Get place result."""
place = Place.from_json(result.get("record"))
return f":round_pushpin: [{place.display_name}]({place.url})"
[docs]def get_project(result):
"""Get project result."""
project = Project.from_json(result.get("record"))
return f":briefcase: [{project.title}]({WWW_BASE_URL}/projects/{project.id})"
[docs]def get_user(result):
"""Get user result."""
user = User.from_json(result.get("record"))
return f":bust_in_silhouette: {format_user_name(user)}"
[docs]def get_taxon(result):
"""Get taxon result (v1/search)."""
taxon = Taxon.from_json(result.get("record"))
return (
f":green_circle: [{format_taxon_name(taxon, with_term=True)}]"
f"({WWW_BASE_URL}/taxa/{taxon.id})"
)
[docs]def get_taxon2(result):
"""Get taxon result (/v1/taxa)."""
taxon = Taxon.from_json(result)
return (
f":green_circle: [{format_taxon_name(taxon, with_term=True)}]"
f"({WWW_BASE_URL}/taxa/{taxon.id})"
)
# pylint: disable=invalid-name
get_result_type = {
"Place": get_place,
"Project": get_project,
"User": get_user,
"Taxon": get_taxon,
"Inactive": get_taxon2,
}
[docs]def get_result(result, result_type: str = None):
"""Get fields for any result type."""
res_type = result_type or result.get("type")
return get_result_type[res_type](result)
# pylint: disable=too-few-public-methods
[docs]class INatSiteSearch:
"""Lookup helper for site search."""
def __init__(self, cog):
self.cog = cog
[docs] async def search(self, ctx, query, **kwargs):
"""Search iNat site."""
# Through experimentation on May 25, 2020, I've determined a smaller
# number than 500 will usually be returned:
# - for /v1/taxa it will be 500
# - for /v1/search?source=x (for any single source) it will be 100
# - for /v1/search without a source it will be 30
# If more than the maximum per_page is specified, however, it defaults
# back to 30, so we try to intelligently adjust the per_page in our
# request.
result_type = "Inactive" if "is_active" in kwargs else None
if result_type == "Inactive":
per_page = 500
elif "sources" in kwargs:
per_page = 100
else:
per_page = 30
home = await get_home(ctx)
api_kwargs = {"q": query, "per_page": per_page, "preferred_place_id": home}
api_kwargs.update(kwargs)
search_results = await self.cog.api.get_search_results(**api_kwargs)
results = [
get_result(result, result_type) for result in search_results["results"]
]
# But we return the actual per_page so the pager can accurately report
# how many results were not shown.
return (results, search_results["total_results"], search_results["per_page"])