tradera-cli 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/PKG-INFO +1 -1
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/pyproject.toml +1 -1
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tests/test_api.py +124 -14
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tests/test_cli.py +26 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli/api.py +76 -73
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli.egg-info/PKG-INFO +1 -1
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/LICENSE +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/README.md +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/setup.cfg +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tests/test_cli_entry.py +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tests/test_formatters.py +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tests/test_import.py +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tests/test_main_module.py +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli/__init__.py +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli/__main__.py +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli/cli.py +1 -1
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli/formatters.py +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli.egg-info/SOURCES.txt +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli.egg-info/dependency_links.txt +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli.egg-info/entry_points.txt +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli.egg-info/requires.txt +0 -0
- {tradera_cli-0.1.2 → tradera_cli-0.1.4}/tradera_cli.egg-info/top_level.txt +0 -0
|
@@ -190,29 +190,46 @@ def test_ensure_client_token_raises_on_http_error() -> None:
|
|
|
190
190
|
client._ensure_client_token()
|
|
191
191
|
|
|
192
192
|
|
|
193
|
-
def
|
|
193
|
+
def test_search_reads_current_search_page_state() -> None:
|
|
194
194
|
client = TraderaClient()
|
|
195
195
|
captured: dict[str, object] = {}
|
|
196
|
+
next_data = {
|
|
197
|
+
"props": {
|
|
198
|
+
"pageProps": {
|
|
199
|
+
"initialState": {
|
|
200
|
+
"discover": {
|
|
201
|
+
"items": [{"itemId": 42, "shortDescription": "Apple TV"}],
|
|
202
|
+
"queryParams": {"q": "kamera"},
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
196
208
|
|
|
197
|
-
def fake_request(method: str, path: str, **
|
|
209
|
+
def fake_request(method: str, path: str, **_kwargs: object) -> str:
|
|
198
210
|
captured["method"] = method
|
|
199
211
|
captured["path"] = path
|
|
200
|
-
|
|
201
|
-
|
|
212
|
+
return (
|
|
213
|
+
'<script id="__NEXT_DATA__" type="application/json">'
|
|
214
|
+
f"{json.dumps(next_data)}"
|
|
215
|
+
"</script>"
|
|
216
|
+
)
|
|
202
217
|
|
|
203
218
|
client._request = fake_request # type: ignore[method-assign]
|
|
204
219
|
|
|
205
220
|
result = client.search("kamera", page=2, page_size=10, sort_by="EndDate")
|
|
206
221
|
|
|
207
|
-
assert result
|
|
208
|
-
assert captured["method"] == "
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
assert
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
222
|
+
assert result["items"][0]["itemId"] == 42
|
|
223
|
+
assert captured["method"] == "GET"
|
|
224
|
+
parsed = urlparse(str(captured["path"]))
|
|
225
|
+
assert parsed.path == "/search"
|
|
226
|
+
assert parse_qs(parsed.query) == {
|
|
227
|
+
"q": ["kamera"],
|
|
228
|
+
"paging": ["2"],
|
|
229
|
+
"pageSize": ["10"],
|
|
230
|
+
"sortBy": ["EndDate"],
|
|
231
|
+
"languageCodeIso2": ["sv"],
|
|
232
|
+
}
|
|
216
233
|
|
|
217
234
|
|
|
218
235
|
def test_search_uses_search_page_for_sold_items() -> None:
|
|
@@ -251,6 +268,7 @@ def test_search_uses_search_page_for_sold_items() -> None:
|
|
|
251
268
|
assert parse_qs(parsed.query) == {
|
|
252
269
|
"q": ["kamera"],
|
|
253
270
|
"paging": ["3"],
|
|
271
|
+
"pageSize": ["50"],
|
|
254
272
|
"sortBy": ["EndDate"],
|
|
255
273
|
"languageCodeIso2": ["sv"],
|
|
256
274
|
"itemStatus": ["Sold"],
|
|
@@ -293,6 +311,7 @@ def test_search_uses_search_page_for_condition_filter() -> None:
|
|
|
293
311
|
assert parse_qs(parsed.query) == {
|
|
294
312
|
"q": ["kamera"],
|
|
295
313
|
"paging": ["1"],
|
|
314
|
+
"pageSize": ["50"],
|
|
296
315
|
"sortBy": ["Relevance"],
|
|
297
316
|
"languageCodeIso2": ["sv"],
|
|
298
317
|
"af-condition": ["Oanvänt"],
|
|
@@ -350,6 +369,7 @@ def test_search_uses_search_page_for_additional_page_filters() -> None:
|
|
|
350
369
|
assert parse_qs(parsed.query) == {
|
|
351
370
|
"q": ["kamera"],
|
|
352
371
|
"paging": ["1"],
|
|
372
|
+
"pageSize": ["50"],
|
|
353
373
|
"sortBy": ["Relevance"],
|
|
354
374
|
"languageCodeIso2": ["sv"],
|
|
355
375
|
"itemType": ["FixedPrice"],
|
|
@@ -396,6 +416,7 @@ def test_search_uses_search_page_for_search_type() -> None:
|
|
|
396
416
|
assert parse_qs(parsed.query) == {
|
|
397
417
|
"q": ["kamera"],
|
|
398
418
|
"paging": ["1"],
|
|
419
|
+
"pageSize": ["50"],
|
|
399
420
|
"sortBy": ["Relevance"],
|
|
400
421
|
"languageCodeIso2": ["sv"],
|
|
401
422
|
"searchType": ["ExactSearch"],
|
|
@@ -412,7 +433,24 @@ def test_search_page_raises_when_next_data_is_missing() -> None:
|
|
|
412
433
|
|
|
413
434
|
def test_item_returns_dict_or_raises() -> None:
|
|
414
435
|
client = TraderaClient()
|
|
415
|
-
|
|
436
|
+
next_data = {
|
|
437
|
+
"props": {
|
|
438
|
+
"pageProps": {
|
|
439
|
+
"initialState": {
|
|
440
|
+
"views": {
|
|
441
|
+
"viewItem": {
|
|
442
|
+
"itemDetails": {"itemId": 123, "title": "Demo"},
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
client._request = lambda *_args, **_kwargs: ( # type: ignore[method-assign]
|
|
450
|
+
'<script id="__NEXT_DATA__" type="application/json">'
|
|
451
|
+
f"{json.dumps(next_data)}"
|
|
452
|
+
"</script>"
|
|
453
|
+
)
|
|
416
454
|
assert client.item(123)["itemId"] == 123
|
|
417
455
|
|
|
418
456
|
client._request = lambda *_args, **_kwargs: "not a dict" # type: ignore[method-assign]
|
|
@@ -420,6 +458,78 @@ def test_item_returns_dict_or_raises() -> None:
|
|
|
420
458
|
client.item(123)
|
|
421
459
|
|
|
422
460
|
|
|
461
|
+
def test_item_reads_current_item_page_state() -> None:
|
|
462
|
+
client = TraderaClient()
|
|
463
|
+
calls: list[tuple[str, str]] = []
|
|
464
|
+
next_data = {
|
|
465
|
+
"props": {
|
|
466
|
+
"pageProps": {
|
|
467
|
+
"initialState": {
|
|
468
|
+
"views": {
|
|
469
|
+
"viewItem": {
|
|
470
|
+
"bidInfo": {
|
|
471
|
+
"leadingBidAmount": 926,
|
|
472
|
+
"nextValidBidAmount": 951,
|
|
473
|
+
"bidCount": 79,
|
|
474
|
+
},
|
|
475
|
+
"itemDetails": {
|
|
476
|
+
"itemId": 731572375,
|
|
477
|
+
"title": "Apple TV 32GB",
|
|
478
|
+
"itemType": "Auction",
|
|
479
|
+
"openingBid": 1,
|
|
480
|
+
"leadingBid": 926,
|
|
481
|
+
"seller": {"alias": "Lufox"},
|
|
482
|
+
"paymentCalculations": {"paymentAmountForBid": 974},
|
|
483
|
+
},
|
|
484
|
+
"purchaseInfo": {"finalPrice": 926},
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
def fake_request(method: str, path: str, **_kwargs: object) -> object:
|
|
493
|
+
calls.append((method, path))
|
|
494
|
+
return (
|
|
495
|
+
'<script id="__NEXT_DATA__" type="application/json">'
|
|
496
|
+
f"{json.dumps(next_data)}"
|
|
497
|
+
"</script>"
|
|
498
|
+
)
|
|
499
|
+
|
|
500
|
+
client._request = fake_request # type: ignore[method-assign]
|
|
501
|
+
|
|
502
|
+
result = client.item(731572375)
|
|
503
|
+
|
|
504
|
+
assert result["itemId"] == 731572375
|
|
505
|
+
assert result["title"] == "Apple TV 32GB"
|
|
506
|
+
assert result["leadingBid"] == 926
|
|
507
|
+
assert result["bidCount"] == 79
|
|
508
|
+
assert result["nextBid"] == 951
|
|
509
|
+
assert result["price"] == 926
|
|
510
|
+
assert result["finalPrice"] == 926
|
|
511
|
+
assert result["currency"] == "SEK"
|
|
512
|
+
assert calls == [("GET", "/item/731572375")]
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def test_item_falls_back_to_ajax_when_page_parse_fails() -> None:
|
|
516
|
+
client = TraderaClient()
|
|
517
|
+
calls: list[tuple[str, str]] = []
|
|
518
|
+
|
|
519
|
+
def fake_request(method: str, path: str, **_kwargs: object) -> object:
|
|
520
|
+
calls.append((method, path))
|
|
521
|
+
if path == "/item/123":
|
|
522
|
+
raise TraderaApiError("Could not parse item page response for item 123")
|
|
523
|
+
return {"itemId": 123, "title": "Legacy"}
|
|
524
|
+
|
|
525
|
+
client._request = fake_request # type: ignore[method-assign]
|
|
526
|
+
|
|
527
|
+
result = client.item(123)
|
|
528
|
+
|
|
529
|
+
assert result == {"itemId": 123, "title": "Legacy"}
|
|
530
|
+
assert calls == [("GET", "/item/123"), ("GET", "/ajax/item/123")]
|
|
531
|
+
|
|
532
|
+
|
|
423
533
|
def test_item_payment_calculations_returns_dict() -> None:
|
|
424
534
|
client = TraderaClient()
|
|
425
535
|
next_data = {
|
|
@@ -207,6 +207,32 @@ def test_cmd_item_table_uses_payment_calculations_for_bid_total(
|
|
|
207
207
|
assert "4690" in out
|
|
208
208
|
|
|
209
209
|
|
|
210
|
+
def test_cmd_item_table_prefers_auction_price_over_next_bid(
|
|
211
|
+
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
|
212
|
+
) -> None:
|
|
213
|
+
class ItemClient(DummyClient):
|
|
214
|
+
def item(self, _item_id: int) -> dict:
|
|
215
|
+
return {
|
|
216
|
+
"itemId": 66,
|
|
217
|
+
"title": "Ended auction",
|
|
218
|
+
"leadingBid": 926,
|
|
219
|
+
"nextBid": 951,
|
|
220
|
+
"bidCount": 79,
|
|
221
|
+
"currency": "SEK",
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
def item_payment_calculations(self, _item_id: int) -> dict:
|
|
225
|
+
return {"paymentAmountForBid": 974}
|
|
226
|
+
|
|
227
|
+
monkeypatch.setattr(cli, "TraderaClient", ItemClient)
|
|
228
|
+
|
|
229
|
+
args = argparse.Namespace(item="66", format="table")
|
|
230
|
+
assert cli.cmd_item(args) == 0
|
|
231
|
+
out = capsys.readouterr().out
|
|
232
|
+
assert "926" in out
|
|
233
|
+
assert "951" not in out
|
|
234
|
+
|
|
235
|
+
|
|
210
236
|
def test_cmd_categories_jsonl(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None:
|
|
211
237
|
class CategoriesClient(DummyClient):
|
|
212
238
|
def categories(self, **_kwargs: object) -> list:
|
|
@@ -32,7 +32,7 @@ class TraderaClient:
|
|
|
32
32
|
self.session.headers.update(
|
|
33
33
|
{
|
|
34
34
|
"accept": "application/json, text/plain, */*",
|
|
35
|
-
"user-agent": "
|
|
35
|
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
|
36
36
|
}
|
|
37
37
|
)
|
|
38
38
|
|
|
@@ -68,6 +68,20 @@ class TraderaClient:
|
|
|
68
68
|
raise TraderaApiError(f"Invalid JSON response from {path}") from exc
|
|
69
69
|
return response.text
|
|
70
70
|
|
|
71
|
+
def _next_data_from_html(self, html: str, context: str) -> dict[str, Any]:
|
|
72
|
+
match = re.search(r'<script id="__NEXT_DATA__" type="application/json">(.*?)</script>', html)
|
|
73
|
+
if not match:
|
|
74
|
+
raise TraderaApiError(f"Could not parse {context}")
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
data = json.loads(match.group(1))
|
|
78
|
+
except ValueError as exc:
|
|
79
|
+
raise TraderaApiError(f"Invalid {context}") from exc
|
|
80
|
+
|
|
81
|
+
if not isinstance(data, dict):
|
|
82
|
+
raise TraderaApiError(f"Unexpected {context}")
|
|
83
|
+
return data
|
|
84
|
+
|
|
71
85
|
def _ensure_client_token(self, force: bool = False) -> None:
|
|
72
86
|
if not force and self.session.cookies.get("trd_at"):
|
|
73
87
|
return
|
|
@@ -101,70 +115,38 @@ class TraderaClient:
|
|
|
101
115
|
search_type: str | None = None,
|
|
102
116
|
) -> dict[str, Any]:
|
|
103
117
|
normalized_item_status = item_status or "Active"
|
|
104
|
-
|
|
118
|
+
filters: dict[str, str] = {}
|
|
105
119
|
if search_type:
|
|
106
|
-
|
|
120
|
+
filters["searchType"] = search_type
|
|
107
121
|
if normalized_item_status in {"Sold", "Unsold"}:
|
|
108
|
-
|
|
122
|
+
filters["itemStatus"] = normalized_item_status
|
|
109
123
|
if condition:
|
|
110
|
-
|
|
124
|
+
filters["af-condition"] = condition
|
|
111
125
|
if item_type and item_type != "All":
|
|
112
|
-
|
|
126
|
+
filters["itemType"] = item_type
|
|
113
127
|
if from_price is not None:
|
|
114
|
-
|
|
128
|
+
filters["fromPrice"] = str(from_price)
|
|
115
129
|
if to_price is not None:
|
|
116
|
-
|
|
130
|
+
filters["toPrice"] = str(to_price)
|
|
117
131
|
if allowed_buyer_regions:
|
|
118
|
-
|
|
132
|
+
filters["allowedBuyerRegions"] = ALLOWED_BUYER_REGIONS[allowed_buyer_regions]
|
|
119
133
|
if counties:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
payload: dict[str, Any] = {
|
|
132
|
-
"isCsaSearchQuery": False,
|
|
133
|
-
"query": query,
|
|
134
|
-
"page": page,
|
|
135
|
-
"pageSize": page_size,
|
|
136
|
-
"sortBy": sort_by,
|
|
137
|
-
"languageCodeIso2": language_code_iso2.lower(),
|
|
138
|
-
"shippingCountryCodeIso2": shipping_country_code_iso2.upper(),
|
|
139
|
-
"automaticTranslationPreferred": automatic_translation_preferred,
|
|
140
|
-
"attributeFilters": [],
|
|
141
|
-
"categoryPath": [],
|
|
142
|
-
"currentCategoryId": 0,
|
|
143
|
-
"filterCounties": None,
|
|
144
|
-
"filterCategories": {},
|
|
145
|
-
"filterPrice": {},
|
|
146
|
-
"filters": {},
|
|
147
|
-
"headerText": None,
|
|
148
|
-
"internalSearch": {"showSearchBar": False},
|
|
149
|
-
"introText": None,
|
|
150
|
-
"isSavedSearchEmailEnabled": False,
|
|
151
|
-
"isShopOwnedByCurrentMember": False,
|
|
152
|
-
"items": [],
|
|
153
|
-
"relatedItems": [],
|
|
154
|
-
"itemsOnDisplay": [],
|
|
155
|
-
"mainText": None,
|
|
156
|
-
"pagination": None,
|
|
157
|
-
"totalItems": 0,
|
|
158
|
-
"searchLanguages": [],
|
|
159
|
-
"itemsMatchedViewModel": None,
|
|
160
|
-
"suggestion": None,
|
|
161
|
-
}
|
|
162
|
-
return self._request("POST", "/api/webapi/discover/web/independent-search", json=payload)
|
|
134
|
+
filters["counties"] = ";".join(counties)
|
|
135
|
+
|
|
136
|
+
return self._search_page(
|
|
137
|
+
query=query,
|
|
138
|
+
page=page,
|
|
139
|
+
page_size=page_size,
|
|
140
|
+
sort_by=sort_by,
|
|
141
|
+
language_code_iso2=language_code_iso2,
|
|
142
|
+
filters=filters,
|
|
143
|
+
)
|
|
163
144
|
|
|
164
145
|
def _search_page(
|
|
165
146
|
self,
|
|
166
147
|
query: str,
|
|
167
148
|
page: int,
|
|
149
|
+
page_size: int,
|
|
168
150
|
sort_by: str,
|
|
169
151
|
language_code_iso2: str,
|
|
170
152
|
filters: dict[str, str],
|
|
@@ -172,6 +154,7 @@ class TraderaClient:
|
|
|
172
154
|
params = {
|
|
173
155
|
"q": query,
|
|
174
156
|
"paging": page,
|
|
157
|
+
"pageSize": page_size,
|
|
175
158
|
"sortBy": sort_by,
|
|
176
159
|
"languageCodeIso2": language_code_iso2.lower(),
|
|
177
160
|
}
|
|
@@ -180,14 +163,7 @@ class TraderaClient:
|
|
|
180
163
|
if not isinstance(html, str):
|
|
181
164
|
raise TraderaApiError("Unexpected search page response")
|
|
182
165
|
|
|
183
|
-
|
|
184
|
-
if not match:
|
|
185
|
-
raise TraderaApiError("Could not parse search page response")
|
|
186
|
-
|
|
187
|
-
try:
|
|
188
|
-
data = json.loads(match.group(1))
|
|
189
|
-
except ValueError as exc:
|
|
190
|
-
raise TraderaApiError("Invalid search page data") from exc
|
|
166
|
+
data = self._next_data_from_html(html, "search page response")
|
|
191
167
|
|
|
192
168
|
discover = data.get("props", {}).get("pageProps", {}).get("initialState", {}).get("discover")
|
|
193
169
|
if not isinstance(discover, dict):
|
|
@@ -195,34 +171,61 @@ class TraderaClient:
|
|
|
195
171
|
return discover
|
|
196
172
|
|
|
197
173
|
def item(self, item_id: int) -> dict[str, Any]:
|
|
198
|
-
|
|
174
|
+
try:
|
|
175
|
+
return self._item_from_page(item_id)
|
|
176
|
+
except TraderaApiError:
|
|
177
|
+
data = self._request("GET", f"/ajax/item/{item_id}")
|
|
199
178
|
if not isinstance(data, dict):
|
|
200
179
|
raise TraderaApiError(f"Unexpected item response for item {item_id}")
|
|
201
180
|
return data
|
|
202
181
|
|
|
203
|
-
def
|
|
182
|
+
def _item_page_state(self, item_id: int) -> dict[str, Any]:
|
|
204
183
|
html = self._request("GET", f"/item/{item_id}")
|
|
205
184
|
if not isinstance(html, str):
|
|
206
185
|
raise TraderaApiError(f"Unexpected item page response for item {item_id}")
|
|
207
186
|
|
|
208
|
-
|
|
209
|
-
if not match:
|
|
210
|
-
raise TraderaApiError(f"Could not parse item page response for item {item_id}")
|
|
187
|
+
data = self._next_data_from_html(html, f"item page response for item {item_id}")
|
|
211
188
|
|
|
212
|
-
|
|
213
|
-
data = json.loads(match.group(1))
|
|
214
|
-
except ValueError as exc:
|
|
215
|
-
raise TraderaApiError(f"Invalid item page data for item {item_id}") from exc
|
|
216
|
-
|
|
217
|
-
payment_calculations = (
|
|
189
|
+
view_item = (
|
|
218
190
|
data.get("props", {})
|
|
219
191
|
.get("pageProps", {})
|
|
220
192
|
.get("initialState", {})
|
|
221
193
|
.get("views", {})
|
|
222
194
|
.get("viewItem", {})
|
|
223
|
-
.get("itemDetails", {})
|
|
224
|
-
.get("paymentCalculations", {})
|
|
225
195
|
)
|
|
196
|
+
if not isinstance(view_item, dict):
|
|
197
|
+
raise TraderaApiError(f"Unexpected item page data for item {item_id}")
|
|
198
|
+
return view_item
|
|
199
|
+
|
|
200
|
+
def _item_from_page(self, item_id: int) -> dict[str, Any]:
|
|
201
|
+
view_item = self._item_page_state(item_id)
|
|
202
|
+
item_details = view_item.get("itemDetails")
|
|
203
|
+
if not isinstance(item_details, dict) or not item_details:
|
|
204
|
+
raise TraderaApiError(f"Unexpected item response for item {item_id}")
|
|
205
|
+
|
|
206
|
+
data = dict(item_details)
|
|
207
|
+
bid_info = view_item.get("bidInfo")
|
|
208
|
+
if isinstance(bid_info, dict):
|
|
209
|
+
if bid_info.get("bidCount") is not None:
|
|
210
|
+
data.setdefault("bidCount", bid_info.get("bidCount"))
|
|
211
|
+
if bid_info.get("leadingBidAmount") is not None:
|
|
212
|
+
data.setdefault("leadingBid", bid_info.get("leadingBidAmount"))
|
|
213
|
+
if bid_info.get("nextValidBidAmount") is not None:
|
|
214
|
+
data.setdefault("nextBid", bid_info.get("nextValidBidAmount"))
|
|
215
|
+
|
|
216
|
+
purchase_info = view_item.get("purchaseInfo")
|
|
217
|
+
if isinstance(purchase_info, dict) and purchase_info.get("finalPrice") is not None:
|
|
218
|
+
data.setdefault("price", purchase_info.get("finalPrice"))
|
|
219
|
+
data.setdefault("finalPrice", purchase_info.get("finalPrice"))
|
|
220
|
+
|
|
221
|
+
data.setdefault("currency", "SEK")
|
|
222
|
+
return data
|
|
223
|
+
|
|
224
|
+
def item_payment_calculations(self, item_id: int) -> dict[str, Any]:
|
|
225
|
+
item_details = self._item_page_state(item_id).get("itemDetails", {})
|
|
226
|
+
if not isinstance(item_details, dict):
|
|
227
|
+
raise TraderaApiError(f"Unexpected payment calculations for item {item_id}")
|
|
228
|
+
payment_calculations = item_details.get("paymentCalculations", {})
|
|
226
229
|
if not isinstance(payment_calculations, dict):
|
|
227
230
|
raise TraderaApiError(f"Unexpected payment calculations for item {item_id}")
|
|
228
231
|
return payment_calculations
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -97,9 +97,9 @@ def cmd_item(args: argparse.Namespace) -> int:
|
|
|
97
97
|
"title": data.get("shortDescription") or data.get("title") or "",
|
|
98
98
|
"price": (
|
|
99
99
|
data.get("buyNowPrice")
|
|
100
|
-
or data.get("nextBid")
|
|
101
100
|
or data.get("price")
|
|
102
101
|
or data.get("leadingBid")
|
|
102
|
+
or data.get("nextBid")
|
|
103
103
|
or data.get("fixedPrice")
|
|
104
104
|
or data.get("openingBid")
|
|
105
105
|
or ""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|