Skip to content

Commit dee734d

Browse files
authored
Add Auctionet bridge (#4452)
1 parent 744f996 commit dee734d

File tree

1 file changed

+344
-0
lines changed

1 file changed

+344
-0
lines changed

bridges/AuctionetBridge.php

+344
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
<?php
2+
3+
class AuctionetBridge extends BridgeAbstract
4+
{
5+
const NAME = 'Auctionet';
6+
const URI = 'https://www.auctionet.com';
7+
const DESCRIPTION = 'Fetches info about auction objects from Auctionet (an auction platform for many European auction houses)';
8+
const MAINTAINER = 'Qluxzz';
9+
const PARAMETERS = [[
10+
'category' => [
11+
'name' => 'Category',
12+
'type' => 'list',
13+
'values' => [
14+
'All categories' => '',
15+
'Art' => [
16+
'All' => '25-art',
17+
'Drawings' => '119-drawings',
18+
'Engravings & Prints' => '27-engravings-prints',
19+
'Other' => '30-other',
20+
'Paintings' => '28-paintings',
21+
'Photography' => '26-photography',
22+
'Sculptures & Bronzes' => '29-sculptures-bronzes',
23+
],
24+
'Asiatica' => [
25+
'All' => '117-asiatica',
26+
],
27+
'Books, Maps & Manuscripts' => [
28+
'All' => '50-books-maps-manuscripts',
29+
'Autographs & Manuscripts' => '206-autographs-manuscripts',
30+
'Books' => '204-books',
31+
'Maps' => '205-maps',
32+
'Other' => '207-other',
33+
],
34+
'Carpets & Textiles' => [
35+
'All' => '35-carpets-textiles',
36+
'Carpets' => '36-carpets',
37+
'Textiles' => '37-textiles',
38+
],
39+
'Ceramics & Porcelain' => [
40+
'All' => '9-ceramics-porcelain',
41+
'European' => '10-european',
42+
'Oriental' => '11-oriental',
43+
'Rest of the world' => '12-rest-of-the-world',
44+
'Tableware' => '210-tableware',
45+
],
46+
'Clocks & Watches' => [
47+
'All' => '31-clocks-watches',
48+
'Carriage & Miniature Clocks' => '258-carriage-miniature-clocks',
49+
'Longcase clocks' => '32-longcase-clocks',
50+
'Mantel clocks' => '33-mantel-clocks',
51+
'Other clocks' => '34-other-clocks',
52+
'Pocket & Stop Watches' => '110-pocket-stop-watches',
53+
'Wall Clocks' => '127-wall-clocks',
54+
'Wristwatches' => '15-wristwatches',
55+
],
56+
'Coins, Medals & Stamps' => [
57+
'All' => '46-coins-medals-stamps',
58+
'Coins' => '128-coins',
59+
'Orders & Medals' => '135-orders-medals',
60+
'Other' => '131-other',
61+
'Stamps' => '136-stamps',
62+
],
63+
'Folk art' => [
64+
'All' => '58-folk-art',
65+
'Bowls & Boxes' => '121-bowls-boxes',
66+
'Furniture' => '122-furniture',
67+
'Other' => '123-other',
68+
'Tools & Gears' => '120-tools-gears',
69+
],
70+
'Furniture' => [
71+
'All' => '16-furniture',
72+
'Armchairs & Chairs' => '18-armchairs-chairs',
73+
'Chests of drawers' => '24-chests-of-drawers',
74+
'Cupboards, Cabinets & Shelves' => '23-cupboards-cabinets-shelves',
75+
'Dining room furniture' => '22-dining-room-furniture',
76+
'Garden' => '21-garden',
77+
'Other' => '17-other',
78+
'Sofas & seatings' => '20-sofas-seatings',
79+
'Tables' => '19-tables',
80+
],
81+
'Glass' => [
82+
'All' => '6-glass',
83+
'Art glass' => '208-art-glass',
84+
'Other' => '8-other',
85+
'Tableware' => '7-tableware',
86+
'Utility glass' => '209-utility-glass',
87+
],
88+
'Jewellery & Gemstones' => [
89+
'All' => '13-jewellery-gemstones',
90+
'Alliance rings' => '113-alliance-rings',
91+
'Bracelets' => '106-bracelets',
92+
'Brooches & Pendants' => '107-brooches-pendants',
93+
'Costume Jewellery' => '259-costume-jewellery',
94+
'Cufflinks & Tie Pins' => '111-cufflinks-tie-pins',
95+
'Ear studs' => '116-ear-studs',
96+
'Earrings' => '115-earrings',
97+
'Gemstones' => '48-gemstones',
98+
'Jewellery' => '14-jewellery',
99+
'Jewellery Suites' => '109-jewellery-suites',
100+
'Necklace' => '104-necklace',
101+
'Other' => '118-other',
102+
'Rings' => '112-rings',
103+
'Signet rings' => '105-signet-rings',
104+
'Solitaire rings' => '114-solitaire-rings',
105+
],
106+
'Licence weapons' => [
107+
'All' => '59-licence-weapons',
108+
'Combi/Combo' => '63-combi-combo',
109+
'Double express rifles' => '60-double-express-rifles',
110+
'Rifles' => '61-rifles',
111+
'Shotguns' => '62-shotguns',
112+
],
113+
'Lighting & Lamps' => [
114+
'All' => '1-lighting-lamps',
115+
'Candlesticks' => '4-candlesticks',
116+
'Ceiling lights' => '3-ceiling-lights',
117+
'Chandeliers' => '203-chandeliers',
118+
'Floor lights' => '2-floor-lights',
119+
'Other lighting' => '5-other-lighting',
120+
'Table Lamps' => '125-table-lamps',
121+
'Wall Lights' => '124-wall-lights',
122+
],
123+
'Mirrors' => [
124+
'All' => '42-mirrors',
125+
],
126+
'Miscellaneous' => [
127+
'All' => '43-miscellaneous',
128+
'Fishing equipment' => '54-fishing-equipment',
129+
'Miscellaneous' => '47-miscellaneous',
130+
'Modern Tools' => '133-modern-tools',
131+
'Modern consumer electronics' => '52-modern-consumer-electronics',
132+
'Musical instruments' => '51-musical-instruments',
133+
'Technica & Nautica' => '45-technica-nautica',
134+
],
135+
'Photo, Cameras & Lenses' => [
136+
'All' => '57-photo-cameras-lenses',
137+
'Cameras & accessories' => '71-cameras-accessories',
138+
'Optics' => '66-optics',
139+
'Other' => '72-other',
140+
],
141+
'Silver & Metals' => [
142+
'All' => '38-silver-metals',
143+
'Other metals' => '40-other-metals',
144+
'Pewter, Brass & Copper' => '41-pewter-brass-copper',
145+
'Silver' => '39-silver',
146+
'Silver plated' => '213-silver-plated',
147+
],
148+
'Toys' => [
149+
'All' => '44-toys',
150+
'Comics' => '211-comics',
151+
'Toys' => '212-toys',
152+
],
153+
'Tribal art' => [
154+
'All' => '134-tribal-art',
155+
],
156+
'Vehicles, Boats & Parts' => [
157+
'All' => '249-vehicles-boats-parts',
158+
'Automobilia & Transport' => '255-automobilia-transport',
159+
'Bicycles' => '132-bicycles',
160+
'Boats & Accessories' => '250-boats-accessories',
161+
'Car parts' => '253-car-parts',
162+
'Cars' => '215-cars',
163+
'Moped parts' => '254-moped-parts',
164+
'Mopeds' => '216-mopeds',
165+
'Motorcycle parts' => '252-motorcycle-parts',
166+
'Motorcycles' => '251-motorcycles',
167+
'Other' => '256-other',
168+
],
169+
'Vintage & Designer Fashion' => [
170+
'All' => '49-vintage-designer-fashion',
171+
],
172+
'Weapons & Militaria' => [
173+
'All' => '137-weapons-militaria',
174+
'Airguns' => '257-airguns',
175+
'Armour & Uniform' => '138-armour-uniform',
176+
'Edged weapons' => '130-edged-weapons',
177+
'Guns & Rifles' => '129-guns-rifles',
178+
'Other' => '214-other',
179+
],
180+
'Wine, Port & Spirits' => [
181+
'All' => '170-wine-port-spirits',
182+
],
183+
]
184+
],
185+
'sort_order' => [
186+
'name' => 'Sort order',
187+
'type' => 'list',
188+
'values' => [
189+
'Most bids' => 'bids_count_desc',
190+
'Lowest bid' => 'bid_asc',
191+
'Highest bid' => 'bid_desc',
192+
'Last bid on' => 'bid_on',
193+
'Ending soonest' => 'end_asc_active',
194+
'Lowest estimate' => 'estimate_asc',
195+
'Highest estimate' => 'estimate_desc',
196+
'Recently added' => 'recent'
197+
],
198+
],
199+
'country' => [
200+
'name' => 'Country',
201+
'type' => 'list',
202+
'values' => [
203+
'All' => '',
204+
'Denmark' => 'DK',
205+
'Finland' => 'FI',
206+
'Germany' => 'DE',
207+
'Spain' => 'ES',
208+
'Sweden' => 'SE',
209+
'United Kingdom' => 'GB'
210+
]
211+
],
212+
'language' => [
213+
'name' => 'Language',
214+
'type' => 'list',
215+
'values' => [
216+
'English' => 'en',
217+
'Español' => 'es',
218+
'Deutsch' => 'de',
219+
'Svenska' => 'sv',
220+
'Dansk' => 'da',
221+
'Suomi' => 'fi',
222+
],
223+
],
224+
]];
225+
226+
const CACHE_TIMEOUT = 3600; // 1 hour
227+
228+
private $title;
229+
230+
public function collectData()
231+
{
232+
// Each page contains 48 auctions
233+
// So we fetch 10 pages so we decrease the likelihood
234+
// of missing auctions between feed refreshes
235+
236+
// Fetch first page and use that to get title
237+
{
238+
$url = $this->getUrl(1);
239+
$data = getContents($url);
240+
241+
$title = $this->getDocumentTitle($data);
242+
243+
$this->items = array_merge($this->items, $this->parsePageData($data));
244+
}
245+
246+
// Fetch remaining pages
247+
for ($page = 2; $page <= 10; $page++) {
248+
$url = $this->getUrl($page);
249+
250+
$data = getContents($url);
251+
252+
$this->items = array_merge($this->items, $this->parsePageData($data));
253+
}
254+
}
255+
256+
public function getName()
257+
{
258+
return $this->title ?: parent::getName();
259+
}
260+
261+
262+
/* HELPERS */
263+
264+
private function getUrl($page)
265+
{
266+
$category = $this->getInput('category');
267+
$language = $this->getInput('language');
268+
$sort_order = $this->getInput('sort_order');
269+
$country = $this->getInput('country');
270+
271+
$url = self::URI . '/' . $language . '/search';
272+
273+
if ($category) {
274+
$url = $url . '/' . $category;
275+
}
276+
277+
$query = [];
278+
$query['page'] = $page;
279+
280+
if ($sort_order) {
281+
$query['order'] = $sort_order;
282+
}
283+
284+
if ($country) {
285+
$query['country_code'] = $country;
286+
}
287+
288+
if (count($query) > 0) {
289+
$url = $url . '?' . http_build_query($query);
290+
}
291+
292+
return $url;
293+
}
294+
295+
private function getDocumentTitle($data)
296+
{
297+
$title_elem = '<title>';
298+
$title_elem_length = strlen($title_elem);
299+
$title_start = strpos($data, $title_elem);
300+
$title_end = strpos($data, '</title>', $title_start);
301+
$title_length = $title_end - $title_start + strlen($title_elem);
302+
$title = substr($data, $title_start + strlen($title_elem), $title_length);
303+
304+
return $title;
305+
}
306+
307+
/**
308+
* The auction items data is included in the HTML document
309+
* as a HTML entities encoded JSON structure
310+
* which is used to hydrate the React component for the list of auctions
311+
*/
312+
private function parsePageData($data)
313+
{
314+
$key = 'data-react-props="';
315+
$keyLength = strlen($key);
316+
317+
$start = strpos($data, $key);
318+
$end = strpos($data, '"', $start + strlen($key));
319+
$length = $end - ($start + $keyLength);
320+
321+
$jsonString = substr($data, $start + $keyLength, $length);
322+
323+
$jsonData = json_decode(htmlspecialchars_decode($jsonString), false);
324+
325+
$items = [];
326+
327+
foreach ($jsonData->{'items'} as $item) {
328+
$title = $item->{'longTitle'};
329+
$relative_url = $item->{'url'};
330+
$images = $item->{'imageUrls'};
331+
$id = $item->{'auctionId'};
332+
333+
$items[] = [
334+
'title' => $title,
335+
'uri' => self::URI . $relative_url,
336+
'uid' => $id,
337+
'content' => count($images) > 0 ? "<img src='$images[0]'/><br/>$title" : $title,
338+
'enclosures' => array_slice($images, 1),
339+
];
340+
}
341+
342+
return $items;
343+
}
344+
}

0 commit comments

Comments
 (0)