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'",
]