mirror of
https://github.com/searxng/searxng.git
synced 2025-04-16 00:14:11 +00:00
Merge f1e970e25d
into 391bb1268d
This commit is contained in:
commit
667d95fd46
2 changed files with 150 additions and 0 deletions
144
searx/engines/senscritique.py
Normal file
144
searx/engines/senscritique.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
"""SensCritique (movies)
|
||||
"""
|
||||
|
||||
from json import dumps, loads
|
||||
from typing import Any, Optional
|
||||
|
||||
about = {
|
||||
"website": 'https://www.senscritique.com/',
|
||||
"wikidata_id": 'Q16676060',
|
||||
"official_api_documentation": None,
|
||||
"use_official_api": False,
|
||||
"require_api_key": False,
|
||||
"results": 'JSON',
|
||||
'language': 'fr',
|
||||
}
|
||||
|
||||
categories = ['movies']
|
||||
paging = True
|
||||
page_size = 16
|
||||
graphql_url = 'https://apollo.senscritique.com/'
|
||||
|
||||
graphql_query = """query SearchProductExplorer($query: String, $offset: Int, $limit: Int,
|
||||
$sortBy: SearchProductExplorerSort) {
|
||||
searchProductExplorer(
|
||||
query: $query
|
||||
filters: []
|
||||
sortBy: $sortBy
|
||||
offset: $offset
|
||||
limit: $limit
|
||||
) {
|
||||
items {
|
||||
category
|
||||
dateRelease
|
||||
duration
|
||||
id
|
||||
originalTitle
|
||||
rating
|
||||
title
|
||||
url
|
||||
yearOfProduction
|
||||
medias {
|
||||
picture
|
||||
}
|
||||
countries {
|
||||
name
|
||||
}
|
||||
genresInfos {
|
||||
label
|
||||
}
|
||||
directors {
|
||||
name
|
||||
}
|
||||
stats {
|
||||
ratingCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
|
||||
def request(query: str, params: dict[str, Any]) -> dict[str, Any]:
|
||||
offset = (params['pageno'] - 1) * page_size
|
||||
|
||||
data = {
|
||||
"operationName": "SearchProductExplorer",
|
||||
"variables": {"offset": offset, "limit": page_size, "query": query, "sortBy": "RELEVANCE"},
|
||||
"query": graphql_query,
|
||||
}
|
||||
|
||||
params['url'] = graphql_url
|
||||
params['method'] = 'POST'
|
||||
params['headers']['Content-Type'] = 'application/json'
|
||||
params['data'] = dumps(data)
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def response(resp: Any) -> list[dict[str, Any]]:
|
||||
results = []
|
||||
response_data = loads(resp.text)
|
||||
|
||||
items = response_data.get('data', {}).get('searchProductExplorer', {}).get('items', [])
|
||||
if not items:
|
||||
return results
|
||||
|
||||
for item in items:
|
||||
results.append(parse_item(item))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def parse_item(item: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Parse a single item from the SensCritique API response"""
|
||||
title = item.get('title', '')
|
||||
year = item.get('yearOfProduction')
|
||||
original_title = item.get('originalTitle')
|
||||
|
||||
thumbnail = None
|
||||
if item.get('medias', {}) and item['medias'].get('picture'):
|
||||
thumbnail = item['medias']['picture']
|
||||
|
||||
content_parts = build_content_parts(item, title, original_title)
|
||||
url = f"https://www.senscritique.com{item['url']}" if item.get('url') else None
|
||||
|
||||
return {
|
||||
'url': url,
|
||||
'title': title + (f' ({year})' if year else ''),
|
||||
'content': ' | '.join(content_parts),
|
||||
'thumbnail': thumbnail,
|
||||
}
|
||||
|
||||
|
||||
def build_content_parts(item: dict[str, Any], title: str, original_title: Optional[str]) -> list[str]:
|
||||
"""Build the content parts for an item"""
|
||||
content_parts = []
|
||||
|
||||
if item.get('category'):
|
||||
content_parts.append(item['category'])
|
||||
|
||||
if original_title and original_title != title:
|
||||
content_parts.append(f"Original title: {original_title}")
|
||||
|
||||
if item.get('directors'):
|
||||
directors = [director['name'] for director in item['directors']]
|
||||
content_parts.append(f"Director(s): {', '.join(directors)}")
|
||||
|
||||
if item.get('countries'):
|
||||
countries = [country['name'] for country in item['countries']]
|
||||
content_parts.append(f"Country: {', '.join(countries)}")
|
||||
|
||||
if item.get('genresInfos'):
|
||||
genres = [genre['label'] for genre in item['genresInfos']]
|
||||
content_parts.append(f"Genre(s): {', '.join(genres)}")
|
||||
|
||||
if item.get('duration'):
|
||||
minutes = item['duration'] // 60
|
||||
if minutes > 0:
|
||||
content_parts.append(f"Duration: {minutes} min")
|
||||
|
||||
if item.get('rating') and item.get('stats', {}).get('ratingCount'):
|
||||
content_parts.append(f"Rating: {item['rating']}/10 ({item['stats']['ratingCount']} votes)")
|
||||
|
||||
return content_parts
|
|
@ -2642,6 +2642,12 @@ engines:
|
|||
shortcut: pgo
|
||||
disabled: true
|
||||
|
||||
- name: senscritique
|
||||
engine: senscritique
|
||||
shortcut: scr
|
||||
timeout: 4.0
|
||||
disabled: true
|
||||
|
||||
# Doku engine lets you access to any Doku wiki instance:
|
||||
# A public one or a privete/corporate one.
|
||||
# - name: ubuntuwiki
|
||||
|
|
Loading…
Reference in a new issue