diff --git a/aiotieba_reviewer/__version__.py b/aiotieba_reviewer/__version__.py index 6a9beea..3d26edf 100644 --- a/aiotieba_reviewer/__version__.py +++ b/aiotieba_reviewer/__version__.py @@ -1 +1 @@ -__version__ = "0.4.0" +__version__ = "0.4.1" diff --git a/aiotieba_reviewer/reviewer/posts/producer.py b/aiotieba_reviewer/reviewer/posts/producer.py index fa7bf4f..76f8fdd 100644 --- a/aiotieba_reviewer/reviewer/posts/producer.py +++ b/aiotieba_reviewer/reviewer/posts/producer.py @@ -24,11 +24,12 @@ async def __default_producer(thread: Thread) -> List[Post]: need_rn = last_floor - len(last_posts) if need_rn > 0: post_set = set(last_posts.objs) - if need_rn <= 30: + rn_clamp = 30 + if need_rn <= rn_clamp: first_posts = await client.get_posts(thread.tid, rn=need_rn, with_comments=True, comment_rn=10) post_set.update(first_posts.objs) else: - first_posts = await client.get_posts(thread.tid, rn=need_rn, with_comments=True, comment_rn=10) + first_posts = await client.get_posts(thread.tid, rn=rn_clamp, with_comments=True, comment_rn=10) post_set.update(first_posts.objs) hot_posts = await client.get_posts(thread.tid, sort=PostSortType.HOT, with_comments=True, comment_rn=10) post_set.update(hot_posts.objs) diff --git a/docs/tutorial/cmd_handler_dev.md b/docs/tutorial/cmd_handler_dev.md index 7f092d2..587876c 100644 --- a/docs/tutorial/cmd_handler_dev.md +++ b/docs/tutorial/cmd_handler_dev.md @@ -2,20 +2,46 @@ ## 配置文件 +在当前工作目录下新建配置文件`account.toml`,并参考下列案例填写你自己的配置 + +```toml +[my_account_0] +BDUSS = "账号0的BDUSS" + +[my_account_1] +BDUSS = "账号1的BDUSS" + +[my_account_2] +BDUSS = "账号2的BDUSS" +``` + +在当前工作目录下新建配置文件`database.toml`,并参考下列案例填写你自己的配置 + +```toml +host = "127.0.0.1" +port = 3306 +user = "" # 填用户名 +password = "" # 填密码 +db = "aiotieba" # 使用的数据库名,不填则默认为aiotieba +unix_socket = "/var/lib/mysql/mysql.sock" # 用于优化linux系统的本机连接速度,看不懂就不用填 +pool_recycle = 3600 # 填连接超时的秒数,需要与服务端保持一致,不填则默认为28800秒 +ssl_cafile = "/path/to/your/cacert.file" # 用于加密连接的CA证书的路径 +``` + 在当前工作目录下新建配置文件`cmd_handler.toml`,并参考下列案例填写你自己的配置 ```toml -listener = "listener" # 在这里填用于监听at信息的账号的BDUSS_key +listener = "my_account_1" # 在这里填用于监听at信息的账号的BDUSS_key [[Forum]] fname = "lol半价" # 在这里填贴吧名 -admin = "default" # 在这里填用于在该吧行使吧务权限的账号的BDUSS_key -speaker = "default" # 在这里填用于在该吧发送回复的账号的BDUSS_key +admin = "my_account_0" # 在这里填用于在该吧行使吧务权限的账号的BDUSS_key +speaker = "my_account_2" # 在这里填用于在该吧发送回复的账号的BDUSS_key [[Forum]] fname = "抗压背锅" # 在这里填另一个贴吧名 -admin = "default" # 在这里填用于在该吧行使吧务权限的账号的BDUSS_key -speaker = "default" # 在这里填用于在该吧发送回复的账号的BDUSS_key +admin = "my_account_1" # 在这里填用于在该吧行使吧务权限的账号的BDUSS_key +speaker = "my_account_1" # 在这里填用于在该吧发送回复的账号的BDUSS_key ``` ## 运行脚本 diff --git a/docs/tutorial/cmd_handler_user.md b/docs/tutorial/cmd_handler_user.md index 2a2c3a5..8207075 100644 --- a/docs/tutorial/cmd_handler_user.md +++ b/docs/tutorial/cmd_handler_user.md @@ -24,7 +24,7 @@ 再输入 -**指令类型**: [`drop`](#drop--drop3--drop1-删封)
+**指令类型**: [`drop`](#drop-删封)
**参数1**: `test1234` (可选的封禁理由) 并发布回复 @@ -55,7 +55,7 @@ 先`@v_guard`并确保@变蓝
再输入 -**指令类型**: [`block`](#block--block3--block1-封禁)
+**指令类型**: [`block`](#block-封禁)
**参数1**: `刚刚复制的那坨东西` (用户id: 包含[tieba_uid](https://aiotieba.cc/tutorial/start#tieba_uid)的字符串) 点击回复 @@ -76,7 +76,7 @@ 先`@v_guard`并确保@变蓝
再输入 -**指令类型**: [`drop3`](#drop--drop3--drop1-删封) +**指令类型**: [`drop3`](#drop-删封) 点击回复 @@ -124,7 +124,7 @@ @v_guard <指令类型> [参数1] [参数2] ... ``` -例如在封禁指令[`block`](#block--block3--block1-封禁) +例如在封禁指令[`block`](#block-封禁) ```text @v_guard block 李彦宏 封禁测试 @@ -267,22 +267,22 @@ --- -### block & block3 & block1 封禁 +### block 封禁 ```text @v_guard block [id] [reason] -@v_guard block3 [id] [reason] -@v_guard block1 [id] [reason] +@v_guard blockx [id] [reason] ``` ***功能*** block: *封禁*`id`对应的用户10天
-block3: *封禁*`id`对应的用户3天
-block1: *封禁*`id`对应的用户1天 +blockx: *封禁*`id`对应的用户x天,x是1~90的任意整数 ***参数说明*** +`x`: 若吧务账号无svip则仅可封禁1/3/10天,分别对应`block1` `block3` `block/block10`。若因无svip导致封禁失败则会再次尝试封禁10天 + `reason`: 可选参数,封禁理由 `id`: [`用户名`](https://aiotieba.cc/tutorial/start#user_name)或[`portrait`](https://aiotieba.cc/tutorial/start#portrait)或包含[`tieba_uid`](https://aiotieba.cc/tutorial/start#tieba_uid)的字符串或包含[`user_id`](https://aiotieba.cc/tutorial/start#user_id)的字符串,它们都可以用来唯一地确定一个贴吧用户 @@ -348,12 +348,11 @@ block1: *封禁*`id`对应的用户1天 --- -### drop & drop3 & drop1 删封 +### drop 删封 ```text @v_guard drop [reason] -@v_guard drop3 [reason] -@v_guard drop1 [reason] +@v_guard dropx [reason] ``` ***功能*** @@ -362,12 +361,13 @@ block1: *封禁*`id`对应的用户1天 如果这条指令是一条`楼中楼`,那么指令所在回复会被*删除*,并且层主会被*封禁*
如果这条指令是一条`转发了另一主题帖的主题帖`,那么被转发的主题帖会被*删除*,并且该主题帖的楼主会被*封禁*
drop: 对应10天封禁
-drop3: 对应3天封禁
-drop1: 对应1天封禁
+dropx: 对应x天封禁
在使用该指令时请**特别注意指令的发送位置**,以免产生意料之外的效果 ***参数说明*** +`x`: 若吧务账号无svip则仅可封禁1/3/10天,分别对应`drop1` `drop3` `drop/drop10`。若因无svip导致封禁失败则会再次尝试封禁10天 + `reason`: 可选参数,封禁理由 ***能使用该指令的最低权限级别*** @@ -376,7 +376,7 @@ drop1: 对应1天封禁
***开发者说*** -[`block`](#block--block3--block1-封禁)和[`delete`](#delete-删帖)的组合,用于提升删封操作效率 +[`block`](#block-封禁)和[`delete`](#delete-删帖)的组合,用于提升删封操作效率 --- @@ -627,9 +627,9 @@ drop1: 对应1天封禁
***功能*** -如果这条指令是一条`回复`,那么指令所在主题帖会被*删除*,楼主的权限级别会被设为`-5`并*封禁*10天
-如果这条指令是一条`楼中楼`,那么指令所在回复会被*删除*,层主的权限级别会被设为`-5`并*封禁*10天
-如果这条指令是一条`转发了另一主题帖的主题帖`,那么被转发的主题帖会被*删除*,该主题帖的楼主的权限级别会被设为`-5`并*封禁*10天
+如果这条指令是一条`回复`,那么指令所在主题帖会被*删除*,楼主的权限级别会被设为`-5`并*封禁*90天
+如果这条指令是一条`楼中楼`,那么指令所在回复会被*删除*,层主的权限级别会被设为`-5`并*封禁*90天
+如果这条指令是一条`转发了另一主题帖的主题帖`,那么被转发的主题帖会被*删除*,该主题帖的楼主的权限级别会被设为`-5`并*封禁*90天
在使用该指令时请**特别注意指令的发送位置**,以免产生意料之外的效果
修改权限时,操作者的权限级别必须大于被操作者的权限级别。若操作者权限不足则修改权限的请求被拒绝而其余请求正常执行 @@ -643,7 +643,7 @@ drop1: 对应1天封禁
***开发者说*** -指令[`block`](#block--block3--block1-封禁) [`delete`](#delete-删帖) [`black`](#black-黑名单)的组合,用于提升删封循操作效率 +指令[`block`](#block-封禁) [`delete`](#delete-删帖) [`black`](#black-黑名单)的组合,用于提升删封循操作效率 --- diff --git a/docs/tutorial/config.md b/docs/tutorial/config.md deleted file mode 100644 index 7c48c6a..0000000 --- a/docs/tutorial/config.md +++ /dev/null @@ -1,31 +0,0 @@ -# 配置文件参考 - -## 完整案例 - -```toml -# aiotieba.toml -[User] - -# default是自定义的BDUSS_key,你可以改成你喜欢的标识 -# 该设计是为了方便通过BDUSS_key快速调用BDUSS,这样你就不用每次都填一串很长的东西作为参数 -[User.default] -# 把你的那一串长长的BDUSS放在这 -BDUSS = "W5RNUVKai2LdUd5TTVHblhFeXoxdGyOVURGUE1OYzNqVXVRaWF-HnpGckRCNFJnRVFBQUFBJCQAAAAAAAAAAAEAAADiglQb0f3Osqmv0rbJ2QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMN6XGDDelxgc" -# 可以不填,一些网页端接口会需要STOKEN -STOKEN = "b77bf99815618155cb661f8b78b06f4d91fd44fd83d8881b0fc279916e67cedb" - -# 如果要另新增一个BDUSS_key为other的用户,参考如下配置 -[User.other] -BDUSS = "" -STOKEN = "" - -[Database] -host = "127.0.0.1" -port = 3306 -user = "" # 填用户名 -password = "" # 填密码 -db = "aiotieba" # 使用的数据库名,不填则默认为aiotieba -unix_socket = "/var/lib/mysql/mysql.sock" # 用于优化linux系统的本机连接速度,看不懂就不用填 -pool_recycle = 3600 # 填连接超时的秒数,需要与服务端保持一致,不填则默认为28800秒 -ssl_cafile = "/path/to/your/cacert.file" # 用于加密连接的CA证书的路径 -``` diff --git a/docs/tutorial/reviewer.md b/docs/tutorial/reviewer.md index 69d5a79..ae1a16c 100644 --- a/docs/tutorial/reviewer.md +++ b/docs/tutorial/reviewer.md @@ -33,7 +33,7 @@ ## 使用方法 1. 首先,你需要一个`MySQL`数据库,用来缓存通过检测的内容id以及记录用户权限级别(黑、白名单) -1. 参考[**该教程**](config.md),填写`Database`字段,以便aiotieba使用你的`MySQL`数据库。aiotieba将会在你第一次调用特定方法时自动创建数据库表,因此你无须手动建表 +1. 参考[**该教程**](cmd_handler_dev.md),填写`database.toml`字段,以便aiotieba-reviewer使用你的`MySQL`数据库。在你第一次调用特定方法时会自动创建数据库表,因此你无须手动建表 1. 自定义审查行为:请参照我给出的例子自己编程修改[reviewer_example.py](https://github.com/Starry-OvO/aiotieba-reviewer/blob/develop/examples/reviewer_example.py) 1. 运行`your_reviewer.py` diff --git a/examples/cmd_handler.py b/examples/cmd_handler.py index ad4b742..b0c82cc 100644 --- a/examples/cmd_handler.py +++ b/examples/cmd_handler.py @@ -6,14 +6,12 @@ from typing import Protocol, Tuple, Union import aiotieba as tb -import async_timeout +import aiotieba_reviewer as tbr from aiotieba.api.get_ats import At from aiotieba.api.get_comments._classdef import Contents_cp from aiotieba.api.get_posts._classdef import Contents_p, Contents_pt -from aiotieba.config import tomllib from aiotieba.logging import get_logger as LOG - -import aiotieba_reviewer as tbr +from aiotieba_reviewer.config import tomllib tb.logging.enable_filelog() @@ -59,28 +57,22 @@ def allow_execute(self) -> bool: class TypeParent(Protocol): @property - def fid(self) -> int: - ... + def fid(self) -> int: ... @property - def fname(self) -> str: - ... + def fname(self) -> str: ... @property - def tid(self) -> int: - ... + def tid(self) -> int: ... @property - def pid(self) -> int: - ... + def pid(self) -> int: ... @property - def author_id(self) -> int: - ... + def author_id(self) -> int: ... @property - def contents(self) -> Union[Contents_pt, Contents_p, Contents_cp]: - ... + def contents(self) -> Union[Contents_pt, Contents_p, Contents_cp]: ... class Context(object): @@ -244,7 +236,7 @@ class Listener(object): ] def __init__(self) -> None: - self.listener = tb.Client(LISTEN_CONFIG['listener']) + self.listener = tb.Client(account=tbr.get_account(LISTEN_CONFIG['listener'])) self.admins = {} self.time_recorder = TimerRecorder(3600 * 12, 10) @@ -278,11 +270,11 @@ async def get_admin(self, fname: str) -> Tuple[tb.Client, tbr.MySQLDB, tb.Client if cfg is None: raise ValueError(f"找不到管理员. fname={fname}") - admin = tb.Client(cfg['admin']) + admin = tb.Client(account=tbr.get_account(cfg['admin'])) await admin.__aenter__() admin_db = tbr.MySQLDB(fname) await admin_db.__aenter__() - speaker = tb.Client(cfg['speaker']) + speaker = tb.Client(account=tbr.get_account(cfg['speaker'])) await speaker.__aenter__() tup = admin, admin_db, speaker @@ -300,8 +292,14 @@ async def __fetch_and_execute_cmds(self) -> None: await asyncio.gather(*[self._execute_cmd(at) for at in ats]) async def _execute_cmd(self, at: At) -> None: - async with async_timeout.timeout(120.0): + async with asyncio.timeout(120.0): ctx = Context(at) + if ctx.cmd_type.startswith('block'): + await self.cmd_block(ctx) + return + if ctx.cmd_type.startswith('drop'): + await self.cmd_drop(ctx) + return cmd_func = getattr(self, f'cmd_{ctx.cmd_type}', self.cmd_default) await cmd_func(ctx) @@ -406,39 +404,18 @@ async def cmd_unhide(self, ctx: Context) -> None: @check_and_log(need_permission=2, need_arg_num=1) async def cmd_block(self, ctx: Context) -> None: """ - block指令 - 通过id封禁对应用户10天 - """ - - await self.__cmd_block(ctx, 10) - - @check_and_log(need_permission=2, need_arg_num=1) - async def cmd_block3(self, ctx: Context) -> None: - """ - block3指令 - 通过id封禁对应用户3天 - """ - - await self.__cmd_block(ctx, 3) - - @check_and_log(need_permission=2, need_arg_num=1) - async def cmd_block1(self, ctx: Context) -> None: - """ - block1指令 - 通过id封禁对应用户1天 - """ - - await self.__cmd_block(ctx, 1) - - async def __cmd_block(self, ctx: Context, day: int) -> None: - """ - 封禁用户 + blockx指令 + 通过id封禁对应用户x天 """ + day = int(d) if (d := ctx.cmd_type.removeprefix('block')) else 10 user = await self.__arg2user_info(ctx.args[0]) note = ctx.args[1] if len(ctx.args) > 1 else ctx.note - if await ctx.admin.block(ctx.fname, user.portrait, day=day, reason=note): + success = await ctx.admin.block(ctx.fname, user.portrait, day=day, reason=note) + if isinstance(success.err, tb.exception.TiebaServerError) and success.err.code == 3150003: + success = await ctx.admin.block(ctx.fname, user.portrait, day=10, reason=note) + if success: await ctx.admin.del_post(ctx.fname, ctx.tid, ctx.pid) @check_and_log(need_permission=2, need_arg_num=1) @@ -453,33 +430,6 @@ async def cmd_unblock(self, ctx: Context) -> None: if await ctx.admin.unblock(ctx.fname, user.user_id): await ctx.admin.del_post(ctx.fname, ctx.tid, ctx.pid) - @check_and_log(need_permission=2, need_arg_num=0) - async def cmd_drop(self, ctx: Context) -> None: - """ - drop指令 - 删帖并封10天 - """ - - await self.__cmd_drop(ctx, 10) - - @check_and_log(need_permission=2, need_arg_num=0) - async def cmd_drop3(self, ctx: Context) -> None: - """ - drop3指令 - 删帖并封3天 - """ - - await self.__cmd_drop(ctx, 3) - - @check_and_log(need_permission=2, need_arg_num=0) - async def cmd_drop1(self, ctx: Context) -> None: - """ - drop1指令 - 删帖并封1天 - """ - - await self.__cmd_drop(ctx, 1) - async def __cmd_drop(self, ctx: Context, day: int = 0) -> None: """ 封禁用户并删除父级 @@ -500,7 +450,19 @@ async def __cmd_drop(self, ctx: Context, day: int = 0) -> None: await ctx.admin.del_post(ctx.parent.fid, ctx.parent.tid, ctx.parent.pid) await ctx.admin.del_post(ctx.fname, ctx.tid, ctx.pid) if day: - await ctx.admin.block(ctx.parent.fid, ctx.parent.author_id, day=day, reason=note) + ret = await ctx.admin.block(ctx.parent.fid, ctx.parent.author_id, day=day, reason=note) + if isinstance(ret.err, tb.exception.TiebaServerError) and ret.err.code == 3150003: + await ctx.admin.block(ctx.parent.fid, ctx.parent.author_id, day=10, reason=note) + + @check_and_log(need_permission=2, need_arg_num=0) + async def cmd_drop(self, ctx: Context) -> None: + """ + dropx指令 + 删帖并封x天 + """ + + day = int(d) if (d := ctx.cmd_type.removeprefix('drop')) else 10 + await self.__cmd_drop(ctx, day) @check_and_log(need_permission=1, need_arg_num=0) async def cmd_recommend(self, ctx: Context) -> None: @@ -613,10 +575,10 @@ async def cmd_reset(self, ctx: Context) -> None: async def cmd_exdrop(self, ctx: Context) -> None: """ exdrop指令 - 删帖并将发帖人加入脚本黑名单+封禁十天 + 删帖并将发帖人加入脚本黑名单+封禁90天 """ - await self.__cmd_drop(ctx, 10) + await self.__cmd_drop(ctx, 90) note = ctx.args[0] if len(ctx.args) > 0 else ctx.note @@ -629,7 +591,7 @@ async def cmd_avada_kedavra(self, ctx: Context) -> None: 删帖 清空发帖人主页显示的在当前吧的所有主题帖 加入脚本黑名单+封禁十天 """ - await self.__cmd_drop(ctx, 10) + await self.__cmd_drop(ctx, 90) note = ctx.args[0] if len(ctx.args) > 0 else ctx.note user_id = ctx.parent.author_id @@ -699,9 +661,9 @@ async def cmd_img_set(self, ctx: Context) -> None: for img in imgs: image = await self.listener.get_image(img.src) - if image is None: + if image.err: continue - img_hash = tbr.imgproc.compute_imghash(image) + img_hash = tbr.imgproc.compute_imghash(image.img) if img_hash == 4412820541203793671: continue @@ -725,9 +687,9 @@ async def cmd_img_reset(self, ctx: Context) -> None: for img in imgs: image = await self.listener.get_image(img.src) - if image is None: + if image.err: continue - img_hash = tbr.imgproc.compute_imghash(image) + img_hash = tbr.imgproc.compute_imghash(image.img) await ctx.admin_db.del_imghash(img_hash) diff --git a/mkdocs.yml b/mkdocs.yml index fc46cf2..22fbdac 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -26,7 +26,6 @@ nav: - 介绍: index.md - 教程: - 云审查教程: tutorial/reviewer.md - - 配置文件参考: tutorial/config.md - 指令管理器使用教程: tutorial/cmd_handler_user.md - 指令管理器配置教程: tutorial/cmd_handler_dev.md diff --git a/pyproject.toml b/pyproject.toml index d54fc0d..c5d69c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ classifiers = [ ] requires-python = ">=3.8,<3.13" dependencies = [ - "aiotieba[img,speedup]<5.0,>=4.0.0", + "aiotieba[speedup,img]<5.0,>=4.0.2", "aiomysql[rsa]<0.3,>=0.1.0", "tomli<3,>=1.1.0;python_version<'3.11'", ]