blocket-api 0.3.5__tar.gz → 0.3.7__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.
- {blocket_api-0.3.5/blocket_api.egg-info → blocket_api-0.3.7}/PKG-INFO +70 -2
- blocket_api-0.3.5/PKG-INFO → blocket_api-0.3.7/README.md +67 -20
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api/blocket.py +41 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api/constants.py +3 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api/models.py +7 -0
- blocket_api-0.3.7/blocket_api/sendbird.py +190 -0
- blocket_api-0.3.5/README.md → blocket_api-0.3.7/blocket_api.egg-info/PKG-INFO +88 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api.egg-info/SOURCES.txt +1 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api.egg-info/requires.txt +2 -1
- {blocket_api-0.3.5 → blocket_api-0.3.7}/pyproject.toml +3 -2
- {blocket_api-0.3.5 → blocket_api-0.3.7}/LICENSE +0 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api/__init__.py +0 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api/decorators.py +0 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api/qasa.py +0 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api.egg-info/dependency_links.txt +0 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/blocket_api.egg-info/top_level.txt +0 -0
- {blocket_api-0.3.5 → blocket_api-0.3.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blocket_api
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: A python API wrapper for blocket.se
|
|
5
5
|
Author-email: dunderrrrrr <emil.bjorkroth@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -15,7 +15,8 @@ Requires-Dist: pydantic>=2.11.7
|
|
|
15
15
|
Requires-Dist: mkdocs>=1.6.1
|
|
16
16
|
Requires-Dist: mkdocs-material>=9.6.21
|
|
17
17
|
Requires-Dist: mkdocs-swagger-ui-tag>=0.7.2
|
|
18
|
-
Requires-Dist:
|
|
18
|
+
Requires-Dist: websockets>=15.0.1
|
|
19
|
+
Requires-Dist: ruff>=0.14.5
|
|
19
20
|
Dynamic: license-file
|
|
20
21
|
|
|
21
22
|
<p align="center">
|
|
@@ -80,6 +81,9 @@ Some calls require a `bearerToken`. However, some calls are public and don't req
|
|
|
80
81
|
| [`api.get_user_by_id()`](#get_user_by_id) | 👏 No | Yes | Get user data from id.
|
|
81
82
|
| [`api.save_ad()`](#save_ad) | 🔐 Yes | - | Save ad to "Saved ads".
|
|
82
83
|
| [`api.get_saved_ads()`](#get_saved_ads) | 🔐 Yes | - | List all saved ads.
|
|
84
|
+
| [`api.get_threads()`](#get_threads) | 🔐 Yes | - | List all threads (messages).
|
|
85
|
+
| [`api.get_messages_from_thread()`](#get_messages_from_thread) | 🔐 Yes | - | Get all messages from a thread.
|
|
86
|
+
| [`api.unread_messages_count()`](#unread_messages_count) | 🔐 Yes | Yes | Get the total count of unread messages.
|
|
83
87
|
|
|
84
88
|
|
|
85
89
|
## 🤓 Detailed usage
|
|
@@ -368,6 +372,70 @@ Returns all of your saved ads from `https://www.blocket.se/sparade/annonser`.
|
|
|
368
372
|
|
|
369
373
|
```
|
|
370
374
|
|
|
375
|
+
### get_threads
|
|
376
|
+
Returns all of your threads/conversations from Blocket. This api requires a token.
|
|
377
|
+
|
|
378
|
+
- `limit` (`int`, optional) - Number of threads to return, default is 15.
|
|
379
|
+
|
|
380
|
+
```py
|
|
381
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
382
|
+
>>> api.get_threads()
|
|
383
|
+
{
|
|
384
|
+
"channels": [
|
|
385
|
+
{
|
|
386
|
+
"channel_url": "sendbird_group_channel_123",
|
|
387
|
+
"name": "from:user-id,ad:1214281684,to:c1-user-id",
|
|
388
|
+
"data": {
|
|
389
|
+
"ad": {
|
|
390
|
+
"id": "1214281684",
|
|
391
|
+
"advertiser_name": "Kalle",
|
|
392
|
+
"subject": "Elsparkcykel",
|
|
393
|
+
"status": "active",
|
|
394
|
+
"url": "https://www.blocket.se/annons/1214281684",
|
|
395
|
+
"price": "2 400 kr"
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
...
|
|
400
|
+
],
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
### get_messages_from_thread
|
|
407
|
+
Returns all of your messages from an existing thread/conversation.
|
|
408
|
+
|
|
409
|
+
- `channel_id` (`str`, required) - The channel id to fetch messages from.
|
|
410
|
+
|
|
411
|
+
```py
|
|
412
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
413
|
+
>>> api.get_messages_from_thread("sendbird_group_channel_123")
|
|
414
|
+
{
|
|
415
|
+
"messages": [
|
|
416
|
+
{
|
|
417
|
+
"type": "MESG",
|
|
418
|
+
"message_id": 1354913370,
|
|
419
|
+
"message": "Hey, is your thing still for sale?",
|
|
420
|
+
...
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### unread_messages_count
|
|
427
|
+
Returns the count of unread messages.
|
|
428
|
+
|
|
429
|
+
```py
|
|
430
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
431
|
+
>>> api.unread_messages_count()
|
|
432
|
+
{
|
|
433
|
+
"unread_count": 5
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
371
439
|
## 🔐 Blocket API token
|
|
372
440
|
|
|
373
441
|
There are two ways to acquire your token:
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: blocket_api
|
|
3
|
-
Version: 0.3.5
|
|
4
|
-
Summary: A python API wrapper for blocket.se
|
|
5
|
-
Author-email: dunderrrrrr <emil.bjorkroth@gmail.com>
|
|
6
|
-
Requires-Python: >=3.10
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
License-File: LICENSE
|
|
9
|
-
Requires-Dist: httpx>=0.28.1
|
|
10
|
-
Requires-Dist: pre-commit>=3.7.1
|
|
11
|
-
Requires-Dist: pytest>=8.2.2
|
|
12
|
-
Requires-Dist: respx>=0.21.1
|
|
13
|
-
Requires-Dist: mypy>=1.15.0
|
|
14
|
-
Requires-Dist: pydantic>=2.11.7
|
|
15
|
-
Requires-Dist: mkdocs>=1.6.1
|
|
16
|
-
Requires-Dist: mkdocs-material>=9.6.21
|
|
17
|
-
Requires-Dist: mkdocs-swagger-ui-tag>=0.7.2
|
|
18
|
-
Requires-Dist: ruff>=0.14.4
|
|
19
|
-
Dynamic: license-file
|
|
20
|
-
|
|
21
1
|
<p align="center">
|
|
22
2
|
<img src="https://blocket-api.se/blocket-api.png" />
|
|
23
3
|
</p>
|
|
@@ -80,6 +60,9 @@ Some calls require a `bearerToken`. However, some calls are public and don't req
|
|
|
80
60
|
| [`api.get_user_by_id()`](#get_user_by_id) | 👏 No | Yes | Get user data from id.
|
|
81
61
|
| [`api.save_ad()`](#save_ad) | 🔐 Yes | - | Save ad to "Saved ads".
|
|
82
62
|
| [`api.get_saved_ads()`](#get_saved_ads) | 🔐 Yes | - | List all saved ads.
|
|
63
|
+
| [`api.get_threads()`](#get_threads) | 🔐 Yes | - | List all threads (messages).
|
|
64
|
+
| [`api.get_messages_from_thread()`](#get_messages_from_thread) | 🔐 Yes | - | Get all messages from a thread.
|
|
65
|
+
| [`api.unread_messages_count()`](#unread_messages_count) | 🔐 Yes | Yes | Get the total count of unread messages.
|
|
83
66
|
|
|
84
67
|
|
|
85
68
|
## 🤓 Detailed usage
|
|
@@ -368,6 +351,70 @@ Returns all of your saved ads from `https://www.blocket.se/sparade/annonser`.
|
|
|
368
351
|
|
|
369
352
|
```
|
|
370
353
|
|
|
354
|
+
### get_threads
|
|
355
|
+
Returns all of your threads/conversations from Blocket. This api requires a token.
|
|
356
|
+
|
|
357
|
+
- `limit` (`int`, optional) - Number of threads to return, default is 15.
|
|
358
|
+
|
|
359
|
+
```py
|
|
360
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
361
|
+
>>> api.get_threads()
|
|
362
|
+
{
|
|
363
|
+
"channels": [
|
|
364
|
+
{
|
|
365
|
+
"channel_url": "sendbird_group_channel_123",
|
|
366
|
+
"name": "from:user-id,ad:1214281684,to:c1-user-id",
|
|
367
|
+
"data": {
|
|
368
|
+
"ad": {
|
|
369
|
+
"id": "1214281684",
|
|
370
|
+
"advertiser_name": "Kalle",
|
|
371
|
+
"subject": "Elsparkcykel",
|
|
372
|
+
"status": "active",
|
|
373
|
+
"url": "https://www.blocket.se/annons/1214281684",
|
|
374
|
+
"price": "2 400 kr"
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
...
|
|
379
|
+
],
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
### get_messages_from_thread
|
|
386
|
+
Returns all of your messages from an existing thread/conversation.
|
|
387
|
+
|
|
388
|
+
- `channel_id` (`str`, required) - The channel id to fetch messages from.
|
|
389
|
+
|
|
390
|
+
```py
|
|
391
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
392
|
+
>>> api.get_messages_from_thread("sendbird_group_channel_123")
|
|
393
|
+
{
|
|
394
|
+
"messages": [
|
|
395
|
+
{
|
|
396
|
+
"type": "MESG",
|
|
397
|
+
"message_id": 1354913370,
|
|
398
|
+
"message": "Hey, is your thing still for sale?",
|
|
399
|
+
...
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### unread_messages_count
|
|
406
|
+
Returns the count of unread messages.
|
|
407
|
+
|
|
408
|
+
```py
|
|
409
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
410
|
+
>>> api.unread_messages_count()
|
|
411
|
+
{
|
|
412
|
+
"unread_count": 5
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
371
418
|
## 🔐 Blocket API token
|
|
372
419
|
|
|
373
420
|
There are two ways to acquire your token:
|
|
@@ -17,11 +17,13 @@ from blocket_api.models import (
|
|
|
17
17
|
SavedSearchResponse,
|
|
18
18
|
StoreListings,
|
|
19
19
|
StoreSearchResults,
|
|
20
|
+
UnreadMessagesCount,
|
|
20
21
|
)
|
|
21
22
|
from blocket_api.qasa import HOME_SEARCH_ORDERING, HomeType, OrderBy, Qasa
|
|
22
23
|
|
|
23
24
|
from .constants import BASE_URL, BYTBIL_URL
|
|
24
25
|
from .decorators import auth_token, public_token
|
|
26
|
+
from .sendbird import Sendbird
|
|
25
27
|
|
|
26
28
|
if TYPE_CHECKING:
|
|
27
29
|
from httpx import Response
|
|
@@ -588,3 +590,42 @@ class BlocketAPI:
|
|
|
588
590
|
url = f"{BASE_URL}/search_bff/v1/saved_content?lim={limit}"
|
|
589
591
|
response = _make_request(url=f"{url}", token=self.token).json()
|
|
590
592
|
return response
|
|
593
|
+
|
|
594
|
+
@auth_token
|
|
595
|
+
def get_threads(self, limit: int = 15) -> dict:
|
|
596
|
+
"""
|
|
597
|
+
Returns set number of conversations/threads from Blocket, ordered by latest message.
|
|
598
|
+
"""
|
|
599
|
+
assert self.token
|
|
600
|
+
sendbird = Sendbird.generate(self.token)
|
|
601
|
+
return sendbird.get_threads(limit=limit)
|
|
602
|
+
|
|
603
|
+
@auth_token
|
|
604
|
+
def get_messages_from_thread(self, channel_id: str) -> dict:
|
|
605
|
+
"""
|
|
606
|
+
Returns all messages from a specific channel/thread.
|
|
607
|
+
Requires a channel_id which can be found by using get_threads().
|
|
608
|
+
Ex: sendbird_group_channel_12345_abc123abcde
|
|
609
|
+
"""
|
|
610
|
+
assert self.token
|
|
611
|
+
sendbird = Sendbird.generate(self.token)
|
|
612
|
+
return sendbird.get_messages_from_thread(channel_id)
|
|
613
|
+
|
|
614
|
+
@overload
|
|
615
|
+
def unread_messages_count(
|
|
616
|
+
self, *, as_objects: Literal[True]
|
|
617
|
+
) -> UnreadMessagesCount: ...
|
|
618
|
+
|
|
619
|
+
@overload
|
|
620
|
+
def unread_messages_count(self, *, as_objects: Literal[False] = False) -> dict: ...
|
|
621
|
+
|
|
622
|
+
@auth_token
|
|
623
|
+
def unread_messages_count(
|
|
624
|
+
self, as_objects: bool = False
|
|
625
|
+
) -> dict | UnreadMessagesCount:
|
|
626
|
+
"""
|
|
627
|
+
Returns the total count of unread messages.
|
|
628
|
+
"""
|
|
629
|
+
assert self.token
|
|
630
|
+
response = Sendbird.generate(self.token).unread_messages_count()
|
|
631
|
+
return UnreadMessagesCount.model_validate(response) if as_objects else response
|
|
@@ -2,3 +2,6 @@ BASE_URL = "https://api.blocket.se"
|
|
|
2
2
|
SITE_URL = "https://www.blocket.se"
|
|
3
3
|
BYTBIL_URL = "https://api.bytbil.com"
|
|
4
4
|
QASA_URL = "https://api.qasa.se/graphql"
|
|
5
|
+
|
|
6
|
+
BLOCKET_SENDBIRD_APP_ID = "162ABE1D-86E9-4C2A-866A-EF1034525DAF"
|
|
7
|
+
SENDBIRD_URL = f"https://api-{BLOCKET_SENDBIRD_APP_ID}.sendbird.com"
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import time
|
|
5
|
+
import urllib.parse
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
from pydantic import BaseModel, ConfigDict
|
|
10
|
+
from websockets.sync.client import connect
|
|
11
|
+
|
|
12
|
+
from .constants import BASE_URL, BLOCKET_SENDBIRD_APP_ID, SENDBIRD_URL
|
|
13
|
+
|
|
14
|
+
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:144.0) Gecko/20100101 Firefox/144.0"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class SendbirdResponse(BaseModel):
|
|
18
|
+
user_id: str
|
|
19
|
+
nickname: str
|
|
20
|
+
profile_url: str
|
|
21
|
+
ekey: str
|
|
22
|
+
metadata: dict
|
|
23
|
+
|
|
24
|
+
ping_interval: int
|
|
25
|
+
pong_timeout: int
|
|
26
|
+
login_ts: int
|
|
27
|
+
|
|
28
|
+
key: str # Session key
|
|
29
|
+
expires_at: int
|
|
30
|
+
|
|
31
|
+
unread_cnt: dict
|
|
32
|
+
premium_feature_list: list[str]
|
|
33
|
+
application_attributes: list[str]
|
|
34
|
+
services: list[str]
|
|
35
|
+
|
|
36
|
+
model_config = ConfigDict(extra="ignore")
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def session_key(self) -> str:
|
|
40
|
+
return self.key
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_blocket_tokens(bearer_token: str) -> dict:
|
|
44
|
+
token_response = httpx.get(
|
|
45
|
+
f"{BASE_URL}/messaging-sendbird-communication/v1/users/tokens",
|
|
46
|
+
headers={
|
|
47
|
+
"Authorization": f"Bearer {bearer_token}",
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
token_response.raise_for_status()
|
|
51
|
+
return token_response.json()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class SendbirdClient:
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
app_id: str,
|
|
58
|
+
user_id: str,
|
|
59
|
+
access_token: str,
|
|
60
|
+
):
|
|
61
|
+
self.app_id = app_id
|
|
62
|
+
self.user_id = user_id
|
|
63
|
+
self.access_token = access_token
|
|
64
|
+
|
|
65
|
+
def _build_wss_url(self) -> str:
|
|
66
|
+
base_url = f"wss://ws-{self.app_id.lower()}.sendbird.com/"
|
|
67
|
+
timestamp = str(int(time.time() * 1000))
|
|
68
|
+
|
|
69
|
+
params = {
|
|
70
|
+
"p": "JS",
|
|
71
|
+
"pv": USER_AGENT,
|
|
72
|
+
"sv": "4.10.8",
|
|
73
|
+
"ai": self.app_id,
|
|
74
|
+
"pmce": "1",
|
|
75
|
+
"active": "1",
|
|
76
|
+
"device_token_types": "gcm,huawei,apns",
|
|
77
|
+
"SB-User-Agent": "JS/c4.10.8///oweb",
|
|
78
|
+
"SB-SDK-User-Agent": "main_sdk_info=chat/js/4.10.8&device_os_platform=web&os_version=Mozilla/5.0 (X11; Linux x86_64; rv:144.0) Gecko/20100101 Firefox/144.0",
|
|
79
|
+
"Request-Sent-Timestamp": timestamp,
|
|
80
|
+
"include_extra_data": "premium_feature_list,file_upload_size_limit,application_attributes,emoji_hash,multiple_file_send_max_size,notifications",
|
|
81
|
+
"use_local_cache": "0",
|
|
82
|
+
"include_poll_details": "1",
|
|
83
|
+
"user_id": self.user_id,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return base_url + "?" + urllib.parse.urlencode(params)
|
|
87
|
+
|
|
88
|
+
def get_data(self) -> str:
|
|
89
|
+
with connect(
|
|
90
|
+
self._build_wss_url(),
|
|
91
|
+
subprotocols=[urllib.parse.quote(json.dumps({"token": self.access_token}))], # type: ignore[list-item]
|
|
92
|
+
additional_headers={
|
|
93
|
+
"User-Agent": USER_AGENT,
|
|
94
|
+
"Origin": "https://www.blocket.se",
|
|
95
|
+
},
|
|
96
|
+
open_timeout=5,
|
|
97
|
+
) as websocket:
|
|
98
|
+
message: str = websocket.recv(timeout=5) # type: ignore[assignment]
|
|
99
|
+
return str(message.split("LOGI")[1])
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass(frozen=True)
|
|
103
|
+
class Sendbird:
|
|
104
|
+
sendbird_client: SendbirdClient
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def generate(cls, blocket_token: str) -> Sendbird:
|
|
108
|
+
tokens = get_blocket_tokens(blocket_token)
|
|
109
|
+
sb_token = tokens["sb_session_token"]
|
|
110
|
+
sb_user_id = tokens["sb_user_id"]
|
|
111
|
+
return cls(
|
|
112
|
+
sendbird_client=SendbirdClient(
|
|
113
|
+
app_id=BLOCKET_SENDBIRD_APP_ID,
|
|
114
|
+
user_id=sb_user_id,
|
|
115
|
+
access_token=sb_token,
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
def get_threads(self, limit: int) -> dict:
|
|
120
|
+
sendbird = SendbirdResponse.model_validate_json(self.sendbird_client.get_data())
|
|
121
|
+
response = httpx.get(
|
|
122
|
+
f"{SENDBIRD_URL}/v3/users/{self.sendbird_client.user_id}/my_group_channels",
|
|
123
|
+
params={
|
|
124
|
+
"token": "",
|
|
125
|
+
"limit": limit,
|
|
126
|
+
"order": "latest_last_message",
|
|
127
|
+
"show_member": True,
|
|
128
|
+
"show_read_receipt": True,
|
|
129
|
+
"show_delivery_receipt": True,
|
|
130
|
+
"show_empty": False,
|
|
131
|
+
"member_state_filter": "all",
|
|
132
|
+
"super_mode": "all",
|
|
133
|
+
"public_mode": "all",
|
|
134
|
+
"unread_filter": "all",
|
|
135
|
+
"name_contains": "",
|
|
136
|
+
"custom_type_startswith": "",
|
|
137
|
+
"hidden_mode": "unhidden_only",
|
|
138
|
+
"show_frozen": True,
|
|
139
|
+
"show_metadata": True,
|
|
140
|
+
"include_chat_notification": False,
|
|
141
|
+
"include_left_channel": False,
|
|
142
|
+
},
|
|
143
|
+
headers={
|
|
144
|
+
"Session-Key": sendbird.session_key,
|
|
145
|
+
"Access-Token": self.sendbird_client.access_token,
|
|
146
|
+
},
|
|
147
|
+
)
|
|
148
|
+
response.raise_for_status()
|
|
149
|
+
return response.json()
|
|
150
|
+
|
|
151
|
+
def get_messages_from_thread(self, channel_id: str) -> dict:
|
|
152
|
+
sendbird = SendbirdResponse.model_validate_json(self.sendbird_client.get_data())
|
|
153
|
+
response = httpx.get(
|
|
154
|
+
f"{SENDBIRD_URL}/v3/group_channels/{channel_id}/messages",
|
|
155
|
+
params={
|
|
156
|
+
"is_sdk": True,
|
|
157
|
+
"prev_limit": 30,
|
|
158
|
+
"next_limit": 0,
|
|
159
|
+
"include": False,
|
|
160
|
+
"reverse": False,
|
|
161
|
+
"message_ts": 9007199254740991,
|
|
162
|
+
"message_type": "",
|
|
163
|
+
"include_reply_type": "none",
|
|
164
|
+
"with_sorted_meta_array": False,
|
|
165
|
+
"include_reactions": False,
|
|
166
|
+
"include_thread_info": False,
|
|
167
|
+
"include_parent_message_info": False,
|
|
168
|
+
"show_subchannel_message_only": False,
|
|
169
|
+
"include_poll_details": True,
|
|
170
|
+
},
|
|
171
|
+
headers={
|
|
172
|
+
"Session-Key": sendbird.session_key,
|
|
173
|
+
"Access-Token": self.sendbird_client.access_token,
|
|
174
|
+
},
|
|
175
|
+
)
|
|
176
|
+
response.raise_for_status()
|
|
177
|
+
return response.json()
|
|
178
|
+
|
|
179
|
+
def unread_messages_count(self) -> dict:
|
|
180
|
+
sendbird = SendbirdResponse.model_validate_json(self.sendbird_client.get_data())
|
|
181
|
+
response = httpx.get(
|
|
182
|
+
f"{SENDBIRD_URL}/v3/users/{self.sendbird_client.user_id}/unread_message_count",
|
|
183
|
+
params={"super_mode": "all", "include_feed_channel": False},
|
|
184
|
+
headers={
|
|
185
|
+
"Session-Key": sendbird.session_key,
|
|
186
|
+
"Access-Token": self.sendbird_client.access_token,
|
|
187
|
+
},
|
|
188
|
+
)
|
|
189
|
+
response.raise_for_status()
|
|
190
|
+
return response.json()
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: blocket_api
|
|
3
|
+
Version: 0.3.7
|
|
4
|
+
Summary: A python API wrapper for blocket.se
|
|
5
|
+
Author-email: dunderrrrrr <emil.bjorkroth@gmail.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: httpx>=0.28.1
|
|
10
|
+
Requires-Dist: pre-commit>=3.7.1
|
|
11
|
+
Requires-Dist: pytest>=8.2.2
|
|
12
|
+
Requires-Dist: respx>=0.21.1
|
|
13
|
+
Requires-Dist: mypy>=1.15.0
|
|
14
|
+
Requires-Dist: pydantic>=2.11.7
|
|
15
|
+
Requires-Dist: mkdocs>=1.6.1
|
|
16
|
+
Requires-Dist: mkdocs-material>=9.6.21
|
|
17
|
+
Requires-Dist: mkdocs-swagger-ui-tag>=0.7.2
|
|
18
|
+
Requires-Dist: websockets>=15.0.1
|
|
19
|
+
Requires-Dist: ruff>=0.14.5
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
1
22
|
<p align="center">
|
|
2
23
|
<img src="https://blocket-api.se/blocket-api.png" />
|
|
3
24
|
</p>
|
|
@@ -60,6 +81,9 @@ Some calls require a `bearerToken`. However, some calls are public and don't req
|
|
|
60
81
|
| [`api.get_user_by_id()`](#get_user_by_id) | 👏 No | Yes | Get user data from id.
|
|
61
82
|
| [`api.save_ad()`](#save_ad) | 🔐 Yes | - | Save ad to "Saved ads".
|
|
62
83
|
| [`api.get_saved_ads()`](#get_saved_ads) | 🔐 Yes | - | List all saved ads.
|
|
84
|
+
| [`api.get_threads()`](#get_threads) | 🔐 Yes | - | List all threads (messages).
|
|
85
|
+
| [`api.get_messages_from_thread()`](#get_messages_from_thread) | 🔐 Yes | - | Get all messages from a thread.
|
|
86
|
+
| [`api.unread_messages_count()`](#unread_messages_count) | 🔐 Yes | Yes | Get the total count of unread messages.
|
|
63
87
|
|
|
64
88
|
|
|
65
89
|
## 🤓 Detailed usage
|
|
@@ -348,6 +372,70 @@ Returns all of your saved ads from `https://www.blocket.se/sparade/annonser`.
|
|
|
348
372
|
|
|
349
373
|
```
|
|
350
374
|
|
|
375
|
+
### get_threads
|
|
376
|
+
Returns all of your threads/conversations from Blocket. This api requires a token.
|
|
377
|
+
|
|
378
|
+
- `limit` (`int`, optional) - Number of threads to return, default is 15.
|
|
379
|
+
|
|
380
|
+
```py
|
|
381
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
382
|
+
>>> api.get_threads()
|
|
383
|
+
{
|
|
384
|
+
"channels": [
|
|
385
|
+
{
|
|
386
|
+
"channel_url": "sendbird_group_channel_123",
|
|
387
|
+
"name": "from:user-id,ad:1214281684,to:c1-user-id",
|
|
388
|
+
"data": {
|
|
389
|
+
"ad": {
|
|
390
|
+
"id": "1214281684",
|
|
391
|
+
"advertiser_name": "Kalle",
|
|
392
|
+
"subject": "Elsparkcykel",
|
|
393
|
+
"status": "active",
|
|
394
|
+
"url": "https://www.blocket.se/annons/1214281684",
|
|
395
|
+
"price": "2 400 kr"
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
...
|
|
400
|
+
],
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
### get_messages_from_thread
|
|
407
|
+
Returns all of your messages from an existing thread/conversation.
|
|
408
|
+
|
|
409
|
+
- `channel_id` (`str`, required) - The channel id to fetch messages from.
|
|
410
|
+
|
|
411
|
+
```py
|
|
412
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
413
|
+
>>> api.get_messages_from_thread("sendbird_group_channel_123")
|
|
414
|
+
{
|
|
415
|
+
"messages": [
|
|
416
|
+
{
|
|
417
|
+
"type": "MESG",
|
|
418
|
+
"message_id": 1354913370,
|
|
419
|
+
"message": "Hey, is your thing still for sale?",
|
|
420
|
+
...
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### unread_messages_count
|
|
427
|
+
Returns the count of unread messages.
|
|
428
|
+
|
|
429
|
+
```py
|
|
430
|
+
>>> api = BlocketAPI("YourBlocketTokenHere")
|
|
431
|
+
>>> api.unread_messages_count()
|
|
432
|
+
{
|
|
433
|
+
"unread_count": 5
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
351
439
|
## 🔐 Blocket API token
|
|
352
440
|
|
|
353
441
|
There are two ways to acquire your token:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "blocket_api"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.7"
|
|
4
4
|
description = "A python API wrapper for blocket.se"
|
|
5
5
|
authors = [{name = "dunderrrrrr", email = "emil.bjorkroth@gmail.com"}]
|
|
6
6
|
readme = "README.md"
|
|
@@ -15,7 +15,8 @@ dependencies = [
|
|
|
15
15
|
"mkdocs>=1.6.1",
|
|
16
16
|
"mkdocs-material>=9.6.21",
|
|
17
17
|
"mkdocs-swagger-ui-tag>=0.7.2",
|
|
18
|
-
"
|
|
18
|
+
"websockets>=15.0.1",
|
|
19
|
+
"ruff>=0.14.5",
|
|
19
20
|
]
|
|
20
21
|
|
|
21
22
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|