Source code for inatcog.query
"""Module to query iNat."""
import re
from dronefly.core.query.query import (
get_base_query_args,
has_value,
Query,
QueryResponse,
)
from dronefly.core.models.controlled_terms import match_controlled_term
from pyinaturalist.models import ControlledTerm, User
from redbot.core.commands import BadArgument, Context
from .common import DEQUOTE
from .converters.base import MemberConverter
[docs]class INatQuery:
"""Query iNat for all requested entities."""
def __init__(self, cog):
self.cog = cog
async def _get_user(self, user: str, **kwargs):
try:
response = await self.cog.api.get_users(user, **kwargs)
if response and response["results"] and len(response["results"]) == 1:
return User.from_json(response["results"][0])
except (BadArgument, LookupError):
pass
return None
[docs] async def get_inat_user(self, ctx: Context, user: str):
"""Get iNat user from iNat user_id, known member, or iNat login, in that order."""
_user = None
if user.isnumeric():
_user = await self._get_user(user)
if not _user:
try:
who = await MemberConverter.convert(ctx, re.sub(DEQUOTE, r"\1", user))
_user = await self.cog.user_table.get_user(who.member)
except (BadArgument, LookupError):
pass
if isinstance(user, str) and not _user and " " not in str(user):
_user = await self._get_user(user, by_login_id=True)
if not _user:
raise LookupError("iNat member is not known or iNat login is not valid.")
return _user
async def _get_controlled_term(self, query_term: str, query_term_value: str):
controlled_terms_dict = await self.cog.api.get_controlled_terms()
controlled_terms = [
ControlledTerm.from_json(term) for term in controlled_terms_dict["results"]
]
controlled_term = match_controlled_term(
controlled_terms, query_term, query_term_value
)
return controlled_term
[docs] async def get(
self, ctx: Context, query: Query, scientific_name=False, locale=None, **kwargs
):
"""Get all requested iNat entities."""
args = get_base_query_args(query)
args["project"] = (
await self.cog.project_table.get_project(ctx.guild, query.project)
if has_value(query.project)
else None
)
args["place"] = (
await self.cog.place_table.get_place(ctx.guild, query.place, ctx.author)
if has_value(query.place)
else None
)
taxon_params = {
"scientific_name": scientific_name,
"locale": locale,
}
if args["place"]:
taxon_params["preferred_place_id"] = args["place"].id
args["taxon"] = (
await self.cog.taxon_query.maybe_match_taxon_compound(
ctx, query, **taxon_params
)
if has_value(query.main)
else None
)
args["user"] = (
await self.get_inat_user(ctx, query.user) if has_value(query.user) else None
)
args["unobserved_by"] = (
await self.get_inat_user(ctx, query.unobserved_by)
if has_value(query.unobserved_by)
else None
)
args["except_by"] = (
await self.get_inat_user(ctx, query.except_by)
if has_value(query.except_by)
else None
)
args["id_by"] = (
await self.get_inat_user(ctx, query.id_by)
if has_value(query.id_by)
else None
)
args["controlled_term"] = (
await self._get_controlled_term(*query.controlled_term)
if has_value(query.controlled_term)
else None
)
return QueryResponse(**args)