def __list_all_devices(_config: IosAccountHelper): ret = _config.post( "获取所有的列表", "https://developer.apple.com/services-account/QH65B2/account/ios/device/listDevices.action?teamId=", data={ "includeRemovedDevices": True, "includeAvailability": True, "pageNumber": 1, "pageSize": 100, "sort": "status%3dasc", "teamId": _config.team_id, }, log=False) for device in ret["devices"]: # type: Dict _reg_device( device["deviceId"], device["deviceNumber"], device.get("model", device.get("deviceClass", "#UNKNOWN#")), device.get("serialNumber", "#UNKNOWN#")) # 更新一下info devices = list(map(lambda x: x["deviceNumber"], ret["devices"])) if json_str(devices) != _config.info.devices: Log("更新设备列表[%s]数量[%s]=>[%s]" % (_config.account, _config.info.devices_num, len(devices))) _config.info.devices = json_str(devices) _config.info.devices_num = len(devices) _config.info.save()
def __profile_detail(_config: IosAccountHelper, _profile: IosProfileInfo): ret = _config.post( "获取profile详情", "https://developer.apple.com/services-account/QH65B2/account/ios/profile/getProvisioningProfile.action?teamId=", data={ "includeInactiveProfiles": True, "provisioningProfileId": _profile.profile_id, "teamId": _config.team_id, }, ) profile = ret["provisioningProfile"] devices = list(map(lambda x: x["deviceNumber"], profile["devices"])) devices_str = json_str(devices) if _profile.devices != devices_str: _profile.devices = devices_str _profile.devices_num = len(devices) __download_profile(_config, _profile) Log("更新profile[%s]" % _profile.sid) _profile.save() certs = [] for each in profile["certificates"]: certs.append(each["certificateId"]) if _profile.certs != json_str(certs): _profile.certs = json_str(certs) _profile.save()
def process_exception(self, request: HttpRequest, e: Exception): Trace("执行[%s][%s]出错" % (request.path, json_str(getattr(request, "_orig_params", {}))[:1000]), e) msg = str(e) if isinstance(e, AssertionError) else "服务器出错" if len(msg) > 1000: msg = msg[:996] + " ..." return HttpResponse(json_str({ "ret": -1, "error": msg, }), content_type="application/json", status=500)
def __save_cookie(self, cookie: Dict): _orig = self.info.cookie _new = json_str(cookie) if _orig == _new: return self.info.cookie = _new self.info.save()
def mongo_pack_set(key: str, value: dict, model: str, size=1 * 1000 * 1000): """ 大于16M的插入 以多个对象存在 """ db = mongo(model) v = json_str(value) if len(v) < size: return mongo_set(key, value, model) # 需要切一下 Assert("__pack__" not in value, "数据内不能有 __pack__ 字段") Assert("__no__" not in value, "数据内不能有 __no__ 字段") Assert("__value__" not in value, "数据内不能有 __value__ 字段") Assert("__length__" not in value, "数据内不能有 __length__ 字段") pack_length = int(ceil(len(v) / size)) new_value = list( map( lambda x: { "__pack__": True, "__no__": v, "__length__": pack_length, "__value__": v[x * size:(x + 1) * size], }, range(0, pack_length))) if mongo(model).find_one({ "_id": "%s_%s" % (model, key) }, ["__pack__", "__length__"]).get("__length__", 0) > pack_length: # 删除旧的部分 mongo_pack_pop(key, model) mongo_set(key, new_value[0], model) for each in new_value[1:]: mongo_set(key, each, model) return True
def _reg_cert(_config: IosAccountInfo, cert_req_id, name, cert_id, sn, type_str, expire): sid = "%s:%s" % (_config.account, name) orig = str_json( db_model.get("IosCertInfo:%s:%s" % (_config.account, name)) or '{}') obj = { "name": name, "app": _config.account, "cert_req_id": cert_req_id, "cert_id": cert_id, "sn": sn, "type_str": type_str, "expire": expire, "expire_str": date_time_str(expire), } if orig == obj: return cert_req_id db_model.set("IosCertInfo:%s:%s" % (_config.account, name), json_str(obj), ex=(expire - now()) // 1000) _info = IosCertInfo() _info.sid = sid _info.app = _config.account _info.cert_req_id = cert_req_id _info.cert_id = cert_id _info.sn = sn _info.type_str = type_str _info.name = name _info.create = now() _info.expire = datetime.datetime.utcfromtimestamp(expire // 1000) _info.save() Log("注册新的证书[%s][%s]" % (name, cert_req_id)) return cert_req_id
def __add_task(_user: UserInfo): _account = IosAccountInfo.objects.filter( account=_user.account).first() # type:IosAccountInfo _project = IosProjectInfo.objects.filter( project=_user.project).first() # type:IosProjectInfo _profile = IosProfileInfo.objects.filter( sid="%s:%s" % (_user.account, _user.project)).first() # type:IosProfileInfo Assert(_profile, "[%s][%s]证书无效" % (_project.project, _account.account)) Log("[%s]发布任务[%s]" % (_user.project, _user.account)) db_session.publish( "task:package", json_str({ "cert": "iPhone Developer: zhangming luo", "cert_p12": "", "mp_url": entry("/apple/download_mp?uuid=%s" % _user.uuid), "mp_md5": md5bytes(base64decode(_profile.profile)), "project": _project.project, "ipa_url": _asset_url("%s/orig.ipa" % _user.project), "ipa_md5": _project.md5sum, "ipa_new": "%s_%s.ipa" % (_account.team_id, _account.devices_num), "upload_url": entry("/apple/upload_ipa?project=%s&account=%s" % (_user.project, _user.account)), "ts": now(), }))
def publish_security_code(account: str, code: str, ts: int): db_session.publish( "account:security:code", json_str({ "account": account, "code": code, "ts": ts, }))
def login_by_fastlane(_req: HttpRequest, cmd: str = "", account: str = ""): """ 通过命令获取会话 fastlane spaceauth -u [email protected] ex. export FASTLANE_SESSION='---\n- !ruby/object:HTTP::Cookie\n name: myacinfo\n value: DAWTKNV2e32a0823580640561dc9dfd382265048c32c2aa5b04485930b2ada1d1c7eba28dee6c6065c749f708f2a429f8f9f2d0f2f7d2ad629652ca5bc3383c0772d51c6ca34a2f7b09141f7b19c358c2b25d0738079ab1e48a06610228a574342c84ef13349ede1a012c25155e265a17989a3b09631dd953954505153fb7ef71aecfe303530cb684c89e8402cb82d8d4d93c3fc3c1209e334f65f71c7ae0cfdf0349ec757abcb104a591f5bea25ac0f1207004c19645b80ed82fb5cd0d3a740224b2f3aef9e91b049bb63a94ae3c76d027411f077069865209d733617a7a84f54cf7e9488e9b4f0a918d29f184f5ec76d95b5f55def61682f70b7f10fc12dc43d6e380213dd1f702a4f3ccab3ad438cd0f6a87c295e028a12ec410aa3fa689210d040377995914d4d3718b90f85ad5452d5db47ef9ae11c6b3216cf8ab61025adc203b0bf072ce832240c384d83f0f4aaf477a3c7313de4c20c5e32c530ff1ad76aebcd8538ac485a9a46941dfa94ee2f3fb40e38666533326562333665333834343461323366383636666563303166613533303330656361323836MVRYV2\n domain: apple.com\n for_domain: true\n path: "/"\n secure: true\n httponly: true\n expires: \n max_age: \n created_at: 2019-03-15 11:55:51.031441000 +08:00\n accessed_at: 2019-03-15 11:55:51.041509000 +08:00\n- !ruby/object:HTTP::Cookie\n name: dqsid\n value: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJzZnp2ZGFldGJPeWpXaTc1LVpTRmNBIn0.IEYqXF-pxIYdIwP2rdNRNhoxdCzJgGxt4olTZa2fXo8\n domain: olympus.itunes.apple.com\n for_domain: false\n path: "/"\n secure: true\n httponly: true\n expires: \n max_age: 1800\n created_at: &1 2019-03-15 11:55:52.798977000 +08:00\n accessed_at: *1\n curl localhost:8000/apple/login_by_fastlane --data $FASTLANE_SESSION """ if not cmd: cmd = _req.body.decode("utf-8") Assert(len(cmd), "命令行不对") cmd = cmd.replace("\\n", "") cookie = dict(re.compile(r"name:\s+(\S+)\s+value:\s+(\S+)").findall(cmd)) if not account: rsp = requests.post( "https://developer.apple.com/services-account/QH65B2/account/getUserProfile", headers={"cookie": to_form_url(cookie, split=';')}) if rsp.status_code != 200: return { "succ": False, "reason": "无效的fastlane export", } data = rsp.json() account = data["userProfile"]["email"] if account: _info = IosAccountInfo.objects.filter( account=account).first() # type:IosAccountInfo if not _info: _info = IosAccountInfo() _info.account = account _info.save() _info.cookie = json_str(cookie) _info.headers = json_str({}) _info.save() Log("通过fastlane登录[%s]" % account) return { "succ": True, "msg": "登录[%s]成功" % account, } else: return { "succ": False, "msg": "请求不具备提取登录信息", }
def _reg_device(account: str, device_id: str, udid: str, model: str, sn: str) -> str: # 需要缓存 _info = IosDeviceInfo() _info.sid = "%s:%s" % (account, udid) _info.account = account _info.udid = udid _info.device_id = device_id _info.model = model _info.sn = sn _info.create = now() _info.save() Log("注册新的设备[%s][%s][%s]" % (udid, device_id, sn)) _account = IosAccountInfo.objects.get(account=account) device_map = str_json(_account.devices) device_map[udid] = device_id if json_str(device_map) != _account.devices: _account.devices = json_str(device_map) _account.devices_num = len(device_map) _account.save() return udid
def _get_app(_config: IosAccountHelper, project: str) -> IosAppInfo: app = IosAppInfo.objects.filter( sid="%s:%s" % (_config.account, project), ).first() # type: IosAppInfo if not app: _project = IosProjectInfo.objects.filter( project=project).first() # type: IosProjectInfo _identifier = "%s.%s" % (_project.bundle_prefix, GetRandomName()) _config.post( "验证一个app", "https://developer.apple.com/services-account/QH65B2/account/ios/identifiers/validateAppId.action?teamId=", data={ "teamId": _config.team_id, "appIdName": "ci%s" % project, "appIdentifierString": _identifier, "type": "explicit", "explicitIdentifier": _identifier, }, ) _config.post( "注册一个app", "https://developer.apple.com/services-account/v1/bundleIds", data=json_str({ "data": { "type": "bundleIds", "attributes": { "name": "ci%s" % project, "identifier": _identifier, "platform": "IOS", "seedId": _config.team_id, "teamId": _config.team_id, }, "relationships": { "bundleIdCapabilities": { "data": tran(get_capability, str_json(_project.capability)), }, }, }, }), ex_headers={ "content-type": "application/vnd.api+json", }, csrf=True, json_api=False, status=201, ) __list_all_app(_config, project) app = IosAppInfo.objects.filter( sid="%s:%s" % (_config.account, project), ).first() # type: IosAppInfo return Assert(app, "账号[%s]缺少app[%s]" % (_config.account, project))
def _newbee(_project: IosProjectInfo): # 默认一天的时效 for _ in range(100): import uuid _uuid = uuid.uuid4() if db_session.set("uuid:%s" % _uuid, json_str({ "project": _project.project, }), ex=3600 * 24, nx=True): return str(_uuid) raise Fail("生成失败")
def _wait_code(info: IosAccountInfo, session: requests.Session, ts, save_now=False): """ 等待二次提交的需要 """ Log("等待[%s]二次验证" % info.account) # last = info.security_code expire = now() + 1200 * 1000 while now() < expire: gevent.sleep(1) for data in message_from_topic(__pub, is_json=True, limit=1): if data.get("ts") > ts: if data.get("code") and data.get("account") in { info.account, "*" }: rsp = session.post( "https://idmsa.apple.com/appleauth/auth/verify/phone/securitycode", json={ "securityCode": { "code": str(data.get("code")), }, "phoneNumber": { "id": 1, }, "mode": "sms", }) # Log("[%s] %s" % (rsp.status_code, rsp.json())) # rsp = session.post("https://idmsa.apple.com/appleauth/auth/verify/trusteddevice/securitycode", json={ # "securityCode": {"code": data["code"]}, # }) if rsp.status_code != 200: Log("账号[%s]验证校验码[%s]失败[%s]" % (info.account, data.get("code"), rsp.status_code)) # if rsp.status_code != 204: # Log("账号[%s]验证校验码[%s]失败[%s]" % (info.account, data.get("code"), rsp.status_code)) # continue rsp = session.get( "https://idmsa.apple.com/appleauth/auth/2sv/trust") if rsp.status_code == 204: session.cookies.update( {"__expire": str(now() + 6 * 3600 * 1000)}) if save_now: info.cookie = json_str(session.cookies) info.save() Log("账号[%s]登录成功" % info.account) return session raise Fail("登录二次验证超时")
def to_response(ret: any, req: HttpRequest = None) -> HttpResponse: if isinstance(ret, HttpResponse): return ret if isinstance(ret, Mapping): pass elif callable(ret) and hasattr(ret, "_is_action"): assert req is not None depth = getattr(req, "_depth", 0) + 1 assert depth < 10 setattr(req, "_depth", depth) return to_response(ret(req)) else: ret = {"msg": ret} rsp = HttpResponse(json_str({ "ret": 0, "result": ret }, cls=DjangoExJSONEncoder), content_type="application/json") rsp["Access-Control-Allow-Origin"] = "*" rsp["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS" return rsp
def resign_ipa(self: Task, uuid: str, cert: str, cert_url: str, cert_md5: str, mp_url, mp_md5, project, ipa_url, ipa_md5, ipa_new, upload_url, process_url: str): worker = self.request.hostname Log("[%s]启动Celery任务[%s][%s][%s]" % (worker, uuid, self.request.retries, json_str(self.request.kwargs))) base = tempfile.gettempdir() _update_state(process_url, worker, "ready") # 确认ipa with Block("cert部分"): if cert in _certs: Log("钥匙串中已经拥有证书[%s]" % cert) else: _refresh_certs() if cert in _certs: Log("钥匙串中已经拥有证书[%s]" % cert) else: _update_state(process_url, worker, "prepare_cert") Log("下载证书p12[%s]" % cert) file_cert = os.path.join(base, "cert.p12") assert call(["wget", cert_url, "-O", file_cert, "-o", "/dev/null"]) == 0, "下载[%s]失败了" % cert_url assert md5bytes( read_binary_file(file_cert)) == cert_md5, "下载[%s]失败" % cert_url Log("导入证书p12[%s]" % cert) assert call([SECURITY_BIN, "import", file_cert, "-P", "q1w2e3r4"]), "导入证书[%s]失败" % cert with Block("mobileprovision部分"): file_mp = os.path.join(base, "package.mobileprovision") if os.path.isfile(file_mp) and md5bytes( read_binary_file(file_mp)) == mp_md5: Log("采用本地的mobileprovision文件") else: _update_state(process_url, worker, "prepare_mp") Log("下载mobileprovision文件") os.makedirs(os.path.join("package", project), exist_ok=True) assert call(["wget", mp_url, "-O", file_mp, "-o", "/dev/null"]) == 0, "下载[%s]失败了" % mp_url assert md5bytes( read_binary_file(file_mp)) == mp_md5, "下载[%s]失败" % mp_url with Block("ipa部分"): file_ipa = os.path.join("package", project, "orig.ipa") if os.path.isfile(file_ipa) and md5bytes( read_binary_file(file_ipa)) == ipa_md5: Log("采用本地的ipa文件") else: _update_state(process_url, worker, "prepare_ipa") Log("下载ipa文件[%s]" % ipa_url) os.makedirs(os.path.join("package", project), exist_ok=True) assert call(["wget", ipa_url, "-O", file_ipa, "-o", "/dev/null"]) == 0, "下载[%s]失败了" % ipa_url assert md5bytes( read_binary_file(file_ipa)) == ipa_md5, "下载[%s]失败了" % ipa_url with Block("打包"): Log("开始打包[%s]" % project) file_new = os.path.join("package", project, ipa_new) _update_state(process_url, worker, "resign") # noinspection PyBroadException try: _package(file_ipa, file_mp, cert, file_new) except Exception: _update_state(process_url, worker, "fail") with Block("上传"): _update_state(process_url, worker, "upload_ipa") Log("上传ipa[%s][%s]" % (project, upload_url)) rsp = requests.post(upload_url, files={ "worker": worker, "file": read_binary_file(file_new), }) assert rsp.status_code == 200 assert rsp.json()["ret"] == 0 Log("任务完成") _update_state(process_url, worker, "succ", fail=True) return { "succ": True, "uuid": uuid, }
def __add_device(account: IosAccountInfo, udid: str, project: str) -> bool: title = "设备%s" % udid _config = IosAccountHelper(account) try: _device = IosDeviceInfo.objects.filter( udid=udid).first() # type:Optional[IosDeviceInfo] if not _device: # 先注册设备 ret = _config.post( "验证设备udid", "https://developer.apple.com/services-account/QH65B2/account/ios/device/validateDevices.action?teamId=", { "deviceNames": title, "deviceNumbers": udid, "register": "single", "teamId": _config.team_id, }, cache=True) Assert( len(ret["failedDevices"]) == 0, "验证udid请求失败[%s][%s]" % (udid, ret["validationMessages"])) __list_all_devices(_config) ret = _config.post( "添加设备", "https://developer.apple.com/services-account/QH65B2/account/ios/device/addDevices.action?teamId=%s" % _config.team_id, { "deviceClasses": "iphone", "deviceNames": title, "deviceNumbers": udid, "register": "single", "teamId": _config.team_id, }, csrf=True) Assert(ret["resultCode"] == 0, "添加udid请求失败[%s]" % udid) Assert(not ret["validationMessages"], "添加udid请求失败[%s]" % udid) Assert(ret["devices"], "添加udid请求失败[%s]" % udid) device = ret["devices"][0] # type: Dict _reg_device(device["deviceId"], device["deviceNumber"], device["model"], device["serialNumber"]) with Block("更新"): ret, _info = __list_all_profile(_config, project) if not _info: _info = IosProfileInfo() _info.sid = "%s:%s" % (_config.account, project) _info.app = _config.account _info.devices = "[]" _info.devices_num = 0 _info.project = project devices = str_json(_info.devices) # type: List[str] if udid in devices: pass else: devices.append(udid) with Block("默认全开当期的设备"): # noinspection PyTypeChecker devices = list( set(devices + str_json(_config.info.devices))) _cert = _get_cert(_config.info) _app = _get_app(_config, project) found = False for each in ret["provisioningProfiles"]: # type: Dict if each["name"] != "专用 %s" % project: continue # todo: 过期更新 ret = _config.post( "更新ProvisioningProfile", "https://developer.apple.com/services-account/QH65B2/account/ios/profile/regenProvisioningProfile.action?teamId=", data={ "provisioningProfileId": each["provisioningProfileId"], "distributionType": "limited", "subPlatform": "", "returnFullObjects": False, "provisioningProfileName": each["name"], "appIdId": _app.app_id_id, "certificateIds": _cert.cert_req_id, "deviceIds": ",".join(_get_device_id(devices).values()), }, csrf=True) Assert(ret["resultCode"] == 0) _info.devices = json_str(devices) _info.profile_id = each["provisioningProfileId"] # noinspection PyTypeChecker _info.profile = ret["provisioningProfile"][ "encodedProfile"] _info.expire = _to_dt( ret["provisioningProfile"]["dateExpire"]) _info.save() found = True Log("更新证书[%s]添加设备[%s][%s]成功" % (project, udid, len(devices))) break if not found: ret = _config.post( "创建ProvisioningProfile", "https://developer.apple.com/services-account/QH65B2/account/ios/profile/createProvisioningProfile.action?teamId=", data={ "subPlatform": "", "certificateIds": _cert.cert_req_id, "deviceIds": ",".join(_get_device_id(devices).values()), "template": "", "returnFullObjects": False, "distributionTypeLabel": "distributionTypeLabel", "distributionType": "limited", "appIdId": _app.app_id_id, "appIdName": _app.name, "appIdPrefix": _app.prefix, "appIdIdentifier": _app.identifier, "provisioningProfileName": "专用 %s" % project, }, csrf=True) Assert(ret["resultCode"] == 0) # noinspection PyTypeChecker _info.profile_id = ret["provisioningProfile"][ "provisioningProfileId"] # noinspection PyTypeChecker _info.profile = ret["provisioningProfile"][ "encodedProfile"] _info.expire = _to_dt( ret["provisioningProfile"]["dateExpire"]) _info.save() Log("添加证书[%s]添加设备[%s][%s]成功" % (project, udid, len(devices))) except Exception as e: Trace("添加设备出错了[%s]" % e, e) return False return True
def __login(self): if self.csrf_ts > now(): return with Block("账号登录"): ret = requests.post( "https://developer.apple.com/services-account/QH65B2/account/getTeams", json={ "includeInMigrationTeams": 1, }, headers={ 'cookie': to_form_url(self.cookie, split=';'), }, timeout=3, verify=False).json() if not self.team_id else {} if ret.get("resultCode") == 0: self.teams = list(map(lambda x: x["teamId"], ret["teams"])) self.info.team_id = self.team_id = self.teams[0] self.info.teams = json_str(self.teams) self.info.save() else: # 重新登录 self.session = requests.session() self.session.headers["User-Agent"] = "Spaceship 2.117.1" rsp = self.session.get( "https://olympus.itunes.apple.com/v1/app/config?hostname=itunesconnect.apple.com" ).json() self.session.headers["X-Apple-Widget-Key"] = rsp[ "authServiceKey"] # self.session.headers["X-Apple-Widget-Key"] = "16452abf721961a1728885bef033f28e" self.session.headers["Accept"] = "application/json" rsp = self.session.post( "https://idmsa.apple.com/appleauth/auth/signin", json={ "accountName": self.account, "password": self.password, "rememberMe": True, }, timeout=3) self.session.headers["x-apple-id-session-id"] = rsp.headers[ "x-apple-id-session-id"] self.session.headers["scnt"] = rsp.headers["scnt"] if rsp.status_code == 409: # 二次验证 # noinspection PyUnusedLocal rsp = self.session.post( "https://idmsa.apple.com/appleauth/auth") # Log("===> https://idmsa.apple.com/appleauth/auth [%s] %s" % (rsp.status_code, rsp.json())) # 切手机验证码 rsp = self.session.put( "https://idmsa.apple.com/appleauth/auth/verify/phone", json={ "phoneNumber": { "id": 1 }, "mode": "sms", }) Assert(rsp.status_code == 200, "[%s]短信发送失败" % self.account) # Log("===> https://idmsa.apple.com/appleauth/auth/verify/phone [%s] %s" % (rsp.status_code, rsp.json())) _wait_code(self.info, self.session, now()) self.cookie.update(self.session.cookies) self.__expire = now() + 3600 * 1000 if not self.team_id: ret = requests.post( "https://developer.apple.com/services-account/QH65B2/account/getTeams", json={ "includeInMigrationTeams": 1, }, headers={ 'cookie': to_form_url(self.cookie, split=';'), }, timeout=3, verify=False).json() if ret["resultCode"] == 0: self.teams = list(map(lambda x: x["teamId"], ret["teams"])) self.info.team_id = self.team_id = self.teams[0] self.info.teams = json_str(self.teams) self.info.save() else: Log("[%s]获取team失败登出了" % self.account) self.__logout() Log("apple账号[%s:%s]登录完成了" % (self.account, self.team_id))
def login_by_curl(_req: HttpRequest, cmd: str = "", account: str = ""): """ 通过拦截网页的curl 请求 https://developer.apple.com/account/getUserProfile ex. curl 'https://developer.apple.com/services-account/QH65B2/account/getUserProfile' -H 'origin: https://developer.apple.com' -H 'accept-encoding: gzip, deflate, br' -H 'accept-language: zh-CN,zh;q=0.9' -H 'csrf: cf0796aee015fe0f03e7ccc656ba4b898b696cc1072027988d89b1f6e607fd67' -H 'cookie: geo=SG; ccl=SR+vWVA/vYTrzR1LkZE2tw==; s_fid=56EE3E795513A2B4-16F81B5466B36881; s_cc=true; s_vi=[CS]v1|2E425B0B852E2C90-40002C5160000006[CE]; dslang=CN-ZH; site=CHN; s_pathLength=developer%3D2%2C; acn01=v+zxzKnMyleYWzjWuNuW1Y9+kAJBxfozY2UAH0paNQB+FA==; myacinfo=DAWTKNV2a5c238e8d27e8ed221c8978cfb02ea94b22777f25ffec5abb1a855da8debe4f59d60b506eae457dec4670d5ca9663ed72c3d1976a9f87c53653fae7c63699abe64991180d7c107c50ce88be233047fc96de200c3f23947bfbf2e064c7b9a7652002d285127345fe15adf53bab3d347704cbc0a8b856338680722e5d0387a5eb763d258cf19b79318be28c4abd01e27029d2ef26a1bd0dff61d141380a1b496b92825575735d0be3dd02a934db2d788c9d6532b6a36bc69d244cc9b4873cef8f4a3a90695f172f6f521330f67f20791fd7d62dfc9d6de43899ec26a8485191d62e2c5139f81fca2388d57374ff31f9f689ad373508bcd74975ddd3d3b7875fe3235323962636433633833653433363562313034383164333833643736393763303538353038396439MVRYV2; DSESSIONID=1c3smahkpfbkp7k3fju30279uoba8p8480gs5ajjgsbbvn8lubqt; s_sq=%5B%5BB%5D%5D' -H 'user-locale: en_US' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36 QQBrowser/4.5.122.400' -H 'content-type: application/json' -H 'accept: application/json' -H 'cache-control: max-age=0, no-cache, no-store, must-revalidate, proxy-revalidate' -H 'authority: developer.apple.com' -H 'referer: https://developer.apple.com/account/' -H 'csrf_ts: 1552204197631' --data-binary '{}' --compressed """ if not cmd: cmd = _req.body.decode("utf-8") Assert(len(cmd) and cmd.startswith("curl"), "命令行不对") parsed_context = curl_parse_context(cmd) params = { "data": parsed_context.data, "headers": dict( filter(lambda x: not x[0].startswith(":"), parsed_context.headers.items())), "cookies": parsed_context.cookies, } if parsed_context.method == 'get': rsp = requests.get( parsed_context.url, **params, ) else: rsp = requests.post( parsed_context.url, **params, ) if rsp.status_code != 200: return { "succ": False, "reason": "无效的curl", } if parsed_context.url != "https://developer.apple.com/services-account/QH65B2/account/getUserProfile": data = rsp.json() account = data["userProfile"]["email"] else: rsp = requests.post( "https://developer.apple.com/services-account/QH65B2/account/getUserProfile", headers={ "cookie": parsed_context.cookies, }) data = rsp.json() account = data["userProfile"]["email"] if account: _info = IosAccountInfo.objects.filter( account=account).first() # type:IosAccountInfo if not _info: _info = IosAccountInfo() _info.account = account _info.save() _info.cookie = json_str(parsed_context.cookies) _info.headers = json_str(parsed_context.headers) _info.save() Log("通过curl登录[%s]" % account) return { "succ": True, "msg": "登录[%s]成功" % account, } else: return { "succ": False, "msg": "请求不具备提取登录信息", }
def wrapper(self, request, *args, **kwargs): return HttpResponse(json_str(self.func(request)))