Browse Source

update: remove legacy code

master
dnomd343 2 years ago
parent
commit
30ea15e0f5
  1. 120
      Check.py
  2. 41
      Loop.py
  3. 86
      Run.py
  4. 455
      Web.py
  5. 8
      docker/init.sh

120
Check.py

@ -1,120 +0,0 @@
#!/usr/bin/python
# -*- coding:utf-8 -*-
import os
import time
import ProxyBuilder as Builder
import ProxyChecker as Checker
import ProxyFilter as Filter
def __loadDir(folderPath: str) -> bool: # 创建文件夹
try:
if os.path.exists(folderPath): # 文件 / 文件夹 存在
if not os.path.isdir(folderPath): # 文件
return False # 无法创建
else: # 不存在
os.makedirs(folderPath) # 递归创建文件夹
return True # 文件夹正常
except:
return False
def __proxyHttpCheck(socksPort: int, httpCheckUrl: str, httpCheckTimeout: float) -> dict or None: # Http检测
try:
health, httpDelay = Checker.httpCheck(
socksPort,
url = httpCheckUrl,
timeout = httpCheckTimeout
)
if health is None: # 连接失败
return None
return {
'delay': httpDelay,
'health': health
}
except: # 未知错误
return None
def proxyTest(
rawInfo: dict,
startDelay: float = 1,
workDir: str = '/tmp/ProxyC',
httpCheckUrl: str = 'http://gstatic.com/generate_204',
httpCheckTimeout: float = 20) -> dict or None:
"""
代理检测入口
程序异常:
return None
启动失败:
return {
'success': False,
'info': proxyInfo
}
测试完成:
return {
'success': True,
'check': checkResult,
'info': proxyInfo
}
"""
if not __loadDir(workDir): # 工作文件夹无效
return None
if 'info' not in rawInfo: # 缺少代理服务器信息
return None
client = None
status, proxyInfo = Filter.filte(rawInfo['info'], isExtra = True)
if not status: # 输入节点错误
return {
'success': False,
'info': None
}
try:
status, client = Builder.build(proxyInfo, workDir)
except Exception as reason: # 构建发生错误
print(str(reason))
Builder.destroy(client)
return None
if not status: # 节点信息有误
return {
'success': False,
'info': proxyInfo
}
time.sleep(startDelay) # 延迟等待客户端启动
try:
status = Builder.check(client) # 检查客户端状态
except: # 检测失败
Builder.destroy(client)
return None
if not status: # 客户端异常退出
Builder.destroy(client)
return {
'success': False,
'info': proxyInfo
}
if 'check' not in rawInfo: # 缺少检测项目
return None
checkItem = rawInfo['check']
checkResult = {}
for item in checkItem:
if item == 'http': # http检测
result = __proxyHttpCheck(client['port'], httpCheckUrl, httpCheckTimeout)
else: # 未知检测项目
result = None
if result is None: # 检测出错
Builder.destroy(client)
return None
checkResult[item] = result
Builder.destroy(client) # 销毁客户端
return {
'success': True,
'check': checkResult,
'info': proxyInfo
}

41
Loop.py

@ -1,41 +0,0 @@
#!/usr/bin/python
# -*- coding:utf-8 -*-
import time
import redis
import subprocess
maxThread = 32
redisPort = 6379
redisHost = 'localhost'
redisPrefix = 'proxyc-'
redisObject = redis.StrictRedis(
db = 0,
host = redisHost,
port = redisPort
)
processList = []
runScript = '/root/ProxyC/Run.py'
# runScript = '/usr/local/share/ProxyC/Run.py'
while True:
spareNum = min(
maxThread - len(processList), # 空余进程数
len(redisObject.keys(redisPrefix + 'check-*')) # 待检测个数
)
if spareNum < 0: # 待运行进程数 > 0
spareNum = 0
for i in range(spareNum): # 运行检测进程
processList.append(
subprocess.Popen(['python', runScript])
)
time.sleep(0.2)
for process in processList: # 遍历子进程
if process.poll() is not None: # 进程已退出
processList.remove(process)
time.sleep(0.5)

