def _check(cond: dict) -> bool: """ 检查某个计划是否满足全部condition """ tm = time.time() st = time.localtime(tm) if "start_hour" in cond: # 时间段条件 sh = cond["start_hour"] eh = cond["end_hour"] ch = st.tm_hour if sh <= eh: flag = sh <= ch <= eh else: flag = (0 <= ch <= eh) or (sh <= ch <= 23) if not flag: return False if "can_juanzeng" in cond: # 可以捐赠条件 AR = AutomatorRecorder(cond["can_juanzeng"], None) ts = AR.get("time_status", UDD["time_status"]) tm = ts["juanzeng"] diff = time.time() - tm if diff < 8 * 3600 + 60: return False if "_last_rec" in cond: # 前置batch条件 if not Schedule.is_complete(cond["_last_rec"]): return False return True
def list_account(): """ 获取账号列表 --- tags: - 账号 description: responses: 2xx: description: 成功 4xx: description: 参数有误等 """ data = [] count = 0 all_users = list_all_users() count = len(all_users) for username in all_users: try: user = AutomatorRecorder(username).getuser() except Exception as e: return NotFoundError(e) if user is not None: data.append({ 'username': user.get('account'), 'password': '******', 'taskname': user.get('taskfile'), 'tags': '-' }) return ListReply(data, count)
def CheckTuitu(): users = list_all_users(0) for acc in users: AR = AutomatorRecorder(acc) ts = AR.get("tuitu_status", UDD["tuitu_status"]) if ts['max'] is not None: print("USER: "******" Normal: ", ts['max'])
def ClearError(acc): """ 重启某用户的错误让他继续跑 :param acc: 要处理的用户名字 """ AR = AutomatorRecorder(acc) rs = AR.get_run_status() rs["error"] = None rs["finished"] = False AR.set_run_status(rs)
def SetFinished(acc): """ 设置某一个用户的状态为已经跑完 :param acc: 用户 """ AR = AutomatorRecorder(acc) rs = AR.get_run_status() rs["error"] = None rs["finished"] = True rs["current"] = "..." AR.set_run_status(rs)
def CheckTuitu(): users = list_all_users(0) for acc in users: AR = AutomatorRecorder(acc) ts = AR.get("tuitu_status", UDD["tuitu_status"]) if ts['max'] is not None or ts["Hmax"] is not None: print("USER: "******" ") if ts['max'] is not None: print("Normal ", ts["max"], end=" ") if ts["Hmax"] is not None: print("Hard ", ts["Hmax"], end=" ") print("")
def save_batches(): # '{"batch": [{"group": "\u88c5\u5907\u519c\u573a","taskfile": "n11\u88c5\u5907\u519c\u573a","priority": 0}]}' try: obj = request.json BatchesFileName = request.json.get("filename") obj.pop("filename") save_dict = {"batch": [obj]} if check_valid_batch(save_dict, is_raise=False): AutomatorRecorder.setbatch(BatchName, save_dict) old_batch = AutomatorRecorder.getbatch(BatchesFileName) return jsonify({"code": 200, "msg": f"{old_batch}-保存成功"}) else: return jsonify({"code": 500, "msg": f"{save_dict}-保存失败"}) except Exception as e: return jsonify({"code": 500, "msg": f"{e}-保存失败"})
def Restart(acc): """ 重置某一个用户,让它重头跑 Restart之后,再次调用RunContinue时,该用户会从头跑 :param acc: 要处理的用户的名字 """ AR = AutomatorRecorder(acc) rs = AR.get_run_status() rs["error"] = None rs["finished"] = False rs["current"] = "..." AR.set_run_status(rs) target = "rec/%s.rec" % acc if os.path.exists(target): os.remove(target) # 删除行动记录文件
def get_schedules_info(filename): # x,y,z都为字典的拆分所产生出来的临时变量 # 后面会优化 try: r = AutomatorRecorder.getschedule(filename) if len(r['schedules']) > 1: count = 0 for i in r['schedules']: x = list(i.values()) y = list(i.keys()) x[2] = [x[2]] y[2] = 'batchlist' r['schedules'][count] = [dict(zip(y, x))] if count < len(r['schedules']): count = count + 1 elif len(r['schedules']) == 1: x = list(r.values()) y = list(x[0][0].keys()) z = list(x[0][0].values()) for i in range(len(y)): if y[i] == 'batchfile': y[i] = 'batchlist' # if not type(z[i]) is list: z[i] = [z[i]] r['schedules'] = [dict(zip(y, z))] if r: return ListReply(r, 0) else: return 500 except Exception as e: return 500
def is_complete(rec): """ 判断记录Rec是否已经全部完成 :param rec: 存档目录 """ if os.path.exists(os.path.join(rec, "_fin")): return True _, bat = os.path.split(rec) parsed = parse_batch(AutomatorRecorder.getbatch(bat)) for _, acc, _, _ in parsed: rs = AutomatorRecorder(acc, rec).get_run_status() if not rs["finished"] or rs["error"] is not None: return False with open(os.path.join(rec, "_fin"), "w") as f: f.write("出现这个文件表示该文件夹内的记录已经刷完。") return True
def save_schedules(): # '{"name":"test","batchlist":["zhuangbeirichang"],"condition":{},"type":"asap"}' try: obj = request.json ScheduleFileName = request.json.get("filename") # old_schedule = AutomatorRecorder.getschedule(ScheduleFileName) obj.pop("filename") save_dict = {"schedules": [obj]} if check_valid_schedule(save_dict, is_raise=False): AutomatorRecorder.setschedule(ScheduleFileName, save_dict) old_schedule = AutomatorRecorder.getschedule(ScheduleFileName) return jsonify({"code": 200, "msg": f"{old_schedule}-保存成功"}) else: return jsonify({"code": 500, "msg": f"{save_dict}-保存失败"}) except Exception as e: return jsonify({"code": 500, "msg": f"{e}-保存失败"})
def ContinueBatch(batch): global PCR if PCR is None: StartPCR() bj = AutomatorRecorder.getbatch(batch) parsed = parse_batch(bj) PCR.add_tasks(parsed, True, f"rec/__batch__/{batch}")
def BindAccount(account): global last_account, AR if account != "": last_account = account AR = AutomatorRecorder(account) with open("bind_account.txt", "w", encoding="utf-8") as f: f.write(account) print("account绑定成功:", account)
def count_complete(rec): """ 统计记录Rec中完成账号的数量 输出:完成数 / 总数 """ _, bat = os.path.split(rec) parsed = parse_batch(AutomatorRecorder.getbatch(bat)) L = len(parsed) if os.path.exists(os.path.join(rec, "_fin")): return L, L else: cnt = 0 for _, acc, _, _ in parsed: rs = AutomatorRecorder(acc, rec).get_run_status() if rs["finished"] and rs["error"] is None: cnt += 1 return cnt, L
def get_batches_info(filename): try: r = AutomatorRecorder.getbatch(filename) if r: return ListReply(r, 0) else: return 500 except Exception as e: return 500
def _add(self, name, batch): """ 将一个schedule添加到PCR中 运行路径: rec/<schedules_name>/<schedule_name>/<batch_name> """ rec_addr = os.path.join("rec", self.name, name, batch) os.makedirs(rec_addr, exist_ok=True) parsed = parse_batch(AutomatorRecorder.getbatch(batch)) self.pcr.add_tasks(parsed, True, rec_addr)
def CheckState(): users = list_all_users(0) for acc in users: AR = AutomatorRecorder(acc) uj = AR.getuser() print("USER: "******" TASK: ", "NONE" if uj["taskfile"] == "" else uj["taskfile"], "STATUS ", end="") rs = AR.get_run_status() if rs["error"] is None: if rs["finished"]: print("FINISHED.") else: print("CURRENT: ", rs["current"]) else: print("ERROR: ", rs["error"])
def add_task(self, task: Union[Tuple[int, str, str, dict], Tuple[int, str, str]], continue_, rec_addr): """ 向优先级队列中增加一个task 该task为六元组,(priority, account, taskname,rec_addr, task, continue_) """ if len(task) == 3: task = (0 - task[0], task[1], task[2], rec_addr, AutomatorRecorder.gettask(task[2]), continue_) else: task = (0 - task[0], task[1], task[2], rec_addr, task[3], continue_) # 最大优先队列 self._add_task(task)
def init(self, address, account): """ device: 如果是 USB 连接,则为 adb devices 的返回结果;如果是模拟器,则为模拟器的控制 URL 。 """ self.appRunning = False self.account = account self.d = u2.connect(address) self.dWidth, self.dHeight = self.d.window_size() self.log = log_handler.pcr_log(account) # 初始化日志 self.AR = AutomatorRecorder(account)
def GetLastAccount(): global last_account, AR if not os.path.exists("bind_account.txt"): last_account = "" AR = None return with open("bind_account.txt", "r", encoding="utf-8") as f: lines = f.readlines() if len(lines) > 0: last_account = lines[0] AR = AutomatorRecorder(last_account)
def ContinueTask(is_group, name, taskname, priority): global PCR if PCR is None: StartPCR() if is_group: accs = AutomatorRecorder.getgroup(name) else: accs = [name] check_users_exists(accs) for acc in accs: PCR.add_task((priority, acc, taskname), True, "rec/__directly__")
def CheckStateReturn(): users = list_all_users(0) acc_task_info = [] for acc in users: AR = AutomatorRecorder(acc) uj = AR.getuser() acc_task_tmpinfo = "账号:%s 任务:%s 状态:" % (acc, "NONE" if uj["taskfile"] == "" else uj["taskfile"]) rs = AR.get_run_status() if rs["error"] is None: if rs["finished"]: acc_task_tmpinfo = acc_task_tmpinfo + "FINISHED." else: acc_task_tmpinfo = acc_task_tmpinfo + "CURRENT:%s" % rs[ "current"] else: acc_task_tmpinfo = acc_task_tmpinfo + "ERROR:%s" % rs["error"] acc_task_info.append(acc_task_tmpinfo) acc_task_info.append('\n') acc_task_info = ''.join(acc_task_info).replace(',', '\n').replace("'", '') return acc_task_info
def _set_users(self, name, mode): """ 统一设置run_status。 mode = 0:完成并清除Error mode = 1:清除Error mode = 2:重置 """ for _, nam, b, _, rec in self.SL: if nam == name or name is None: parsed = parse_batch(AutomatorRecorder.getbatch(b)) for _, acc, _, _ in parsed: AR = AutomatorRecorder(acc, rec) rs = AR.get_run_status() if mode == 0: rs["finished"] = True rs["error"] = None if mode == 1: if rs["error"] is not None: rs["error"] = None rs["finished"] = False if mode == 2: if name is None and nam in self.not_restart_name: continue if name is None or name == nam: if os.path.isdir(rec): self.del_file_in_path(rec) if rs["error"] is None: rs["finished"] = False rs["current"] = "..." AR.set_run_status(rs)
def retrieve_account(username): """ 获取单条账号 --- tags: - 账号 description: parameters: - name: username in: path type: string required: true description: 用户名 responses: 2xx: description: 成功 4xx: description: 参数有误等 """ if username == '': return BadRequestError(f'参数不合法, 用户名:{username}') data = { 'username': '', 'password': '******', 'taskname': '', 'tags': '-' } try: user = AutomatorRecorder(username).getuser() if user is not None: data['username'] = user.get('account') data['taskname'] = user.get('taskfile') return Reply(data) except Exception as e: return NotFoundError(f"获取用户 {username} 失败, {e}")
def _add_task(self, task): """ 队列中添加任务五元组 """ rs = AutomatorRecorder(task[1], task[3]).get_run_status() if task[5] and rs["finished"]: if task not in self.finished_tasks: self.finished_tasks += [task] else: try: if task not in self.tasks.get_attribute("queue"): self.tasks.put(task) except Exception as e: pass
def get_status(self): """ 获取队列中序号、账号、执行目录、当前状态 """ q = self.tasks.get_attribute("queue") L = [] for ind, T in enumerate(q): if type(T) is not tuple or len(T) != 6: print("DEBUG: ", T) break (_, acc, taskname, rec, _, _) = T state = AutomatorRecorder.get_user_state(acc, rec) L += [(ind, acc, taskname, rec, state)] return L
def login_auth(self, ac, pwd): # CreatIDnum() 可能阿B升级了验证,不推荐使用了,没有合法性校验 need_auth = self.login(ac=ac, pwd=pwd) if need_auth == -1: # 这里漏了一句,无法检测验证码。 return -1 if need_auth == 1: if use_my_id: real_id = AutomatorRecorder.load("./idcard.json") id_list = list(real_id.keys()) count = random.randint(0, len(id_list) - 1) self.auth(auth_name=id_list[count], auth_id=real_id[id_list[count]]) else: birthday = str(random.randint(1970, 1999)) auth_name, auth_id = random_name(), validator.fake_id(birthday=birthday) self.auth(auth_name=auth_name, auth_id=auth_id)
def __init__(self, name: str, pcr: Optional[PCRInitializer]): self.pcr = pcr self.state = 0 self.config = {} self.SL = [] # 处理后的schedule self.run_status = {} # 运行状态 self.checked_status = {} # 存放一个计划是否已经被add过 self.subs = {} # 关系表 self.not_restart_name = [] # record=1,不用重启的列表 self.always_restart_name = [] # record=2,循环执行的列表 if name != "": self.name = name self.schedule = AutomatorRecorder.getschedule(name) self._parse() self._init_status() else: self.name = "" self.schedule = {} self.run_thread: Optional[threading.Thread] = None
def show(self): """ 显示当前全部设备状态 """ print("= 设备信息 =") for i, j in self.devices.items(): print(i, ": ", end="") if j.state == Device.DEVICE_OFFLINE: print("离线") elif j.state == Device.DEVICE_AVAILABLE: print("空闲", " 开机时间", time_period_format(time.time() - j.time_wake)) elif j.state == Device.DEVICE_BUSY: tm = time.time() print("正忙", " 开机时间", time_period_format(tm - j.time_wake), " 本次工作时间", time_period_format(tm - j.time_busy), end="") if j.cur_acc != "": print(" 当前任务:账号", j.cur_acc, AutomatorRecorder.get_user_state(j.cur_acc, j.cur_rec), end="") if j.emulator_launcher is not None: print(" [自动控制中]", end="") print()
def del_schedule(filename): try: AutomatorRecorder.del_schedule(filename) return 200 except Exception as e: return 500