2 Commits

Author SHA1 Message Date
Ivan Gabaldon
f6e360a134 [mod] engines: remove stract engine (#5800)
Engine probably dead, developer doesn't have time to maintain it anymore:

- https://github.com/StractOrg/stract/issues/267

Related:

- https://github.com/searxng/searxng/pull/3099
2026-03-03 11:47:15 +01:00
Ivan Gabaldon
bc31c29d8a [mod] engines: remove livespace engine (#5798)
Related:

- https://github.com/searxng/searxng/pull/3222
- https://web.archive.org/web/20240524174947/https://about.live.space/post/thank-you
2026-03-03 11:27:33 +01:00
6 changed files with 4 additions and 210 deletions

View File

@@ -47,7 +47,6 @@
- ``seznam``
- ``sogou``
- ``startpage``
- ``stract``
- ``swisscows``
- ``wikipedia``
- ``yandex``

View File

@@ -87,7 +87,7 @@ Parameters
``autocomplete`` : default from :ref:`settings search`
[ ``google``, ``dbpedia``, ``duckduckgo``, ``mwmbl``, ``startpage``,
``wikipedia``, ``stract``, ``swisscows``, ``qwant`` ]
``wikipedia``, ``swisscows``, ``qwant`` ]
Service which completes words as you type.

View File

@@ -3,9 +3,8 @@
# pylint: disable=use-dict-literal
import json
import html
import typing as t
from urllib.parse import urlencode, quote_plus
from urllib.parse import urlencode
import lxml.etree
import lxml.html
@@ -16,7 +15,7 @@ from searx.engines import (
engines,
google,
)
from searx.network import get as http_get, post as http_post # pyright: ignore[reportUnknownVariableType]
from searx.network import get as http_get, post as http_post
from searx.exceptions import SearxEngineResponseException
from searx.utils import extr, gen_useragent
@@ -268,18 +267,6 @@ def startpage(query: str, sxng_locale: str) -> list[str]:
return results
def stract(query: str, _sxng_locale: str) -> list[str]:
# stract autocompleter (beta)
url = f"https://stract.com/beta/api/autosuggest?q={quote_plus(query)}"
resp = post(url)
results: list[str] = []
if resp.ok:
results = [html.unescape(suggestion['raw']) for suggestion in resp.json()]
return results
def swisscows(query: str, _sxng_locale: str) -> list[str]:
# swisscows autocompleter
url = 'https://swisscows.ch/api/suggest?{query}&itemsCount=5'
@@ -355,7 +342,6 @@ backends: dict[str, t.Callable[[str, str], list[str]]] = {
'seznam': seznam,
'sogou': sogou,
'startpage': startpage,
'stract': stract,
'swisscows': swisscows,
'wikipedia': wikipedia,
'yandex': yandex,

View File

@@ -1,100 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""LiveSpace (Videos)
.. hint::
This engine only search for **live streams**!
"""
from urllib.parse import urlencode
from datetime import datetime
from babel import dates
about = {
"website": 'https://live.space',
"wikidata_id": None,
"official_api_documentation": None,
"use_official_api": True,
"require_api_key": False,
"results": 'JSON',
}
categories = ['videos']
base_url = 'https://backend.live.space'
# engine dependent config
paging = True
results_per_page = 10
def request(query, params):
args = {'page': params['pageno'] - 1, 'searchKey': query, 'size': results_per_page}
params['url'] = f"{base_url}/search/public/stream?{urlencode(args)}"
params['headers'] = {'Accept': 'application/json', 'Content-Type': 'application/json'}
return params
def response(resp):
results = []
json = resp.json()
now = datetime.now()
# for live videos
for result in json.get('result', []):
title = result.get("title")
thumbnailUrl = result.get("thumbnailUrl")
category = result.get("category/name")
username = result.get("user", {}).get("userName", "")
url = f'https://live.space/watch/{username}'
# stream tags
# currently the api seems to always return null before the first tag,
# so strip that unless it's not already there
tags = ''
if result.get("tags"):
tags = [x for x in result.get("tags").split(';') if x and x != 'null']
tags = ', '.join(tags)
content = []
if category:
content.append(f'category - {category}')
if tags and len(tags) > 0:
content.append(f'tags - {tags}')
# time & duration
start_time = None
if result.get("startTimeStamp"):
start_time = datetime.fromtimestamp(result.get("startTimeStamp") / 1000)
# for VODs (videos on demand)
end_time = None
if result.get("endTimeStamp"):
end_time = datetime.fromtimestamp(result.get("endTimeStamp") / 1000)
timestring = ""
if start_time:
delta = (now if end_time is None else end_time) - start_time
timestring = dates.format_timedelta(delta, granularity='second')
results.append(
{
'url': url,
'title': title,
'content': "No category or tags." if len(content) == 0 else ' '.join(content),
'author': username,
'length': (">= " if end_time is None else "") + timestring,
'publishedDate': start_time,
'thumbnail': thumbnailUrl,
'template': 'videos.html',
}
)
return results

View File

@@ -1,79 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Stract is an independent open source search engine. At this state, it's
still in beta and hence this implementation will need to be updated once beta
ends.
"""
from json import dumps
from searx.utils import searxng_useragent
from searx.enginelib.traits import EngineTraits
about = {
"website": "https://stract.com/",
"use_official_api": True,
"official_api_documentation": "https://stract.com/beta/api/docs/#/search/api",
"require_api_key": False,
"results": "JSON",
}
categories = ['general']
paging = True
base_url = "https://stract.com/beta/api"
search_url = base_url + "/search"
def request(query, params):
params['url'] = search_url
params['method'] = "POST"
params['headers'] = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'User-Agent': searxng_useragent(),
}
region = traits.get_region(params["searxng_locale"], default=traits.all_locale)
params['data'] = dumps(
{
'query': query,
'page': params['pageno'] - 1,
'selectedRegion': region,
}
)
return params
def response(resp):
results = []
for result in resp.json()["webpages"]:
results.append(
{
'url': result['url'],
'title': result['title'],
'content': ''.join(fragment['text'] for fragment in result['snippet']['text']['fragments']),
}
)
return results
def fetch_traits(engine_traits: EngineTraits):
# pylint: disable=import-outside-toplevel
from searx import network
from babel import Locale, languages
from searx.locales import region_tag
territories = Locale("en").territories
json = network.get(base_url + "/docs/openapi.json").json()
regions = json['components']['schemas']['Region']['enum']
engine_traits.all_locale = regions[0]
for region in regions[1:]:
for code, name in territories.items():
if region not in (code, name):
continue
for lang in languages.get_official_languages(code, de_facto=True):
engine_traits.regions[region_tag(Locale(lang, code))] = region

View File

@@ -33,7 +33,7 @@ search:
# Filter results. 0: None, 1: Moderate, 2: Strict
safe_search: 0
# Existing autocomplete backends: "360search", "baidu", "brave", "dbpedia", "duckduckgo", "google", "yandex",
# "mwmbl", "naver", "seznam", "sogou", "startpage", "stract", "swisscows", "quark", "qwant", "wikipedia" -
# "mwmbl", "naver", "seznam", "sogou", "startpage", "swisscows", "quark", "qwant", "wikipedia" -
# leave blank to turn it off by default.
autocomplete: ""
# minimun characters to type before autocompleter starts
@@ -2474,13 +2474,6 @@ engines:
disabled: true
inactive: true
- name: livespace
engine: livespace
shortcut: ls
categories: videos
disabled: true
timeout: 5.0
- name: wordnik
engine: wordnik
shortcut: wnik
@@ -2505,11 +2498,6 @@ engines:
results: HTML
language: de
- name: stract
engine: stract
shortcut: str
disabled: true
- name: svgrepo
engine: svgrepo
shortcut: svg