1
0
Fork 0
searxng/searx/answerers/__init__.py

57 lines
1.8 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-or-later
# pylint: disable=missing-module-docstring
from __future__ import annotations
import sys
from collections import defaultdict
from os import listdir
from os.path import realpath, dirname, join, isdir
from typing import Callable
from searx.answerers.models import AnswerModule, AnswerDict
from searx.search.models import BaseQuery
from searx.utils import load_module
answerers_dir = dirname(realpath(__file__))
def load_answerers() -> list[AnswerModule]:
answerers = [] # pylint: disable=redefined-outer-name
for filename in listdir(answerers_dir):
if not isdir(join(answerers_dir, filename)) or filename.startswith('_'):
continue
module = load_module('answerer.py', join(answerers_dir, filename))
if not hasattr(module, 'keywords') or not isinstance(module.keywords, tuple) or not module.keywords:
sys.exit(2)
answerers.append(module)
return answerers
def get_answerers_by_keywords(
answerers: list[AnswerModule], # pylint: disable=redefined-outer-name
) -> dict[str, list[Callable[[BaseQuery], list[AnswerDict]]]]:
by_keyword = defaultdict(list)
for answerer in answerers:
for keyword in answerer.keywords:
for keyword in answerer.keywords:
by_keyword[keyword].append(answerer.answer)
return by_keyword
def ask(query: BaseQuery) -> list[list[AnswerDict]]:
results: list[list[AnswerDict]] = []
query_parts = list(filter(None, query.query.split()))
if not query_parts or query_parts[0] not in answerers_by_keywords:
return results
for answerer in answerers_by_keywords[query_parts[0]]:
result = answerer(query)
if result:
results.append(result)
return results
answerers = load_answerers()
answerers_by_keywords = get_answerers_by_keywords(answerers)