Examination

使用dify.ai构建考试问答机器人

发现问卷星没有强制使用https,本地配置hosts

1
127.0.0.1	kaoshi.wjx.top

实现一个代理服务,注入我们的js代码,实现答题时访问dify api 获取答案,将答案拼接在问题下面。将原来的地址改成http访问,也省需要mitm了。
当然也需要将代理返回内容里的https改成http,否则就访问不了了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.request as urllib2
import logging
import re
import gzip
import logging
import sys
from bs4 import BeautifulSoup

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

fh = logging.FileHandler(sys.path[0] + '/考试.log',mode='a', encoding='utf-8')
fh.setLevel(logging.INFO)
fh.setFormatter(formatter)
logger.addHandler(fh)

ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(formatter)
logger.addHandler(ch)

# logging.basicConfig()

class ProxyHandler(BaseHTTPRequestHandler):
target_host = 'kaoshi.wjx.top'

def proxy(self):
header = dict(self.headers)
logger.info('header: %s', header)
# print(header)
if self.path == '/npm/eruda':
self.send_response(200)
self.end_headers()
with open(sys.path[0] + '/eruda.js', 'r', encoding='utf-8') as f:
self.wfile.write(f.read().encode('utf-8'))
return
elif self.path == '/script.js':
self.send_response(200)
self.end_headers()
with open(sys.path[0] + '/script.js', 'r', encoding='utf-8') as f:
self.wfile.write(f.read().encode('utf-8'))
return
else:
header['Host'] = 'kaoshi.wjx.top'
request = urllib2.Request(url='http://' + "101.37.44.53" + self.path, headers=header, method=self.command)
# print(request.full_url)
logger.info('request: %s', request.full_url)
with urllib2.urlopen(request) as f:
# print(f.status, f.headers)
logger.info("status: %s", f.status)
logger.info("headers: %s", f.headers)

self.send_response(f.status)
for (key, value) in f.headers.items():
if key == 'Content-Type':
self.send_header(key, value)
self.end_headers()
data = f.read()
if f.headers['Content-Encoding'] == 'gzip':
data = gzip.decompress(data)
data = data.decode('utf-8')
# print(data)
if 'https' in data:
data = data.replace('https://', 'http://')
logger.info("data: %s", data)
logger.info('<<<<: %s', self.path)
data = get_answer(data)
self.wfile.write(data.encode('utf-8'))


def do_GET(self):
self.proxy()


def do_POST(self):
self.proxy()

def get_answer(data: str):
if '</body>' in data:
i = data.index('</body>')
script = '''
<script src="//kaoshi.wjx.top/npm/eruda"></script><script>setTimeout(() => eruda.init(), 3000);</script>
'''
script = script + '''<script src="//kaoshi.wjx.top/script.js"></script>'''
data = data[:i] + script + data[i:]
return data

def run():
server_address = ('', 80)
httpd = HTTPServer(server_address, ProxyHandler)
httpd.serve_forever()

if __name__ == '__main__':
run()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
document.addEventListener("DOMContentLoaded", (event) => {
let next = document.querySelector('a[onclick="show_next_page();"]');
next.addEventListener('click', (event) => {
event.preventDefault();
show_next_page();
let q = document.querySelector('fieldset[style=""]');
if (q.page != 1) {
t = q.querySelector('div.topichtml').innerHTML;
o = Array.from(q.querySelectorAll('div.label')).map((e) => e.innerHTML);
console.log(t);
console.log(o);
fetch('https://api.dify.ai/v1/chat-messages', {
method: 'POST',
headers: {
'Authorization': 'Bearer xxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"inputs": {},
// "query": "党员领导干部的配偶、子女及其配偶,违反有关规定在该党员领导干部管辖的地区和业务范围内从事可能影响其公正执行公务的经营活动,或者有其他违反经商办企业禁止规定行为的,该党员领导干部应当按照规定予以纠正;拒不纠正的,()。\nA.其本人应当辞去现任职务\nB.由组织予以调整职务\nC.其本人应当辞去现任职务或者由组织予以调整职务\nD.直接撤销党内职务处分\n答案是什么?",
"query": t + '\n' + o.join('\n') + '\n答案是什么?',
"response_mode": "blocking",
"conversation_id": "",
"user": "abc-123",
"files": [
]
})
})
.then(response => response.json())
.then(data => {
console.log(data);
r = JSON.parse(data)['answers'];
p = document.createElement('p');
p.innerHTML = r;
q.querySelector('div.topichtml').append(p);
});
}
});
});