.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
flickr_noapi.py
Go to the documentation of this file.
1# SPDX-License-Identifier: AGPL-3.0-or-later
2"""Flickr (Images)
3
4"""
5
6from typing import TYPE_CHECKING
7
8import json
9from time import time
10import re
11from urllib.parse import urlencode
12from searx.utils import ecma_unescape, html_to_text
13
14if TYPE_CHECKING:
15 import logging
16
17 logger: logging.Logger
18
19# about
20about = {
21 "website": 'https://www.flickr.com',
22 "wikidata_id": 'Q103204',
23 "official_api_documentation": 'https://secure.flickr.com/services/api/flickr.photos.search.html',
24 "use_official_api": False,
25 "require_api_key": False,
26 "results": 'HTML',
27}
28
29# engine dependent config
30categories = ['images']
31paging = True
32time_range_support = True
33safesearch = False
34
35time_range_dict = {
36 'day': 60 * 60 * 24,
37 'week': 60 * 60 * 24 * 7,
38 'month': 60 * 60 * 24 * 7 * 4,
39 'year': 60 * 60 * 24 * 7 * 52,
40}
41image_sizes = ('o', 'k', 'h', 'b', 'c', 'z', 'm', 'n', 't', 'q', 's')
42
43search_url = 'https://www.flickr.com/search?{query}&page={page}'
44time_range_url = '&min_upload_date={start}&max_upload_date={end}'
45photo_url = 'https://www.flickr.com/photos/{userid}/{photoid}'
46modelexport_re = re.compile(r"^\s*modelExport:\s*({.*}),$", re.M)
47
48
49def build_flickr_url(user_id, photo_id):
50 return photo_url.format(userid=user_id, photoid=photo_id)
51
52
53def _get_time_range_url(time_range):
54 if time_range in time_range_dict:
55 return time_range_url.format(start=time(), end=str(int(time()) - time_range_dict[time_range]))
56 return ''
57
58
59def request(query, params):
60 params['url'] = search_url.format(query=urlencode({'text': query}), page=params['pageno']) + _get_time_range_url(
61 params['time_range']
62 )
63 return params
64
65
66def response(resp): # pylint: disable=too-many-branches
67 results = []
68
69 matches = modelexport_re.search(resp.text)
70 if matches is None:
71 return results
72
73 match = matches.group(1)
74 model_export = json.loads(match)
75
76 if 'legend' not in model_export:
77 return results
78 legend = model_export['legend']
79
80 # handle empty page
81 if not legend or not legend[0]:
82 return results
83
84 for x, index in enumerate(legend):
85 if len(index) != 8:
86 logger.debug("skip legend enty %s : %s", x, index)
87 continue
88
89 photo = model_export['main'][index[0]][int(index[1])][index[2]][index[3]][index[4]][index[5]][int(index[6])][
90 index[7]
91 ]
92 author = ecma_unescape(photo.get('realname', ''))
93 source = ecma_unescape(photo.get('username', ''))
94 if source:
95 source += ' @ Flickr'
96 title = ecma_unescape(photo.get('title', ''))
97 content = html_to_text(ecma_unescape(photo.get('description', '')))
98 img_src = None
99
100 # From the biggest to the lowest format
101 size_data = None
102 for image_size in image_sizes:
103 if image_size in photo['sizes']['data']:
104 size_data = photo['sizes']['data'][image_size]['data']
105 break
106
107 if not size_data:
108 logger.debug('cannot find valid image size: {0}'.format(repr(photo['sizes']['data'])))
109 continue
110
111 img_src = size_data['url']
112 resolution = f"{size_data['width']} x {size_data['height']}"
113
114 # For a bigger thumbnail, keep only the url_z, not the url_n
115 if 'n' in photo['sizes']['data']:
116 thumbnail_src = photo['sizes']['data']['n']['data']['url']
117 elif 'z' in photo['sizes']['data']:
118 thumbnail_src = photo['sizes']['data']['z']['data']['url']
119 else:
120 thumbnail_src = img_src
121
122 if 'ownerNsid' not in photo:
123 # should not happen, disowned photo? Show it anyway
124 url = img_src
125 else:
126 url = build_flickr_url(photo['ownerNsid'], photo['id'])
127
128 result = {
129 'url': url,
130 'img_src': img_src,
131 'thumbnail_src': thumbnail_src,
132 'source': source,
133 'resolution': resolution,
134 'template': 'images.html',
135 }
136 result['author'] = author.encode(errors='ignore').decode()
137 result['source'] = source.encode(errors='ignore').decode()
138 result['title'] = title.encode(errors='ignore').decode()
139 result['content'] = content.encode(errors='ignore').decode()
140 results.append(result)
141
142 return results
build_flickr_url(user_id, photo_id)