summaryrefslogtreecommitdiff
path: root/searx/result_types
diff options
context:
space:
mode:
Diffstat (limited to 'searx/result_types')
-rw-r--r--searx/result_types/__init__.py3
-rw-r--r--searx/result_types/_base.py23
-rw-r--r--searx/result_types/file.py94
3 files changed, 111 insertions, 9 deletions
diff --git a/searx/result_types/__init__.py b/searx/result_types/__init__.py
index a1976c10f..4ae2de816 100644
--- a/searx/result_types/__init__.py
+++ b/searx/result_types/__init__.py
@@ -23,6 +23,7 @@ __all__ = [
"WeatherAnswer",
"Code",
"Paper",
+ "File",
]
import typing as t
@@ -33,6 +34,7 @@ from .answer import AnswerSet, Answer, Translations, WeatherAnswer
from .keyvalue import KeyValue
from .code import Code
from .paper import Paper
+from .file import File
class ResultList(list[Result | LegacyResult], abc.ABC):
@@ -47,6 +49,7 @@ class ResultList(list[Result | LegacyResult], abc.ABC):
KeyValue = KeyValue
Code = Code
Paper = Paper
+ File = File
MainResult = MainResult
Result = Result
Translations = Translations
diff --git a/searx/result_types/_base.py b/searx/result_types/_base.py
index e97894b75..ffcf7f143 100644
--- a/searx/result_types/_base.py
+++ b/searx/result_types/_base.py
@@ -27,7 +27,6 @@ import typing as t
import re
import urllib.parse
import warnings
-import time
import datetime
from collections.abc import Callable
@@ -236,13 +235,6 @@ class Result(msgspec.Struct, kw_only=True):
url: str | None = None
"""A link related to this *result*"""
- template: str = "default.html"
- """Name of the template used to render the result.
-
- By default :origin:`result_templates/default.html
- <searx/templates/simple/result_templates/default.html>` is used.
- """
-
engine: str | None = ""
"""Name of the engine *this* result comes from. In case of *plugins* a
prefix ``plugin:`` is set, in case of *answerer* prefix ``answerer:`` is
@@ -350,6 +342,13 @@ class Result(msgspec.Struct, kw_only=True):
class MainResult(Result): # pylint: disable=missing-class-docstring
"""Base class of all result types displayed in :ref:`area main results`."""
+ template: str = "default.html"
+ """Name of the template used to render the result.
+
+ By default :origin:`result_templates/default.html
+ <searx/templates/simple/result_templates/default.html>` is used.
+ """
+
title: str = ""
"""Link title of the result item."""
@@ -359,6 +358,12 @@ class MainResult(Result): # pylint: disable=missing-class-docstring
img_src: str = ""
"""URL of a image that is displayed in the result item."""
+ iframe_src: str = ""
+ """URL of an embedded ``<iframe>`` / the frame is collapsible."""
+
+ audio_src: str = ""
+ """URL of an embedded ``<audio controls>``."""
+
thumbnail: str = ""
"""URL of a thumbnail that is displayed in the result item."""
@@ -372,7 +377,7 @@ class MainResult(Result): # pylint: disable=missing-class-docstring
completely eliminated.
"""
- length: time.struct_time | None = None
+ length: datetime.timedelta | None = None
"""Playing duration in seconds."""
views: str = ""
diff --git a/searx/result_types/file.py b/searx/result_types/file.py
new file mode 100644
index 000000000..5b58116c2
--- /dev/null
+++ b/searx/result_types/file.py
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+"""
+Typification of the *file* results. Results of this type are rendered in
+the :origin:`file.html <searx/templates/simple/result_templates/file.html>`
+template.
+
+----
+
+.. autoclass:: File
+ :members:
+ :show-inheritance:
+
+"""
+# pylint: disable=too-few-public-methods
+
+
+__all__ = ["File"]
+
+import typing as t
+import mimetypes
+
+from ._base import MainResult
+
+
+@t.final
+class File(MainResult, kw_only=True):
+ """Class for results of type *file*"""
+
+ template: str = "file.html"
+
+ filename: str = ""
+ """Name of the file."""
+
+ size: str = ""
+ """Size of bytes in human readable notation (``MB`` for 1024 * 1024 Bytes
+ file size.)"""
+
+ time: str = ""
+ """Indication of a time, such as the date of the last modification or the
+ date of creation. This is a simple string, the *date* of which can be freely
+ chosen according to the context."""
+
+ mimetype: str = ""
+ """Mimetype/Subtype of the file. For ``audio`` and ``video``, a URL can be
+ passed in the :py:obj:`File.embedded` field to embed the referenced media in
+ the result. If no value is specified, the MIME type is determined from
+ ``self.filename`` or, alternatively, from ``self.embedded`` (if either of
+ the two values is set)."""
+
+ abstract: str = ""
+ """Abstract of the file."""
+
+ author: str = ""
+ """Author of the file."""
+
+ embedded: str = ""
+ """URL of an embedded media type (audio or video) / is collapsible."""
+
+ mtype: str = ""
+ """Used for displaying :py:obj:`File.embedded`. Its value is automatically
+ populated from the base type of :py:obj:`File.mimetype`, and can be
+ explicitly set to enforce e.g. ``audio`` or ``video`` when mimetype is
+ something like "application/ogg" but its know the content is for example a
+ video."""
+
+ subtype: str = ""
+ """Used for displaying :py:obj:`File.embedded`. Its value is automatically
+ populated from the subtype type of :py:obj:`File.mimetype`, and can be
+ explicitly set to enforce a subtype for the :py:obj:`File.embedded`
+ element."""
+
+ def __post_init__(self):
+ super().__post_init__()
+
+ if not self.mtype or not self.subtype:
+
+ fn = self.filename or self.embedded
+ if not self.mimetype and fn:
+ self.mimetype = mimetypes.guess_type(fn, strict=False)[0] or ""
+
+ mtype, subtype = (self.mimetype.split("/", 1) + [""])[:2]
+
+ if not self.mtype:
+ # I don't know why, but the ogg video stream is not displayed,
+ # may https://github.com/videojs/video.js can help?
+ if self.embedded.endswith(".ogv"):
+ self.mtype = "video"
+ elif self.embedded.endswith(".oga"):
+ self.mtype = "audio"
+ else:
+ self.mtype = mtype
+
+ if not self.subtype:
+ self.subtype = subtype