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