86
Run.py

@ -1,86 +0,0 @@
#!/usr/bin/python
# -*- coding:utf-8 -*-
import json
import redis
import Check as Checker
redisPort = 6379
redisHost = 'localhost'
redisPrefix = 'proxyc-'
def __getCheckInfo() -> tuple[str or None, dict or None]:
"""
获取检测任务
无任务或发生异常:
return None, None
任务格式有误:
return tag, None
任务获取成功:
return tag, {...}
"""
try:
checkList = redisObject.keys(redisPrefix + 'check-a-*') # 优先级排序
if len(checkList) == 0:
checkList = redisObject.keys(redisPrefix + 'check-b-*')
if len(checkList) == 0:
checkList = redisObject.keys(redisPrefix + 'check-c-*')
if len(checkList) == 0:
checkList = redisObject.keys(redisPrefix + 'check-d-*')
if len(checkList) == 0:
checkList = redisObject.keys(redisPrefix + 'check-e-*')
if len(checkList) == 0: # 无任务
return None, None
key = checkList[0] # 选取首个任务
taskContent = redisObject.get(key) # 获取任务信息
redisObject.delete(key) # 删除任务记录
tag = str(key[len(redisPrefix) + 8:], encoding = 'utf-8') # {prefix}check-x-{tag}
except:
return None, None
try:
return tag, json.loads(taskContent) # JSON解码
except: # JSON解码失败
return tag, None
def __setCheckResult(checkTag: str, checkResult: dict) -> bool: # 写入检测结果
try:
key = redisPrefix + 'result-' + checkTag
redisObject.set(key, json.dumps(checkResult))
return True
except:
return False
def main(startDelay: float, httpCheckUrl: str, httpCheckTimeout: int) -> None:
checkTag, checkInfo = __getCheckInfo() # 获取检测任务
if checkTag is None:
print("no task found")
return
print(checkInfo)
checkResult = Checker.proxyTest(
checkInfo,
startDelay = startDelay,
httpCheckUrl = httpCheckUrl,
httpCheckTimeout = httpCheckTimeout
)
if checkResult is None:
print("some bad things happen")
return
elif not checkResult['success']:
print("error proxy info")
return
print(checkTag + ' -> ', end = '')
print(checkResult)
if not __setCheckResult(checkTag, checkResult):
print("redis write error")
return
defaultStartDelay = 1.5
defaultHttpCheckTimeout = 20
defaultHttpCheckUrl = 'http://gstatic.com/generate_204'
redisObject = redis.StrictRedis(host = redisHost, port = redisPort, db = 0) # 连接Redis数据库
main(defaultStartDelay, defaultHttpCheckUrl, defaultHttpCheckTimeout)

455
Web.py

