|
| 1 | +# 读书打卡 |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +## 插件开发 |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +插件开发界面: |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | +### 登录插件 |
| 20 | + |
| 21 | +创建xcLogin工具 |
| 22 | + |
| 23 | + |
| 24 | + |
| 25 | +配置工具输入和输出 |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +代码编写: |
| 30 | + |
| 31 | +```python |
| 32 | +import json |
| 33 | +import requests |
| 34 | + |
| 35 | +from runtime import Args |
| 36 | +from typings.xcLogin.xcLogin import Input, Output |
| 37 | + |
| 38 | +browserHeaders = { |
| 39 | + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", |
| 40 | + "Content-Type": "application/json;charset=UTF-8", |
| 41 | + "origin": "https://ims.xinchao.com", |
| 42 | + "referer": "https://ims.xinchao.com" |
| 43 | +} |
| 44 | + |
| 45 | +def handler(args: Args[Input])->Output: |
| 46 | + url = "https://ser-cloud.xinchao.com/portal/pl/pack/login/usernameLogin" |
| 47 | + body = { |
| 48 | + "username": args.input.account, |
| 49 | + "password": args.input.password # 用以前的cookie存放密码 |
| 50 | + } |
| 51 | + |
| 52 | + postRes = requests.post(url=url, data=json.dumps(body), headers=browserHeaders) |
| 53 | + if postRes.status_code != 200: |
| 54 | + isLogin = False; |
| 55 | + else: |
| 56 | + isLogin = True; |
| 57 | + # 获取用户accessToken |
| 58 | + res_json = postRes.json() |
| 59 | + access_token = res_json['data']['accessToken'] |
| 60 | + |
| 61 | + return { |
| 62 | + "isLogin": isLogin, |
| 63 | + "accessToken": access_token |
| 64 | + } |
| 65 | +``` |
| 66 | + |
| 67 | +插件运行测试: |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | +### 获取待读书的书籍信息 |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +配置工具输入和输出 |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | +代码编写: |
| 80 | + |
| 81 | +```python |
| 82 | +from typing import Dict |
| 83 | +from runtime import Args |
| 84 | +from typings.getNeedClockList.getNeedClockList import Input, Output |
| 85 | + |
| 86 | +import requests |
| 87 | + |
| 88 | +browserHeaders = { |
| 89 | + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", |
| 90 | + "Content-Type": "application/json;charset=UTF-8", |
| 91 | + "origin": "https://ims.xinchao.com", |
| 92 | + "referer": "https://ims.xinchao.com" |
| 93 | +} |
| 94 | + |
| 95 | + |
| 96 | +def checkServerRes(res): |
| 97 | + if res['code'] == '000': |
| 98 | + return True |
| 99 | + if res['code'] == 109: |
| 100 | + raise Exception("用户登录失效!") |
| 101 | + return False |
| 102 | + |
| 103 | +def getClockList(args: Args[Input]): |
| 104 | + browserHeadersCopy = browserHeaders.copy() |
| 105 | + browserHeadersCopy['Authorization'] = args.input.accessToken |
| 106 | + |
| 107 | + url = "https://imsapi.xinchao.com/hraccount/api/clockIn/getBookList" |
| 108 | + postRes = requests.get(url=url, headers=browserHeadersCopy) |
| 109 | + if postRes.status_code != 200: |
| 110 | + raise BaseException("服务端my_join_activity接口异常!") |
| 111 | + if postRes.status_code == 200 and postRes.text.startswith("<!DOCTYPE"): |
| 112 | + raise BaseException("你的登录token失效了!") |
| 113 | + res = postRes.json() |
| 114 | + if checkServerRes(res): |
| 115 | + return res['data'] |
| 116 | + return [] |
| 117 | + |
| 118 | +# 获取需要打卡的课程 |
| 119 | +def getNeedClockList(clock_list=None): |
| 120 | + if clock_list is None: |
| 121 | + clock_list = [] |
| 122 | + return [clock for clock in clock_list if clock['status'] == 1] |
| 123 | + |
| 124 | +def handler(args: Args[Input])->Output: |
| 125 | + # 获取参与的打卡的信息 |
| 126 | + clock_list = getClockList(args) |
| 127 | + # 获取需要打卡的书籍任务 |
| 128 | + clock_need_list = getNeedClockList(clock_list) |
| 129 | + |
| 130 | + return {"clock_need_list": clock_need_list} |
| 131 | +``` |
| 132 | + |
| 133 | +插件运行测试: |
| 134 | + |
| 135 | + |
| 136 | + |
| 137 | +### 获取需要打卡的日期列表 |
| 138 | + |
| 139 | + |
| 140 | + |
| 141 | +配置工具输入和输出 |
| 142 | + |
| 143 | + |
| 144 | + |
| 145 | +代码编写: |
| 146 | + |
| 147 | +```python |
| 148 | +from runtime import Args |
| 149 | +from typings.getNeedDakaClockDateList.getNeedDakaClockDateList import Input, Output |
| 150 | + |
| 151 | +import requests |
| 152 | + |
| 153 | +browserHeaders = { |
| 154 | + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", |
| 155 | + "Content-Type": "application/json;charset=UTF-8", |
| 156 | + "origin": "https://ims.xinchao.com", |
| 157 | + "referer": "https://ims.xinchao.com" |
| 158 | +} |
| 159 | + |
| 160 | +def checkServerRes(res): |
| 161 | + if res['code'] == '000': |
| 162 | + return True |
| 163 | + if res['code'] == 109: |
| 164 | + raise Exception("用户登录失效!") |
| 165 | + return False |
| 166 | + |
| 167 | +# 获取课程每日的打卡情况 |
| 168 | +# https://appdpeopqzr1047.h5.xiaoeknow.com/punch_card/get_clock_date_state |
| 169 | +def get_clock_date_state(access_token:str, task_id=None): |
| 170 | + browserHeadersCopy = browserHeaders.copy() |
| 171 | + browserHeadersCopy['Authorization'] = access_token |
| 172 | + |
| 173 | + # url = "https://imsapi.xinchao.com/hraccount/api/clockIn/getCalendar?task_id=10&date=2024-05-24" |
| 174 | + url = "https://imsapi.xinchao.com/hraccount/api/clockIn/getCalendar?task_id=" + str(task_id) |
| 175 | + res = requests.get(url=url, headers=browserHeadersCopy).json() |
| 176 | + if checkServerRes(res): |
| 177 | + return res['data'] |
| 178 | + raise Exception("获取课程每日的打卡情况失败!") |
| 179 | + |
| 180 | +# 获取需要打卡的日期 |
| 181 | +def get_need_daka_clock_date_state(access_token:str, task_id=None): |
| 182 | + clock_date_state = get_clock_date_state(access_token, task_id) |
| 183 | + clock_date_state = clock_date_state["dateList"] |
| 184 | + # calendar_state 枚举状态 0无任务 1已打卡 3未打卡 4未开始 |
| 185 | + return [clock_calendar['date'] for clock_calendar in clock_date_state if clock_calendar['status'] == 3] |
| 186 | + |
| 187 | +def handler(args: Args[Input])->Output: |
| 188 | + access_token = args.input.accessToken |
| 189 | + task_id = args.input.taskId |
| 190 | + daka_clock_date_state_list = get_need_daka_clock_date_state(access_token, task_id) |
| 191 | + return {"needDakaDateList": daka_clock_date_state_list} |
| 192 | +``` |
| 193 | + |
| 194 | +插件运行测试: |
| 195 | + |
| 196 | + |
| 197 | + |
| 198 | +### 打卡请求 |
| 199 | + |
| 200 | + |
| 201 | + |
| 202 | +配置工具输入和输出 |
| 203 | + |
| 204 | + |
| 205 | + |
| 206 | +代码编写: |
| 207 | + |
| 208 | +```python |
| 209 | +from runtime import Args |
| 210 | +from typings.daka.daka import Input, Output |
| 211 | +import requests |
| 212 | +import json |
| 213 | + |
| 214 | +browserHeaders = { |
| 215 | + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", |
| 216 | + "Content-Type": "application/json;charset=UTF-8", |
| 217 | + "origin": "https://ims.xinchao.com", |
| 218 | + "referer": "https://ims.xinchao.com" |
| 219 | +} |
| 220 | + |
| 221 | +def checkServerRes(res): |
| 222 | + if res['code'] == '000': |
| 223 | + return True |
| 224 | + if res['code'] == 109: |
| 225 | + raise Exception("用户登录失效!") |
| 226 | + return False |
| 227 | + |
| 228 | +def daka_request(access_token:str, task_id, data_date, text_content)->Output: |
| 229 | + browserHeadersCopy = browserHeaders.copy() |
| 230 | + browserHeadersCopy['Authorization'] = access_token |
| 231 | + |
| 232 | + url = "https://imsapi.xinchao.com/hraccount/api/clockIn/sumbitClockIn" |
| 233 | + body = { |
| 234 | + "task_id": task_id, |
| 235 | + "date": data_date, |
| 236 | + "content": text_content |
| 237 | + } |
| 238 | + resJson = requests.post(url=url, data=json.dumps(body), headers=browserHeadersCopy).json() |
| 239 | + |
| 240 | + mail_title = "%s日打卡" % data_date |
| 241 | + mail_content = "打卡内容:<b>%s</b>" % text_content |
| 242 | + if checkServerRes(resJson): |
| 243 | + # 打卡成功后给用户发送邮件 |
| 244 | + mail_title = "%s日打卡成功" % data_date |
| 245 | + mail_content = "打卡内容:<b>%s</b>" % text_content |
| 246 | + |
| 247 | + |
| 248 | + #sendEmail(userInfo.receiveMail, mail_title, mail_content) |
| 249 | + return { |
| 250 | + 'isOk': True, |
| 251 | + 'message': resJson['msg'], |
| 252 | + 'title': mail_title, |
| 253 | + 'content': mail_content |
| 254 | + } |
| 255 | + |
| 256 | +def handler(args: Args[Input])->Output: |
| 257 | + print("读书打卡 tool") |
| 258 | + |
| 259 | + access_token:str = args.input.accessToken |
| 260 | + task_id:str = args.input.taskId |
| 261 | + data_date:str = args.input.dakaDate |
| 262 | + text_content:str = args.input.comment |
| 263 | + |
| 264 | + daka_res = daka_request(access_token, task_id, data_date, text_content) |
| 265 | + |
| 266 | + return daka_res |
| 267 | +``` |
| 268 | + |
| 269 | +插件运行测试: |
| 270 | + |
| 271 | + |
| 272 | + |
| 273 | +### 获取要读书的文章内容 |
| 274 | + |
| 275 | + |
| 276 | + |
| 277 | +配置工具输入和输出 |
| 278 | + |
| 279 | + |
| 280 | + |
| 281 | +代码编写: |
| 282 | + |
| 283 | +```python |
| 284 | +from runtime import Args |
| 285 | +from typings.getArticleDetail.getArticleDetail import Input, Output |
| 286 | + |
| 287 | +import requests |
| 288 | + |
| 289 | +browserHeaders = { |
| 290 | + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", |
| 291 | + "Content-Type": "application/json;charset=UTF-8", |
| 292 | + "origin": "https://ims.xinchao.com", |
| 293 | + "referer": "https://ims.xinchao.com" |
| 294 | +} |
| 295 | + |
| 296 | +def checkServerRes(res): |
| 297 | + if res['code'] == '000': |
| 298 | + return True |
| 299 | + if res['code'] == 109: |
| 300 | + raise Exception("用户登录失效!") |
| 301 | + return False |
| 302 | + |
| 303 | +# 获取课程对应日期的打卡内容 |
| 304 | +# https://imsapi.xinchao.com/hraccount/api/clockIn/getDetail?task_id=10&date=2024-05-27&type=0 |
| 305 | +def getPublishDiaryDetail(access_token:str, task_id=None, clock_date="2022-11-10"): |
| 306 | + browserHeadersCopy = browserHeaders.copy() |
| 307 | + browserHeadersCopy['Authorization'] = access_token |
| 308 | + |
| 309 | + url = f"https://imsapi.xinchao.com/hraccount/api/clockIn/getDetail?task_id={task_id}&date={clock_date}&type=0" |
| 310 | + res = requests.get(url=url, headers=browserHeadersCopy).json() |
| 311 | + if checkServerRes(res): |
| 312 | + return res['data'] |
| 313 | + raise Exception("获取文章id失败!") |
| 314 | + |
| 315 | + |
| 316 | +def handler(args: Args[Input])->Output: |
| 317 | + access_token:str = args.input.accessToken |
| 318 | + task_id:str = args.input.taskId |
| 319 | + daka_date:str = args.input.dakaDate |
| 320 | + |
| 321 | + # 获取课程对应日期的打卡文章信息 |
| 322 | + diary_detail = getPublishDiaryDetail(access_token, task_id=task_id, clock_date=daka_date) |
| 323 | + article_content = diary_detail["task"]["task_content_string"] |
| 324 | + |
| 325 | + return { |
| 326 | + "articleContent": article_content |
| 327 | + } |
| 328 | +``` |
| 329 | + |
| 330 | +插件运行测试: |
| 331 | + |
| 332 | + |
| 333 | + |
| 334 | +## 工作流设计 |
| 335 | + |
| 336 | +### 创建工作流 |
| 337 | + |
| 338 | + |
| 339 | + |
| 340 | + |
| 341 | + |
| 342 | +### 添加自定义的插件 |
| 343 | + |
| 344 | + |
| 345 | + |
| 346 | +### 完成后的流程布局: |
| 347 | + |
| 348 | + |
| 349 | + |
| 350 | +> 其中选取任务id和选取打卡日期,只是在出现多个任务,多个日期的时候,只选取出一个任务/日期出来使用。 |
| 351 | +
|
| 352 | +### 测试运行: |
| 353 | + |
| 354 | + |
| 355 | + |
| 356 | +在postman中允许: |
| 357 | + |
| 358 | + |
| 359 | + |
| 360 | +当然也可以获取到bash的请求脚本,添加到服务器定时执行: |
| 361 | + |
| 362 | +```bash |
| 363 | +curl --location 'https://api.coze.cn/v1/workflow/run' \ |
| 364 | +--header 'Authorization: Bearer pat_Y8JcB96LMxxxxxxxxxxxxxxxxxxk8krE2MSSH' \ |
| 365 | +--header 'Content-Type: application/json' \ |
| 366 | +--data '{ |
| 367 | + "workflow_id": "7498634616628445241", |
| 368 | + "parameters": { |
| 369 | + "account":"XCxxxxxx", |
| 370 | + "passwored":"xxxx" |
| 371 | + } |
| 372 | +}' |
| 373 | +``` |
| 374 | + |
0 commit comments