From d6a27c206b77c86d9361cd03ac345cb88595eff2 Mon Sep 17 00:00:00 2001 From: gfhdhytghd <3391146750@qq.com> Date: Wed, 31 Jul 2024 15:37:03 +0800 Subject: [PATCH] v 0.0.2 OHHHHH First Virsion able to use in Production! --- README.md | 18 ++- SendQzone/qzonegettag.py | 21 ---- SendQzone/send.py | 26 +++- getmsgserv/HTMLwork/gotojpg.sh | 13 +- getmsgserv/LM_work/sendtoLM.py | 2 +- getmsgserv/LM_work/test.py | 16 --- getmsgserv/serv.py | 17 ++- main.sh | 220 +++++++++++++++++++++------------ 8 files changed, 198 insertions(+), 135 deletions(-) delete mode 100644 getmsgserv/LM_work/test.py diff --git a/README.md b/README.md index 88dfe63..f3a60cd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # OQQWall # 开放QQ校园墙自动运营系统 -### 当前版本的架构很快就不会再维护了,我们正在尝试切换到nonebot架构 ## 简介 本系统是一个校园墙自动运营系统,可以实现如下功能:
获取用户投稿消息,通过大语言模型实现自动分段,自动判断匿名与否 @@ -12,11 +11,8 @@ #### 目前系统处于非常早期的版本,完全不保证可用性。 已知问题如下: -
群消息会导致发稿流程激活
错误的群审核指令会导致上一条指令被执行 -
qq空间两天就会退出登录
拉格朗日机器人偶尔会抽风 -
“否”指令有一些问题
使用qwen大语言模型的情况下,处理不了太长的帖子 # 使用方法 @@ -40,7 +36,7 @@ 打开./SendQzone/qzonegettag
翻到60行 -
填写主账号到driendlist,辅助账号到my_qq +
填写主账号到friendlist,辅助账号到my_qq
打开main.sh,填写管理群群号到group_id
打开getmsgserv/serv.py
找到第49行的if,填写管理群号到 == 和 and中间,群号两边记得留空格。 @@ -52,15 +48,16 @@ 注:确保你的api余额够用。 -注:目前使用的模型是qwen2-72b-instruct,效果还行,有能力的可以自己换更牛逼的模型。 +注:目前使用的模型是qwen2-72b-instruct,效果还行,有能力的可以自己换更牛逼的模型,或者自己测试一下哪个模型好用。 手动登陆主账号qq空间,发送一条说说,文案需要由#0开头,这是为了初始化编号系统
如果此帐号之前就是使用 #数字 方式进行编号,不需要进行这一步 启动主程序
打开QQ,登陆辅助账号 -
./main.sh +
终端输入./main.sh
然后,理论上,应该就可以用了。 +
注意ctrl+c关闭程序时,Lagrange.Onebot和serv.py不会一并关闭,需要手动终止进程 ### 审核群使用方法:
墙会在有新消息时将渲染好的消息图片带着编号一起发到群中来 @@ -75,13 +72,12 @@
指令有以下几种:
是:发送
否:机器跳过此条,人工去处理 -
当前版本不建议使用此指令,有bug,建议用“删”替代 +
当前版本等效于删
等:等待180秒,然后重新执行分段-渲染-审核流程,常用于稿件没发完的情况
删:从系统中删掉这个人的消息记录,常用于用户来找你聊天或者删帖等需要手动处理的情况
比如 - -
@校园墙 348 是 +@校园墙 348 是
将348号帖子发送出去
@校园墙 348 否 -
不删除任何东西,跳过此条 +
从系统中删掉这个人的消息记录,人工前往处理 diff --git a/SendQzone/qzonegettag.py b/SendQzone/qzonegettag.py index ad8efd3..58c8f87 100644 --- a/SendQzone/qzonegettag.py +++ b/SendQzone/qzonegettag.py @@ -13,7 +13,6 @@ def login(my_qq): browser.get('https://i.qq.com/') time.sleep(2) browser.switch_to.frame("login_frame") - time.sleep(2) try: find = browser.find_element(By.ID, f'img_out_{my_qq}') @@ -36,7 +35,6 @@ def find_number(text): # Get the text from the website and analyze it def get(html): print('Trying to get shuoshuos') - time.sleep(2) soup = BeautifulSoup(html, "html.parser") shuoshuos = soup.find_all(name="li", attrs={"class": "feed"}) print(f'There are {len(shuoshuos)} messages.') @@ -62,8 +60,6 @@ def main(): # Get to the friend's QQ Zone friendlist = [''] print('Trying to get into the QQ Zone') - time.sleep(2) - driver.get(f'https://user.qzone.qq.com/{friendlist[0]}/311') print('Get in!') @@ -71,26 +67,9 @@ def main(): while True: # Move to the QQ Zone frame iframe = driver.find_element(By.ID, 'app_canvas_frame') - time.sleep(2) wait_element = WebDriverWait(driver, 20) wait_element.until(EC.frame_to_be_available_and_switch_to_it(iframe)) - # Find the unfold buttons and click them - while True: - try: - print('Trying to find unfold button') - buttons = driver.find_elements(By.XPATH, '//a[contains(@class, "has_more_con") and contains(text(), "展开查看全文")]') - for button in buttons: - print(button) - time.sleep(5) - driver.execute_script('arguments[0].scrollIntoView(false);', button) - time.sleep(2) - button.click() - break - except Exception as error: - print(f'\033[0;31mUnfold error! {error} \033[0m') - continue - # Get the HTML source code time.sleep(2) html = driver.page_source diff --git a/SendQzone/send.py b/SendQzone/send.py index 3901ecd..14265f2 100644 --- a/SendQzone/send.py +++ b/SendQzone/send.py @@ -283,12 +283,15 @@ async def publish_emotion(self, content: str, images: list[bytes] = []) -> str: async def main(): - if len(sys.argv) != 3: + if len(sys.argv) > 3: print("Usage: python3 test.py ") return message = sys.argv[1] - image_directory = sys.argv[2] + try: + image_directory = sys.argv[2] + except: + image_directory='./getmsgserv/post-step5' try: with open('./cookies.json', 'r') as f: @@ -296,6 +299,25 @@ async def main(): except: cookies = None + if message == 'relogin': + login = QzoneLogin() + + async def qrcode_callback(qrcode: bytes): + with open("qrcode.png", "wb") as f: + f.write(qrcode) + + try: + cookies = await login.login_via_qrcode(qrcode_callback) + print("Cookies after login:", cookies) + with open('cookies.json', 'w') as f: + json.dump(cookies, f) + os.remove('./qrcode.png') + except Exception as e: + print("Failed to generate login QR code.") + traceback.print_exc() + return + sys.exit() + if not cookies: login = QzoneLogin() diff --git a/getmsgserv/HTMLwork/gotojpg.sh b/getmsgserv/HTMLwork/gotojpg.sh index ca8c1a6..574e4e7 100755 --- a/getmsgserv/HTMLwork/gotojpg.sh +++ b/getmsgserv/HTMLwork/gotojpg.sh @@ -1,5 +1,14 @@ #!/bin/bash input="$1" -mkdir ./getmsgserv/post-step5/${input} -rm ./getmsgserv/post-step5/${input}/* +folder=./getmsgserv/post-step5/${input} +jsonfile=./getmsgserv/post-step2/${input}.json +mkdir -p "$folder" magick convert -density 320 -quality 95 ./getmsgserv/post-step4/${input}.pdf ./getmsgserv/post-step5/${input}/${input}.jpeg +existing_files=$(ls "$folder" | wc -l) +next_file_index=$existing_files +jq -r '.messages[].message[] | select(.type=="image") | .data.url' "$jsonfile" | while read -r url; do + # 下载文件并命名 + curl -o "$folder/$input-$next_file_index" "$url" + # 增加文件索引 + next_file_index=$((next_file_index + 1)) +done \ No newline at end of file diff --git a/getmsgserv/LM_work/sendtoLM.py b/getmsgserv/LM_work/sendtoLM.py index dfd2dce..ea9c493 100644 --- a/getmsgserv/LM_work/sendtoLM.py +++ b/getmsgserv/LM_work/sendtoLM.py @@ -47,7 +47,7 @@ " # 判断他有没有说完,通常通过用语义来判断,检查记录中是否有“没发完”“发完了”一类的语句,判断已经发来的内容是否构成一个完整的稿件,也可以通过time判断,在最后一条消息的time距离timenow很久远的情况下可以判断为完整稿件,只有在非常肯定他发完了的情况下才为true\n" " \"notregular\": \"true/false\",\n" " # 判断这条信息是否需要非常规,规则如下" - " #任何一个\"message\" [\"type\"的值 非 \"text\"/\"image\"/\"video\"的需要人工介入,比如含有record,poke等的即为非常规" + " #任何一个\"message\" [\"type\"的值,\"text\"/\"image\"的为常规,其他的,比如含有video,record,poke等的即为非常规" " #内容中要求对之前发送的稿件进行修改或撤回等操作的为非常规" " \"messages\": [\n" " # 接下来输出分好组的message信息\n" diff --git a/getmsgserv/LM_work/test.py b/getmsgserv/LM_work/test.py deleted file mode 100644 index 6c9ff1c..0000000 --- a/getmsgserv/LM_work/test.py +++ /dev/null @@ -1,16 +0,0 @@ -import sys - -def main(): - if len(sys.argv) != 3: - print("Usage: python3 test.py ") - sys.exit(1) - - input_value = sys.argv[1] - output_value = sys.argv[2] - - print(f"Input: {input_value}") - print(f"Output: {output_value}") - -if __name__ == "__main__": - main() - diff --git a/getmsgserv/serv.py b/getmsgserv/serv.py index c313455..4667f33 100755 --- a/getmsgserv/serv.py +++ b/getmsgserv/serv.py @@ -45,10 +45,10 @@ def do_POST(self): sender = data.get('sender', {}) raw_message = data.get('raw_message', '') - if (group_id == and sender.get('role') == 'admin' and - raw_message.startswith('[CQ:at,qq=xxx]')): + if (group_id == 814783587 and sender.get('role') == 'admin' and + raw_message.startswith('[CQ:at,qq=1050373508]')): # Extract and save the relevant part of raw_message - command_text = raw_message[len('[CQ:at,qq=xxx] '):] + command_text = raw_message[len('[CQ:at,qq=1050373508] '):] command_file_path = os.path.join(COMMAND_DIR, 'commands.txt') with open(command_file_path, 'a', encoding='utf-8') as f: @@ -95,6 +95,17 @@ def do_POST(self): with open(file_path, 'w', encoding='utf-8') as f: json.dump(sorted_data, f, ensure_ascii=False, indent=4) + priv_post_path = os.path.join(ALLPOST_DIR, 'priv_post.json') + if os.path.exists(priv_post_path): + with open(priv_post_path, 'r', encoding='utf-8') as f: + priv_post_data = json.load(f) + else: + priv_post_data = [] + + priv_post_data.append(data) + with open(priv_post_path, 'w', encoding='utf-8') as f: + json.dump(priv_post_data, f, ensure_ascii=False, indent=4) + # 返回响应 self.send_response(200) self.end_headers() diff --git a/main.sh b/main.sh index 9bc17bd..b65b117 100755 --- a/main.sh +++ b/main.sh @@ -1,50 +1,72 @@ #!/bin/bash + +groupid= + +# Activate virtual environment source ./venv/bin/activate -python3 ./getmsgserv/serv.py & -nohup ./qqBot/Lagrange.OneBot & -echo onebot-start + +# Check if the serv.py process is running +if pgrep -f "python3 ./getmsgserv/serv.py" > /dev/null +then + echo "serv.py is already running" +else + python3 ./getmsgserv/serv.py & + echo "serv.py started" +fi + +# Check if the Lagrange.OneBot process is running +if pgrep -f "./qqBot/Lagrange.OneBot" > /dev/null +then + echo "Lagrange.OneBot is already running" +else + nohup ./qqBot/Lagrange.OneBot & + echo "Lagrange.OneBot started" +fi + sleep 10 -file_to_watch="./getmsgserv/all/all_posts.json" +#避免消息反复处理 +file_to_watch="./getmsgserv/all/priv_post.json" command_file="./qqBot/command/commands.txt" -group_id= + sendimagetoqqgroup() { -# 设置文件夹路径 -folder_path="$(pwd)/getmsgserv/post-step5/$numnext" + # 设置文件夹路径 + folder_path="$(pwd)/getmsgserv/post-step5/$numnext" -# 检查文件夹是否存在 -if [ ! -d "$folder_path" ]; then - echo "文件夹 $folder_path 不存在" - exit 1 -fi + # 检查文件夹是否存在 + if [ ! -d "$folder_path" ]; then + echo "文件夹 $folder_path 不存在" + exit 1 + fi -find "$folder_path" -maxdepth 1 -type f | sort | while IFS= read -r file_path; do - echo "发送文件: $file_path" - command="google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$group_id&message=[CQ:image,file=$file_path]'" - eval $command - sleep 1 # 添加延时以避免过于频繁的请求 -done -echo "所有文件已发送" + find "$folder_path" -maxdepth 1 -type f | sort | while IFS= read -r file_path; do + echo "发送文件: $file_path" + command="google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$groupid&message=[CQ:image,file=$file_path]'" + eval $command + sleep 1 # 添加延时以避免过于频繁的请求 + done + echo "所有文件已发送" } -sendqbotloginqrtogroup() { - command="google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$group_id&message=[CQ:image,file=$(pwd)/qrcode.png]'" - eval $command -} + askforintro(){ - command="google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$group_id&message=$numnext 是否继续发送?'" + command="google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$groupid&message=$numnext 请发送指令'" eval $command + # 初始化文件的上次修改时间 last_mod_time_cmd=$(stat -c %Y "$command_file") + while true; do sleep 5 # 获取文件的当前修改时间 current_mod_time_cmd=$(stat -c %Y "$command_file") - + # 检查文件是否已被修改 if [ "$current_mod_time_cmd" -ne "$last_mod_time_cmd" ]; then + echo 检测到指令 break - fi + fi done + mapfile -t lines < "$command_file" for (( i=${#lines[@]}-1; i>=0; i-- )); do line=${lines[$i]} @@ -57,15 +79,36 @@ askforintro(){ case $status in 是) postcmd="true" + postqzone ;; 否) postcmd="false" + rm ./getmsgserv/rawpost/$id.json + rm -rf ./getmsgserv/post-step5/350 ;; 等) postcmd="wait" + sleep 180 ;; 删) postcmd="del" + rm ./getmsgserv/rawpost/$id.json + rm -rf ./getmsgserv/post-step5/350 + ;; + esac + # 找到符合条件的行后退出循环 + break + fi + if [[ $number -eq relogin ]]; then + case $status in + 是) + postcmd="true" + renewqzonelogin + ;; + 否) + postcmd="false" + echo retry... + sendmsggroup 重新尝试发送中... ;; esac # 找到符合条件的行后退出循环 @@ -74,78 +117,97 @@ askforintro(){ done } postqzone(){ + if [ ! -f "./cookies.json" ]; then + echo "Cookies file does not exist. Executing relogin script." + python3 SendQzone/send.py relogin & + sleep 2 + sendmsggroup 请立即扫描二维码 + command="google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$groupid&message=[CQ:image,file=$(pwd)/qrcode.png]'" + eval $command + sleep 60 + else + echo "Cookies file exists. No action needed." + fi + postcommand="python3 ./SendQzone/send.py '#$numnext' ./getmsgserv/post-step5/$numnext/" - eval $postcommand + output=$(eval $postcommand) + if echo "$output" | grep -q "Failed to publish."; then + sendmsggroup 空间发送错误,可能需要重新登陆,错误: + sendmsggroup 发送 '@本账号 relogin 是' 以重新登陆 + askforintro rm ./getmsgserv/rawpost/$id.json + fi +} +renewqzonelogin(){ + rm ./cookies.json + rm ./qrcode.png + postqzone & + sleep 2 + command="google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$groupid&message=[CQ:image,file=$(pwd)/qrcode.png]'" + eval $command + sleep 60 +} +sendmsggroup(){ +google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=$groupid&message='$1'' } -while true; do - -# 获取文件的初始修改时间 last_mod_time=$(stat -c %Y "$file_to_watch") +while true; do + while true; do sleep 5 # 获取文件的当前修改时间 current_mod_time=$(stat -c %Y "$file_to_watch") - + # 检查文件是否已被修改 if [ "$current_mod_time" -ne "$last_mod_time" ]; then echo "有新消息" break fi done -#主逻辑代码 -python3 ./SendQzone/qzonegettag.py -numnow=$( cat ./numb.txt ) -numnext=$[ numnow + 1 ] -sleep 300 -id=$(find ./getmsgserv/rawpost -type f -printf '%T+ %p\n' | sort | head -n 1 | awk '{print $2}') -id=$(basename "$id" .json) -id=$(echo "$id" | sed 's/.*\///') -echo 'wait-for-LM...' -python3 ./getmsgserv/LM_work/sendtoLM.py ${id} ${numnext} - -json_file=./getmsgserv/post-step2/${numnext}.json -isover=$(jq -r '.isover' "$json_file") -notregular=$(jq -r '.notregular' "$json_file") - -if [ "$isover" = "true" ] && [ "$notregular" = "false" ]; then + + #主逻辑代码 + python3 ./SendQzone/qzonegettag.py + numnow=$( cat ./numb.txt ) + numnext=$[ numnow + 1 ] + sleep 120 + id=$(find ./getmsgserv/rawpost -type f -printf '%T+ %p\n' | sort | head -n 1 | awk '{print $2}') + id=$(basename "$id" .json) + id=$(echo "$id" | sed 's/.*\///') + echo $id + echo 'wait-for-LM...' + python3 ./getmsgserv/LM_work/sendtoLM.py ${id} ${numnext} + + json_file=./getmsgserv/post-step2/${numnext}.json + isover=$(jq -r '.isover' "$json_file") + notregular=$(jq -r '.notregular' "$json_file") + safemsg=$(jq -r '.safemsg' "$json_file") + python3 ./getmsgserv/HTMLwork/gotohtml.py "$numnext" ./getmsgserv/HTMLwork/gotopdf.sh "$numnext" ./getmsgserv/HTMLwork/gotojpg.sh "$numnext" - echo sendtogroup... - google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=814783587&message=有常规消息' - echo sendimagetogroup... - sendimagetoqqgroup - echo askforgroup... - askforintro - if [ "$postcmd" = "true" ]; then - postqzone - elif [ "$postcmd" = "false" ]; then - echo jump - elif [ "$postcmd" = "wait" ]; then - sleep 180 - elif [ "$postcmd" = "del" ];then - rm ./getmsgserv/rawpost/$id.json + + if [ "$isover" = "true" ] && [ "$notregular" = "false" ]; then + sendmsggroup 有常规消息 + elif [ "$isover" = "true" ] && [ "$notregular" = "true" ]; then + sendmsggroup 有非常规消息 + elif [ "$isover" = "false" ] && [ "$notregular" = "true" ]; then + sendmsggroup 有常规但疑似未写完帖子 + elif [ "$isover" = "false" ] && [ "$notregular" = "false" ]; then + sendmsggroup 有非常规且疑似未写完帖子 + else + sendmsggroup 有需要审核的消息 fi -else - echo "Conditions not met: isover=$isover, notregular=$notregular" - python3 ./getmsgserv/HTMLwork/gotohtml.py "$numnext" - ./getmsgserv/HTMLwork/gotopdf.sh "$numnext" - ./getmsgserv/HTMLwork/gotojpg.sh "$numnext" - google-chrome-stable --headless --screenshot 'http://127.0.0.1:8083/send_group_msg?group_id=814783587&message=有需要审核的消息' + + if [ "$safemsg" = "true" ]; then + sendmsggroup AI审核判定安全 + elif [ "$safemsg" = "false" ]; then + sendmsggroup AI审核判定不安全 + fi + sendimagetoqqgroup + echo askforgroup... askforintro - if [ "$postcmd" = "true" ]; then - postqzone - elif [ "$postcmd" = "false" ]; then - echo jump - elif [ "$postcmd" = "wait" ]; then - sleep 180 - elif [ "$postcmd" = "del" ];then - rm ./getmsgserv/rawpost/$id.json - fi -fi -done - \ No newline at end of file + last_mod_time=$(stat -c %Y "$file_to_watch") +done \ No newline at end of file