@ -1,455 +0,0 @@
#!/usr/bin/python
# -*- coding:utf-8 -*-
import json
import redis
import random
from flask import Flask, request
apiPath = '/'
api = Flask(__name__)
redisPort = 6379
redisHost = 'localhost'
redisPrefix = 'proxyc-'
accessToken = 'dnomd343'
def httpPostArg(field: str) -> dict or str or None: # 获取HTTP POST参数
try:
if request.values.get(field) is not None: # application/x-www-form-urlencoded
return request.values.get(field)
elif request.json.get(field) is not None: # application/json
return request.json.get(field)
elif request.form.get(field) is not None: # multipart/form-data
return request.form.get(field)
except:
pass
return None
def genRandomId(length: int = 24) -> str: # 生成随机ID
tag = ''
for i in range(0, length):
tmp = random.randint(0, 15)
if tmp >= 10:
tag += chr(tmp + 87) # a ~ f
else:
tag += str(tmp) # 0 ~ 9
return tag
def genError(message: str) -> dict: # 生成错误回复
return {
'success': False,
'message': message
}
def genSuccess(data: dict) -> dict: # 生成成功返回
data['success'] = True
return data
def getCheckList(userId: str) -> list or None: # 获取检测任务列表
try:
taskList = []
rawTaskList = redisObject.keys(redisPrefix + 'task-' + userId + '*')
for task in rawTaskList: # 获取任务ID
taskList.append(str(task[len(redisPrefix) + 5:], encoding = 'utf-8'))
return taskList
except:
return None
def addCheckTask(checkList: dict, proxyList: dict, priority: str, userId: str) -> dict: # 新增检测任务
try:
import ProxyDecoder as Decoder
import ProxyFilter as Filter
checkList = list(set(checkList)) # 检测方式去重
for checkMethod in checkList:
if checkMethod not in ['http']:
return genError('unknown check method `' + checkMethod + '`')
for i in range(0, len(proxyList)):
proxyList[i] = Decoder.decode(proxyList[i]) # 解码分享链接
if proxyList[i] is None:
return genError('could not decode index ' + str(i))
status, proxyList[i] = Filter.filte(proxyList[i], isExtra = True) # 节点信息检查
if not status: # 节点不合法
return genError('index ' + str(i) + ': ' + proxyList[i])
tagList = []
for proxyInfo in proxyList:
tag = genRandomId(32) # 32位检测ID
tagList.append(tag)
redisObject.set( # 写入数据库
redisPrefix + 'check-' + priority + '-' + tag,
json.dumps({
'tag': tag,
'check': checkList,
'info': proxyInfo
})
)
checkId = userId + genRandomId(8) # 24位userId + 8位随机 -> 32位任务ID
redisObject.set( # 记录任务
redisPrefix + 'task-' + checkId,
json.dumps({
'checkId': checkId,
'priority': priority,
'check': checkList,
'proxy': tagList,
'complete': False
})
)
return genSuccess({
'checkId': checkId
})
except:
return genError('server error')
def getTaskInfo(checkId: str) -> dict: # 获取任务详情
try:
taskKey = redisObject.keys(redisPrefix + 'task-' + checkId)
if not taskKey: # 任务ID不存在
return genError('invalid check id')
taskKey = str(taskKey[0], encoding = 'utf-8')
taskInfo = json.loads(
redisObject.get(taskKey)
)
if taskInfo['complete']: # 任务已完成
return {
'success': True,
'complete': True,
'checkId': checkId,
'number': len(taskInfo['proxy']),
'result': taskInfo['result']
}
completeNum = 0 # 测试完成数目
for tag in taskInfo['proxy']:
if redisObject.keys(redisPrefix + 'result-' + tag): # 暂未测试
completeNum += 1
if completeNum < len(taskInfo['proxy']): # 测试未完成
return {
'success': True,
'complete': False,
'checkId': checkId,
'number': len(taskInfo['proxy']),
'schedule': round(completeNum / len(taskInfo['proxy']), 2)
}
checkResult = []
for tag in taskInfo['proxy']: # 遍历检测结果
checkResult.append(
json.loads(
redisObject.get(redisPrefix + 'result-' + tag)
)
)
redisObject.delete(redisPrefix + 'result-' + tag) # 删除测试结果
taskInfo['complete'] = True
taskInfo['result'] = checkResult
redisObject.set(taskKey, json.dumps(taskInfo)) # 记入数据库
return {
'success': True,
'complete': True,
'checkId': checkId,
'number': len(taskInfo['proxy']),
'result': taskInfo['result']
}
except:
return genError('server error')
def deleteTask(checkId: str) -> dict: # 删除任务
try:
taskKey = redisObject.keys(redisPrefix + 'task-' + checkId)
if not taskKey: # 任务ID不存在
return genError('invalid check id')
taskKey = str(taskKey[0], encoding = 'utf-8')
taskInfo = json.loads(
redisObject.get(taskKey)
)
if not taskInfo['complete']: # 任务未完成
return genError('task not complete')
redisObject.delete(taskKey)
return {
'success': True,
'checkId': checkId
}
except:
return genError('server error')
def isAdminToken(token: str) -> bool:
"""
是否为管理员token
验证成功:
return True
验证失败:
return False
"""
adminToken = accessToken
return token == adminToken
def isUserToken(token: str) -> bool:
"""
是否为有效token
token有效:
return True
token无效:
return False
"""
try:
if token.encode('utf-8') in redisObject.smembers(redisPrefix + 'users'):
return True
except:
pass
return False
def addUser(priority: str, remain: int or str) -> tuple[bool, str]:
"""
添加账号
添加成功:
return True, userId
添加异常:
return False, {reason}
"""
try:
userId = genRandomId(length = 24)
if priority not in ['a', 'b', 'c', 'd', 'e']: # 优先级无效
return False, 'invalid priority'
remain = int(remain)
if remain < 0:
remain = -1 # 不限次数
userInfo = {
'token': userId,
'priority': priority,
'remain': remain
}
redisObject.sadd( # 添加账号token
redisPrefix + 'users', userId
)
redisObject.set( # 记录账号信息
redisPrefix + 'user-' + userId,
json.dumps(userInfo)
)
return True, userId # 返回userId
except:
return False, 'server error'
def delUser(userId: str) -> tuple[bool, str]:
"""
删除账号
删除成功:
return True, userId
删除失败:
return False, {reason}
"""
try:
if not isUserToken(userId):
return False, 'invalid user id'
taskList = redisObject.keys(redisPrefix + 'task-' + userId + '*')
if taskList:
return False, 'task list not empty'
redisObject.srem(redisPrefix + 'users', userId)
redisObject.delete(redisPrefix + 'user-' + userId)
return True, userId
except:
return False, 'server error'
def getUserInfo(userId: str, minus: bool = False) -> dict or None:
"""
获取账号信息 (minus = True: 剩余次数 - 1)
获取异常:
return None
获取成功:
return {
'token': '...'
'priority': '...',
'remain': ...
}
"""
try:
if not isUserToken(userId): # userId不存在
return None
userInfo = json.loads(
redisObject.get(redisPrefix + 'user-' + userId) # 账号信息
)
if minus and userInfo['remain'] > 0:
userInfo['remain'] -= 1 # 剩余次数 - 1
redisObject.set(
redisPrefix + 'user-' + userId, # 记入数据库
json.dumps(userInfo)
)
return userInfo
except:
return None # 异常
def getUserList() -> dict or None:
"""
获取所有账号信息
获取异常:
return None
获取成功:
return {
'token_1': {
'priority': '...',
'working': ...,
'remain': ...,
},
'token_2': {
...
}
...
}
"""
try:
userList = {}
for userId in redisObject.smembers(redisPrefix + 'users'): # 遍历全部账号
userId = str(userId, encoding = 'utf-8')
userInfo = getUserInfo(userId)
userInfo.pop('token')
userList[userId] = userInfo # 记录账号信息
return userList
except:
return None
def modifyUserInfo(userId: str, priority: str = None, remain = None) -> bool:
"""
修改账号信息
修改成功:
return True
修改失败:
return False
"""
try:
userInfo = getUserInfo(userId)
if userInfo is None: # 账号不存在
return False
if priority is not None: # 优先级变动
if priority not in ['a', 'b', 'c', 'd', 'e']: # 优先级无效
return False
userInfo['priority'] = priority
if remain is not None: # 剩余次数变动
remain = int(remain)
if remain < 0:
remain = -1 # 不限次数
userInfo['remain'] = remain
redisObject.set(
redisPrefix + 'user-' + userId, # 记录账号信息
json.dumps(userInfo)
)
return True
except:
return False
@api.route(apiPath + '/user', methods = ['GET', 'POST'])
def apiUser() -> dict:
if request.method == 'GET': # 获取账号列表
if not isAdminToken(request.args.get('token')): # 非管理员token
return genError('invalid admin token')
userList = getUserList()
if userList is None: # 获取失败
return genError('server error')
return genSuccess({
'user': userList
})
elif request.method == 'POST': # 添加账号
if not isAdminToken(httpPostArg('token')): # 非管理员token
return genError('invalid admin token')
priority = httpPostArg('priority')
if priority is None:
priority = 'c' # 默认优先级
remain = httpPostArg('remain')
if remain is None:
remain = '-1' # 默认剩余次数
status, userId = addUser(priority, remain) # 创建新账号
if not status:
return genError(userId) # 创建错误
return genSuccess({
'userId': userId # 创建成功
})
@api.route(apiPath + '/user/<userId>', methods = ['GET', 'PUT', 'PATCH', 'DELETE'])
def apiUserId(userId: str) -> dict:
if request.method == 'GET': # 获取账号信息
userInfo = getUserInfo(userId)
if userInfo is None:
return genError('invalid user id')
return genSuccess(userInfo)
elif request.method == 'PUT' or request.method == 'PATCH': # 更新账号信息
if not isAdminToken(httpPostArg('token')): # 非管理员token
return genError('invalid admin token')
priority = httpPostArg('priority')
remain = httpPostArg('remain')
if request.method == 'PUT':
if priority is None or remain is None: # 参数不全
return genError('missing parameter')
if not modifyUserInfo(userId, priority = priority, remain = remain): # 更新账号信息
return genError('server error')
return genSuccess(
getUserInfo(userId) # 更新成功
)
elif request.method == 'DELETE': # 销毁账号
if not isAdminToken(httpPostArg('token')): # 非管理员token
return genError('invalid admin token')
status, reason = delUser(userId)
if not status:
return genError(reason)
return genSuccess({
'userId': userId # 删除成功
})
@api.route(apiPath + '/check', methods = ['GET', 'POST'])
def apiCheck() -> dict:
if request.method == 'GET': # 获取检测任务列表
token = request.args.get('token')
if not isUserToken(token):
return genError('invalid user token')
taskList = getCheckList(token)
if taskList is None:
return genError('server error')
return genSuccess({
'taskList': taskList
})
elif request.method == 'POST': # 添加检测任务
token = httpPostArg('token')
if not isUserToken(token):
return genError('invalid user token')
checkList = httpPostArg('check') # 检测列表
if checkList is None:
return genError('missing check list')
proxyList = httpPostArg('proxy') # 代理列表
if proxyList is None:
return genError('missing proxy list')
priority = getUserInfo(token, minus = True)['priority'] # 获取账号优先级
if priority is None:
return genError('server error')
return addCheckTask(checkList, proxyList, priority, token)
@api.route(apiPath + '/check/<checkId>', methods = ['GET', 'DELETE'])
def apiCheckId(checkId: str) -> dict:
if request.method == 'GET': # 获取检测任务状态
return getTaskInfo(checkId)
elif request.method == 'DELETE': # 删除检测任务
return deleteTask(checkId)
redisObject = redis.StrictRedis(
db = 0,
host = redisHost,
port = redisPort
)
api.run(host = '0.0.0.0', port = 43581, debug = True)

8
docker/init.sh

@ -1,8 +0,0 @@
python /usr/local/share/ProxyC/docker/compile.py&
/usr/bin/redis-server /etc/redis.conf
dnsproxy -p 53 -u 223.5.5.5 &
echo "nameserver 127.0.0.1" > /etc/resolv.conf
python /usr/local/share/ProxyC/Loop.py&
python /usr/local/share/ProxyC/Web.py
Loading…
Cancel
Save