add missing string id representation to models #116

Этот коммит содержится в:
Vlad Pronsky 2024-02-10 18:56:29 +02:00
родитель 748ceae053
Коммит 277ebd1649
4 изменённых файлов: 45 добавлений и 8 удалений

Двоичные данные
.github/example.png поставляемый Обычный файл

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 218 KiB

Просмотреть файл

@ -13,7 +13,7 @@
Twitter GraphQL API implementation with [SNScrape](https://github.com/JustAnotherArchivist/snscrape) data models.
<div align="center">
<img src="https://miro.medium.com/v2/resize:fit:1400/format:webp/1*0erkeMBhl_qqRofIeU5jMQ.png" alt="example of cli usage" width="560px">
<img src=".github/example.png" alt="example of cli usage" width="560px">
</div>
## Install

Просмотреть файл

@ -4,7 +4,7 @@ from typing import Callable
from twscrape import API, gather
from twscrape.logger import set_log_level
from twscrape.models import Tweet, User, parse_tweet
from twscrape.models import Tweet, User, UserRef, parse_tweet
BASE_DIR = os.path.dirname(__file__)
DATA_DIR = os.path.join(BASE_DIR, "mocked-data")
@ -49,18 +49,33 @@ def mock_rep(fn: Callable, filename: str, as_generator=False):
def check_tweet(doc: Tweet | None):
assert doc is not None
assert doc.id is not None
assert doc.id_str is not None
assert isinstance(doc.id, int)
assert isinstance(doc.id_str, str)
assert doc.id == int(doc.id_str)
assert str(doc.id) == doc.id_str
assert doc.url is not None
assert doc.id_str in doc.url
assert doc.user is not None
assert isinstance(doc.conversationId, int)
assert isinstance(doc.conversationIdStr, str)
assert str(doc.conversationId) == doc.conversationIdStr
if doc.inReplyToTweetId is not None:
assert isinstance(doc.inReplyToTweetId, int)
assert isinstance(doc.inReplyToTweetIdStr, str)
assert str(doc.inReplyToTweetId) == doc.inReplyToTweetIdStr
if doc.inReplyToUser:
check_user_ref(doc.inReplyToUser)
if doc.mentionedUsers:
for x in doc.mentionedUsers:
check_user_ref(x)
obj = doc.dict()
assert doc.id == obj["id"]
assert doc.id_str == obj["id_str"]
assert doc.user.id == obj["user"]["id"]
assert "url" in obj
@ -104,10 +119,9 @@ def check_tweet(doc: Tweet | None):
def check_user(doc: User):
assert doc.id is not None
assert doc.id_str is not None
assert isinstance(doc.id, int)
assert isinstance(doc.id_str, str)
assert doc.id == int(doc.id_str)
assert str(doc.id) == doc.id_str
assert doc.username is not None
assert doc.descriptionLinks is not None
@ -127,6 +141,19 @@ def check_user(doc: User):
assert str(doc.id) in txt
def check_user_ref(doc: UserRef):
assert isinstance(doc.id, int)
assert isinstance(doc.id_str, str)
assert str(doc.id) == doc.id_str
assert doc.username is not None
assert doc.displayname is not None
obj = doc.dict()
assert doc.id == obj["id"]
assert doc.id_str == obj["id_str"]
async def test_search():
api = API()
mock_rep(api.search_raw, "raw_search", as_generator=True)

Просмотреть файл

@ -84,13 +84,19 @@ class TextLink(JSONTrait):
@dataclass
class UserRef(JSONTrait):
id: int
id_str: str
username: str
displayname: str
_type: str = "snscrape.modules.twitter.UserRef"
@staticmethod
def parse(obj: dict):
return UserRef(id=int(obj["id_str"]), username=obj["screen_name"], displayname=obj["name"])
return UserRef(
id=int(obj["id_str"]),
id_str=obj["id_str"],
username=obj["screen_name"],
displayname=obj["name"],
)
@dataclass
@ -163,6 +169,7 @@ class Tweet(JSONTrait):
likeCount: int
quoteCount: int
conversationId: int
conversationIdStr: str
hashtags: list[str]
cashtags: list[str]
mentionedUsers: list[UserRef]
@ -173,6 +180,7 @@ class Tweet(JSONTrait):
place: Optional[Place] = None
coordinates: Optional[Coordinates] = None
inReplyToTweetId: int | None = None
inReplyToTweetIdStr: str | None = None
inReplyToUser: UserRef | None = None
source: str | None = None
sourceUrl: str | None = None
@ -217,6 +225,7 @@ class Tweet(JSONTrait):
likeCount=obj["favorite_count"],
quoteCount=obj["quote_count"],
conversationId=int(obj["conversation_id_str"]),
conversationIdStr=obj["conversation_id_str"],
hashtags=[x["text"] for x in get_or(obj, "entities.hashtags", [])],
cashtags=[x["text"] for x in get_or(obj, "entities.symbols", [])],
mentionedUsers=[UserRef.parse(x) for x in get_or(obj, "entities.user_mentions", [])],
@ -229,6 +238,7 @@ class Tweet(JSONTrait):
place=Place.parse(obj["place"]) if obj.get("place") else None,
coordinates=Coordinates.parse(obj),
inReplyToTweetId=int_or(obj, "in_reply_to_status_id_str"),
inReplyToTweetIdStr=get_or(obj, "in_reply_to_status_id_str"),
inReplyToUser=_get_reply_user(obj, res),
source=obj.get("source", None),
sourceUrl=_get_source_url(obj),