[fix] 500px: migrate to new search endpoint

This commit is contained in:
Bnyro
2026-09-13 13:28:21 +02:00
parent 32f2da4ef0
commit e61d097562

View File

@@ -12,8 +12,6 @@ through our exclusive distribution partners.
import typing as t import typing as t
import codecs import codecs
import random
import string
from searx.result_types import EngineResults from searx.result_types import EngineResults
@@ -33,11 +31,11 @@ about = {
} }
base_url = "https://500px.com" base_url = "https://500px.com"
api_url = "https://api.500px.com" api_url = "https://api-neo.500px.com"
categories = ["images"] categories = ["images"]
paging = True paging = True
results_per_page = 30 results_per_page = 30
"""Number of results to return in the request. """Number of results to return in the request.
@@ -46,47 +44,71 @@ The default was taken from the WEB UI, where the GraphQL query sets the value to
""" """
SXNG_query = """query PhotoSearchPaginationContainerQuery( SXNG_query = """
$first: Int, $cursor: String, $search: String!, $sort: PhotoSort, $filters: [PhotoSearchFilter!], $nlp: Boolean query searchResource(
$keyword: String!
$type: SearchType = TEXT
$first: Int!
$after: String
$resourceTypes: [SearchResourceType!]
$categories: [String!]
$equipments: [String!]
$downloadable: PhotoDownloadable
$sort: SearchSortOption = RELEVANCE
$excludeNsfw: Boolean
) {
searchResource(
keyword: $keyword
type: $type
first: $first
after: $after
resourceTypes: $resourceTypes
categories: $categories
equipments: $equipments
downloadable: $downloadable
sort: $sort
excludeNsfw: $excludeNsfw
) { ) {
...SXNG_query
}
fragment SXNG_query on Query {
photoSearch(sort: $sort, first: $first, after: $cursor, search: $search, filters: $filters, nlp: $nlp) {
edges { edges {
cursor
node { node {
__typename
... on Photo {
id id
canonicalPath title
name
description description
licensing {
status
__typename
}
urls {
size_600
size_1024
size_2048
size_4k
__typename
}
uploader {
displayName
__typename
}
isNsfw
width width
height height
photographer: uploader { dominantColorLight
displayName dominantColorDark
} uploadedAt
images(sizes: [35, 33]) { __typename
size
url
jpegUrl
webpUrl
id
} }
} }
cursor __typename
} }
__typename
} }
} }
""" """
def setup(_) -> bool:
global SXNG_query # pylint: disable=global-statement
rand_str: str = "".join(random.choices(string.ascii_letters, k=5))
SXNG_query = SXNG_query.replace("SXNG_query", "PhotoSearchPaginationContainer_query_1" + rand_str)
return True
def request(query: str, params: "OnlineParams") -> None: def request(query: str, params: "OnlineParams") -> None:
# cursor is the base64 hash of the string "pos-<offset-1>", e.g. "pos-29" -> "cG9zLTI5" # cursor is the base64 hash of the string "pos-<offset-1>", e.g. "pos-29" -> "cG9zLTI5"
offset = ((params["pageno"] - 1) * results_per_page) - 1 offset = ((params["pageno"] - 1) * results_per_page) - 1
@@ -95,14 +117,14 @@ def request(query: str, params: "OnlineParams") -> None:
params["url"] = f"{api_url}/graphql" params["url"] = f"{api_url}/graphql"
params["method"] = "POST" params["method"] = "POST"
params["json"] = { params["json"] = {
"operationName": "PhotoSearchPaginationContainerQuery", "operationName": "searchResource",
"variables": { "variables": {
"after": cursor,
"first": results_per_page, "first": results_per_page,
"cursor": cursor, "keyword": query,
"search": query, "resourceTypes": ["PHOTO"],
"sort": "RELEVANCE", "sort": "RELEVANCE",
"filters": [], "type": "TEXT",
"nlp": False,
}, },
"query": SXNG_query, "query": SXNG_query,
} }
@@ -110,27 +132,20 @@ def request(query: str, params: "OnlineParams") -> None:
def response(resp: "SXNG_Response"): def response(resp: "SXNG_Response"):
res = EngineResults() res = EngineResults()
json_data = resp.json()["data"]["photoSearch"] json_data = resp.json()["data"]["searchResource"]
for edge in json_data["edges"]: for edge in json_data["edges"]:
node = edge["node"] # pyright: ignore[reportAny] node = edge["node"] # pyright: ignore[reportAny]
if not node["images"]: image_urls = [url for (resolution, url) in node["urls"].items() if resolution.startswith("size_")]
continue
images: list[dict[str, str]] = sorted(node["images"], key=lambda i: i["size"])
thumbnail_src = images[0]["url"]
img_src = images[-1]["url"]
res.add( res.add(
res.types.LegacyResult( res.types.Image(
{ url=f"{base_url}/photo/{node['id']}",
"template": "images.html", thumbnail_src=image_urls[0],
"url": base_url + node["canonicalPath"], img_src=image_urls[-1],
"thumbnail_src": thumbnail_src, title=node["title"],
"img_src": img_src, content=node["description"],
"title": node["name"], author=node["uploader"]["displayName"],
"content": node["description"], resolution=f"{node['width']}x{node['height']}",
"author": node["photographer"]["displayName"],
"resolution": f"{node['width']}x{node['height']}",
}
) )
) )