提交 0e712744 authored 作者: 张孟夏's avatar 张孟夏

修改1.1不兼容的用例,调整grpc客户端代码

上级 d48f651e
...@@ -13,7 +13,7 @@ ${path} /api/system/config/client ...@@ -13,7 +13,7 @@ ${path} /api/system/config/client
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Should Be Equal As Strings ${content["data"]} {\"grpc_host\":\"192.168.110.211:9090\",\"grpc_use_ssl\":false} Should Contain ${content["data"]} \"grpc_host\":\"192.168.110.211:9090\",\"grpc_use_ssl\":false
反例-不传入token 反例-不传入token
[Tags] E [Tags] E
...@@ -22,7 +22,7 @@ ${path} /api/system/config/client ...@@ -22,7 +22,7 @@ ${path} /api/system/config/client
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Should Be Equal As Strings ${content["data"]} {\"grpc_host\":\"192.168.110.211:9090\",\"grpc_use_ssl\":false} Should Contain ${content["data"]} \"grpc_host\":\"192.168.110.211:9090\",\"grpc_use_ssl\":false
反例-传入错误的token 反例-传入错误的token
[Tags] E [Tags] E
...@@ -31,4 +31,4 @@ ${path} /api/system/config/client ...@@ -31,4 +31,4 @@ ${path} /api/system/config/client
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Should Be Equal As Strings ${content["data"]} {\"grpc_host\":\"192.168.110.211:9090\",\"grpc_use_ssl\":false} Should Contain ${content["data"]} \"grpc_host\":\"192.168.110.211:9090\",\"grpc_use_ssl\":false
...@@ -4,6 +4,7 @@ Resource res_zmx.resource ...@@ -4,6 +4,7 @@ Resource res_zmx.resource
*** Variables *** *** Variables ***
${path} /api/chat/write ${path} /api/chat/write
${uploadpath} /api/file-ref/upload
${jpg_file} testpicture.jpg ${jpg_file} testpicture.jpg
${gif_file} testpicture.gif ${gif_file} testpicture.gif
${jpeg_file} testpicture.jpeg ${jpeg_file} testpicture.jpeg
...@@ -16,12 +17,13 @@ ${md_file} testfile.md ...@@ -16,12 +17,13 @@ ${md_file} testfile.md
${txt_file} testfile.txt ${txt_file} testfile.txt
${xls_file} testfile.xls ${xls_file} testfile.xls
${xlsx_file} testfile.xlsx ${xlsx_file} testfile.xlsx
${clientId} a68ad587830d41aebf418a919006353e
*** Test Cases *** *** Test Cases ***
正例-正常发送文字消息 正例-正常发送文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好"} 200 ${token} ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}"} 200 ${token}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -33,23 +35,18 @@ ${xlsx_file} testfile.xlsx ...@@ -33,23 +35,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${jpg_file}', open(r'${CURDIR}${/}testfiles${/}${jpg_file}', 'rb')) ${file} Evaluate (r'${jpg_file}', open(r'${CURDIR}${/}testfiles${/}${jpg_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${jpg_streamId} ${content["data"]} Set Global Variable ${jpg_streamId} ${content["data"]["id"]}
正例-正常发送jpg+文字消息 正例-正常发送jpg+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${jpg_file}', open(r'${CURDIR}${/}testfiles${/}${jpg_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${jpg_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这张图是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -61,23 +58,18 @@ ${xlsx_file} testfile.xlsx ...@@ -61,23 +58,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${gif_file}', open(r'${CURDIR}${/}testfiles${/}${gif_file}', 'rb')) ${file} Evaluate (r'${gif_file}', open(r'${CURDIR}${/}testfiles${/}${gif_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${gif_streamId} ${content["data"]} Set Global Variable ${gif_streamId} ${content["data"]["id"]}
正例-正常发送gif+文字消息 正例-正常发送gif+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${gif_file}', open(r'${CURDIR}${/}testfiles${/}${gif_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${gif_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这张图是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -89,23 +81,18 @@ ${xlsx_file} testfile.xlsx ...@@ -89,23 +81,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${jpeg_file}', open(r'${CURDIR}${/}testfiles${/}${jpeg_file}', 'rb')) ${file} Evaluate (r'${jpeg_file}', open(r'${CURDIR}${/}testfiles${/}${jpeg_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${jpeg_streamId} ${content["data"]} Set Global Variable ${jpeg_streamId} ${content["data"]["id"]}
正例-正常发送jpeg+文字消息 正例-正常发送jpeg+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${jpeg_file}', open(r'${CURDIR}${/}testfiles${/}${jpeg_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${jpeg_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这张图是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -117,23 +104,18 @@ ${xlsx_file} testfile.xlsx ...@@ -117,23 +104,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${png_file}', open(r'${CURDIR}${/}testfiles${/}${png_file}', 'rb')) ${file} Evaluate (r'${png_file}', open(r'${CURDIR}${/}testfiles${/}${png_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${png_streamId} ${content["data"]} Set Global Variable ${png_streamId} ${content["data"]["id"]}
正例-正常发送png+文字消息 正例-正常发送png+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${png_file}', open(r'${CURDIR}${/}testfiles${/}${png_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${png_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这张图是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -145,23 +127,18 @@ ${xlsx_file} testfile.xlsx ...@@ -145,23 +127,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${webp_file}', open(r'${CURDIR}${/}testfiles${/}${webp_file}', 'rb')) ${file} Evaluate (r'${webp_file}', open(r'${CURDIR}${/}testfiles${/}${webp_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${webp_streamId} ${content["data"]} Set Global Variable ${webp_streamId} ${content["data"]["id"]}
正例-正常发送webp+文字消息 正例-正常发送webp+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${webp_file}', open(r'${CURDIR}${/}testfiles${/}${webp_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${webp_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这张图是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -173,23 +150,18 @@ ${xlsx_file} testfile.xlsx ...@@ -173,23 +150,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${csv_file}', open(r'${CURDIR}${/}testfiles${/}${csv_file}', 'rb')) ${file} Evaluate (r'${csv_file}', open(r'${CURDIR}${/}testfiles${/}${csv_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${csv_streamId} ${content["data"]} Set Global Variable ${csv_streamId} ${content["data"]["id"]}
正例-正常发送csv+文字消息 正例-正常发送csv+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${csv_file}', open(r'${CURDIR}${/}testfiles${/}${csv_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${csv_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这个文件是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -201,23 +173,18 @@ ${xlsx_file} testfile.xlsx ...@@ -201,23 +173,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${doc_file}', open(r'${CURDIR}${/}testfiles${/}${doc_file}', 'rb')) ${file} Evaluate (r'${doc_file}', open(r'${CURDIR}${/}testfiles${/}${doc_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${doc_streamId} ${content["data"]} Set Global Variable ${doc_streamId} ${content["data"]["id"]}
正例-正常发送doc+文字消息 正例-正常发送doc+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${doc_file}', open(r'${CURDIR}${/}testfiles${/}${doc_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${doc_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这个文件是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -229,23 +196,18 @@ ${xlsx_file} testfile.xlsx ...@@ -229,23 +196,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${docx_file}', open(r'${CURDIR}${/}testfiles${/}${docx_file}', 'rb')) ${file} Evaluate (r'${docx_file}', open(r'${CURDIR}${/}testfiles${/}${docx_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${docx_streamId} ${content["data"]} Set Global Variable ${docx_streamId} ${content["data"]["id"]}
正例-正常发送docx+文字消息 正例-正常发送docx+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${docx_file}', open(r'${CURDIR}${/}testfiles${/}${docx_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${docx_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这个文件是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -257,23 +219,18 @@ ${xlsx_file} testfile.xlsx ...@@ -257,23 +219,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${md_file}', open(r'${CURDIR}${/}testfiles${/}${md_file}', 'rb')) ${file} Evaluate (r'${md_file}', open(r'${CURDIR}${/}testfiles${/}${md_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${md_streamId} ${content["data"]} Set Global Variable ${md_streamId} ${content["data"]["id"]}
正例-正常发送md+文字消息 正例-正常发送md+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${md_file}', open(r'${CURDIR}${/}testfiles${/}${md_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${md_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这个文件是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -285,23 +242,18 @@ ${xlsx_file} testfile.xlsx ...@@ -285,23 +242,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${txt_file}', open(r'${CURDIR}${/}testfiles${/}${txt_file}', 'rb')) ${file} Evaluate (r'${txt_file}', open(r'${CURDIR}${/}testfiles${/}${txt_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${txt_streamId} ${content["data"]} Set Global Variable ${txt_streamId} ${content["data"]["id"]}
正例-正常发送txt+文字消息 正例-正常发送txt+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${txt_file}', open(r'${CURDIR}${/}testfiles${/}${txt_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${txt_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这个文件是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -313,23 +265,18 @@ ${xlsx_file} testfile.xlsx ...@@ -313,23 +265,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${xls_file}', open(r'${CURDIR}${/}testfiles${/}${xls_file}', 'rb')) ${file} Evaluate (r'${xls_file}', open(r'${CURDIR}${/}testfiles${/}${xls_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${xls_streamId} ${content["data"]} Set Global Variable ${xls_streamId} ${content["data"]["id"]}
正例-正常发送xls+文字消息 正例-正常发送xls+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${xls_file}', open(r'${CURDIR}${/}testfiles${/}${xls_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${xls_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这个文件是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -341,23 +288,18 @@ ${xlsx_file} testfile.xlsx ...@@ -341,23 +288,18 @@ ${xlsx_file} testfile.xlsx
${file} Evaluate (r'${xlsx_file}', open(r'${CURDIR}${/}testfiles${/}${xlsx_file}', 'rb')) ${file} Evaluate (r'${xlsx_file}', open(r'${CURDIR}${/}testfiles${/}${xlsx_file}', 'rb'))
${data} Create Dictionary sessionId=${sessionId} ${data} Create Dictionary sessionId=${sessionId}
${header} Create Dictionary Authorization=${token} ${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file} ${files} Create Dictionary file=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header} ${resp} Post On Session URI ${uploadpath} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()} ${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
Set Global Variable ${xlsx_streamId} ${content["data"]} Set Global Variable ${xlsx_streamId} ${content["data"]["id"]}
正例-正常发送xlsx+文字消息 正例-正常发送xlsx+文字消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${file} Evaluate (r'${xlsx_file}', open(r'${CURDIR}${/}testfiles${/}${xlsx_file}', 'rb')) ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}","files":"${xlsx_streamId}"} 200 ${token}
${data} Create Dictionary sessionId=${sessionId} text="这个文件是什么格式"
${header} Create Dictionary Authorization=${token}
${files} Create Dictionary files=${file}
${resp} Post On Session URI ${path} files=${files} data=${data} headers=${header}
${content} Set Variable ${resp.json()}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -366,7 +308,7 @@ ${xlsx_file} testfile.xlsx ...@@ -366,7 +308,7 @@ ${xlsx_file} testfile.xlsx
反例-传入错误token 反例-传入错误token
[Tags] E [Tags] E
create session URI ${URL} create session URI ${URL}
${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好"} 401 {} ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}"} 401 {}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 401 Should Be Equal As Strings ${content["code"]} 401
Should Be Equal As Strings ${content["message"]} 无效的access token Should Be Equal As Strings ${content["message"]} 无效的access token
...@@ -374,7 +316,7 @@ ${xlsx_file} testfile.xlsx ...@@ -374,7 +316,7 @@ ${xlsx_file} testfile.xlsx
反例-传入空白token 反例-传入空白token
[Tags] E [Tags] E
create session URI ${URL} create session URI ${URL}
${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好"} 401 ${EMPTY} ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好","workerId":"${clientId}"} 401 ${EMPTY}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 401 Should Be Equal As Strings ${content["code"]} 401
Should Be Equal As Strings ${content["message"]} 没有找到认证信息 Should Be Equal As Strings ${content["message"]} 没有找到认证信息
...@@ -382,15 +324,24 @@ ${xlsx_file} testfile.xlsx ...@@ -382,15 +324,24 @@ ${xlsx_file} testfile.xlsx
反例-不传入sessionId参数 反例-不传入sessionId参数
[Tags] E [Tags] E
create session URI ${URL} create session URI ${URL}
${content} POST请求结果_PARAMS ${path} {} 200 ${token} ${content} POST请求结果_PARAMS ${path} {"text":"你好","workerId":"${clientId}"} 200 ${token}
log ${content}
Should Be Equal As Strings ${content["code"]} 500
Should Be Equal As Strings ${content["message"]} Server busy, please try later
反例-不传入workerId参数
[Tags] E
create session URI ${URL}
${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"你好"} 200 ${token}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 500 Should Be Equal As Strings ${content["code"]} 500
Should Be Equal As Strings ${content["message"]} Server busy, please try later Should Be Equal As Strings ${content["message"]} Server busy, please try later
正例-正常发送文字消息,进入探索 正例-正常发送文字消息,进入探索
[Tags] F [Tags] F
Sleep 10
create session URI ${URL} create session URI ${URL}
${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"使用探索工具,打开boss直聘"} 200 ${token} ${content} POST请求结果_PARAMS ${path} {"sessionId":"${sessionId}","text":"使用探索工具,打开百度","workerId":"${clientId}"} 200 ${token}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
......
...@@ -5,20 +5,26 @@ Library get_expId.py ...@@ -5,20 +5,26 @@ Library get_expId.py
*** Variables *** *** Variables ***
${path} /api/chat/read ${path} /api/chat/read
${clientId} a68ad587830d41aebf418a919006353e
*** Test Cases *** *** Test Cases ***
正例-正常读取消息 正例-正常读取消息
[Tags] F [Tags] F
Sleep 10
${resp} Get ExpId http://bitagent.sit.ninetechone.com/${path} ${sessionId} ${ex_streamId} ${token} ${resp} Get ExpId http://bitagent.sit.ninetechone.com/${path} ${sessionId} ${ex_streamId} ${token}
log ${resp} log ${resp}
Should Contain ${resp}[0] EXP_ Should Contain ${resp["sessionId"]} P_EXP
Set Global Variable ${expId} ${resp}[0] Set Global Variable ${expId} ${resp["sessionId"]}
${content} GET请求结果 /api/chat/retry {"sessionId":"${expId}","workerId":"${clientId}"} 200 ${token}
Set Global Variable ${streamId} ${content["data"]}
${resp1} Get ExpId http://bitagent.sit.ninetechone.com/${path} ${expId} ${streamId} ${token}
log ${resp1}
正例-正常读取对话消息 正例-正常读取对话消息
[Tags] F [Tags] F
${resp} Get Message http://bitagent.sit.ninetechone.com/${path} ${sessionId} ${text_streamId} ${token} ${resp} Get Message http://bitagent.sit.ninetechone.com/${path} ${sessionId} ${text_streamId} ${token}
log ${resp} log ${resp}
Should Contain ${resp}[0] 让我想想 Should Contain ${resp}[0] 你好
Should Contain ${resp}[-1] 关闭 Should Contain ${resp}[-1] 关闭
反例-传入错误的token 反例-传入错误的token
......
...@@ -9,7 +9,7 @@ ${path} /api/chat/interrupt ...@@ -9,7 +9,7 @@ ${path} /api/chat/interrupt
正例-正常中断消息 正例-正常中断消息
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${content} GET请求结果 ${path} {"sessionId":"${sessionId}"} 200 ${token} ${content} GET请求结果 ${path} {"sessionId":"${sessionId}","streamId":"${ex_streamId}"} 200 ${token}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -17,7 +17,7 @@ ${path} /api/chat/interrupt ...@@ -17,7 +17,7 @@ ${path} /api/chat/interrupt
反例-传入错误的token 反例-传入错误的token
[Tags] E [Tags] E
create session URI ${URL} create session URI ${URL}
${content} GET请求结果 ${path} {"sessionId":"${sessionId}"} 401 testtoken ${content} GET请求结果 ${path} {"sessionId":"${sessionId}","streamId":"${ex_streamId}"} 401 testtoken
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 401 Should Be Equal As Strings ${content["code"]} 401
Should Be Equal As Strings ${content["message"]} 无效的access token Should Be Equal As Strings ${content["message"]} 无效的access token
...@@ -25,7 +25,7 @@ ${path} /api/chat/interrupt ...@@ -25,7 +25,7 @@ ${path} /api/chat/interrupt
反例-传入空白token 反例-传入空白token
[Tags] E [Tags] E
create session URI ${URL} create session URI ${URL}
${content} GET请求结果 ${path} {"sessionId":"${sessionId}"} 401 ${EMPTY} ${content} GET请求结果 ${path} {"sessionId":"${sessionId}","streamId":"${ex_streamId}"} 401 ${EMPTY}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 401 Should Be Equal As Strings ${content["code"]} 401
Should Be Equal As Strings ${content["message"]} 没有找到认证信息 Should Be Equal As Strings ${content["message"]} 没有找到认证信息
...@@ -33,7 +33,15 @@ ${path} /api/chat/interrupt ...@@ -33,7 +33,15 @@ ${path} /api/chat/interrupt
反例-不传sessionId参数 反例-不传sessionId参数
[Tags] E [Tags] E
create session URI ${URL} create session URI ${URL}
${content} GET请求结果 ${path} {} 200 ${token} ${content} GET请求结果 ${path} {"streamId":"${ex_streamId}"} 200 ${token}
log ${content}
Should Be Equal As Strings ${content["code"]} 500
Should Be Equal As Strings ${content["message"]} Server busy, please try later
反例-不传streamId参数
[Tags] E
create session URI ${URL}
${content} GET请求结果 ${path} {"sessionId":"${sessionId}"} 200 ${token}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 500 Should Be Equal As Strings ${content["code"]} 500
Should Be Equal As Strings ${content["message"]} Server busy, please try later Should Be Equal As Strings ${content["message"]} Server busy, please try later
...@@ -40,8 +40,9 @@ ${path} /api/ability/steps ...@@ -40,8 +40,9 @@ ${path} /api/ability/steps
反例-会话过期 反例-会话过期
[Tags] F [Tags] F
create session URI ${URL} Comment 当前版本会话保持持久化,不会过期,此用例废弃
${content} GET请求结果 ${path} {"exploreSessionId":1,"chatbotSessionId":10} 200 ${token} Comment create session URI ${URL}
log ${content} Comment ${content} GET请求结果 ${path} {"exploreSessionId":1,"chatbotSessionId":10} 200 ${token}
Should Be Equal As Strings ${content["code"]} BAE0001 Comment log ${content}
Should Be Equal As Strings ${content["message"]} 会话已过期,请开启新对话 Comment Should Be Equal As Strings ${content["code"]} BAE0001
Comment Should Be Equal As Strings ${content["message"]} 会话已过期,请开启新对话
...@@ -12,7 +12,7 @@ ${path} /api/ability ...@@ -12,7 +12,7 @@ ${path} /api/ability
${random_string} Generate Random String 12 [LOWER] ${random_string} Generate Random String 12 [LOWER]
log ${random_string} log ${random_string}
create session URI ${URL} create session URI ${URL}
${content} POST请求结果 ${path} {"exploreSessionId":"${expId}","filteredStepIndices":[0],"draft":{"name":"${random_string}","description":"自动化测试能力","startPageUrl":"https://www.baidu.com","parameters":[{"name":"search_query","description":"用户希望在百度上搜索的关键词。","example": "天气预报","type": "string"}],"stepIndices": [0]}} 200 ${token} ${content} POST请求结果 ${path} {"exploreSessionId":"${expId}","filteredStepIndices":[0],"draft":{"name":"${random_string}","description":"自动化测试","parameters":[],"startPageUrl":"https://www.baidu.com","stepIndices":[0]}} 200 ${token}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} 200 Should Be Equal As Strings ${content["code"]} 200
Should Be Equal As Strings ${content["message"]} 成功 Should Be Equal As Strings ${content["message"]} 成功
...@@ -45,7 +45,7 @@ ${path} /api/ability ...@@ -45,7 +45,7 @@ ${path} /api/ability
反例-能力名已存在 反例-能力名已存在
[Tags] F [Tags] F
create session URI ${URL} create session URI ${URL}
${content} POST请求结果 ${path} {"exploreSessionId":"${expId}","filteredStepIndices":[0],"draft":{"name":"outhagent","description":"该能力用于访问百度主页,以查看其内容和功能。用户可以通过此能力快速打开百度主页,进行信息搜索和浏览。","startPageUrl":"https://www.baidu.com","parameters":[{"name":"search_query","description":"用户希望在百度上搜索的关键词。","example": "天气预报","type": "string"}],"stepIndices": [0]}} 200 ${token} ${content} POST请求结果 ${path} {"exploreSessionId":"${expId}","filteredStepIndices":[0],"draft":{"name":"outhagent","description":"自动化测试","parameters":[],"startPageUrl":"https://www.baidu.com","stepIndices":[0]}} 200 ${token}
log ${content} log ${content}
Should Be Equal As Strings ${content["code"]} BAE0008 Should Be Equal As Strings ${content["code"]} BAE0008
Should Be Equal As Strings ${content["message"]} 此能力名已存在 Should Be Equal As Strings ${content["message"]} 此能力名已存在
...@@ -62,6 +62,6 @@ def get_message(url,sessionId,streamId,token,timeout=180): ...@@ -62,6 +62,6 @@ def get_message(url,sessionId,streamId,token,timeout=180):
return oplist return oplist
# print(get_expId('http://bitagent.sit.ninetechone.com/api/chat/read','CB_2a7714d1e41e4d0891fc5c13a39a4063','CB_a556efbc8502461ba473d789da439c55','Bearer c1391926-e8ba-46c0-a0d1-c5e3c38503da')) # print(get_expId('http://bitagent.sit.ninetechone.com/api/chat/read','P_CB_f21b81ef55ab48f8b87530500ced227d','P_CB_976bebae52514b39a140e38f88cd2dee','Bearer d25c4717-087b-4472-aaaa-2a1939f22680'))
# print(get_expId('http://bitagent.sit.ninetechone.com/api/chat/read','CB_e48bea09fe1e4c8388883ff11384bef8','CB_0e7c9c99d6494d9f977b0c2fbb73e2e3','Bearer c1391926-e8ba-46c0-a0d1-c5e3c38503da')) # print(get_expId('http://bitagent.sit.ninetechone.com/api/chat/read','CB_e48bea09fe1e4c8388883ff11384bef8','CB_0e7c9c99d6494d9f977b0c2fbb73e2e3','Bearer c1391926-e8ba-46c0-a0d1-c5e3c38503da'))
# print(get_message('http://bitagent.sit.ninetechone.com/api/chat/read','CB_e268fb27e7d146009d18e0912c23be58','CB_bc6ed32cc3e0476d90c7b243c75cf2a9','Bearer c1391926-e8ba-46c0-a0d1-c5e3c38503da')) # print(get_message('http://bitagent.sit.ninetechone.com/api/chat/read','P_CB_f21b81ef55ab48f8b87530500ced227d','P_CB_976bebae52514b39a140e38f88cd2dee','Bearer d25c4717-087b-4472-aaaa-2a1939f22680'))
import json
import logging
from typing import Optional
from pydantic import BaseModel
from models import ResultModel
logger = logging.getLogger(__name__)
class RequestBodyModel(BaseModel):
path: str
data: str
headers: str
def parse_request_body(body: str) -> Optional[RequestBodyModel]:
if not body:
return None
parts = body.split("\n", maxsplit=2)
if len(parts) == 3:
return RequestBodyModel(
path=parts[0].strip("/"), headers=parts[1], data=parts[2]
)
else:
logger.error(f"指令格式错误:{body}")
return None
def format_response_body(consume_result: ResultModel):
responseBody = f"{consume_result.code}\n{consume_result.message}"
if consume_result.code == 200 and consume_result.data is not None:
try:
response_headers = json.dumps(
{},
default=lambda o: o.__dict__,
ensure_ascii=False,
)
response_data = json.dumps(
consume_result.data,
default=lambda o: o.__dict__,
ensure_ascii=False,
)
responseBody = f"{consume_result.code}\n{response_headers}\n{response_data}"
except Exception as e:
logger.exception(f"json encode error:{consume_result.data} {e}")
return responseBody
...@@ -5,8 +5,6 @@ from typing import Callable, List, Optional ...@@ -5,8 +5,6 @@ from typing import Callable, List, Optional
import grpc import grpc
import grpc.aio import grpc.aio
# from native.config import settings
# from native.utils.utils import singleton
from protos.BitAgentWorker_pb2_grpc import ConnectServiceStub from protos.BitAgentWorker_pb2_grpc import ConnectServiceStub
...@@ -15,13 +13,13 @@ logger = logging.getLogger(__name__) ...@@ -15,13 +13,13 @@ logger = logging.getLogger(__name__)
class GrpcClient: class GrpcClient:
GRPC_CHANNEL_OPTIONS = [ GRPC_CHANNEL_OPTIONS = [
("grpc.max_send_message_length", 1000), ("grpc.max_send_message_length", 10*1024*1024),
("grpc.max_receive_message_length", 1000), ("grpc.max_receive_message_length", 10*1024*1024),
# ("grpc.keep_alive_time", settings.GRPC_HEART_INTERVAL_SECONDS), # ("grpc.keep_alive_time", settings.GRPC_HEART_INTERVAL_SECONDS),
# ("grpc.keep_alive_timeout", settings.GRPC_HEART_INTERVAL_SECONDS), # ("grpc.keep_alive_timeout", settings.GRPC_HEART_INTERVAL_SECONDS),
# ("grpc.enable_retries", 1), # ("grpc.enable_retries", 1),
] ]
connect_timeout_seconds: int = 30 connect_timeout_seconds: int = 60
def __init__(self): def __init__(self):
self._address: str = "" self._address: str = ""
...@@ -62,7 +60,7 @@ class GrpcClient: ...@@ -62,7 +60,7 @@ class GrpcClient:
if address is None or address == "": if address is None or address == "":
raise ValueError("grpc address must be set") raise ValueError("grpc address must be set")
logger.debug( logger.info(
f"connect grpc to {address} use_ssl:{use_ssl} header:{str(self._header)}" f"connect grpc to {address} use_ssl:{use_ssl} header:{str(self._header)}"
) )
self._is_disconnected = False self._is_disconnected = False
...@@ -131,7 +129,7 @@ class GrpcClient: ...@@ -131,7 +129,7 @@ class GrpcClient:
# 创建通道 # 创建通道
if not self._channel: if not self._channel:
logger.debug("create channel") logger.info("create channel")
if self._use_ssl: if self._use_ssl:
credits: grpc.ChannelCredentials = ( credits: grpc.ChannelCredentials = (
grpc.ssl_channel_credentials() grpc.ssl_channel_credentials()
...@@ -145,7 +143,7 @@ class GrpcClient: ...@@ -145,7 +143,7 @@ class GrpcClient:
) )
# 等待连接 # 等待连接
logger.debug(f"wait channel ready to {self._address}") logger.info(f"wait channel ready to {self._address}")
await asyncio.wait_for( await asyncio.wait_for(
self._channel.channel_ready(), timeout=self.connect_timeout_seconds self._channel.channel_ready(), timeout=self.connect_timeout_seconds
) )
......
import asyncio import asyncio
import json
import logging import logging
from collections import deque from collections import deque
from typing import Callable, Coroutine, Optional from typing import Callable, Coroutine, Optional
import grpc.aio import grpc.aio
from result import ResultModel
from models import ResultModel
from body import format_response_body, parse_request_body
from grpc_client import GrpcClient from grpc_client import GrpcClient
from protos.BitAgentWorker_pb2 import ReversalRequest, ReversalResponse from protos.BitAgentWorker_pb2 import ReversalRequest, ReversalResponse
...@@ -30,6 +30,9 @@ class GrpcListener: ...@@ -30,6 +30,9 @@ class GrpcListener:
Optional[Callable[[str, str], Coroutine[None, None, ResultModel]]] Optional[Callable[[str, str], Coroutine[None, None, ResultModel]]]
) = None ) = None
client.state_changed_handlers.append(self._on_channel_state_changed) client.state_changed_handlers.append(self._on_channel_state_changed)
# 新增:发送队列和发送任务
self._send_queue = asyncio.Queue()
self._send_task: Optional[asyncio.Task] = None
def _on_channel_state_changed(self, connect: bool) -> None: def _on_channel_state_changed(self, connect: bool) -> None:
"""处理通道状态变更""" """处理通道状态变更"""
...@@ -59,6 +62,9 @@ class GrpcListener: ...@@ -59,6 +62,9 @@ class GrpcListener:
self.is_running = True self.is_running = True
self._listen_task = asyncio.create_task(self._listen_loop()) self._listen_task = asyncio.create_task(self._listen_loop())
# 启动发送任务
if not self._send_task or self._send_task.done():
self._send_task = asyncio.create_task(self._send_loop())
async def _listen_loop(self) -> None: async def _listen_loop(self) -> None:
read_pass_count = 0 read_pass_count = 0
...@@ -109,7 +115,7 @@ class GrpcListener: ...@@ -109,7 +115,7 @@ class GrpcListener:
await asyncio.sleep(1) await asyncio.sleep(1)
continue continue
except Exception as e: except Exception as e:
logger.debug(f"ListenHandle exception:{type(e)}") logger.info(f"ListenHandle exception:{type(e)}")
if not self.is_running: if not self.is_running:
break break
if isinstance(e, grpc.aio.AioRpcError): if isinstance(e, grpc.aio.AioRpcError):
...@@ -142,50 +148,30 @@ class GrpcListener: ...@@ -142,50 +148,30 @@ class GrpcListener:
return return
self._request_id_set.add(data.id) self._request_id_set.add(data.id)
self._request_id_deque.append(data.id) self._request_id_deque.append(data.id)
if len(self._request_id_set) > 100000: if len(self._request_id_set) > 3000:
self._request_id_set.remove( self._request_id_set.remove(
self._request_id_deque.popleft() self._request_id_deque.popleft()
) # 最早的指令移除 ) # 最早的指令移除
# 3. 消费指令 # 3. 消费指令
consume_result: ResultModel = ResultModel(code=500, message="client error") consume_result: ResultModel = ResultModel.error("client error")
try: try:
if self.message_received: request_data = parse_request_body(data.body)
parts = data.body.split("\n", maxsplit=2) if request_data is None:
if len(parts) == 3: consume_result = ResultModel.error("指令格式错误")
request_path = parts[0].strip("/") elif self.message_received:
request_data = parts[2] consume_result = await self.message_received(
consume_result = await self.message_received( request_data.path, request_data.data
request_path, request_data )
)
else:
consume_result = ResultModel(code=500, message="指令格式错误")
logger.error(f"指令格式错误:{data.body}")
except Exception as e: except Exception as e:
consume_result = ResultModel(code=500, message=str(e)) consume_result = ResultModel.error(str(e))
logger.exception(f"消费指令异常:{data} {e}") logger.exception(f"消费指令异常:{data} {e}")
# 3. 回复执行结果 # 3. 回复执行结果
responseBody = f"{consume_result.code}\n{consume_result.message}" log = consume_result.log_str()
if consume_result.code == 200 and consume_result.data is not None: await self.send_to_all_stream(
try: data.id, format_response_body(consume_result), retry_count=3, log=log
response_headers = json.dumps( )
{},
default=lambda o: o.__dict__,
ensure_ascii=False,
)
response_data = json.dumps(
consume_result.data,
default=lambda o: o.__dict__,
ensure_ascii=False,
)
responseBody = (
f"{consume_result.code}\n{response_headers}\n{response_data}"
)
except Exception as e:
logger.exception(f"json encode error:{consume_result.data} {e}")
await self.send_to_all_stream(data.id, responseBody, retry_count=3)
except Exception as e: except Exception as e:
logger.exception(f"on_message_received error:{e}") logger.exception(f"on_message_received error:{e}")
...@@ -203,6 +189,11 @@ class GrpcListener: ...@@ -203,6 +189,11 @@ class GrpcListener:
self._listen_task.cancel() self._listen_task.cancel()
self._listen_task = None self._listen_task = None
# 停止发送任务
if self._send_task:
self._send_task.cancel()
self._send_task = None
await self._close_call_stream() await self._close_call_stream()
async def _close_call_stream(self) -> None: async def _close_call_stream(self) -> None:
...@@ -219,68 +210,118 @@ class GrpcListener: ...@@ -219,68 +210,118 @@ class GrpcListener:
logger.exception("Stream dispose error") logger.exception("Stream dispose error")
self._call_stream = None self._call_stream = None
async def _send_loop(self):
while self.is_running:
try:
send_args = await self._send_queue.get()
*real_args, fut = send_args
try:
result = await self._do_send_to_all_stream(*real_args)
except Exception as e:
logger.exception(f"Send loop error: {e}")
result = False
finally:
if fut:
fut.set_result(result)
except asyncio.CancelledError:
break
async def send_to_all_stream( async def send_to_all_stream(
self, requestId: str, body: str, type: int = 1, retry_count: int = 0 self,
requestId: str,
body: str,
type: int = 1,
retry_count: int = 0,
log: Optional[str] = None,
) -> bool: ) -> bool:
"""发送数据到所有流""" """入队,串行发送数据"""
if type == -1: if type == -1:
if not self._send_queue.empty():
logger.debug("ignore:ping")
return True
if self._ping_count == 6: if self._ping_count == 6:
self._ping_count = 0 self._ping_count = 0
self._ping_count += 1 self._ping_count += 1
if len(body) < 2000: log = "#ping"
log = f"{requestId} content:{body}"
else: else:
log = f"{requestId} len:{len(body)} content:{body[:2000]}..." if not log:
count = retry_count log = f'"{requestId}":\n{body}'
while count >= 0: else:
try: log = f'"{requestId}":\n{log}'
# 判断是否可以发送数据
if retry_count > 0: fut = asyncio.get_event_loop().create_future()
if count < retry_count: await self._send_queue.put((requestId, body, type, retry_count, log, fut))
logger.info("send retry ") return await fut
await self._client.wait_reconnecting(
30 async def _do_send_to_all_stream(
) self,
else: requestId: str,
if not self._client.check_can_send(log): body: str,
await self._close_call_stream() type: int = 1,
retry_count: int = 0,
log: Optional[str] = None,
) -> bool:
try:
count = retry_count
while count >= 0:
try:
# 判断是否可以发送数据
if retry_count > 0:
if count < retry_count:
logger.info("send retry ")
await self._client.wait_reconnecting(
60
)
else:
if not self._client.check_can_send(log or ""):
await self._close_call_stream()
continue
# 分段发送数据
partitionIndex = 0
stream = await self.call_stream
if not stream:
logger.error(f"call_stream is null:{log}")
continue continue
for i in range(0, len(body), 1024*1024*10):
if partitionIndex > 0:
logger.info(f"partition:{partitionIndex}")
data = ReversalResponse(
requestId=requestId,
type=type,
partitionIndex=partitionIndex,
partitionData=body[
i : i + 1024*1024*10
],
)
await stream.write(data)
partitionIndex += 1
# 分段发送数据 # 发送结束标志
partitionIndex = 0 if type == 1:
stream = await self.call_stream await stream.write(
if not stream: ReversalResponse(requestId=data.requestId, type=2)
logger.error(f"call_stream is null:{log}") )
continue if type != -1 or self._ping_count == 1:
for i in range(0, len(body), 1000): logger.info(f"send {log}")
if partitionIndex > 0: return True
logger.info(f"partition:{partitionIndex}") except Exception as e:
data = ReversalResponse( if isinstance(e, grpc.aio.AioRpcError):
requestId=requestId, logger.error(f"send RpcException:{log},{str(e)},{e.details()}")
type=type, await self._client._handle_rpc_exception(e)
partitionIndex=partitionIndex, elif isinstance(e, asyncio.InvalidStateError):
partitionData=body[i : i + 1000], logger.error(
) f"send StateError:{log},{str(e)},{self._client.state}"
await stream.write(data) )
partitionIndex += 1 await self._close_call_stream()
# 发送结束标志 await self._client.reconnect(force=True)
if type == 1: else:
await stream.write( logger.error(
ReversalResponse(requestId=data.requestId, type=2) f"send Exception:{log},{str(e)},{self._client.state}"
) )
if type != -1 or self._ping_count == 1: finally:
logger.info(f"send {log}") count -= 1
return True return False
except Exception as e: except Exception as e:
if isinstance(e, grpc.aio.AioRpcError): logger.exception(f"_do_send_to_all_stream error: {e}")
logger.error(f"send RpcException:{log},{str(e)},{e.details()}") return False
await self._client._handle_rpc_exception(e)
elif isinstance(e, asyncio.InvalidStateError):
logger.error(f"send StateError:{log},{str(e)},{self._client.state}")
await self._close_call_stream()
await self._client.reconnect(force=True)
else:
logger.error(f"send Exception:{log},{str(e)},{self._client.state}")
finally:
count -= 1
return False
import asyncio import asyncio
import logging import logging
import random
import time
import requests import requests
import json import json
import grpc.aio
from grpc_client import GrpcClient from grpc_client import GrpcClient
from grpc_listener import GrpcListener from grpc_listener import GrpcListener
from result import ResultModel from models import ResultModel
# 配置日志 # 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
#定义全局变量 fetchUI次数
async def handle_message(request_path: str, request_data: str) -> ResultModel: isopentab = 0
"""增强版消息处理函数""" isfetchui = 0
logging.info(f"收到请求路径: {request_path}, 数据: {request_data}") # 认证配置
auth_config = {
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Sm4-Key": "dUVNkTJLlzMHPqBTZh085jT0N6S7930l6sgddJsYSC8=",
"Cookie": "ENCRYPT_KEY=f48bf3-05fe-4978"
},
"params": {
"username": "api_tester",
"password": "$SM4$Nd/e40vIS6UD9VMaSOmYGlrBORfo7r5/1z9D5d4E4es=$4MS$",
"tenantCode": "API_test",
"scope": "all",
"client_id": "a68ad587830d41aebf418a919006353e",
"client_secret": "Ninetech@123",
"grant_type": "password"
}
}
# 特定消息处理逻辑 async def handle_message(request_path, request_data):
global isopentab
global isfetchui
if request_path == "list_mcp_servers": # 特定指令1 if request_path == "list_mcp_servers": # 特定指令1
return ResultModel(code=200, data=[]) return ResultModel(code=200, data=[], message="")
elif request_path == "adaptable_activities": # 特定指令2 elif request_path == "adaptable_activities": # 特定指令2
return ResultModel(code=200, data=[ {"id": "sleep_seconds", "name": "sleep_seconds", "displayName": "等待", "description": "此工具的用途是在目标无法达成时进行等待,最多等待2次", "parametersSchema": {"description": "等待", "properties": {"wait_seconds": {"default": 5, "description": "默认5秒,可修改为1-5秒时间", "title": "Wait Seconds", "type": "integer"}}, "title": "SleepSeconds", "type": "object", "required": []}, "elementIdJsonPaths": [], "icon": "sleep_seconds", "timeout": 180}]) return ResultModel(code=200, data=[
{"id": "keyboard_entry", "name": "keyboard_entry", "displayName": "键盘输入", "description": "键盘输入", "parametersSchema": {"description": "键盘输入", "properties": {"key_code": {"description": "输入键盘码或组合快捷键,支持Playwright键盘码和组合快捷键,例如:[`F1`, `F2`, `F3`, `F4`, `F5`, `F6`, `F7`, `F8`, `F9`, `F10`, `F11`, `F12`, `Digit0`, `Digit1`, `Digit2`, `Digit3`, `Digit4`, `Digit5`, `Digit6`, `Digit7`, `Digit8`, `Digit9`, `KeyA`, `KeyB`, `KeyC`, `KeyD`, `KeyE`, `KeyF`, `KeyG`, `KeyH`, `KeyI`, `KeyJ`, `KeyK`, `KeyL`, `KeyM`, `KeyN`, `KeyO`, `KeyP`, `KeyQ`, `KeyR`, `KeyS`, `KeyT`, `KeyU`, `KeyV`, `KeyW`, `KeyX`, `KeyY`, `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,`Delete`, `Escape`, `ArrowDown`, `PageDown`, `PageUp`, `ArrowLeft`,`ArrowRight`, `ArrowUp`],Shortcuts such as `Control+o`, `Control++`, `Control+Shift+T` , `Alt+ArrowRight` or `Alt+ArrowLeft`", "title": "Key Code", "type": "string"}}, "required": ["key_code"], "title": "KeyboardEntry", "type": "object"}, "elementIdJsonPaths": [], "icon": "keyboard_entry", "timeout": 180}, {"id": "navigate_page", "name": "navigate_page", "displayName": "跳转到网页", "description": "跳转到网页", "parametersSchema": {"$defs": {"NavigatePageType": {"enum": ["go_to", "go_back", "go_forward", "refresh"], "title": "NavigatePageType", "type": "string"}}, "description": "跳转到网页", "properties": {"url": {"default": "", "description": "需要打开的url", "title": "Url", "type": "string"}, "type": {"$ref": "#/$defs/NavigatePageType", "description": "需要操作的类型"}}, "required": ["type"], "title": "NavigatePage", "type": "object"}, "elementIdJsonPaths": [], "icon": "navigate_page", "timeout": 180}, {"id": "sleep_seconds", "name": "sleep_seconds", "displayName": "等待", "description": "此工具的用途是在目标无法达成时进行等待,最多等待2次", "parametersSchema": {"description": "等待", "properties": {"wait_seconds": {"default": 5, "description": "默认5秒,可修改为1-5秒时间", "title": "Wait Seconds", "type": "integer"}}, "title": "SleepSeconds", "type": "object", "required": []}, "elementIdJsonPaths": [], "icon": "sleep_seconds", "timeout": 180}, {"id": "switch_page", "name": "switch_page", "displayName": "切换页面", "description": "切换页面", "parametersSchema": {"description": "切换页面", "properties": {"page_id": {"description": "需要切换的页面id,如果id对应的页面不存在将不会切换成功", "title": "Page Id", "type": "string"}}, "required": ["page_id"], "title": "SwitchPage", "type": "object"}, "elementIdJsonPaths": [], "icon": "switch_page", "timeout": 180}, {"id": "click", "name": "click", "displayName": "点击元素", "description": "点击某个元素", "parametersSchema": {"description": "点击某个元素", "properties": {"element_id": {"description": "需要操作元素的id", "title": "Element Id", "type": "string"}}, "required": ["element_id"], "title": "ClickElement", "type": "object"}, "elementIdJsonPaths": ["$.element_id"], "icon": "click", "timeout": 180}, {"id": "input_text", "name": "input_text", "displayName": "输入文本", "description": "输入文本", "parametersSchema": {"description": "输入内容", "properties": {"element_id": {"description": "需要操作元素的id", "title": "Element Id", "type": "string"}, "content": {"description": "需要输入的内容", "title": "Content", "type": "string"}}, "required": ["element_id", "content"], "title": "InputText", "type": "object"}, "elementIdJsonPaths": ["$.element_id"], "icon": "input_text", "timeout": 180}, {"id": "select_option", "name": "select_option", "displayName": "选择选项", "description": "选择某个选项,仅适用于radio,checkbox,select,option标签及点击后有dropdown menu效果的标签。label,value,index三者至少填一个", "parametersSchema": {"description": "选择某个选项", "properties": {"element_id": {"description": "需要操作元素的id", "title": "Element Id", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": None, "description": "需要选择的选项的label", "title": "Label"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": None, "description": "需要选择的选项的value", "title": "Value"}, "index": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": None, "description": "需要选择的选项的index索引", "title": "Index"}}, "required": ["element_id"], "title": "SelectOption", "type": "object"}, "elementIdJsonPaths": ["$.element_id"], "icon": "select_option", "timeout": 180}, {"id": "upload_file", "name": "upload_file", "displayName": "上传文件", "description": "上传文件", "parametersSchema": {"description": "上传文件", "properties": {"element_id": {"description": "需要操作元素的id", "title": "Element Id", "type": "string"}, "file_id": {"description": "文件ID,从文件空间中选取", "title": "File Id", "type": "string"}}, "required": ["element_id", "file_id"], "title": "UploadFile", "type": "object"}, "elementIdJsonPaths": ["$.element_id"], "icon": "upload_file", "timeout": 180}],
message="")
elif request_path == "get_current_tab": elif request_path == "get_current_tab":
return ResultModel(code=200, data={"id":"test_tab","url":"https://www.zhipin.com/chengdu/?seoRefer=index","title":"BOSS直聘-找工作上BOSS直聘直接谈!招聘求职找工作!","screenshot":[]}) return ResultModel(code=200, data={
"id": "test_tab",
"url": "https://www.baidu.com/",
"title": "百度一下,你就知道",
"screenshot": []
}, message="")
elif request_path == "open_tab":
isopentab = 1
return ResultModel(code=200, data={
"id": "test_tab",
"url": "https://www.baidu.com/",
"title": "百度一下,你就知道",
"screenshot": []
}, message="")
elif request_path == "fetch_ui":
if isopentab == 1 or isfetchui == 1 :
isopentab = 0
isfetchui = 0
time.sleep(5)
return ResultModel(code=200, data= {"url": "https://www.baidu.com/", "content": "<a href=\"http://news.baidu.com\" id=\"pcWI\">新闻</a><a href=\"https://www.hao123.com?src=from_pc\" id=\"KkD4\">hao123</a><a href=\"http://map.baidu.com\" id=\"ZsH9\">地图</a><a href=\"http://tieba.baidu.com/\" id=\"Ggy7\">贴吧</a><a href=\"https://haokan.baidu.com/?sfrom=baidu-top\" id=\"AOeX\">视频</a><a href=\"http://image.baidu.com/\" id=\"Xd1C\">图片</a><a href=\"https://pan.baidu.com?from=1026962h\" id=\"8IWL\">网盘</a><a href=\"https://wenku.baidu.com/?fr=bdpcindex\" id=\"lCsO\">文库</a><a href=\"https://chat.baidu.com/search?isShowHello=1&pd=csaitab&setype=csaitab&extParamsJson=%7B%22enter_type%22%3A%22home_tab%22%7D\" id=\"b5rX\"><img class=\"s-top-tab-image\" id=\"5QSr\"></a><a href=\"http://www.baidu.com/more/\" name=\"tj_briicon\" id=\"lduS\">更多</a><a href=\"https://senode.baidu.com/seop-landing/knowledge_question?ref_sa=searchpromo_selftask_dati_shouyetab\" id=\"SnLp\"><div class=\"operate-image\" id=\"5eWj\"></div></a><span name=\"tj_settingicon\" id=\"LoOR\">设置</span><a href=\"https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F&sms=5\" name=\"tj_login\" id=\"iGko\">登录</a><span class=\"soutu-btn\" id=\"XlOq\"></span><input name=\"wd\" value maxlength=\"255\" placeholder=\"王曼昱亮相美国大满贯海报\" id=\"Ie3z\"><input type=\"submit\" value=\"百度一下\" id=\"zqXv\"><a href=\"https://chat.baidu.com/search?extParams=%7B%22enter_type%22%3A%22ai_explore_home%22%7D&isShowHello=1\" id=\"E13Q\"><div class=\"new_search_guide_bub_container_left\" id=\"jv0S\"><svg></svg><svg></svg></div><div class=\"new_search_guide_bub_container_center\" id=\"j8J7\">AI搜索已支持「DeepSeek-R1」最新版</div><div class=\"new_search_guide_bub_container_right\" id=\"dHgS\">立即体验</div></a><div aria-label=\"百度热搜\" id=\"E7v6\"><i class=\"c-icon hot-title-icon\" id=\"y7ZQ\"></i><i class=\"c-icon arrow\" id=\"Ekyf\"></i></div><a class=\"hot-refresh c-font-normal c-color-gray2\" id=\"lNcM\"><i class=\"c-icon refresh-icon\" id=\"XZkU\"></i><span class=\"hot-refresh-text\" id=\"hF5v\">换一换</span></a><a href=\"{{_86d720161c56c8c50ca074b8addea74e08f618a7d03681af9f56b5bf60a6e109}}\" id=\"914C\"><i class=\"c-icon title-content-top-icon c-color-red c-gap-right-small\" id=\"6EZe\"></i><span class=\"title-content-title\" id=\"R5B4\">世界上最大的政党是如何炼成的</span></a><a href=\"{{_0609df375efd9ef496de58f77a745debd62d2390ee7b5c6861d3c38f98b4f2b6}}\" id=\"7t6N\"><span class=\"title-content-index c-index-single c-index-single-hot5 \" id=\"p5Zy\">5</span><span class=\"title-content-title\" id=\"FqiJ\">《新华字典》称小孩是累赘</span></a><a href=\"{{_0d7c4837c7faf638c147babd6e8a213b9a1cd92f94e8e24f5c502940e96c5833}}\" id=\"ayzg\"><span class=\"title-content-index c-index-single c-index-single-hot1 \" id=\"vJa0\">1</span><span class=\"title-content-title\" id=\"RQ4p\">高校引进高层次人才 第2名举报第1名</span></a><span class=\"title-content-mark ie-vertical c-text c-gap-left-small c-text-new\" id=\"z7Cd\">新</span><a href=\"{{_e6b1b4573d70f6f8f7fd7d217d73aff2aba5b9e3746e6a9783470b3330bd1917}}\" id=\"ff9J\"><span class=\"title-content-index c-index-single c-index-single-hot6 \" id=\"ovY0\">6</span><span class=\"title-content-title\" id=\"0rtw\">党的旗帜所指 即是网警铁翼所向</span></a><a href=\"{{_13ec6819a42ac28f147cb75ea1b8877a3a7296df40f4a456963f38d2adcba54d}}\" id=\"6TtQ\"><span class=\"title-content-index c-index-single c-index-single-hot2 \" id=\"EAry\">2</span><span class=\"title-content-title\" id=\"DVrk\">韦东奕晋升北大长聘副教授?校方回应</span></a><span class=\"title-content-mark ie-vertical c-text c-gap-left-small c-text-new\" id=\"Y2ua\">新</span><a href=\"{{_4d4c744b982ab1cd8436ea8806a2785a8c2d258bfdd57828e543080616d50704}}\" id=\"4240\"><span class=\"title-content-index c-index-single c-index-single-hot7 \" id=\"dXlE\">7</span><span class=\"title-content-title\" id=\"k2E1\">广州男子开车看手机撞人致3死3伤</span></a><span class=\"title-content-mark ie-vertical c-text c-gap-left-small c-text-new\" id=\"JA4p\">新</span><a href=\"{{_2d2cb344298e3c01a7eb639603d5d60037253006c48d5a997856bc86d5e01c9b}}\" id=\"ORRe\"><span class=\"title-content-index c-index-single c-index-single-hot3 \" id=\"j3h2\">3</span><span class=\"title-content-title\" id=\"Bmkd\">香港回归祖国28周年</span></a><a href=\"{{_c938881ae5de8a4a2a8395ee6482ca79a7d140eb1c5a7b0d0ddf48d57e9869b9}}\" id=\"hSRq\"><span class=\"title-content-index c-index-single c-index-single-hot8 \" id=\"aTwd\">8</span><span class=\"title-content-title\" id=\"9XGF\">男子8公斤黄金卖了612万赚312万</span></a><a href=\"{{_833e2addd1c5511c52653c92a46d9a996b7bfa3b7ba32168502057514e315095}}\" id=\"Qb7j\"><span class=\"title-content-index c-index-single c-index-single-hot4 \" id=\"iegt\">4</span><span class=\"title-content-title\" id=\"ubEb\">女子遇已故同学父亲摆摊:买下所有瓜</span></a><span class=\"title-content-mark ie-vertical c-text c-gap-left-small c-text-new\" id=\"PSS1\">新</span><a href=\"{{_8ae1eeb912dc25e1f8532a67bee6c7923fbf8fbf6b9ecc3cc0e13641c7d8e826}}\" id=\"qDqK\"><span class=\"title-content-index c-index-single c-index-single-hot9 \" id=\"ToGA\">9</span><span class=\"title-content-title\" id=\"3IYi\">客机高空急坠亲历者:给老公写了遗书</span></a><span class=\"title-content-mark ie-vertical c-text c-gap-left-small c-text-hot\" id=\"ZSGD\">热</span><a href=\"//home.baidu.com\" id=\"G6xr\">关于百度</a><a href=\"http://ir.baidu.com\" id=\"F2zX\">About Baidu</a><a href=\"//www.baidu.com/duty\" id=\"cN4M\">使用百度前必读</a><a href=\"https://help.baidu.com/question?prod_id=1\" id=\"nvcN\">帮助中心</a><a href=\"https://e.baidu.com/?refer=1271\" id=\"2xUA\">企业推广</a><span class=\"c-icon\" id=\"6r4L\"></span><span class=\"c-icon c-color-gray2\" id=\"Bdmj\"></span>", "elementIdSelectorMapping": {}, "screenshotsBase64": [], "text": "", "page_tabs": [{"id": "B9EF2368E1361855B8603FE716C87B69", "title": "百度一下,你就知道", "url": "https://www.baidu.com/", "active": True, "children": []}]}, message="")
else:
isfetchui = 1
return ResultModel(code=200, data= {"url": "about:blank", "content": "当前页面为空白页", "elementIdSelectorMapping": {}, "screenshotsBase64": [], "text": "", "page_tabs": []}, message="")
# 默认响应 # 默认响应
return ResultModel(code=200, data={"message": "请求处理成功"}) return ResultModel(code=200, data={"message": "请求处理成功"})
async def send_ping(listener):
async def send_ping(listener: GrpcListener):
"""心跳维护任务"""
while True: while True:
try: await asyncio.sleep(5)
await listener.send_to_all_stream("ping", "#ping", type=-1, retry_count=3) await listener.send_to_all_stream(requestId="ping", body="#ping", type=-1)
logging.info("心跳包已发送")
except Exception as e:
logging.error(f"发送心跳异常: {e}")
await asyncio.sleep(5) # 每5秒发送一次
async def respond_to_server(listener: GrpcListener):
"""服务端消息响应器"""
while True:
try:
# 实际业务中可添加消息检测逻辑
# 示例:当收到特定通知时发送响应
# if 收到特殊通知:
# response = {"status": "OK", "timestamp": int(time.time())}
# await listener.send_to_all_stream("response", json.dumps(response))
await asyncio.sleep(1) # 防止CPU过载
except Exception as e:
logging.error(f"响应器异常: {e}")
await asyncio.sleep(5) # 异常时延长等待
async def main(): async def main():
# 认证配置
auth_config = {
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Sm4-Key": "dUVNkTJLlzMHPqBTZh085jT0N6S7930l6sgddJsYSC8=",
"Cookie": "ENCRYPT_KEY=f48bf3-05fe-4978"
},
"params": {
"username": "api_tester",
"password": "$SM4$Nd/e40vIS6UD9VMaSOmYGlrBORfo7r5/1z9D5d4E4es=$4MS$",
"tenantCode": "API_test",
"scope": "all",
"client_id": "a68ad587830d41aebf418a919006353e",
"client_secret": "Ninetech@123",
"grant_type": "password"
}
}
try: try:
# 获取访问令牌 # 获取访问令牌
token_res = requests.post( token_res = requests.post(
...@@ -93,41 +98,33 @@ async def main(): ...@@ -93,41 +98,33 @@ async def main():
} }
logging.info(f"gRPC配置加载完成: {grpc_config}") logging.info(f"gRPC配置加载完成: {grpc_config}")
# 初始化gRPC客户端 # 创建 gRPC 客户端
client = GrpcClient() client = GrpcClient()
client.set_header(grpc_config["token"], grpc_config["client_id"]) client.set_header(token=grpc_config["token"], client_id=grpc_config["client_id"])
connected = await client.connect(address=grpc_config["host"], use_ssl=grpc_config["is_ssl"])
# 建立连接 if not connected:
if not await client.connect(grpc_config["host"], grpc_config["is_ssl"]): logger.error("Failed to connect to gRPC server.")
logging.error("gRPC服务器连接失败")
return return
# 启动消息监听器 # 创建 gRPC 监听器
listener = GrpcListener(client) listener = GrpcListener(client)
listener.message_received = handle_message listener.message_received = handle_message
listener.start() listener.start()
# 启动后台任务 # 启动 ping 任务
tasks = [ ping_task = asyncio.create_task(send_ping(listener))
asyncio.create_task(send_ping(listener)),
asyncio.create_task(respond_to_server(listener))
]
# 主循环
try: try:
while True: await asyncio.gather(ping_task)
await asyncio.sleep(1) except asyncio.CancelledError:
except KeyboardInterrupt:
logging.info("正在关闭服务...")
await listener.stop() await listener.stop()
await client.disconnect()
for task in tasks:
task.cancel()
await asyncio.gather(*tasks, return_exceptions=True)
except requests.RequestException as e:
logger.error(f"Request error: {e}")
except grpc.aio.AioRpcError as e:
logger.error(f"gRPC error: {e}")
except Exception as e: except Exception as e:
logging.error(f"服务启动失败: {e}") logger.error(f"Unexpected error: {e}")
if __name__ == "__main__": if __name__ == "__main__":
asyncio.run(main()) asyncio.run(main())
\ No newline at end of file
import json
from copy import deepcopy
from enum import Flag, auto
from typing import Any
from pydantic import BaseModel
class ActivityType(Flag):
BROWSER = auto() # 1
APP = auto() # 2
def truncate_base64_fields(data: Any, truncate_length: int = 10) -> Any:
if isinstance(data, dict):
new_data = {}
for key, value in data.items():
# 如果是base64图片字段,截断
if key in [
"screenshots",
"screenshotsBase64",
"screenshots_base64",
] and isinstance(value, list):
truncated_list = [
(item[:truncate_length] + "...")
if isinstance(item, str) and len(item) > truncate_length
else item
for item in value
]
new_data[key] = truncated_list
else:
new_data[key] = truncate_base64_fields(value, truncate_length)
return new_data
elif isinstance(data, list):
return [truncate_base64_fields(item, truncate_length) for item in data]
else:
return data
class ResultModel(BaseModel):
code: int
data: Any = None
message: str = ""
@staticmethod
def success(data: Any = None, message: str = "") -> "ResultModel":
return ResultModel(code=200, data=data, message=message)
@staticmethod
def error(
message: str,
code: int = 500,
data: Any = None,
) -> "ResultModel":
return ResultModel(code=code, message=message, data=data)
def log_str(self) -> str:
try:
raw_dict = self.dict()
safe_dict = deepcopy(raw_dict)
log = truncate_base64_fields(safe_dict)
return json.dumps(
log,
default=lambda o: o.__dict__,
ensure_ascii=False,
)
except Exception:
return json.dumps(
self,
default=lambda o: o.__dict__,
ensure_ascii=False,
)
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
import grpc import grpc
import grpc_manager.protos.BitAgentWorker_pb2 as BitAgentWorker__pb2
import protos.BitAgentWorker_pb2 as BitAgentWorker__pb2
GRPC_GENERATED_VERSION = "1.69.0" GRPC_GENERATED_VERSION = "1.69.0"
GRPC_VERSION = grpc.__version__ GRPC_VERSION = grpc.__version__
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论