tiebameow 0.2.8__py3-none-any.whl
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.
- tiebameow/__init__.py +0 -0
- tiebameow/client/__init__.py +4 -0
- tiebameow/client/http_client.py +103 -0
- tiebameow/client/tieba_client.py +517 -0
- tiebameow/models/__init__.py +0 -0
- tiebameow/models/dto.py +391 -0
- tiebameow/models/orm.py +572 -0
- tiebameow/parser/__init__.py +45 -0
- tiebameow/parser/parser.py +362 -0
- tiebameow/parser/rule_parser.py +990 -0
- tiebameow/py.typed +0 -0
- tiebameow/renderer/__init__.py +5 -0
- tiebameow/renderer/config.py +18 -0
- tiebameow/renderer/playwright_core.py +148 -0
- tiebameow/renderer/renderer.py +508 -0
- tiebameow/renderer/static/fonts/NotoSansSC-Regular.woff2 +0 -0
- tiebameow/renderer/style.py +32 -0
- tiebameow/renderer/templates/base.html +270 -0
- tiebameow/renderer/templates/macros.html +100 -0
- tiebameow/renderer/templates/text.html +99 -0
- tiebameow/renderer/templates/text_simple.html +79 -0
- tiebameow/renderer/templates/thread.html +8 -0
- tiebameow/renderer/templates/thread_detail.html +18 -0
- tiebameow/renderer/templates/thread_info.html +35 -0
- tiebameow/schemas/__init__.py +0 -0
- tiebameow/schemas/fragments.py +188 -0
- tiebameow/schemas/rules.py +247 -0
- tiebameow/serializer/__init__.py +15 -0
- tiebameow/serializer/serializer.py +115 -0
- tiebameow/utils/__init__.py +0 -0
- tiebameow/utils/logger.py +129 -0
- tiebameow/utils/time_utils.py +15 -0
- tiebameow-0.2.8.dist-info/METADATA +142 -0
- tiebameow-0.2.8.dist-info/RECORD +36 -0
- tiebameow-0.2.8.dist-info/WHEEL +4 -0
- tiebameow-0.2.8.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Literal, cast, overload
|
|
6
|
+
|
|
7
|
+
from ..models.dto import (
|
|
8
|
+
BaseForumDTO,
|
|
9
|
+
BaseThreadDTO,
|
|
10
|
+
BaseUserDTO,
|
|
11
|
+
CommentDTO,
|
|
12
|
+
CommentsDTO,
|
|
13
|
+
CommentUserDTO,
|
|
14
|
+
PageInfoDTO,
|
|
15
|
+
PostDTO,
|
|
16
|
+
PostsDTO,
|
|
17
|
+
PostUserDTO,
|
|
18
|
+
ThreadDTO,
|
|
19
|
+
ThreadpDTO,
|
|
20
|
+
ThreadsDTO,
|
|
21
|
+
ThreadUserDTO,
|
|
22
|
+
UserInfoDTO,
|
|
23
|
+
)
|
|
24
|
+
from ..schemas.fragments import FRAG_MAP, Fragment, FragUnknownModel
|
|
25
|
+
from ..utils.time_utils import SHANGHAI_TZ
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from aiotieba.api._classdef.contents import (
|
|
29
|
+
FragAt,
|
|
30
|
+
FragEmoji,
|
|
31
|
+
FragImage,
|
|
32
|
+
FragItem,
|
|
33
|
+
FragLink,
|
|
34
|
+
FragText,
|
|
35
|
+
FragTiebaPlus,
|
|
36
|
+
FragUnknown,
|
|
37
|
+
FragVideo,
|
|
38
|
+
)
|
|
39
|
+
from aiotieba.api.get_comments._classdef import Forum_c, Page_c, UserInfo_c
|
|
40
|
+
from aiotieba.api.get_posts._classdef import (
|
|
41
|
+
Comment_p,
|
|
42
|
+
Forum_p,
|
|
43
|
+
Page_p,
|
|
44
|
+
ShareThread_pt,
|
|
45
|
+
Thread_p,
|
|
46
|
+
UserInfo_p,
|
|
47
|
+
UserInfo_pt,
|
|
48
|
+
)
|
|
49
|
+
from aiotieba.api.get_threads._classdef import Forum_t, Page_t, ShareThread, UserInfo_t
|
|
50
|
+
from aiotieba.api.tieba_uid2user_info import UserInfo_TUid
|
|
51
|
+
from aiotieba.typing import Comment, Comments, Post, Posts, Thread, Threads, UserInfo
|
|
52
|
+
|
|
53
|
+
type AiotiebaType = Thread | Post | Comment
|
|
54
|
+
type AiotiebaFragType = (
|
|
55
|
+
FragAt | FragEmoji | FragImage | FragItem | FragLink | FragText | FragTiebaPlus | FragUnknown | FragVideo
|
|
56
|
+
)
|
|
57
|
+
type AiotiebaUserType = UserInfo_t | UserInfo_p | UserInfo_c | UserInfo_TUid
|
|
58
|
+
type AiotiebaPageType = Page_t | Page_p | Page_c
|
|
59
|
+
type AiotiebaForumType = Forum_t | Forum_p | Forum_c
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def convert_aiotieba_fragment(obj: AiotiebaFragType | Any) -> Fragment:
|
|
63
|
+
source_type_name = type(obj).__name__
|
|
64
|
+
target_model_name = source_type_name.rsplit("_", 1)[0]
|
|
65
|
+
|
|
66
|
+
target_model = FRAG_MAP.get(target_model_name)
|
|
67
|
+
|
|
68
|
+
if target_model is None:
|
|
69
|
+
return FragUnknownModel(raw_data=repr(obj))
|
|
70
|
+
|
|
71
|
+
data_dict = dataclasses.asdict(obj)
|
|
72
|
+
return target_model(**data_dict)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def convert_aiotieba_content_list(contents: list[AiotiebaFragType | Any]) -> list[Fragment]:
|
|
76
|
+
if not contents:
|
|
77
|
+
return []
|
|
78
|
+
return [convert_aiotieba_fragment(frag) for frag in contents]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def convert_aiotieba_tiebauiduser(user: UserInfo_TUid) -> BaseUserDTO:
|
|
82
|
+
return BaseUserDTO(
|
|
83
|
+
user_id=user.user_id,
|
|
84
|
+
portrait=user.portrait,
|
|
85
|
+
user_name=user.user_name,
|
|
86
|
+
nick_name_new=user.nick_name,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def convert_aiotieba_threaduser(user: UserInfo_t | UserInfo_pt) -> ThreadUserDTO:
|
|
91
|
+
gender: Literal["UNKNOWN", "MALE", "FEMALE"] = "UNKNOWN"
|
|
92
|
+
if hasattr(user, "gender"):
|
|
93
|
+
gender = cast("UserInfo_t", user).gender.name
|
|
94
|
+
return ThreadUserDTO(
|
|
95
|
+
user_id=user.user_id,
|
|
96
|
+
portrait=user.portrait,
|
|
97
|
+
user_name=user.user_name,
|
|
98
|
+
nick_name_new=user.nick_name,
|
|
99
|
+
level=user.level,
|
|
100
|
+
glevel=user.glevel,
|
|
101
|
+
gender=gender,
|
|
102
|
+
icons=user.icons,
|
|
103
|
+
is_bawu=user.is_bawu,
|
|
104
|
+
is_vip=user.is_vip,
|
|
105
|
+
is_god=user.is_god,
|
|
106
|
+
priv_like=user.priv_like.name,
|
|
107
|
+
priv_reply=user.priv_reply.name,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def convert_aiotieba_postuser(user: UserInfo_p) -> PostUserDTO:
|
|
112
|
+
return PostUserDTO(
|
|
113
|
+
user_id=user.user_id,
|
|
114
|
+
portrait=user.portrait,
|
|
115
|
+
user_name=user.user_name,
|
|
116
|
+
nick_name_new=user.nick_name,
|
|
117
|
+
level=user.level,
|
|
118
|
+
glevel=user.glevel,
|
|
119
|
+
gender=user.gender.name,
|
|
120
|
+
ip=user.ip,
|
|
121
|
+
icons=user.icons,
|
|
122
|
+
is_bawu=user.is_bawu,
|
|
123
|
+
is_vip=user.is_vip,
|
|
124
|
+
is_god=user.is_god,
|
|
125
|
+
priv_like=user.priv_like.name,
|
|
126
|
+
priv_reply=user.priv_reply.name,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def convert_aiotieba_commentuser(user: UserInfo_c | UserInfo_p) -> CommentUserDTO:
|
|
131
|
+
return CommentUserDTO(
|
|
132
|
+
user_id=user.user_id,
|
|
133
|
+
portrait=user.portrait,
|
|
134
|
+
user_name=user.user_name,
|
|
135
|
+
nick_name_new=user.nick_name,
|
|
136
|
+
level=user.level,
|
|
137
|
+
gender=user.gender.name,
|
|
138
|
+
icons=user.icons,
|
|
139
|
+
is_bawu=user.is_bawu,
|
|
140
|
+
is_vip=user.is_vip,
|
|
141
|
+
is_god=user.is_god,
|
|
142
|
+
priv_like=user.priv_like.name,
|
|
143
|
+
priv_reply=user.priv_reply.name,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def convert_aiotieba_userinfo(user: UserInfo) -> UserInfoDTO:
|
|
148
|
+
return UserInfoDTO(
|
|
149
|
+
user_id=user.user_id,
|
|
150
|
+
portrait=user.portrait,
|
|
151
|
+
user_name=user.user_name,
|
|
152
|
+
nick_name_new=user.nick_name,
|
|
153
|
+
nick_name_old=user.nick_name_old,
|
|
154
|
+
tieba_uid=user.tieba_uid,
|
|
155
|
+
glevel=user.glevel,
|
|
156
|
+
gender=user.gender.name,
|
|
157
|
+
age=user.age,
|
|
158
|
+
post_num=user.post_num,
|
|
159
|
+
agree_num=user.agree_num,
|
|
160
|
+
fan_num=user.fan_num,
|
|
161
|
+
follow_num=user.follow_num,
|
|
162
|
+
forum_num=user.forum_num,
|
|
163
|
+
sign=user.sign,
|
|
164
|
+
ip=user.ip,
|
|
165
|
+
icons=user.icons,
|
|
166
|
+
is_vip=user.is_vip,
|
|
167
|
+
is_god=user.is_god,
|
|
168
|
+
is_blocked=user.is_blocked,
|
|
169
|
+
priv_like=user.priv_like.name,
|
|
170
|
+
priv_reply=user.priv_reply.name,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@overload
|
|
175
|
+
def convert_aiotieba_user(user: UserInfo) -> UserInfoDTO: ...
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@overload
|
|
179
|
+
def convert_aiotieba_user(user: UserInfo_t) -> ThreadUserDTO: # type: ignore[overload-cannot-match]
|
|
180
|
+
...
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@overload
|
|
184
|
+
def convert_aiotieba_user(user: UserInfo_p) -> PostUserDTO: # type: ignore[overload-cannot-match]
|
|
185
|
+
...
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@overload
|
|
189
|
+
def convert_aiotieba_user(user: UserInfo_c) -> CommentUserDTO: # type: ignore[overload-cannot-match]
|
|
190
|
+
...
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@overload
|
|
194
|
+
def convert_aiotieba_user(user: UserInfo_TUid) -> BaseUserDTO: # type: ignore[overload-cannot-match]
|
|
195
|
+
...
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def convert_aiotieba_user(
|
|
199
|
+
user: UserInfo_TUid | AiotiebaUserType | UserInfo,
|
|
200
|
+
) -> BaseUserDTO | ThreadUserDTO | UserInfoDTO:
|
|
201
|
+
if hasattr(user, "post_num"):
|
|
202
|
+
return convert_aiotieba_userinfo(cast("UserInfo", user))
|
|
203
|
+
if hasattr(user, "ip"):
|
|
204
|
+
return convert_aiotieba_postuser(cast("UserInfo_p", user))
|
|
205
|
+
if hasattr(user, "glevel"):
|
|
206
|
+
return convert_aiotieba_threaduser(cast("UserInfo_t", user))
|
|
207
|
+
if hasattr(user, "is_bawu"):
|
|
208
|
+
return convert_aiotieba_commentuser(cast("UserInfo_c", user))
|
|
209
|
+
return convert_aiotieba_tiebauiduser(cast("UserInfo_TUid", user))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def convert_aiotieba_share_thread(share_thread: ShareThread | ShareThread_pt) -> BaseThreadDTO:
|
|
213
|
+
pid = getattr(share_thread, "pid", 0)
|
|
214
|
+
return BaseThreadDTO(
|
|
215
|
+
pid=pid,
|
|
216
|
+
tid=share_thread.tid,
|
|
217
|
+
fid=share_thread.fid,
|
|
218
|
+
fname=share_thread.fname,
|
|
219
|
+
author_id=share_thread.author_id,
|
|
220
|
+
title=share_thread.title,
|
|
221
|
+
contents=convert_aiotieba_content_list(share_thread.contents.objs),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def convert_aiotieba_thread(tb_thread: Thread) -> ThreadDTO:
|
|
226
|
+
"""
|
|
227
|
+
将 aiotieba 的 Thread 对象转换为 tiebameow 的通用模型
|
|
228
|
+
"""
|
|
229
|
+
return ThreadDTO(
|
|
230
|
+
pid=tb_thread.pid,
|
|
231
|
+
tid=tb_thread.tid,
|
|
232
|
+
fid=tb_thread.fid,
|
|
233
|
+
fname=tb_thread.fname,
|
|
234
|
+
author_id=tb_thread.author_id,
|
|
235
|
+
author=convert_aiotieba_threaduser(tb_thread.user),
|
|
236
|
+
title=tb_thread.title,
|
|
237
|
+
contents=convert_aiotieba_content_list(tb_thread.contents.objs),
|
|
238
|
+
is_good=tb_thread.is_good,
|
|
239
|
+
is_top=tb_thread.is_top,
|
|
240
|
+
is_share=tb_thread.is_share,
|
|
241
|
+
is_hide=tb_thread.is_hide,
|
|
242
|
+
is_livepost=tb_thread.is_livepost,
|
|
243
|
+
is_help=tb_thread.is_help,
|
|
244
|
+
agree_num=tb_thread.agree,
|
|
245
|
+
disagree_num=tb_thread.disagree,
|
|
246
|
+
reply_num=tb_thread.reply_num,
|
|
247
|
+
view_num=tb_thread.view_num,
|
|
248
|
+
share_num=tb_thread.share_num,
|
|
249
|
+
create_time=datetime.fromtimestamp(tb_thread.create_time, SHANGHAI_TZ),
|
|
250
|
+
last_time=datetime.fromtimestamp(tb_thread.last_time, SHANGHAI_TZ),
|
|
251
|
+
thread_type=tb_thread.type,
|
|
252
|
+
tab_id=tb_thread.tab_id,
|
|
253
|
+
share_origin=convert_aiotieba_share_thread(tb_thread.share_origin),
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def convert_aiotieba_threadp(tb_thread: Thread_p) -> ThreadpDTO:
|
|
258
|
+
return ThreadpDTO(
|
|
259
|
+
pid=tb_thread.pid,
|
|
260
|
+
tid=tb_thread.tid,
|
|
261
|
+
fid=tb_thread.fid,
|
|
262
|
+
fname=tb_thread.fname,
|
|
263
|
+
author_id=tb_thread.author_id,
|
|
264
|
+
author=convert_aiotieba_threaduser(tb_thread.user),
|
|
265
|
+
title=tb_thread.title,
|
|
266
|
+
contents=convert_aiotieba_content_list(tb_thread.contents.objs),
|
|
267
|
+
is_share=tb_thread.is_share,
|
|
268
|
+
agree_num=tb_thread.agree,
|
|
269
|
+
disagree_num=tb_thread.disagree,
|
|
270
|
+
reply_num=tb_thread.reply_num,
|
|
271
|
+
view_num=tb_thread.view_num,
|
|
272
|
+
share_num=tb_thread.share_num,
|
|
273
|
+
create_time=datetime.fromtimestamp(tb_thread.create_time, SHANGHAI_TZ),
|
|
274
|
+
thread_type=tb_thread.type,
|
|
275
|
+
share_origin=convert_aiotieba_share_thread(tb_thread.share_origin),
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def convert_aiotieba_post(tb_post: Post) -> PostDTO:
|
|
280
|
+
return PostDTO(
|
|
281
|
+
pid=tb_post.pid,
|
|
282
|
+
tid=tb_post.tid,
|
|
283
|
+
fid=tb_post.fid,
|
|
284
|
+
fname=tb_post.fname,
|
|
285
|
+
author_id=tb_post.author_id,
|
|
286
|
+
author=convert_aiotieba_postuser(tb_post.user),
|
|
287
|
+
contents=convert_aiotieba_content_list(tb_post.contents.objs),
|
|
288
|
+
sign=tb_post.sign,
|
|
289
|
+
comments=convert_aiotieba_commentsp(tb_post.comments),
|
|
290
|
+
is_aimeme=tb_post.is_aimeme,
|
|
291
|
+
is_thread_author=tb_post.is_thread_author,
|
|
292
|
+
agree_num=tb_post.agree,
|
|
293
|
+
disagree_num=tb_post.disagree,
|
|
294
|
+
reply_num=tb_post.reply_num,
|
|
295
|
+
create_time=datetime.fromtimestamp(tb_post.create_time, SHANGHAI_TZ),
|
|
296
|
+
floor=tb_post.floor,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def convert_aiotieba_comment(tb_comment: Comment | Comment_p) -> CommentDTO:
|
|
301
|
+
return CommentDTO(
|
|
302
|
+
cid=tb_comment.pid,
|
|
303
|
+
pid=tb_comment.ppid,
|
|
304
|
+
tid=tb_comment.tid,
|
|
305
|
+
fid=tb_comment.fid,
|
|
306
|
+
fname=tb_comment.fname,
|
|
307
|
+
author_id=tb_comment.author_id,
|
|
308
|
+
author=convert_aiotieba_commentuser(tb_comment.user),
|
|
309
|
+
contents=convert_aiotieba_content_list(tb_comment.contents.objs),
|
|
310
|
+
reply_to_id=tb_comment.reply_to_id,
|
|
311
|
+
is_thread_author=tb_comment.is_thread_author,
|
|
312
|
+
agree_num=tb_comment.agree,
|
|
313
|
+
disagree_num=tb_comment.disagree,
|
|
314
|
+
create_time=datetime.fromtimestamp(tb_comment.create_time, SHANGHAI_TZ),
|
|
315
|
+
floor=tb_comment.floor,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def convert_aiotieba_commentsp(tb_post_comments: list[Comment_p]) -> list[CommentDTO]:
|
|
320
|
+
return [convert_aiotieba_comment(tb_comment) for tb_comment in tb_post_comments]
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def convert_aiotieba_pageinfo(page: AiotiebaPageType) -> PageInfoDTO:
|
|
324
|
+
return PageInfoDTO(
|
|
325
|
+
page_size=page.page_size,
|
|
326
|
+
current_page=page.current_page,
|
|
327
|
+
total_page=page.total_page,
|
|
328
|
+
total_count=page.total_count,
|
|
329
|
+
has_more=page.has_more,
|
|
330
|
+
has_prev=page.has_prev,
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def convert_aiotieba_forum(forum: AiotiebaForumType) -> BaseForumDTO:
|
|
335
|
+
return BaseForumDTO(
|
|
336
|
+
fid=forum.fid,
|
|
337
|
+
fname=forum.fname,
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def convert_aiotieba_threads(tb_threads: Threads) -> ThreadsDTO:
|
|
342
|
+
return ThreadsDTO(
|
|
343
|
+
objs=[convert_aiotieba_thread(tb_thread) for tb_thread in tb_threads.objs],
|
|
344
|
+
page=convert_aiotieba_pageinfo(tb_threads.page),
|
|
345
|
+
forum=convert_aiotieba_forum(tb_threads.forum),
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def convert_aiotieba_posts(tb_posts: Posts) -> PostsDTO:
|
|
350
|
+
return PostsDTO(
|
|
351
|
+
objs=[convert_aiotieba_post(tb_post) for tb_post in tb_posts.objs],
|
|
352
|
+
page=convert_aiotieba_pageinfo(tb_posts.page),
|
|
353
|
+
forum=convert_aiotieba_forum(tb_posts.forum),
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def convert_aiotieba_comments(tb_comments: Comments) -> CommentsDTO:
|
|
358
|
+
return CommentsDTO(
|
|
359
|
+
objs=[convert_aiotieba_comment(tb_comment) for tb_comment in tb_comments.objs],
|
|
360
|
+
page=convert_aiotieba_pageinfo(tb_comments.page),
|
|
361
|
+
forum=convert_aiotieba_forum(tb_comments.forum),
|
|
362
|
+
)
|