From 3c8544bddacd9af7b26ce780beb40d72a2add56a Mon Sep 17 00:00:00 2001 From: 623756217 <623756217@qq.com> Date: Tue, 28 Mar 2023 15:43:44 +0800 Subject: [PATCH] Init --- bot.log | 0 commons/__pycache__/apiUtil.cpython-37.pyc | Bin 0 -> 1219 bytes commons/__pycache__/logUtil.cpython-37.pyc | Bin 0 -> 1552 bytes commons/apiUtil.py | 31 +++++ commons/authUtil.py | 47 +++++++ commons/logUtil.py | 57 +++++++++ config/__pycache__/baseConfig.cpython-37.pyc | Bin 0 -> 565 bytes config/baseConfig.py | 49 +++++++ config/botConfig.py | 11 ++ .../__pycache__/prController.cpython-37.pyc | Bin 0 -> 1579 bytes controllers/prController.py | 65 ++++++++++ dbResource/pulldb.sql | 33 +++++ entity/pull.py | 3 + jobs/__pycache__/tasks.cpython-37.pyc | Bin 0 -> 797 bytes jobs/tasks.py | 40 ++++++ main.py | 31 +++++ .../__pycache__/pullService.cpython-37.pyc | Bin 0 -> 2579 bytes services/pullService.py | 120 ++++++++++++++++++ 18 files changed, 487 insertions(+) create mode 100644 bot.log create mode 100644 commons/__pycache__/apiUtil.cpython-37.pyc create mode 100644 commons/__pycache__/logUtil.cpython-37.pyc create mode 100644 commons/apiUtil.py create mode 100644 commons/authUtil.py create mode 100644 commons/logUtil.py create mode 100644 config/__pycache__/baseConfig.cpython-37.pyc create mode 100644 config/baseConfig.py create mode 100644 config/botConfig.py create mode 100644 controllers/__pycache__/prController.cpython-37.pyc create mode 100644 controllers/prController.py create mode 100644 dbResource/pulldb.sql create mode 100644 entity/pull.py create mode 100644 jobs/__pycache__/tasks.cpython-37.pyc create mode 100644 jobs/tasks.py create mode 100644 main.py create mode 100644 services/__pycache__/pullService.cpython-37.pyc create mode 100644 services/pullService.py diff --git a/bot.log b/bot.log new file mode 100644 index 0000000..e69de29 diff --git a/commons/__pycache__/apiUtil.cpython-37.pyc b/commons/__pycache__/apiUtil.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..704f87c62695c2adeba392566b0208f6143d4060 GIT binary patch literal 1219 zcmZuw-A@}w5Z}FT8$v!6q{2Vo7osX}QB_5tzBLrJjVf7|PRH#A&bbd~_pXq{NF>lE zt)N6z3o5N5TOtXGl#sS4Bmva_V_(Ca?I)i4p4q#$BvRL&+1d5@H?#Ab89jEaj9}H3 zVRBPL=#4!5yWos2g767Y1QG0`YO&)g&d*AqRy8c|6kiXFssXl2v_(`kiB1gIEm|Vx zRfT;@O=6J}DKDttgTFwPz8;{W@d_4(A5BeB=Bn}nmJVWojDhe`P%)}wf?G-xHE~mE ztAl7xjn%r=RN)sL#30JDI;X{E%OYx1Yn9q)5VbKzg$>cP@f#mF4e#97AD+88C%=uv z_c<6NbsmKkMVQmnA(U}pHdr+4QJxG!JpE zSG*}<0Pr*zMgh%aJ(&VZXcA6nd1zhe(M(90&=_q*Lia*K zXN8&o9^mjs6mt3)u~YEBzhyDTF4Qh_NVJx%-btT6OdqV)Ca$~F4htq&RHtstYZL4% z>bp@uN29m~djJ?UnPcqvBaQ1~;QeQn0F_&y5IzH+Q<$9r+r{z*)_Zh(4i`ssv@uYD zi880eYDCb+kH&-qEdgRt43o7v*Z;ohxsck4lV?{50)MR#i_`~7yh^GAC3*L3%Fw%a~ zKHOXC{rp$9_M*48o&EMC-B|40`!-$K>Mrab?5+2HSw7hRp}XDgEIsS2FLt*#dv{jS zAD4=o?)*2MM_bwbTiN`hH}kh4*iO3gJzy0m5MP+UdrZT)q6&>TvBPBN=JY1RV7ZJs zF)jK=Rv$c%I;W4xdNSGH%#^Ahl+Z~MG&qwa2(1zEn8~p`>KN7s$BHhjyg;@`*a_)s zj(v9N(kJ6zva{0rq*Ss`3Uyj~oc^C=q#u`I5k7%6JfNJFoDWHN%eDi@3vFAJW|CRY ziRwux`X-|op2S_|P78d#QqJ=%5XAUEjR*mE?Y34fxO55 o3mQ5Bwe5G3&!3UM!1^eNNaE9vWs&&+C<|M-ANQ-4WtA=b76@j7!~g&Q literal 0 HcmV?d00001 diff --git a/commons/__pycache__/logUtil.cpython-37.pyc b/commons/__pycache__/logUtil.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc66f6bd5c6ee899b3361747350bda40dc2e714e GIT binary patch literal 1552 zcmb_cPm3Hy6tAl8>8_c~><-C6aW6TzkVdn32}lSbY;aYOaWMp;87SJW+S!?OPp?%q z;*PVY1mZ9h!Z zKmE8RKjVb_j+@ozfp7zsc^!x(l4c~XIE~5ML^A2!BhtIeVy4(#GWQlF_9eYVBL6v9 zkY0*(^)V1`z;fOciK!$plT@;MB=)2yec--q$N+dlhLQshWD~r#%J98nFc^*pDXqOB z$LHNdhu48fIwOKuI%kqCQ1(Ff7X+lnjEoxdz|v8;pcGE#d_f#bI9Xq2>Jyb!`>UXvgJLoOOL%rifID$8 z%oN_2A?z@Vvbk62Jh4{kvLy~ya@-s!i;2QG_P zI^`ywVU+qHqNQ(CcJLk1Z79uOyI82J{o6)q(?5N1fBF44%SR9T`^V{FqVs)Sj8tk( ze_wy7vb4z6ZejbtbBNN1XWX{KZ0G2>~>aa z>t@dV8TcG;v@zXzleSG@mx699;EWi5U z^x>oBZx5e6{d#%-=UxI%wAfvJK0i7s5Dg)9EX#JpbK^b;g)2nmBk~0|7IZklP8hWW+`uWbNbp zNI?7-{t25g$eoOWx)R}>&j7|yi2%SEPF@BVbtPN@poxF{@}w%m{{+_|A#?J)0fDBC zi9NXdX5_^@Pd?o}hPjB(eUzkkCPz1m$=H@$jnhIxt9wz?bwHz8%s_U`%MU;H!uofOJffD0ur33GsM9UBcYmsKQrN!Z}EV)G@eF{3i{ow9=cWS g-L3Oj26(6R8K*7=dM^33>S@=}nL{_Y4>sQT8x2L2zW@LL literal 0 HcmV?d00001 diff --git a/commons/apiUtil.py b/commons/apiUtil.py new file mode 100644 index 0000000..121b598 --- /dev/null +++ b/commons/apiUtil.py @@ -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") diff --git a/commons/authUtil.py b/commons/authUtil.py new file mode 100644 index 0000000..94e542c --- /dev/null +++ b/commons/authUtil.py @@ -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") \ No newline at end of file diff --git a/commons/logUtil.py b/commons/logUtil.py new file mode 100644 index 0000000..39ebcee --- /dev/null +++ b/commons/logUtil.py @@ -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() \ No newline at end of file diff --git a/config/__pycache__/baseConfig.cpython-37.pyc b/config/__pycache__/baseConfig.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42ad96b50223aeb7165ee63d803fbf9ba014e755 GIT binary patch literal 565 zcmXw1&2AGh5Z+`ro6XNc)e{m_;+jJ@e^f*jLNw{20$Kt|1z0Op&W@9~IP1msX34$) zZ_rb&AaUS@d`0CAxZ_RL`Q*>znUQAZlZU=vw~QU^KY;_svi=m0d#f7fl{s=?2rMW; z8EkN%0`AsD7F5B58q~KoDnSF4p^0qp4IXUE$bpBb0{+Bm?dclh5oSv+m39Q@3VB)D z9dwTRJ>(`SV=$YdYO3ag)$Ccz)y`dIDv8iuf~Cy30OSEyc!niG4U@S_V;XTFx*9F9 zkVNH;bDmSiaQi6e!mf{3TxPvi6WBA-qs1KD4)&+D^!*2(Dl&Dra zeu&?FmH8e{5=JAeD39CMlE*DOuV0!W4o?;&R@y&F)shRE?<(@OTfhps2iVV35?^=b0nq~{rHAptvd$Hn>GV;=V14}+KR4(1aa|_RNoRVYL Fo&V!Otd0Nx literal 0 HcmV?d00001 diff --git a/config/baseConfig.py b/config/baseConfig.py new file mode 100644 index 0000000..68f241c --- /dev/null +++ b/config/baseConfig.py @@ -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", +# } +# } diff --git a/config/botConfig.py b/config/botConfig.py new file mode 100644 index 0000000..d998832 --- /dev/null +++ b/config/botConfig.py @@ -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" diff --git a/controllers/__pycache__/prController.cpython-37.pyc b/controllers/__pycache__/prController.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37b3e0611fc307704ed17e5e957f7b7f47e16b7a GIT binary patch literal 1579 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 literal 0 HcmV?d00001 diff --git a/services/pullService.py b/services/pullService.py new file mode 100644 index 0000000..abc3fed --- /dev/null +++ b/services/pullService.py @@ -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()