From 32cec2b0f2632fc167c975d7822be441f91f5016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=E9=92=9F?= <7406423+albert_zhong@user.noreply.gitee.com> Date: Wed, 28 Jul 2021 08:44:01 +0000 Subject: [PATCH 1/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20APIs?= =?UTF-8?q?.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIs.py | 122 -------------------------------------------------------- 1 file changed, 122 deletions(-) delete mode 100644 APIs.py diff --git a/APIs.py b/APIs.py deleted file mode 100644 index 5bb9064..0000000 --- a/APIs.py +++ /dev/null @@ -1,122 +0,0 @@ -import requests -from json import dumps, loads -from bs4 import BeautifulSoup - -class codemaoAPI(object): - def __init__(self,UA='Mozilla/5.0 (Windows NT 10.0; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',debug=False): - self.debug = debug - self.ses = requests.session() - self.headers = {"Content-Type": "application/json", "User-Agent": UA} - self.log('Successfully creat a codemao user.') - - def login(self,identity,password): - self.log('getting pid...') - soup = BeautifulSoup(requests.get('https://shequ.codemao.cn', headers = self.headers).text, 'html.parser') - pid = loads(soup.find_all("script")[0].string.split("=")[1])['pid'] - self.log('Successfully get pid;pid=' + pid) - self.log('loginning...') - a = self.ses.post('https://api.codemao.cn/tiger/v3/web/accounts/login', headers = self.headers,data = dumps({"identity": identity, "password": password, "pid": pid})) - if a.status_code == 200: - self.log("Successfully login to codemao.cn") - else: - self.log('End of login to codemao.cn;response', a.status_code) - - def log(self, *msg): - if self.debug: - print(*msg) - - def send_post(self, board, title, message): - self.log('posting...') - a = self.ses.post(f'https://api.codemao.cn/web/forums/boards/{board}/posts', headers = self.headers,data = dumps({'title': title, 'content': message})) - self.log('End.response', a.status_code) - - def replies(self, postID, message): - self.log('replieing...') - a = self.ses.post(f'https://api.codemao.cn/web/forums/posts/{postID}/replies', headers = self.headers,data = dumps({'content': message})) - self.log('End.response', a.status_code) - - def __delete_work(self, workID): # BUG - self.log('deleting...') - a = self.ses.delete(f'https://api.codemao.cn/tiger/work/{workID}/temporarily', headers = self.headers) - self.log('End.response', a.status_code) - - def __recove_work(self, workID): # BUG - self.log('recoving...') - a = self.ses.patch(f'https://api.codemao.cn/tiger/work/{workID}/recover', headers = self.headers) - self.log('End.response', a.status_code) - - def __permanent_work(self, workID): # BUG - self.log('permanenting...') - a = self.ses.delete(f'https://api.codemao.cn/tiger/work/{workID}/permanently', headers = self.headers) - self.log('End.response', a.status_code) - - def delete_all_work(self): - self.log('All work are permanenting...') - a = self.ses.delete('https://api.codemao.cn/tiger/work/user/works/permanently', headers = self.headers) - self.log('End.response', a.status_code) - - def send_post_to_work_shop(self, work_shop_ID, message): - self.log('posting...') - a = self.ses.post(f'https://api.codemao.cn/web/discussions/{work_shop_ID}/comment', headers = self.headers,data = dumps({"content": message, "rich_content": message, "source": "WORK_SHOP"})) - self.log('End.response', a.status_code) - - def top_replies(self, repliesID): - self.log('On top...') - a = self.ses.put(f'https://api.codemao.cn/web/forums/replies/{repliesID}/top', headers = self.headers, - data = r'{}') - self.log('End.response', a.status_code) - - def untop_replies(self, repliesID): - self.log('Untop...') - a = self.ses.delete(f'https://api.codemao.cn/web/forums/replies/{repliesID}/top', headers = self.headers) - self.log('End.response', a.status_code) - - def like_replies(self, repliesID): - self.log('liking...') - self.ses.put(f'https://api.codemao.cn/web/forums/comments/{repliesID}/liked?source=REPLY',headers = self.headers, data = r'{}') - self.log('End.response', a.status_code) - - def unlike_replies(self, repliesID): - self.log('Unliking...') - self.ses.delete(f'https://api.codemao.cn/web/forums/comments/{repliesID}/liked?source=REPLY',headers = self.headers) - - def search_post(self,key,to):#同步执行,可能帖子太多会有点慢。。。。 - self.log('searching...') - res=[] - page=1 - keeprun=True - while keeprun: - resp=self.ses.get(f'https://api.codemao.cn/web/forums/posts/search?title={key}&limit=30&page={page}',headers=self.headers).json() - if resp['items']==[]: - break - for msg in resp['items']: - if (to!=None) and (len(res)>=to): - keeprun=False - break - res.append({'user':{'userid':msg['user']['id'],'username':msg['user']['nickname']},'id':msg['id'],'title':msg['title']}) - page+=1 - return res - - def logout(self): - self.log('logouting...') - a=self.ses.options('https://api.codemao.cn/tiger/v3/web/accounts/logout',headers=self.headers) - if a.status_code==204: - self.log('Successfully logout from codemao.cn') - else: - self.log('End of logout from codemao.cn;response', a.status_code) - - def like_work(self,workID): - self.log('liking...') - a=self.ses.post(f'https://api.codemao.cn/nemo/v2/works/{workID}/like',headers=self.headers,data='{}') - if a.status_code==200: - self.log('Successfully like work') - else: - self.log('End of liking;response', a.status_code) - - def unlike_work(self,workID): - self.log('unliking...') - a=self.ses.delete(f'https://api.codemao.cn/nemo/v2/works/{workID}/like',headers=self.headers) - if a.status_code==200: - self.log('Successfully unlike work') - else: - self.log('End of unliking;response', a.status_code) \ No newline at end of file -- Gitee From 1fd0ae38b615194c96f3c330157036ca80a6a061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=E9=92=9F?= <7406423+albert_zhong@user.noreply.gitee.com> Date: Wed, 28 Jul 2021 08:44:08 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20LICE?= =?UTF-8?q?NSE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 LICENSE diff --git a/LICENSE b/LICENSE deleted file mode 100644 index d6993e3..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 wrmdcxy - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -- Gitee From 8d172109ca6e1bbc17ef908396f32ca6fb9a943b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=E9=92=9F?= <7406423+albert_zhong@user.noreply.gitee.com> Date: Wed, 28 Jul 2021 08:44:17 +0000 Subject: [PATCH 3/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20READ?= =?UTF-8?q?ME.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 2dffd80..0000000 --- a/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# **codemao-apis** -
dd
"})) -print("成功" if a.status_code == 201 else "失败") \ No newline at end of file -- Gitee From a258053c5775ac205774d164a0c1c7b9e4a02765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=E9=92=9F?= <7406423+albert_zhong@user.noreply.gitee.com> Date: Wed, 28 Jul 2021 08:45:54 +0000 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=B8=E5=BF=83?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E6=89=A9=E5=B1=95=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 21 ++ api.py | 191 ++++++++++++++++++ test.py | 7 + ...66\345\270\226\347\245\236\345\231\250.py" | 25 +++ 4 files changed, 244 insertions(+) create mode 100644 LICENSE create mode 100644 api.py create mode 100644 test.py create mode 100644 "\351\241\266\345\270\226\347\245\236\345\231\250.py" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d6993e3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 wrmdcxy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/api.py b/api.py new file mode 100644 index 0000000..d4cd648 --- /dev/null +++ b/api.py @@ -0,0 +1,191 @@ +from requests import * +from json import dumps, loads +from bs4 import BeautifulSoup +import os + + +class CodemaoApi(): + def __init__(self, UA='Mozilla/5.0 (Windows NT 10.0; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36', debug=False): + # New: api sets + self.apis = {'home': 'https://shequ.codemao.cn', + 'matomoApi': 'https://matomo.codemao.cn/piwik.js', + 'login': 'https://api.codemao.cn/tiger/v3/web/accounts/login', + 'postArticle': 'https://api.codemao.cn/web/forums/boards/{}/posts', + 'postReply': 'https://api.codemao.cn/web/forums/posts/{}/replies', + 'clearWork': 'https://api.codemao.cn/tiger/work/user/works/permanently', + 'requireWorkshop': 'https://api.codemao.cn/web/discussions/{}/comment', + 'topReply': 'https://api.codemao.cn/web/forums/replies/{}/top', + 'untopReply': 'https://api.codemao.cn/web/forums/replies/{}/top', + 'likeReply': 'https://api.codemao.cn/web/forums/comments/{}/liked?source=REPLY', + 'unlikeReply': 'https://api.codemao.cn/web/forums/comments/{}/liked?source=REPLY', + 'searchArticle': 'https://api.codemao.cn/web/forums/posts/search?title={}&limit=30&page={}', + 'logout': 'https://api.codemao.cn/tiger/v3/web/accounts/logout', + 'likeWork': 'https://api.codemao.cn/nemo/v2/works/{}/like', + 'unlikeWork': 'https://api.codemao.cn/nemo/v2/works/{}/like'} + self.debug = debug + # Use abs path to create in the root path, not cwd + self.logpath = os.path.split(__file__)[0] + os.sep + 'runtime.log' + self.ses = session() + self.headers = {"Content-Type": "application/json", "User-Agent": UA} + self.log('Successfully create the main session') + + def log(self, *msg): + if self.debug: + print(*msg) + # New: temp log file in the root dir + if not os.path.exists(self.logpath): + open(self.logpath, 'w', encoding='utf-8').close() + with open(self.logpath, 'a', encoding='utf-8') as log: + msg = [str(i) for i in msg] + text = ' '.join(msg) + '\n' # list -> str + log.write(text) + + def login(self, identity, password): + # Get PID + self.log('getting pid...') + text = get(self.apis['home'], headers = self.headers).text + soup = BeautifulSoup(text, 'html.parser') + json = soup.find('script').string.split("=")[1] + pid = loads(json)['pid'] + self.log('Successfully get pid; pid:' + pid) + # Log-in + self.log('logging in...') + res = self.ses.post(self.apis['login'], headers=self.headers, data=dumps({"identity": identity, "password": password, "pid": pid})) + if res.status_code == 200: + self.log("Successfully login to codemao.cn") + else: + self.log('End of logging in to codemao.cn; response', res.status_code) + return res.json() + + def logout(self): + self.log('logging out...') + res = self.ses.options(self.apis['logout'], headers=self.headers) + if res.status_code == 204: + self.log('Successfully log-out from codemao.cn') + else: + self.log('End of logout from codemao.cn; response', res.status_code) + return res.json() + + def postArticle(self, board, title, content): + self.log('posting...') + res = self.ses.post(self.apis['postArticle'].format(board), headers=self.headers, data=dumps({'title': title, 'content': content})) + if res.status_code == 201: + self.log("Successfully post article") + else: + self.log('End of posting; response', res.status_code) + return res.json() + + def postReply(self, arid, content): + self.log('posting...') + res = self.ses.post(self.apis['postReply'].format(arid), headers=self.headers, data=dumps({'content': content})) + if res.status_code == 200: + self.log("Successfully post reply") + else: + self.log('End of posting; response', res.status_code) + return res.json() + + # Not changed + def __delete_work(self, workID): # BUG + self.log('deleting...') + a = self.ses.delete(f'https://api.codemao.cn/tiger/work/{workID}/temporarily', headerss = self.headerss) + self.log('End.response', a.status_code) + + def __recove_work(self, workID): # BUG + self.log('recoving...') + a = self.ses.patch(f'https://api.codemao.cn/tiger/work/{workID}/recover', headerss = self.headerss) + self.log('End.response', a.status_code) + + def __permanent_work(self, workID): # BUG + self.log('permanenting...') + a = self.ses.delete(f'https://api.codemao.cn/tiger/work/{workID}/permanently', headerss = self.headerss) + self.log('End.response', a.status_code) + + def clearWork(self): + self.log('clearing...') + res = self.ses.delete(self.apis['clearWork'], headers=self.headers, data=dumps({'title': title, 'content': content})) + if res.status_code == 200: + self.log("Successfully send request to workshop") + else: + self.log('End of requiring; response', res.status_code) + return res.json() + + def requireWorkshop(self, wsid, content): + self.log('requiring...') + res = self.ses.post(self.apis['requireWorkshop'].format(wsid), headers=self.headers, data=dumps({'content': content, 'rich_content': content, 'source': 'WORK_SHOP'})) + if res.status_code == 200: + self.log("Successfully send request to workshop") + else: + self.log('End of requiring; response', res.status_code) + return res.json() + + def topReply(self, rpid): + self.log('Setting...') + res = self.ses.put(self.apis['topReply'].format(rpid), headers=self.headers, data=r'{}') + if res.status_code == 200: + self.log("Successfully set top reply") + else: + self.log('End of requiring; response', res.status_code) + return res.json() + + def untopReply(self, rpid): + self.log('Setting...') + res = self.ses.delete(self.apis['untopReply'].format(rpid), headers=self.headers) + if res.status_code == 200: + self.log("Successfully cancel top reply") + else: + self.log('End of requiring; response', res.status_code) + return res.json() + + def likeReply(self, rpid): + self.log('Setting...') + res = self.ses.put(self.apis['likeReply'].format(rpid), headers=self.headers, data=r'{}') + if res.status_code == 200: + self.log("Successfully set liked reply") + else: + self.log('End of setting; response', res.status_code) + return res.json() + + def unlikeReply(self, rpid): + self.log('Setting...') + res = self.ses.put(self.apis['unlikeReply'].format(rpid), headers=self.headers) + if res.status_code == 200: + self.log("Successfully cancel liked reply") + else: + self.log('End of setting; response', res.status_code) + return res.json() + + def searchArticle(self, key, to): + # Not changed + self.log('searching...') + res = [] + page = 1 + keeprun = True + while keeprun: + resp=self.ses.get(self.apis['searchArticle'].format(key, page), headers=self.headers).json() + if resp['items']==[]: + break + for msg in resp['items']: + if to != None and len(res) >= to: + keeprun = False + break + res.append({'user':{'userid':msg['user']['id'], 'username':msg['user']['nickname']},'id':msg['id'],'title':msg['title']}) + page+=1 + return res + + def likeWork(self, wkid): + self.log('setting...') + res = self.ses.post(self.apis['likeWork'].format(wkid), headers=self.headers, data=r'{}') + if res.status_code == 200: + self.log('Successfully set liked work') + else: + self.log('End of setting; response', res.status_code) + return res.json() + + def unlikeWork(self,workID): + self.log('setting...') + res = self.ses.delete(self.apis['unlikeWork'].format(wkid), headers=self.headers) + if res.status_code == 200: + self.log('Successfully cancel liked work') + else: + self.log('End of setting; response', res.status_code) + return res.json() \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..eaf0c29 --- /dev/null +++ b/test.py @@ -0,0 +1,7 @@ +from api import * + +api = CodemaoApi(debug=True) +print(api.login('', '')) +print(api.postArticle('11', 'testing', 'dd
"})) +print("成功" if a.status_code == 201 else "失败") \ No newline at end of file -- Gitee From 6ea2429ae553170be40b63d16ae058f26a38f1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=E9=92=9F?= <7406423+albert_zhong@user.noreply.gitee.com> Date: Wed, 28 Jul 2021 10:45:42 +0000 Subject: [PATCH 6/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?=E9=A1=B6=E5=B8=96=E7=A5=9E=E5=99=A8.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...66\345\270\226\347\245\236\345\231\250.py" | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 "\351\241\266\345\270\226\347\245\236\345\231\250.py" diff --git "a/\351\241\266\345\270\226\347\245\236\345\231\250.py" "b/\351\241\266\345\270\226\347\245\236\345\231\250.py" deleted file mode 100644 index 18c0dc0..0000000 --- "a/\351\241\266\345\270\226\347\245\236\345\231\250.py" +++ /dev/null @@ -1,25 +0,0 @@ -import requests -from guimaker import inputbox -from bs4 import BeautifulSoup -from json import loads,dumps - -identity=input("用户名/手机号/邮箱:") -password=input("密码:") - - -ses = requests.session() -headers = {"Content-Type": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"} -print('正在寻找登录密钥...') -soup = BeautifulSoup(requests.get('https://shequ.codemao.cn', headers = headers).text, 'html.parser') -pid = loads(soup.find_all("script")[0].string.split("=")[1])['pid'] -print('秘药为:',pid) -print('正在登录') -a = ses.post('https://api.codemao.cn/tiger/v3/web/accounts/login', headers = headers,data = dumps({"identity": identity, "password": password, "pid": pid})) -if a.status_code == 200: - print("登录成功") -else: - exit("不能登录编程猫") -print('正在顶帖') -postID = inputbox(type_ = int,text="ID?") -a = ses.post(f'https://api.codemao.cn/web/forums/posts/{postID}/replies', headers = headers,data = dumps({'content': "dd
"})) -print("成功" if a.status_code == 201 else "失败") \ No newline at end of file -- Gitee