mirror of
				https://github.com/whyour/qinglong.git
				synced 2025-11-01 01:16:07 +08:00 
			
		
		
		
	ck管理增加排序,禁用,实时状态变成手动获取
This commit is contained in:
		
							parent
							
								
									ef24fc8354
								
							
						
					
					
						commit
						fb98bc44e4
					
				|  | @ -2,53 +2,18 @@ import { Router, Request, Response, NextFunction } from 'express'; | |||
| import { Container } from 'typedi'; | ||||
| import CookieService from '../services/cookie'; | ||||
| import { Logger } from 'winston'; | ||||
| import { celebrate, Joi } from 'celebrate'; | ||||
| const route = Router(); | ||||
| 
 | ||||
| export default (app: Router) => { | ||||
|   app.use('/', route); | ||||
|   route.get( | ||||
|     '/qrcode', | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         if (req) { | ||||
|           const cookieService = Container.get(CookieService); | ||||
|           const { qrurl } = await cookieService.getQrUrl(); | ||||
|           return res.send({ code: 200, qrcode: qrurl }); | ||||
|         } else { | ||||
|           return res.send({ code: 1, msg: 'loginFaild' }); | ||||
|         } | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|       } | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   route.get( | ||||
|     '/cookies', | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.getCookies(); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|       } | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   route.get( | ||||
|     '/cookie', | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.addQrCookie( | ||||
|           req.query.cookie as string, | ||||
|         ); | ||||
|         const data = await cookieService.cookies(); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -58,17 +23,16 @@ export default (app: Router) => { | |||
|   ); | ||||
| 
 | ||||
|   route.post( | ||||
|     '/cookie', | ||||
|     '/cookies', | ||||
|     celebrate({ | ||||
|       body: Joi.array().items(Joi.string().required()).min(1), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.addCookie(req.body.cookies); | ||||
|         if (data) { | ||||
|           return res.send({ code: 400, data }); | ||||
|         } else { | ||||
|           return res.send({ code: 200, data: '新建成功' }); | ||||
|         } | ||||
|         const data = await cookieService.create(req.body); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|  | @ -77,17 +41,19 @@ export default (app: Router) => { | |||
|   ); | ||||
| 
 | ||||
|   route.put( | ||||
|     '/cookie', | ||||
|     '/cookies', | ||||
|     celebrate({ | ||||
|       body: Joi.object({ | ||||
|         value: Joi.string().required(), | ||||
|         _id: Joi.string().required(), | ||||
|       }), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.updateCookie(req.body); | ||||
|         if (data) { | ||||
|           return res.send({ code: 400, data }); | ||||
|         } else { | ||||
|           return res.send({ code: 200, data: '新建成功' }); | ||||
|         } | ||||
|         const data = await cookieService.update(req.body); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|  | @ -96,19 +62,18 @@ export default (app: Router) => { | |||
|   ); | ||||
| 
 | ||||
|   route.delete( | ||||
|     '/cookie', | ||||
|     '/cookies/:id', | ||||
|     celebrate({ | ||||
|       params: Joi.object({ | ||||
|         id: Joi.string().required(), | ||||
|       }), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.deleteCookie( | ||||
|           req.body.cookie as string, | ||||
|         ); | ||||
|         if (data) { | ||||
|           return res.send({ code: 400, data }); | ||||
|         } else { | ||||
|           return res.send({ code: 200, data: '新建成功' }); | ||||
|         } | ||||
|         const data = await cookieService.remove(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|  | @ -116,13 +81,102 @@ export default (app: Router) => { | |||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   route.post( | ||||
|     '/cookie/refresh', | ||||
|   route.put( | ||||
|     '/cookies/:id/move', | ||||
|     celebrate({ | ||||
|       params: Joi.object({ | ||||
|         id: Joi.string().required(), | ||||
|       }), | ||||
|       body: Joi.object({ | ||||
|         fromIndex: Joi.number().required(), | ||||
|         toIndex: Joi.number().required(), | ||||
|       }), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.refreshCookie(req.body); | ||||
|         const data = await cookieService.move(req.params.id, req.body); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|       } | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   route.get( | ||||
|     '/cookies/:id/refresh', | ||||
|     celebrate({ | ||||
|       params: Joi.object({ | ||||
|         id: Joi.string().required(), | ||||
|       }), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.refreshCookie(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|       } | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   route.get( | ||||
|     '/cookies/:id/disable', | ||||
|     celebrate({ | ||||
|       params: Joi.object({ | ||||
|         id: Joi.string().required(), | ||||
|       }), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.disabled(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|       } | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   route.get( | ||||
|     '/cookies/:id/enable', | ||||
|     celebrate({ | ||||
|       params: Joi.object({ | ||||
|         id: Joi.string().required(), | ||||
|       }), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.enabled(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|         return next(e); | ||||
|       } | ||||
|     }, | ||||
|   ); | ||||
| 
 | ||||
|   route.get( | ||||
|     '/cookies/:id', | ||||
|     celebrate({ | ||||
|       params: Joi.object({ | ||||
|         id: Joi.string().required(), | ||||
|       }), | ||||
|     }), | ||||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CookieService); | ||||
|         const data = await cookieService.get(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  |  | |||
|  | @ -14,8 +14,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.crontabs( | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.crontabs( | ||||
|           req.query.searchValue as string, | ||||
|         ); | ||||
|         return res.send({ code: 200, data }); | ||||
|  | @ -38,8 +38,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.create(req.body); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.create(req.body); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -58,8 +58,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.run(req.params.id); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.run(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -78,8 +78,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.disabled(req.params.id); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.disabled(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -98,8 +98,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.enabled(req.params.id); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.enabled(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -118,8 +118,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.log(req.params.id); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.log(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -141,8 +141,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.update(req.body); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.update(req.body); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -161,8 +161,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.remove(req.params.id); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.remove(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -176,8 +176,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.import_crontab(); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.import_crontab(); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  | @ -196,8 +196,8 @@ export default (app: Router) => { | |||
|     async (req: Request, res: Response, next: NextFunction) => { | ||||
|       const logger: Logger = Container.get('logger'); | ||||
|       try { | ||||
|         const cookieService = Container.get(CronService); | ||||
|         const data = await cookieService.get(req.params.id); | ||||
|         const cronService = Container.get(CronService); | ||||
|         const data = await cronService.get(req.params.id); | ||||
|         return res.send({ code: 200, data }); | ||||
|       } catch (e) { | ||||
|         logger.error('🔥 error: %o', e); | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ const configString = 'config sample crontab shareCode diy'; | |||
| const dbPath = path.join(rootPath, 'db/'); | ||||
| const manualLogPath = path.join(rootPath, 'manual_log/'); | ||||
| const cronDbFile = path.join(rootPath, 'db/crontab.db'); | ||||
| const cookieDbFile = path.join(rootPath, 'db/cookie.db'); | ||||
| 
 | ||||
| if (envFound.error) { | ||||
|   throw new Error("⚠️  Couldn't find .env file  ⚠️"); | ||||
|  | @ -53,5 +54,6 @@ export default { | |||
|   }, | ||||
|   dbPath, | ||||
|   cronDbFile, | ||||
|   cookieDbFile, | ||||
|   manualLogPath, | ||||
| }; | ||||
|  |  | |||
							
								
								
									
										27
									
								
								back/data/cookie.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								back/data/cookie.ts
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| export class Cookie { | ||||
|   value?: string; | ||||
|   timestamp?: string; | ||||
|   created?: number; | ||||
|   _id?: string; | ||||
|   status?: CookieStatus; | ||||
|   position?: number; | ||||
| 
 | ||||
|   constructor(options: Cookie) { | ||||
|     this.value = options.value; | ||||
|     this._id = options._id; | ||||
|     this.created = options.created || new Date().valueOf(); | ||||
|     this.status = options.status || CookieStatus.noacquired; | ||||
|     this.timestamp = new Date().toString(); | ||||
|     this.position = options.position; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export enum CookieStatus { | ||||
|   'noacquired', | ||||
|   'normal', | ||||
|   'disabled', | ||||
|   'invalid', | ||||
|   'abnormal', | ||||
| } | ||||
| 
 | ||||
| export const initCookiePosition = 9999999999; | ||||
|  | @ -5,180 +5,21 @@ import { getFileContentByName } from '../config/util'; | |||
| import config from '../config'; | ||||
| import * as fs from 'fs'; | ||||
| import got from 'got'; | ||||
| 
 | ||||
| enum Status { | ||||
|   '正常', | ||||
|   '失效', | ||||
|   '状态异常', | ||||
| } | ||||
| import DataStore from 'nedb'; | ||||
| import { Cookie, CookieStatus, initCookiePosition } from '../data/cookie'; | ||||
| 
 | ||||
| @Service() | ||||
| export default class CookieService { | ||||
|   private cookies: string = ''; | ||||
|   private s_token: string = ''; | ||||
|   private guid: string = ''; | ||||
|   private lsid: string = ''; | ||||
|   private lstoken: string = ''; | ||||
|   private okl_token: string = ''; | ||||
|   private token: string = ''; | ||||
|   constructor(@Inject('logger') private logger: winston.Logger) {} | ||||
| 
 | ||||
|   public async getQrUrl(): Promise<{ qrurl: string }> { | ||||
|     await this.step1(); | ||||
|     const qrurl = await this.step2(); | ||||
|     return { qrurl }; | ||||
|   private cronDb = new DataStore({ filename: config.cookieDbFile }); | ||||
|   constructor(@Inject('logger') private logger: winston.Logger) { | ||||
|     this.cronDb.loadDatabase((err) => { | ||||
|       if (err) throw err; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   private async step1() { | ||||
|     try { | ||||
|       let timeStamp = new Date().getTime(); | ||||
|       let url = | ||||
|         'https://plogin.m.jd.com/cgi-bin/mm/new_login_entrance?lang=chs&appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=' + | ||||
|         timeStamp + | ||||
|         '&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport'; | ||||
|       const text = await fetch(url, { | ||||
|         method: 'get', | ||||
|         headers: { | ||||
|           Connection: 'Keep-Alive', | ||||
|           'Content-Type': 'application/x-www-form-urlencoded', | ||||
|           Accept: 'application/json, text/plain, */*', | ||||
|           'Accept-Language': 'zh-cn', | ||||
|           Referer: | ||||
|             'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=' + | ||||
|             timeStamp + | ||||
|             '&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport', | ||||
|           'User-Agent': | ||||
|             'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', | ||||
|           Host: 'plogin.m.jd.com', | ||||
|         }, | ||||
|       }); | ||||
|       await this.praseSetCookies(text); | ||||
|     } catch (error) { | ||||
|       this.logger.error(error); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   private async step2() { | ||||
|     try { | ||||
|       if (this.cookies == '') { | ||||
|         return ''; | ||||
|       } | ||||
|       let timeStamp = new Date().getTime(); | ||||
|       let url = | ||||
|         'https://plogin.m.jd.com/cgi-bin/m/tmauthreflogurl?s_token=' + | ||||
|         this.s_token + | ||||
|         '&v=' + | ||||
|         timeStamp + | ||||
|         '&remember=true'; | ||||
|       const response: any = await fetch(url, { | ||||
|         method: 'post', | ||||
|         body: JSON.stringify({ | ||||
|           lang: 'chs', | ||||
|           appid: 300, | ||||
|           returnurl: | ||||
|             'https://wqlogin2.jd.com/passport/LoginRedirect?state=' + | ||||
|             timeStamp + | ||||
|             '&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action', | ||||
|           source: 'wq_passport', | ||||
|         }), | ||||
|         headers: { | ||||
|           Connection: 'Keep-Alive', | ||||
|           'Content-Type': 'application/x-www-form-urlencoded; Charset=UTF-8', | ||||
|           Accept: 'application/json, text/plain, */*', | ||||
|           Cookie: this.cookies, | ||||
|           Referer: | ||||
|             'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=' + | ||||
|             timeStamp + | ||||
|             '&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport', | ||||
|           'User-Agent': | ||||
|             'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', | ||||
|           Host: 'plogin.m.jd.com', | ||||
|         }, | ||||
|       }); | ||||
|       const body = await response.json(); | ||||
|       this.token = body.token; | ||||
|       const setCookies = response.headers.get('set-cookie'); | ||||
|       this.okl_token = setCookies.match(/okl_token=(.+?);/)[1]; | ||||
|       var qrUrl = | ||||
|         'https://plogin.m.jd.com/cgi-bin/m/tmauth?appid=300&client_type=m&token=' + | ||||
|         this.token; | ||||
|       return qrUrl; | ||||
|     } catch (error) { | ||||
|       console.log(error.response.body); | ||||
|       return ''; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   private async praseSetCookies(response: any) { | ||||
|     const body = await response.json(); | ||||
|     this.s_token = body.s_token; | ||||
|     const setCookies = response.headers.get('set-cookie'); | ||||
|     this.guid = setCookies.match(/guid=(.+?);/)[1]; | ||||
|     this.lsid = setCookies.match(/lsid=(.+?);/)[1]; | ||||
|     this.lstoken = setCookies.match(/lstoken=(.+?);/)[1]; | ||||
|     this.cookies = | ||||
|       'guid=' + | ||||
|       this.guid + | ||||
|       '; lang=chs; lsid=' + | ||||
|       this.lsid + | ||||
|       '; lstoken=' + | ||||
|       this.lstoken + | ||||
|       '; '; | ||||
|   } | ||||
| 
 | ||||
|   private getCookie(response: any) { | ||||
|     const setCookies = response.headers['set-cookie']; | ||||
|     var TrackerID = setCookies[0].match(/TrackerID=(.+?);/)[1]; | ||||
|     var pt_key = setCookies[1].match(/pt_key=(.+?);/)[1]; | ||||
|     var pt_pin = setCookies[2].match(/pt_pin=(.+?);/)[1]; | ||||
|     var pt_token = setCookies[3].match(/pt_token=(.+?);/)[1]; | ||||
|     var pwdt_id = setCookies[4].match(/pwdt_id=(.+?);/)[1]; | ||||
|     var s_key = setCookies[5].match(/s_key=(.+?);/)[1]; | ||||
|     var s_pin = setCookies[6].match(/s_pin=(.+?);/)[1]; | ||||
|     this.cookies = | ||||
|       'TrackerID=' + | ||||
|       TrackerID + | ||||
|       '; pt_key=' + | ||||
|       pt_key + | ||||
|       '; pt_pin=' + | ||||
|       pt_pin + | ||||
|       '; pt_token=' + | ||||
|       pt_token + | ||||
|       '; pwdt_id=' + | ||||
|       pwdt_id + | ||||
|       '; s_key=' + | ||||
|       s_key + | ||||
|       '; s_pin=' + | ||||
|       s_pin + | ||||
|       '; wq_skey='; | ||||
|     var userCookie = 'pt_key=' + pt_key + ';pt_pin=' + pt_pin + ';'; | ||||
|     return userCookie; | ||||
|   } | ||||
| 
 | ||||
|   public async addQrCookie(cookie: string) { | ||||
|     const res: any = await this.checkLogin(); | ||||
|     if (res.body.errcode === 0) { | ||||
|       let ucookie = this.getCookie(res); | ||||
|       let content = getFileContentByName(config.confFile); | ||||
|       const regx = /.*Cookie[0-9]{1}\=\"(.+?)\"/g; | ||||
|       if (content.match(regx)) { | ||||
|         const lastCookie = cookie || (content.match(regx) as any[]).pop(); | ||||
|         const cookieRegx = /Cookie([0-9]+)\=.+?/.exec(lastCookie); | ||||
|         if (cookieRegx) { | ||||
|           const num = parseInt(cookieRegx[1]) + 1; | ||||
|           const newCookie = `${lastCookie}\nCookie${num}="${ucookie}"`; | ||||
|           const result = content.replace(lastCookie, newCookie); | ||||
|           fs.writeFileSync(config.confFile, result); | ||||
|         } | ||||
|       } else { | ||||
|         const newCookie = `Cookie1="${ucookie}"`; | ||||
|         const result = content.replace(`Cookie1=""`, newCookie); | ||||
|         fs.writeFileSync(config.confFile, result); | ||||
|       } | ||||
|       return { cookie: ucookie }; | ||||
|     } else { | ||||
|       return res.body; | ||||
|     } | ||||
|   public async getCookies() { | ||||
|     const content = getFileContentByName(config.cookieFile); | ||||
|     return this.formatCookie(content.split('\n').filter((x) => !!x)); | ||||
|   } | ||||
| 
 | ||||
|   public async addCookie(cookies: string[]) { | ||||
|  | @ -215,53 +56,6 @@ export default class CookieService { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   private async checkLogin() { | ||||
|     try { | ||||
|       if (this.cookies == '') { | ||||
|         return ''; | ||||
|       } | ||||
|       let timeStamp = new Date().getTime(); | ||||
|       let url = | ||||
|         'https://plogin.m.jd.com/cgi-bin/m/tmauthchecktoken?&token=' + | ||||
|         this.token + | ||||
|         '&ou_state=0&okl_token=' + | ||||
|         this.okl_token; | ||||
|       return got.post(url, { | ||||
|         responseType: 'json', | ||||
|         form: { | ||||
|           lang: 'chs', | ||||
|           appid: 300, | ||||
|           returnurl: | ||||
|             'https://wqlogin2.jd.com/passport/LoginRedirect?state=1100399130787&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action', | ||||
|           source: 'wq_passport', | ||||
|         }, | ||||
|         headers: { | ||||
|           Referer: | ||||
|             'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=' + | ||||
|             timeStamp + | ||||
|             '&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport', | ||||
|           Cookie: this.cookies, | ||||
|           Connection: 'Keep-Alive', | ||||
|           'Content-Type': 'application/x-www-form-urlencoded; Charset=UTF-8', | ||||
|           Accept: 'application/json, text/plain, */*', | ||||
|           'User-Agent': | ||||
|             'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36', | ||||
|         }, | ||||
|       }); | ||||
|     } catch (error) { | ||||
|       console.log(error); | ||||
|       let res: any = {}; | ||||
|       res.body = { check_ip: 0, errcode: 222, message: '出错' }; | ||||
|       res.headers = {}; | ||||
|       return res; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public async getCookies() { | ||||
|     const content = getFileContentByName(config.cookieFile); | ||||
|     return this.formatCookie(content.split('\n').filter((x) => !!x)); | ||||
|   } | ||||
| 
 | ||||
|   private async formatCookie(data: any[]) { | ||||
|     const result = []; | ||||
|     for (const x of data) { | ||||
|  | @ -285,14 +79,12 @@ export default class CookieService { | |||
|     return result; | ||||
|   } | ||||
| 
 | ||||
|   public async refreshCookie(body: any) { | ||||
|     const { cookie } = body; | ||||
|     const { nickname, status } = await this.getJdInfo(cookie); | ||||
|   public async refreshCookie(_id: string) { | ||||
|     const current = await this.get(_id); | ||||
|     const { status } = await this.getJdInfo(current.value); | ||||
|     return { | ||||
|       pin: cookie.match(/pt_pin=(.+?);/)[1], | ||||
|       cookie, | ||||
|       ...current, | ||||
|       status, | ||||
|       nickname: nickname, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|  | @ -317,11 +109,140 @@ export default class CookieService { | |||
|       .then((x) => x.json()) | ||||
|       .then((x) => { | ||||
|         if (x.retcode === '0' && x.data && x.data.userInfo) { | ||||
|           return { nickname: x.data.userInfo.baseInfo.nickname, status: 0 }; | ||||
|           return { | ||||
|             nickname: x.data.userInfo.baseInfo.nickname, | ||||
|             status: CookieStatus.normal, | ||||
|           }; | ||||
|         } else if (x.retcode === 13) { | ||||
|           return { status: 1, nickname: '-' }; | ||||
|           return { status: CookieStatus.invalid, nickname: '-' }; | ||||
|         } | ||||
|         return { status: 2, nickname: '-' }; | ||||
|         return { status: CookieStatus.abnormal, nickname: '-' }; | ||||
|       }); | ||||
|   } | ||||
| 
 | ||||
|   public async create(payload: string[]): Promise<void> { | ||||
|     const cookies = await this.cookies('', { postion: 1 }); | ||||
|     let position = initCookiePosition; | ||||
|     if (cookies && cookies.length > 0) { | ||||
|       position = cookies[0].position / 2; | ||||
|     } | ||||
|     const tabs = payload.map((x) => { | ||||
|       const cookie = new Cookie({ value: x, position }); | ||||
|       position = position / 2; | ||||
|       return cookie; | ||||
|     }); | ||||
|     this.cronDb.insert(tabs); | ||||
|     await this.set_cookies(); | ||||
|   } | ||||
| 
 | ||||
|   public async update(payload: Cookie): Promise<void> { | ||||
|     const { _id, ...other } = payload; | ||||
|     const doc = await this.get(_id); | ||||
|     const tab = new Cookie({ ...doc, ...other }); | ||||
|     this.cronDb.update({ _id }, tab, { returnUpdatedDocs: true }); | ||||
|     await this.set_cookies(); | ||||
|   } | ||||
| 
 | ||||
|   public async remove(_id: string) { | ||||
|     this.cronDb.remove({ _id }, {}); | ||||
|     await this.set_cookies(); | ||||
|   } | ||||
| 
 | ||||
|   public async move( | ||||
|     _id: string, | ||||
|     { | ||||
|       fromIndex, | ||||
|       toIndex, | ||||
|     }: { | ||||
|       fromIndex: number; | ||||
|       toIndex: number; | ||||
|     }, | ||||
|   ) { | ||||
|     let targetPosition: number; | ||||
|     const isUpward = fromIndex > toIndex; | ||||
|     const cookies = await this.cookies(); | ||||
|     if (toIndex === 0 || toIndex === cookies.length - 1) { | ||||
|       targetPosition = isUpward | ||||
|         ? (cookies[0].position * 2 + 1) / 2 | ||||
|         : (cookies[toIndex].position * 2 - 1) / 2; | ||||
|     } else { | ||||
|       targetPosition = isUpward | ||||
|         ? (cookies[toIndex].position + cookies[toIndex - 1].position) / 2 | ||||
|         : (cookies[toIndex].position + cookies[toIndex + 1].position) / 2; | ||||
|     } | ||||
|     this.update({ | ||||
|       _id, | ||||
|       position: targetPosition, | ||||
|     }); | ||||
|     await this.set_cookies(); | ||||
|   } | ||||
| 
 | ||||
|   public async cookies( | ||||
|     searchText?: string, | ||||
|     sort: any = { position: -1 }, | ||||
|   ): Promise<Cookie[]> { | ||||
|     let query = {}; | ||||
|     if (searchText) { | ||||
|       const reg = new RegExp(searchText); | ||||
|       query = { | ||||
|         $or: [ | ||||
|           { | ||||
|             name: reg, | ||||
|           }, | ||||
|           { | ||||
|             command: reg, | ||||
|           }, | ||||
|         ], | ||||
|       }; | ||||
|     } | ||||
|     return new Promise((resolve) => { | ||||
|       this.cronDb | ||||
|         .find(query) | ||||
|         .sort({ ...sort }) | ||||
|         .exec((err, docs) => { | ||||
|           resolve(docs); | ||||
|         }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   public async get(_id: string): Promise<Cookie> { | ||||
|     return new Promise((resolve) => { | ||||
|       this.cronDb.find({ _id }).exec((err, docs) => { | ||||
|         resolve(docs[0]); | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   public async getBySort(sort: any): Promise<Cookie> { | ||||
|     return new Promise((resolve) => { | ||||
|       this.cronDb | ||||
|         .find({}) | ||||
|         .sort({ ...sort }) | ||||
|         .limit(1) | ||||
|         .exec((err, docs) => { | ||||
|           resolve(docs[0]); | ||||
|         }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   public async disabled(_id: string) { | ||||
|     this.cronDb.update({ _id }, { $set: { status: CookieStatus.disabled } }); | ||||
|     await this.set_cookies(); | ||||
|   } | ||||
| 
 | ||||
|   public async enabled(_id: string) { | ||||
|     this.cronDb.update({ _id }, { $set: { status: CookieStatus.noacquired } }); | ||||
|   } | ||||
| 
 | ||||
|   private async set_cookies() { | ||||
|     const cookies = await this.cookies(); | ||||
|     let cookie_string = ''; | ||||
|     cookies.forEach((tab) => { | ||||
|       if (tab.status !== CookieStatus.disabled) { | ||||
|         cookie_string += tab.value; | ||||
|         cookie_string += '\n'; | ||||
|       } | ||||
|     }); | ||||
|     fs.writeFileSync(config.cookieFile, cookie_string); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -90,7 +90,7 @@ export default class CronService { | |||
|       this.logger.silly('Original command: ' + res.command); | ||||
| 
 | ||||
|       let logFile = `${config.manualLogPath}${res._id}.log`; | ||||
|       fs.writeFileSync(logFile, `${new Date().toString()}\n\n`); | ||||
|       fs.writeFileSync(logFile, `开始执行...\n\n${new Date().toString()}\n`); | ||||
| 
 | ||||
|       let cmdStr = res.command; | ||||
|       if (res.command.startsWith('js')) { | ||||
|  | @ -121,6 +121,18 @@ export default class CronService { | |||
|         this.logger.silly(err); | ||||
|         fs.appendFileSync(logFile, err.stack); | ||||
|       }); | ||||
| 
 | ||||
|       cmd.on('exit', (code: number, signal: any) => { | ||||
|         this.logger.silly(`cmd exit ${code}`); | ||||
|         this.cronDb.update({ _id }, { $set: { status: CrontabStatus.idle } }); | ||||
|         fs.appendFileSync(logFile, `\n\n执行结束...`); | ||||
|       }); | ||||
| 
 | ||||
|       cmd.on('disconnect', () => { | ||||
|         this.logger.silly(`cmd disconnect`); | ||||
|         this.cronDb.update({ _id }, { $set: { status: CrontabStatus.idle } }); | ||||
|         fs.appendFileSync(logFile, `\n\n连接断开...`); | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,6 +41,8 @@ | |||
|     "qrcode.react": "^1.0.1", | ||||
|     "react-codemirror2": "^7.2.1", | ||||
|     "react-diff-viewer": "^3.1.1", | ||||
|     "react-dnd": "^14.0.2", | ||||
|     "react-dnd-html5-backend": "^14.0.0", | ||||
|     "reflect-metadata": "^0.1.13", | ||||
|     "typedi": "^0.8.0", | ||||
|     "umi": "^3.3.9", | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ export function render(oldRender: any) { | |||
|     }) | ||||
|     .catch((e) => { | ||||
|       console.log(e); | ||||
|       if (e.response.status === 401) { | ||||
|       if (e.response && e.response.status === 401) { | ||||
|         localStorage.removeItem(config.authKey); | ||||
|         history.push('/login'); | ||||
|         oldRender(); | ||||
|  |  | |||
|  | @ -49,12 +49,6 @@ export default { | |||
|         icon: <DiffOutlined />, | ||||
|         component: '@/pages/diff/index', | ||||
|       }, | ||||
|       { | ||||
|         path: '/code', | ||||
|         name: '互助码', | ||||
|         icon: <CodeOutlined />, | ||||
|         component: '@/pages/code/index', | ||||
|       }, | ||||
|       { | ||||
|         path: '/log', | ||||
|         name: '日志', | ||||
|  |  | |||
|  | @ -1,77 +0,0 @@ | |||
| import React, { PureComponent, Fragment, useState, useEffect } from 'react'; | ||||
| import { Button, notification, Modal } from 'antd'; | ||||
| import config from '@/utils/config'; | ||||
| import { PageContainer } from '@ant-design/pro-layout'; | ||||
| import { Controlled as CodeMirror } from 'react-codemirror2'; | ||||
| import { request } from '@/utils/http'; | ||||
| 
 | ||||
| const Crontab = () => { | ||||
|   const [width, setWdith] = useState('100%'); | ||||
|   const [marginLeft, setMarginLeft] = useState(0); | ||||
|   const [marginTop, setMarginTop] = useState(-72); | ||||
|   const [value, setValue] = useState(''); | ||||
|   const [loading, setLoading] = useState(true); | ||||
| 
 | ||||
|   const getConfig = () => { | ||||
|     setLoading(true); | ||||
|     request | ||||
|       .get(`${config.apiPrefix}config/shareCode`) | ||||
|       .then((data) => { | ||||
|         setValue(data.data); | ||||
|       }) | ||||
|       .finally(() => setLoading(false)); | ||||
|   }; | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (document.body.clientWidth < 768) { | ||||
|       setWdith('auto'); | ||||
|       setMarginLeft(0); | ||||
|       setMarginTop(0); | ||||
|     } else { | ||||
|       setWdith('100%'); | ||||
|       setMarginLeft(0); | ||||
|       setMarginTop(-72); | ||||
|     } | ||||
|     getConfig(); | ||||
|   }, []); | ||||
| 
 | ||||
|   return ( | ||||
|     <PageContainer | ||||
|       className="code-mirror-wrapper" | ||||
|       title="互助码" | ||||
|       header={{ | ||||
|         style: { | ||||
|           padding: '4px 16px 4px 15px', | ||||
|           position: 'sticky', | ||||
|           top: 0, | ||||
|           left: 0, | ||||
|           zIndex: 20, | ||||
|           marginTop, | ||||
|           width, | ||||
|           marginLeft, | ||||
|         }, | ||||
|       }} | ||||
|       style={{ | ||||
|         height: '100vh', | ||||
|       }} | ||||
|     > | ||||
|       <CodeMirror | ||||
|         value={value} | ||||
|         options={{ | ||||
|           lineNumbers: true, | ||||
|           lineWrapping: true, | ||||
|           styleActiveLine: true, | ||||
|           matchBrackets: true, | ||||
|           mode: 'shell', | ||||
|           readOnly: true, | ||||
|         }} | ||||
|         onBeforeChange={(editor, data, value) => { | ||||
|           setValue(value); | ||||
|         }} | ||||
|         onChange={(editor, data, value) => {}} | ||||
|       /> | ||||
|     </PageContainer> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| export default Crontab; | ||||
|  | @ -0,0 +1,7 @@ | |||
| tr.drop-over-downward td { | ||||
|   border-bottom: 2px dashed #1890ff; | ||||
| } | ||||
| 
 | ||||
| tr.drop-over-upward td { | ||||
|   border-top: 2px dashed #1890ff; | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| import React, { PureComponent, Fragment, useState, useEffect } from 'react'; | ||||
| import React, { useCallback, useRef, useState, useEffect } from 'react'; | ||||
| import { | ||||
|   Button, | ||||
|   notification, | ||||
|  | @ -7,48 +7,121 @@ import { | |||
|   Tag, | ||||
|   Space, | ||||
|   Typography, | ||||
|   Tooltip, | ||||
| } from 'antd'; | ||||
| import { EditOutlined, DeleteOutlined } from '@ant-design/icons'; | ||||
| import { | ||||
|   EditOutlined, | ||||
|   DeleteOutlined, | ||||
|   SyncOutlined, | ||||
|   CheckCircleOutlined, | ||||
|   StopOutlined, | ||||
| } from '@ant-design/icons'; | ||||
| import config from '@/utils/config'; | ||||
| import { PageContainer } from '@ant-design/pro-layout'; | ||||
| import { request } from '@/utils/http'; | ||||
| import QRCode from 'qrcode.react'; | ||||
| import CookieModal from './modal'; | ||||
| import { DndProvider, useDrag, useDrop } from 'react-dnd'; | ||||
| import { HTML5Backend } from 'react-dnd-html5-backend'; | ||||
| import './index.less'; | ||||
| 
 | ||||
| const { Text } = Typography; | ||||
| 
 | ||||
| enum Status { | ||||
|   '未获取', | ||||
|   '正常', | ||||
|   '失效', | ||||
|   '已禁用', | ||||
|   '已失效', | ||||
|   '状态异常', | ||||
| } | ||||
| 
 | ||||
| enum StatusColor { | ||||
|   'default', | ||||
|   'success', | ||||
|   'error', | ||||
|   'warning', | ||||
|   'error', | ||||
| } | ||||
| 
 | ||||
| const type = 'DragableBodyRow'; | ||||
| 
 | ||||
| const DragableBodyRow = ({ | ||||
|   index, | ||||
|   moveRow, | ||||
|   className, | ||||
|   style, | ||||
|   ...restProps | ||||
| }: any) => { | ||||
|   const ref = useRef(); | ||||
|   const [{ isOver, dropClassName }, drop] = useDrop( | ||||
|     () => ({ | ||||
|       accept: type, | ||||
|       collect: (monitor) => { | ||||
|         const { index: dragIndex } = monitor.getItem() || ({} as any); | ||||
|         if (dragIndex === index) { | ||||
|           return {}; | ||||
|         } | ||||
|         return { | ||||
|           isOver: monitor.isOver(), | ||||
|           dropClassName: | ||||
|             dragIndex < index ? ' drop-over-downward' : ' drop-over-upward', | ||||
|         }; | ||||
|       }, | ||||
|       drop: (item: any) => { | ||||
|         moveRow(item.index, index); | ||||
|       }, | ||||
|     }), | ||||
|     [index], | ||||
|   ); | ||||
|   const [, drag, preview] = useDrag( | ||||
|     () => ({ | ||||
|       type, | ||||
|       item: { index }, | ||||
|       collect: (monitor) => ({ | ||||
|         isDragging: monitor.isDragging(), | ||||
|       }), | ||||
|     }), | ||||
|     [index], | ||||
|   ); | ||||
|   drop(drag(ref)); | ||||
| 
 | ||||
|   return ( | ||||
|     <tr | ||||
|       ref={ref} | ||||
|       className={`${className}${isOver ? dropClassName : ''}`} | ||||
|       style={{ cursor: 'move', ...style }} | ||||
|       {...restProps} | ||||
|     > | ||||
|       {restProps.children} | ||||
|     </tr> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| const Config = () => { | ||||
|   const columns = [ | ||||
|     { | ||||
|       title: '序号', | ||||
|       align: 'center' as const, | ||||
|       render: (text: string, record: any, index: number) => { | ||||
|         return <span style={{ cursor: 'text' }}>{index + 1} </span>; | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       title: '用户名', | ||||
|       dataIndex: 'pin', | ||||
|       key: 'pin', | ||||
|       align: 'center' as const, | ||||
|       render: (text: string, record: any) => { | ||||
|         return <span>{decodeURIComponent(text)}</span>; | ||||
|         const match = record.value.match(/pt_pin=([^; ]+)(?=;?)/); | ||||
|         const val = (match && match[1]) || '未匹配用户名'; | ||||
|         return ( | ||||
|           <span style={{ cursor: 'text' }}>{decodeURIComponent(val)}</span> | ||||
|         ); | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       title: '昵称', | ||||
|       dataIndex: 'nickname', | ||||
|       key: 'nickname', | ||||
|       align: 'center' as const, | ||||
|     }, | ||||
|     { | ||||
|       title: '值', | ||||
|       dataIndex: 'cookie', | ||||
|       key: 'cookie', | ||||
|       dataIndex: 'value', | ||||
|       key: 'value', | ||||
|       align: 'center' as const, | ||||
|       width: '50%', | ||||
|       render: (text: string, record: any) => { | ||||
|  | @ -58,6 +131,7 @@ const Config = () => { | |||
|               textAlign: 'left', | ||||
|               display: 'inline-block', | ||||
|               wordBreak: 'break-all', | ||||
|               cursor: 'text', | ||||
|             }} | ||||
|           > | ||||
|             {text} | ||||
|  | @ -70,12 +144,23 @@ const Config = () => { | |||
|       key: 'status', | ||||
|       dataIndex: 'status', | ||||
|       align: 'center' as const, | ||||
|       render: (text: string, record: any) => { | ||||
|       width: '15%', | ||||
|       render: (text: string, record: any, index: number) => { | ||||
|         return ( | ||||
|           <Space size="middle"> | ||||
|             <Tag color={StatusColor[record.status]}> | ||||
|           <Space size="middle" style={{ cursor: 'text' }}> | ||||
|             <Tag | ||||
|               color={StatusColor[record.status] || StatusColor[3]} | ||||
|               style={{ marginRight: 0 }} | ||||
|             > | ||||
|               {Status[record.status]} | ||||
|             </Tag> | ||||
|             {record.status !== Status.已禁用 && ( | ||||
|               <Tooltip title="刷新"> | ||||
|                 <a onClick={() => refreshStatus(record, index)}> | ||||
|                   <SyncOutlined /> | ||||
|                 </a> | ||||
|               </Tooltip> | ||||
|             )} | ||||
|           </Space> | ||||
|         ); | ||||
|       }, | ||||
|  | @ -86,8 +171,25 @@ const Config = () => { | |||
|       align: 'center' as const, | ||||
|       render: (text: string, record: any, index: number) => ( | ||||
|         <Space size="middle"> | ||||
|           <EditOutlined onClick={() => editCookie(record, index)} /> | ||||
|           <DeleteOutlined onClick={() => deleteCookie(record, index)} /> | ||||
|           <Tooltip title="编辑"> | ||||
|             <a onClick={() => editCookie(record, index)}> | ||||
|               <EditOutlined /> | ||||
|             </a> | ||||
|           </Tooltip> | ||||
|           <Tooltip title={record.status === Status.已禁用 ? '启用' : '禁用'}> | ||||
|             <a onClick={() => enabledOrDisabledCron(record, index)}> | ||||
|               {record.status === Status.已禁用 ? ( | ||||
|                 <CheckCircleOutlined /> | ||||
|               ) : ( | ||||
|                 <StopOutlined /> | ||||
|               )} | ||||
|             </a> | ||||
|           </Tooltip> | ||||
|           <Tooltip title="删除"> | ||||
|             <a onClick={() => deleteCookie(record, index)}> | ||||
|               <DeleteOutlined /> | ||||
|             </a> | ||||
|           </Tooltip> | ||||
|         </Space> | ||||
|       ), | ||||
|     }, | ||||
|  | @ -95,7 +197,7 @@ const Config = () => { | |||
|   const [width, setWdith] = useState('100%'); | ||||
|   const [marginLeft, setMarginLeft] = useState(0); | ||||
|   const [marginTop, setMarginTop] = useState(-72); | ||||
|   const [value, setValue] = useState(); | ||||
|   const [value, setValue] = useState<any[]>([]); | ||||
|   const [loading, setLoading] = useState(true); | ||||
|   const [isModalVisible, setIsModalVisible] = useState(false); | ||||
|   const [editedCookie, setEditedCookie] = useState(); | ||||
|  | @ -110,98 +212,77 @@ const Config = () => { | |||
|       .finally(() => setLoading(false)); | ||||
|   }; | ||||
| 
 | ||||
|   function sleep(time: number) { | ||||
|     return new Promise((resolve) => setTimeout(resolve, time)); | ||||
|   } | ||||
| 
 | ||||
|   const showQrCode = (oldCookie?: string) => { | ||||
|     request.get(`${config.apiPrefix}qrcode`).then(async (data) => { | ||||
|       if (data.qrcode) { | ||||
|         const modal = Modal.info({ | ||||
|           title: '二维码', | ||||
|           content: ( | ||||
|             <div | ||||
|               style={{ | ||||
|                 display: 'flex', | ||||
|                 flexDirection: 'column', | ||||
|                 alignItems: 'center', | ||||
|                 marginLeft: -38, | ||||
|               }} | ||||
|             > | ||||
|               <QRCode | ||||
|                 style={{ | ||||
|                   width: 200, | ||||
|                   height: 200, | ||||
|                   marginBottom: 10, | ||||
|                   marginTop: 20, | ||||
|                 }} | ||||
|                 value={data.qrcode} | ||||
|               /> | ||||
|             </div> | ||||
|           ), | ||||
|         }); | ||||
|         getCookie(modal, oldCookie); | ||||
|       } else { | ||||
|         notification.error({ message: '获取二维码失败' }); | ||||
|       } | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   const getCookie = async ( | ||||
|     modal: { destroy: () => void }, | ||||
|     oldCookie: string = '', | ||||
|   ) => { | ||||
|     for (let i = 0; i < 50; i++) { | ||||
|       const { | ||||
|         data: { cookie, errcode, message }, | ||||
|       } = await request.get(`${config.apiPrefix}cookie?cookie=${oldCookie}`); | ||||
|       if (cookie) { | ||||
|         notification.success({ | ||||
|           message: 'Cookie获取成功', | ||||
|         }); | ||||
|         modal.destroy(); | ||||
|         Modal.success({ | ||||
|           title: '获取Cookie成功', | ||||
|           content: <div>{cookie}</div>, | ||||
|         }); | ||||
|         getCookies(); | ||||
|         break; | ||||
|       } | ||||
|       if (errcode !== 176) { | ||||
|         notification.error({ message }); | ||||
|         break; | ||||
|       } | ||||
|       await sleep(2000); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   const reacquire = async (record: any) => { | ||||
|     await showQrCode(record.cookie); | ||||
|   }; | ||||
| 
 | ||||
|   const refreshStatus = (record: any, index: number) => { | ||||
|     request | ||||
|       .post(`${config.apiPrefix}cookie/refresh`, { | ||||
|         data: { cookie: record.cookie }, | ||||
|       }) | ||||
|       .get(`${config.apiPrefix}cookies/${record._id}/refresh`) | ||||
|       .then(async (data: any) => { | ||||
|         if (data.data && data.data.cookie) { | ||||
|         if (data.data && data.data.value) { | ||||
|           (value as any).splice(index, 1, data.data); | ||||
|           setValue([...(value as any)] as any); | ||||
|           notification.success({ message: '更新状态成功' }); | ||||
|         } else { | ||||
|           notification.error({ message: '更新状态失败' }); | ||||
|         } | ||||
|       }); | ||||
|   }; | ||||
| 
 | ||||
|   const enabledOrDisabledCron = (record: any, index: number) => { | ||||
|     Modal.confirm({ | ||||
|       title: `确认${record.status === Status.已禁用 ? '启用' : '禁用'}`, | ||||
|       content: ( | ||||
|         <> | ||||
|           确认{record.status === Status.已禁用 ? '启用' : '禁用'} | ||||
|           Cookie{' '} | ||||
|           <Text style={{ wordBreak: 'break-all' }} type="warning"> | ||||
|             {record.value} | ||||
|           </Text>{' '} | ||||
|           吗 | ||||
|         </> | ||||
|       ), | ||||
|       onOk() { | ||||
|         request | ||||
|           .get( | ||||
|             `${config.apiPrefix}cookies/${record._id}/${ | ||||
|               record.status === Status.已禁用 ? 'enable' : 'disable' | ||||
|             }`,
 | ||||
|             { | ||||
|               data: { _id: record._id }, | ||||
|             }, | ||||
|           ) | ||||
|           .then((data: any) => { | ||||
|             if (data.code === 200) { | ||||
|               notification.success({ | ||||
|                 message: `${ | ||||
|                   record.status === Status.已禁用 ? '启用' : '禁用' | ||||
|                 }成功`,
 | ||||
|               }); | ||||
|               const newStatus = | ||||
|                 record.status === Status.已禁用 ? Status.未获取 : Status.已禁用; | ||||
|               const result = [...value]; | ||||
|               result.splice(index, 1, { | ||||
|                 ...record, | ||||
|                 status: newStatus, | ||||
|               }); | ||||
|               setValue(result); | ||||
|             } else { | ||||
|               notification.error({ | ||||
|                 message: data, | ||||
|               }); | ||||
|             } | ||||
|           }); | ||||
|       }, | ||||
|       onCancel() { | ||||
|         console.log('Cancel'); | ||||
|       }, | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   const addCookie = () => { | ||||
|     setEditedCookie(null as any); | ||||
|     setIsModalVisible(true); | ||||
|   }; | ||||
| 
 | ||||
|   const editCookie = (record: any, index: number) => { | ||||
|     setEditedCookie(record.cookie); | ||||
|     setEditedCookie(record); | ||||
|     setIsModalVisible(true); | ||||
|   }; | ||||
| 
 | ||||
|  | @ -210,20 +291,24 @@ const Config = () => { | |||
|       title: '确认删除', | ||||
|       content: ( | ||||
|         <> | ||||
|           确认删除Cookie <Text type="warning">{record.cookie}</Text> 吗 | ||||
|           确认删除Cookie{' '} | ||||
|           <Text style={{ wordBreak: 'break-all' }} type="warning"> | ||||
|             {record.value} | ||||
|           </Text>{' '} | ||||
|           吗 | ||||
|         </> | ||||
|       ), | ||||
|       onOk() { | ||||
|         request | ||||
|           .delete(`${config.apiPrefix}cookie`, { | ||||
|             data: { cookie: record.cookie }, | ||||
|           }) | ||||
|           .delete(`${config.apiPrefix}cookies/${record._id}`) | ||||
|           .then((data: any) => { | ||||
|             if (data.code === 200) { | ||||
|               notification.success({ | ||||
|                 message: '删除成功', | ||||
|               }); | ||||
|               getCookies(); | ||||
|               const result = [...value]; | ||||
|               result.splice(index, 1); | ||||
|               setValue(result); | ||||
|             } else { | ||||
|               notification.error({ | ||||
|                 message: data, | ||||
|  | @ -240,10 +325,53 @@ const Config = () => { | |||
|   const handleCancel = (needUpdate?: boolean) => { | ||||
|     setIsModalVisible(false); | ||||
|     if (needUpdate) { | ||||
|       getCookies(); | ||||
|       getCookieDetail(editedCookie); | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   const getCookieDetail = (cookie: any) => { | ||||
|     request | ||||
|       .get(`${config.apiPrefix}cookies/${cookie._id}`) | ||||
|       .then((data: any) => { | ||||
|         const index = value.findIndex((x) => x._id === cookie._id); | ||||
|         const result = [...value]; | ||||
|         result.splice(index, 1, { | ||||
|           ...cookie, | ||||
|           ...data.data, | ||||
|         }); | ||||
|         setValue(result); | ||||
|       }) | ||||
|       .finally(() => setLoading(false)); | ||||
|   }; | ||||
| 
 | ||||
|   const components = { | ||||
|     body: { | ||||
|       row: DragableBodyRow, | ||||
|     }, | ||||
|   }; | ||||
| 
 | ||||
|   const moveRow = useCallback( | ||||
|     (dragIndex, hoverIndex) => { | ||||
|       const dragRow = value[dragIndex]; | ||||
|       const newData = [...value]; | ||||
|       newData.splice(dragIndex, 1); | ||||
|       newData.splice(hoverIndex, 0, dragRow); | ||||
|       setValue([...newData]); | ||||
|       request | ||||
|         .put(`${config.apiPrefix}cookies/${dragRow._id}/move`, { | ||||
|           data: { fromIndex: dragIndex, toIndex: hoverIndex }, | ||||
|         }) | ||||
|         .then((data: any) => { | ||||
|           if (data.code !== 200) { | ||||
|             notification.error({ | ||||
|               message: data, | ||||
|             }); | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     [value], | ||||
|   ); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (document.body.clientWidth < 768) { | ||||
|       setWdith('auto'); | ||||
|  | @ -283,15 +411,24 @@ const Config = () => { | |||
|         height: '100vh', | ||||
|       }} | ||||
|     > | ||||
|       <Table | ||||
|         columns={columns} | ||||
|         pagination={false} | ||||
|         dataSource={value} | ||||
|         rowKey="pin" | ||||
|         size="middle" | ||||
|         bordered | ||||
|         scroll={{ x: 768 }} | ||||
|       /> | ||||
|       <DndProvider backend={HTML5Backend}> | ||||
|         <Table | ||||
|           columns={columns} | ||||
|           pagination={false} | ||||
|           dataSource={value} | ||||
|           rowKey="value" | ||||
|           size="middle" | ||||
|           bordered | ||||
|           scroll={{ x: 768 }} | ||||
|           components={components} | ||||
|           onRow={(record, index) => { | ||||
|             return { | ||||
|               index, | ||||
|               moveRow, | ||||
|             } as any; | ||||
|           }} | ||||
|         /> | ||||
|       </DndProvider> | ||||
|       <CookieModal | ||||
|         visible={isModalVisible} | ||||
|         handleCancel={handleCancel} | ||||
|  |  | |||
|  | @ -8,14 +8,14 @@ const CookieModal = ({ | |||
|   handleCancel, | ||||
|   visible, | ||||
| }: { | ||||
|   cookie?: string; | ||||
|   cookie?: any; | ||||
|   visible: boolean; | ||||
|   handleCancel: (needUpdate?: boolean) => void; | ||||
| }) => { | ||||
|   const [form] = Form.useForm(); | ||||
| 
 | ||||
|   const handleOk = async (values: any) => { | ||||
|     const cookies = values.cookie | ||||
|     const cookies = values.value | ||||
|       .split('\n') | ||||
|       .map((x: any) => x.trim().replace(/\s/g, '')); | ||||
|     let flag = false; | ||||
|  | @ -30,10 +30,8 @@ const CookieModal = ({ | |||
|       return; | ||||
|     } | ||||
|     const method = cookie ? 'put' : 'post'; | ||||
|     const payload = cookie | ||||
|       ? { cookie: cookies[0], oldCookie: cookie } | ||||
|       : { cookies }; | ||||
|     const { code, data } = await request[method](`${config.apiPrefix}cookie`, { | ||||
|     const payload = cookie ? { value: cookies[0], _id: cookie._id } : cookies; | ||||
|     const { code, data } = await request[method](`${config.apiPrefix}cookies`, { | ||||
|       data: payload, | ||||
|     }); | ||||
|     if (code === 200) { | ||||
|  | @ -49,11 +47,7 @@ const CookieModal = ({ | |||
|   }; | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (cookie) { | ||||
|       form.setFieldsValue({ cookie }); | ||||
|     } else { | ||||
|       form.resetFields(); | ||||
|     } | ||||
|     form.resetFields(); | ||||
|   }, [cookie]); | ||||
| 
 | ||||
|   return ( | ||||
|  | @ -74,9 +68,15 @@ const CookieModal = ({ | |||
|       onCancel={() => handleCancel()} | ||||
|       destroyOnClose | ||||
|     > | ||||
|       <Form form={form} layout="vertical" name="form_in_modal" preserve={false}> | ||||
|       <Form | ||||
|         form={form} | ||||
|         layout="vertical" | ||||
|         name="form_in_modal" | ||||
|         preserve={false} | ||||
|         initialValues={cookie} | ||||
|       > | ||||
|         <Form.Item | ||||
|           name="cookie" | ||||
|           name="value" | ||||
|           rules={[ | ||||
|             { required: true, message: '请输入Cookie' }, | ||||
|             { | ||||
|  |  | |||
|  | @ -169,7 +169,11 @@ const Crontab = () => { | |||
|       title: '确认删除', | ||||
|       content: ( | ||||
|         <> | ||||
|           确认删除定时任务 <Text type="warning">{record.name}</Text> 吗 | ||||
|           确认删除定时任务{' '} | ||||
|           <Text style={{ wordBreak: 'break-all' }} type="warning"> | ||||
|             {record.name} | ||||
|           </Text>{' '} | ||||
|           吗 | ||||
|         </> | ||||
|       ), | ||||
|       onOk() { | ||||
|  | @ -201,7 +205,11 @@ const Crontab = () => { | |||
|       title: '确认运行', | ||||
|       content: ( | ||||
|         <> | ||||
|           确认运行定时任务 <Text type="warning">{record.name}</Text> 吗 | ||||
|           确认运行定时任务{' '} | ||||
|           <Text style={{ wordBreak: 'break-all' }} type="warning"> | ||||
|             {record.name} | ||||
|           </Text>{' '} | ||||
|           吗 | ||||
|         </> | ||||
|       ), | ||||
|       onOk() { | ||||
|  | @ -236,7 +244,11 @@ const Crontab = () => { | |||
|       content: ( | ||||
|         <> | ||||
|           确认{record.status === CrontabStatus.disabled ? '启用' : '禁用'} | ||||
|           定时任务 <Text type="warning">{record.name}</Text> 吗 | ||||
|           定时任务{' '} | ||||
|           <Text style={{ wordBreak: 'break-all' }} type="warning"> | ||||
|             {record.name} | ||||
|           </Text>{' '} | ||||
|           吗 | ||||
|         </> | ||||
|       ), | ||||
|       onOk() { | ||||
|  | @ -415,7 +427,7 @@ const Crontab = () => { | |||
|           defaultPageSize: 20, | ||||
|         }} | ||||
|         dataSource={value} | ||||
|         rowKey="pin" | ||||
|         rowKey="_id" | ||||
|         size="middle" | ||||
|         bordered | ||||
|         scroll={{ x: 768 }} | ||||
|  |  | |||
|  | @ -3,6 +3,12 @@ import { Modal, notification, Input, Form } from 'antd'; | |||
| import { request } from '@/utils/http'; | ||||
| import config from '@/utils/config'; | ||||
| 
 | ||||
| enum CrontabStatus { | ||||
|   'running', | ||||
|   'idle', | ||||
|   'disabled', | ||||
| } | ||||
| 
 | ||||
| const CronLogModal = ({ | ||||
|   cron, | ||||
|   handleCancel, | ||||
|  | @ -12,14 +18,14 @@ const CronLogModal = ({ | |||
|   visible: boolean; | ||||
|   handleCancel: () => void; | ||||
| }) => { | ||||
|   const [value, setValue] = useState<string>('运行中...'); | ||||
|   const [value, setValue] = useState<string>('启动中...'); | ||||
|   const [logTimer, setLogTimer] = useState<any>(); | ||||
| 
 | ||||
|   const getCronLog = () => { | ||||
|     request | ||||
|       .get(`${config.apiPrefix}crons/${cron._id}/log`) | ||||
|       .then((data: any) => { | ||||
|         setValue(data.data); | ||||
|         setValue(data.data || '暂无日志'); | ||||
|       }); | ||||
|   }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,9 @@ import config from './config'; | |||
| const time = Date.now(); | ||||
| const errorHandler = function (error: any) { | ||||
|   if (error.response) { | ||||
|     const message = error.data ? error.data.message : error.response.statusText; | ||||
|     const message = error.data | ||||
|       ? error.data.message || error.data | ||||
|       : error.response.statusText; | ||||
|     if (error.response.status !== 401) { | ||||
|       notification.error({ message }); | ||||
|     } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 whyour
						whyour