forked from Trustie-Study-Group/PRWelBot4SECourse
Init
This commit is contained in:
parent
05c587ce76
commit
3c8544bdda
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/python
|
||||
# 负责调用平台接口 完成各项操作
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
import requests
|
||||
import json
|
||||
import config.baseConfig as baseconfig
|
||||
from commons.logUtil import logger
|
||||
|
||||
|
||||
# 获取 pull状态新信息
|
||||
def get_pull_infor(owner, repo, index):
|
||||
url = baseconfig.apiUrl + "api/v1/{}/pulls/{}.json".format(repo, index)
|
||||
response = requests.get(url, headers=baseconfig.header, proxies = baseconfig.proxies)
|
||||
logger.info("get_pull_infor调用:"+str(response.json()))
|
||||
return response.json()
|
||||
|
||||
|
||||
# 获取 添加pull评论信息
|
||||
def create_pull_comment(issue_id):
|
||||
url = baseconfig.apiUrl + "api/issues/{}/journals.json".format(issue_id)
|
||||
COMMENT = "注意!\n该合并请求已创建满两小时,长时间未处理可能会降低贡献的质量和贡献者积极性。\n请及时处理!"
|
||||
data = json.dumps({'content': COMMENT})
|
||||
|
||||
response = requests.post(url, data=data, headers=baseconfig.header, proxies = baseconfig.proxies)
|
||||
logger.info("create_pull_comment调用:"+str(response.json()))
|
||||
return response.json()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
get_pull_infor("wuxiaojun", "wuxiaojun/botreascrch", "3")
|
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/python
|
||||
# 负责调用平台接口 完成各项操作
|
||||
import json
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
import jwt
|
||||
import time
|
||||
import sys
|
||||
|
||||
|
||||
# 通过bot基本信息字段获取JWT 和 token
|
||||
def getJWT():
|
||||
if len(sys.argv) > 1:
|
||||
pem = sys.argv[1]
|
||||
else:
|
||||
# pem = input("Enter path of private PEM file: ")
|
||||
pem = 'C:\\Users\\文学奖\\Downloads\\my-first-apps1.2023-02-05.private-key (1).pem' # (1)
|
||||
|
||||
# Get the App ID
|
||||
if len(sys.argv) > 2:
|
||||
app_id = sys.argv[2]
|
||||
else:
|
||||
# app_id = input("Enter your APP ID: ")
|
||||
app_id = 10009 #"CrnV5uYEmwMGu7H6osHHi-4aSyKdY99qRMw4i44Kfi4" #186702
|
||||
|
||||
# Open PEM
|
||||
with open(pem, 'rb') as pem_file:
|
||||
signing_key = jwt.jwk_from_pem(pem_file.read())
|
||||
#signing_key = jwt.jwk_from_pem(privateKey)
|
||||
|
||||
payload = {
|
||||
# Issued at time
|
||||
'iat': int(time.time()),
|
||||
# JWT expiration time (10 minutes maximum)
|
||||
'exp': int(time.time()) + 600,
|
||||
# GitHub App's identifier
|
||||
'iss': app_id
|
||||
}
|
||||
|
||||
# Create JWT
|
||||
jwt_instance = jwt.JWT()
|
||||
encoded_jwt = jwt_instance.encode(payload, signing_key, alg='RS256')
|
||||
print(f"JWT: ", encoded_jwt)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("hello")
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/python
|
||||
import logging
|
||||
import logging.handlers
|
||||
|
||||
|
||||
'''
|
||||
日志工具类
|
||||
'''
|
||||
class Logging:
|
||||
def __init__(self):
|
||||
# log文件存储路径
|
||||
self._log_filename = 'bot.log'
|
||||
|
||||
'''
|
||||
%(levelno)s: 打印日志级别的数值
|
||||
%(levelname)s: 打印日志级别名称
|
||||
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
|
||||
%(filename)s: 打印当前执行程序名
|
||||
%(funcName)s: 打印日志的当前函数
|
||||
%(lineno)d: 打印日志的当前行号
|
||||
%(asctime)s: 打印日志的时间
|
||||
%(thread)d: 打印线程ID
|
||||
%(threadName)s: 打印线程名称
|
||||
%(process)d: 打印进程ID
|
||||
%(message)s: 打印日志信息
|
||||
'''
|
||||
# 日志信息输出格式
|
||||
self._formatter = logging.Formatter('%(asctime)s - %(process)d - '
|
||||
'%(pathname)s - %(levelname)s: %(message)s')
|
||||
# 创建一个日志对象
|
||||
self._logger = logging.getLogger()
|
||||
# 设置控制台日志的输出级别: 级别排序:CRITICAL > ERROR > WARNING > INFO > DEBUG
|
||||
self._logger.setLevel(logging.INFO) # 大于info级别的日志信息都会被输出
|
||||
self.set_console_logger()
|
||||
self.set_file_logger()
|
||||
|
||||
def set_console_logger(self):
|
||||
'''设置控制台日志输出'''
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setFormatter(self._formatter)
|
||||
self._logger.addHandler(console_handler)
|
||||
|
||||
def set_file_logger(self):
|
||||
'''设置日志文件输出'''
|
||||
formatter = logging.Formatter('%(asctime)s - %(process)d - '
|
||||
'%(pathname)s - %(levelname)s: %(message)s')
|
||||
# 将输出日志信息保存到文件中
|
||||
file_handler = logging.handlers.RotatingFileHandler(
|
||||
self._log_filename, maxBytes=10485760, backupCount=5, encoding="utf-8")
|
||||
file_handler.setFormatter(self._formatter)
|
||||
self._logger.addHandler(file_handler)
|
||||
|
||||
def get_logger(self):
|
||||
return self._logger
|
||||
|
||||
|
||||
logger = Logging().get_logger()
|
Binary file not shown.
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/python
|
||||
# mysql 数据库配置信息
|
||||
db_config = {
|
||||
'host': 'localhost',
|
||||
'user': '',
|
||||
'password': '',
|
||||
'database': 'pulldb',
|
||||
'use_unicode': True,
|
||||
'charset': 'utf8mb4'
|
||||
}
|
||||
|
||||
|
||||
# request 头部配置 目前token写死在头部,正常需通过 api来获取有效token
|
||||
header = {
|
||||
'User-Agent': 'Mozilla/5.0',
|
||||
'Authorization': 'Bearer token_str',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
# app配置
|
||||
host = "0.0.0.0"
|
||||
port = 3090
|
||||
|
||||
# request 代理配置
|
||||
proxies = {"http": None, "https": None}
|
||||
|
||||
|
||||
# 平台接口url
|
||||
apiUrl = "https://www.gitlink.org.cn/"
|
||||
|
||||
|
||||
# payload = {
|
||||
# "action":"closed",
|
||||
# "number":2,
|
||||
# "pull_request":{
|
||||
# "id":3406,
|
||||
# "url":"https://gitlink.org.cn/wuxiaojun/botreascrch/pulls/2",
|
||||
# "number":2,
|
||||
# "user":{
|
||||
# "id":42378,
|
||||
# "login":"wuxiaojun",
|
||||
# },
|
||||
# "created_at":"2023-03-22T21:36:54+08:00",
|
||||
# },
|
||||
# "repository":{
|
||||
# "id":10203,
|
||||
# "name":"botreascrch",
|
||||
# }
|
||||
# }
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
botId = 10009
|
||||
|
||||
clientId = "ENmlgAJo2FBsENZH0DE-xbS67bxOSyTjMPNRoi_pzXQ"
|
||||
|
||||
clientSecret = "xaMJ4Xyb4s5SAthe9ZCo6zX7LrB9cG6y-vrucEmXsIk"
|
||||
|
||||
pemPath = 'C:\\Users\\文学奖\\Downloads\\my-first-apps1.2023-02-05.private-key (1).pem'
|
||||
|
||||
token = "1XPMnNzTSS8s3hlYvHfw0wivKHJvtQLtzCt3mDRnOqs"
|
Binary file not shown.
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/python
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
from flask import Flask, jsonify, request
|
||||
from flask_cors import CORS, cross_origin
|
||||
import json
|
||||
import services.pullService as pullService
|
||||
import datetime
|
||||
from commons.logUtil import logger
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
# 测试
|
||||
@app.route('/hello', methods=['get'])
|
||||
@cross_origin()
|
||||
def hello():
|
||||
return jsonify({
|
||||
"code": 0,
|
||||
"msg": "hello"
|
||||
})
|
||||
|
||||
|
||||
# 功能:每当有一个新的PR创建/关闭时,根据状态执行存储或更新操作
|
||||
@app.route('/prwelcome', methods=['POST'])
|
||||
@cross_origin()
|
||||
def pr_welcome():
|
||||
try:
|
||||
payload = request.json
|
||||
print(payload)
|
||||
logger.info("获取webhook信息成功:" + str(payload))
|
||||
# # 判断是新创建issue,还是issue的状态发生改变
|
||||
if payload["action"] == 'opened':
|
||||
pull_id = payload["pull_request"]["id"]
|
||||
index = payload["pull_request"]["number"]
|
||||
time = payload["pull_request"]["created_at"][:19]
|
||||
owner = payload["pull_request"]["user"]["login"]
|
||||
repo = payload["repository"]["full_name"]
|
||||
created = datetime.datetime.strptime(time, "%Y-%m-%dT%H:%M:%S")
|
||||
check_time = created + datetime.timedelta(hours=2)
|
||||
values = (pull_id, index, owner, repo, created, check_time, 0)
|
||||
# print(values)
|
||||
pullService.insert_pull(values)
|
||||
|
||||
# 关闭 更新数据库对应pr状态 (合并或者拒绝都属于关闭)
|
||||
elif payload["action"] == 'closed':
|
||||
index = payload["pull_request"]["number"]
|
||||
owner = payload["pull_request"]["user"]["login"]
|
||||
repo = payload["repository"]["full_name"]
|
||||
pullService.update_pull(index, owner, repo)
|
||||
|
||||
return jsonify({
|
||||
"code": 0,
|
||||
"msg": "success"
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
"code": -1,
|
||||
"msg": "exception:" + str(e)
|
||||
})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(port=3090)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Navicat MySQL Data Transfer
|
||||
|
||||
Source Server : localhost
|
||||
Source Server Version : 80023
|
||||
Source Host : localhost:3306
|
||||
Source Database : pulldb
|
||||
|
||||
Target Server Type : MYSQL
|
||||
Target Server Version : 80023
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 2023-03-23 16:56:23
|
||||
*/
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for pull
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `pull`;
|
||||
CREATE TABLE `pull` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||
`pullid` int NOT NULL COMMENT 'pr主键id',
|
||||
`index` int DEFAULT NULL COMMENT 'pull下标',
|
||||
`owner` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '仓库拥有者login',
|
||||
`repo` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '仓库名称',
|
||||
`created` datetime NOT NULL COMMENT 'pr创建时间',
|
||||
`closed` datetime DEFAULT NULL COMMENT '关闭时间',
|
||||
`checktime` datetime NOT NULL COMMENT 'pr预期有变化时间',
|
||||
`status` int NOT NULL DEFAULT '0' COMMENT 'Pull状态,0:打开,1 关闭,2 提醒完成',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# 注意 number 和 id有什么区别
|
Binary file not shown.
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/python
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
import datetime
|
||||
from apscheduler.schedulers.blocking import BlockingScheduler
|
||||
|
||||
# 定时任务处理与调度
|
||||
|
||||
|
||||
# 测试程序
|
||||
def func():
|
||||
now = datetime.datetime.now()
|
||||
ts = now.strftime('%Y-%m-%d %H:%M:%S')
|
||||
print('do func time :', ts)
|
||||
|
||||
|
||||
# 扫描数据库,获取未完成的到期pr,执行相关操作
|
||||
def check_pr():
|
||||
# 查询数据库,获取未完成的到期pr
|
||||
|
||||
# 循环遍历,调用接口查询pr状态(是否新增评论或者状态为关闭)
|
||||
|
||||
# 对不活跃的pr调用接口,发表评论提醒处理
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
# 定时执行任务
|
||||
# 参数 func 定时函数 time 间隔时间(min)
|
||||
def do_timer_job(func, time):
|
||||
# 创建调度器:BlockingScheduler
|
||||
scheduler = BlockingScheduler()
|
||||
# 添加任务,时间间隔5S
|
||||
scheduler.add_job(func, 'interval', seconds=time, id='timer_job1')
|
||||
scheduler.start()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
do_timer_job(func, 1)
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/python
|
||||
# 项目主函数入口
|
||||
import datetime
|
||||
import time
|
||||
from commons.logUtil import logger
|
||||
from controllers.prController import app
|
||||
from services.pullService import check_and_update_pull
|
||||
from threading import Thread
|
||||
import config.baseConfig as baseConfig
|
||||
|
||||
|
||||
def monitoring_loop():
|
||||
while True:
|
||||
check_and_update_pull()
|
||||
now = datetime.datetime.now()
|
||||
logger.info('执行定时任务 :' + now.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
time.sleep(600)
|
||||
|
||||
|
||||
def run():
|
||||
monitoring_thread = Thread(target=monitoring_loop)
|
||||
monitoring_thread.start()
|
||||
|
||||
app.run(host=baseConfig.host, port=baseConfig.port)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
|
||||
|
Binary file not shown.
|
@ -0,0 +1,120 @@
|
|||
import sys
|
||||
|
||||
sys.path.append('..')
|
||||
import config.baseConfig as baseConfig
|
||||
import pymysql
|
||||
import datetime
|
||||
import commons.apiUtil as api
|
||||
|
||||
|
||||
# 插入一条pull表记录
|
||||
def insert_pull(values):
|
||||
# 打开数据库连接
|
||||
db = pymysql.connect(**baseConfig.db_config)
|
||||
# 使用 cursor() 方法创建一个游标对象 cursor
|
||||
cursor = db.cursor()
|
||||
|
||||
# 插入语句
|
||||
# value = (1, 2, "b", "b", now_time, now_time, 0)
|
||||
ins_sql = """INSERT INTO pull(`pullid`, `index`, `owner`, `repo`, `created`, `checktime`, `status`)
|
||||
VALUES (%s, %s, "%s", "%s","%s", "%s", %s)""" % values
|
||||
print(ins_sql)
|
||||
try:
|
||||
cursor.execute(ins_sql)
|
||||
db.commit()
|
||||
except Exception as e:
|
||||
print("ERR0R!insert pull error:")
|
||||
db.rollback()
|
||||
print(e)
|
||||
# 关闭数据库连接
|
||||
db.close()
|
||||
|
||||
|
||||
# 更新一条pull表记录
|
||||
def update_pull(index, owner, repo):
|
||||
# 打开数据库连接
|
||||
db = pymysql.connect(**baseConfig.db_config)
|
||||
# 使用 cursor() 方法创建一个游标对象 cursor
|
||||
cursor = db.cursor()
|
||||
# 更新语句
|
||||
sql_update = "UPDATE pull set `status` = 1 where `index` = '%d' AND `owner` = '%s' AND `repo` = '%s'" % (
|
||||
index, owner, repo)
|
||||
try:
|
||||
cursor.execute(sql_update)
|
||||
db.commit()
|
||||
except Exception as e:
|
||||
print("ERR0R!update pull error:")
|
||||
db.rollback()
|
||||
print(e)
|
||||
# 关闭数据库连接
|
||||
db.close()
|
||||
|
||||
|
||||
# 查询并更新
|
||||
def check_and_update_pull():
|
||||
# 打开数据库连接
|
||||
db = pymysql.connect(**baseConfig.db_config)
|
||||
# 使用 cursor() 方法创建一个游标对象 cursor
|
||||
cursor = db.cursor()
|
||||
|
||||
now_time = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')
|
||||
sql_query = "select * from pull where `status` = 0 and `checktime` < '%s'" % now_time
|
||||
# print(sql_query)
|
||||
|
||||
try:
|
||||
# 执行SQL语句
|
||||
cursor.execute(sql_query)
|
||||
# 获取所有记录列表
|
||||
results = cursor.fetchall()
|
||||
print(results)
|
||||
for item in results:
|
||||
# 调用接口查询pr状态
|
||||
# (7, 1, 2, 'b', 'b', datetime.datetime(), None, datetime.datetime(2023, 3, 23, 11, 46, 13), 0)
|
||||
# 提取 pr记录信息
|
||||
pull_id = item[0]
|
||||
pull_index = item[2]
|
||||
owner = item[3]
|
||||
repo = item[4]
|
||||
pr_infor = api.get_pull_infor(owner, repo, pull_index)
|
||||
print(pr_infor)
|
||||
issue_id = pr_infor["issue"]["id"];
|
||||
|
||||
# pr 状态标志位,0表示未完成,1表示已经完成
|
||||
flag = check_pr(pr_infor)
|
||||
|
||||
# 数据库 pr记录 更新语句
|
||||
sql_update = ""
|
||||
# 若新增评论或者状态为关闭 则修改数据库
|
||||
if flag == 1:
|
||||
# pr已完成更新语句
|
||||
sql_update = "UPDATE pull set status = 1 where id = '%d'" % pull_id
|
||||
# 否则对不活跃的pr调用接口,发表评论提醒处理
|
||||
|
||||
try:
|
||||
cursor.execute(sql_update)
|
||||
db.commit()
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
print("ERR0R!update pull error:")
|
||||
print(e)
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
print("ERR0R!deal pull error:")
|
||||
print(e)
|
||||
# 关闭数据库连接
|
||||
db.close()
|
||||
|
||||
|
||||
# 检查 pr状态,已完成返回1,未完成返回0
|
||||
def check_pr(pr_infor):
|
||||
# pr已经关闭
|
||||
if pr_infor["status"] == "closed":
|
||||
return 1
|
||||
# pr有动态
|
||||
if pr_infor["issue"]["journals_count"] != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_and_update_pull()
|
Loading…
Reference in New Issue