This commit is contained in:
relikd
2024-04-02 21:54:37 +02:00
commit 8f04d673d9
119 changed files with 20136 additions and 0 deletions

View File

View File

@@ -0,0 +1,47 @@
__all__ = ['iTunesClient']
import json
import re
from reqs.schemas.itunes_lookup_resp import ItunesLookupResp
import requests
STORE_TABLE = {"AE":"143481-2,32","AG":"143540-2,32","AI":"143538-2,32","AL":"143575-2,32","AM":"143524-2,32","AO":"143564-2,32","AR":"143505-28,32","AT":"143445-4,32","AU":"143460-27,32","AZ":"143568-2,32","BB":"143541-2,32","BE":"143446-2,32","BF":"143578-2,32","BG":"143526-2,32","BH":"143559-2,32","BJ":"143576-2,32","BM":"143542-2,32","BN":"143560-2,32","BO":"143556-28,32","BR":"143503-15,32","BS":"143539-2,32","BT":"143577-2,32","BW":"143525-2,32","BY":"143565-2,32","BZ":"143555-2,32","CA":"143455-6,32","CG":"143582-2,32","CH":"143459-57,32","CL":"143483-28,32","CN":"143465-19,32","CO":"143501-28,32","CR":"143495-28,32","CV":"143580-2,32","CY":"143557-2,32","CZ":"143489-2,32","DE":"143443-4,32","DK":"143458-2,32","DM":"143545-2,32","DO":"143508-28,32","DZ":"143563-2,32","EC":"143509-28,32","EE":"143518-2,32","EG":"143516-2,32","ES":"143454-8,32","FI":"143447-2,32","FJ":"143583-2,32","FM":"143591-2,32","FR":"143442-3,32","GB":"143444-2,32","GD":"143546-2,32","GH":"143573-2,32","GM":"143584-2,32","GR":"143448-2,32","GT":"143504-28,32","GW":"143585-2,32","GY":"143553-2,32","HK":"143463-45,32","HN":"143510-28,32","HR":"143494-2,32","HU":"143482-2,32","ID":"143476-2,32","IE":"143449-2,32","IL":"143491-2,32","IN":"143467-2,32","IS":"143558-2,32","IT":"143450-7,32","JM":"143511-2,32","JO":"143528-2,32","JP":"143462-9,32","KE":"143529-2,32","KG":"143586-2,32","KH":"143579-2,32","KN":"143548-2,32","KR":"143466-13,32","KW":"143493-2,32","KY":"143544-2,32","KZ":"143517-2,32","LA":"143587-2,32","LB":"143497-2,32","LC":"143549-2,32","LK":"143486-2,32","LR":"143588-2,32","LT":"143520-2,32","LU":"143451-2,32","LV":"143519-2,32","MD":"143523-2,32","MG":"143531-2,32","MK":"143530-2,32","ML":"143532-2,32","MN":"143592-2,32","MO":"143515-45,32","MR":"143590-2,32","MS":"143547-2,32","MT":"143521-2,32","MU":"143533-2,32","MW":"143589-2,32","MX":"143468-28,32","MY":"143473-2,32","MZ":"143593-2,32","NA":"143594-2,32","NE":"143534-2,32","NG":"143561-2,32","NI":"143512-28,32","NL":"143452-10,32","NO":"143457-2,32","NP":"143484-2,32","NZ":"143461-27,32","OM":"143562-2,32","PA":"143485-28,32","PE":"143507-28,32","PG":"143597-2,32","PH":"143474-2,32","PK":"143477-2,32","PL":"143478-2,32","PT":"143453-24,32","PW":"143595-2,32","PY":"143513-28,32","QA":"143498-2,32","RO":"143487-2,32","RU":"143469-16,32","SA":"143479-2,32","SB":"143601-2,32","SC":"143599-2,32","SE":"143456-17,32","SG":"143464-19,32","SI":"143499-2,32","SK":"143496-2,32","SL":"143600-2,32","SN":"143535-2,32","SR":"143554-2,32","ST":"143598-2,32","SV":"143506-28,32","SZ":"143602-2,32","TC":"143552-2,32","TD":"143581-2,32","TH":"143475-2,32","TJ":"143603-2,32","TM":"143604-2,32","TN":"143536-2,32","TR":"143480-2,32","TT":"143551-2,32","TW":"143470-18,32","TZ":"143572-2,32","UA":"143492-2,32","UG":"143537-2,32","US":"143441-1,32","UY":"143514-2,32","UZ":"143566-2,32","VC":"143550-2,32","VE":"143502-28,32","VG":"143543-2,32","VN":"143471-2,32","YE":"143571-2,32","ZA":"143472-2,32","ZW":"143605-2,32"}
class iTunesClient(object):
def __init__(self, sess: requests.Session):
self.sess = sess
# curl -k -X GET \
# -H "Content-Type: application/x-www-form-urlencoded" \
# https://itunes.apple.com/lookup?bundleId=com.touchingapp.potatsolite&limit=1&media=software
def lookup(self, bundleId=None, appId=None, term=None, country="US", limit=1, media="software") -> ItunesLookupResp:
r = self.sess.get("https://itunes.apple.com/lookup?",
params={
"bundleId": bundleId,
"id": appId,
"term": term,
"country": country,
"limit": limit,
"media": media,
},
headers={
"Content-Type": "application/x-www-form-urlencoded",
})
return ItunesLookupResp.from_dict(r.json())
def getAppVerId(self, appId, country):
if not ',' in country:
storeFront = STORE_TABLE[country.upper()]
else:
storeFront = country
appInfo = requests.get("https://apps.apple.com/app/id%s" % appId, headers={"X-Apple-Store-Front": storeFront}).text
try:
appParam = re.findall(r'"buyParams":"(.*?)"', appInfo)[0]
except:
appParam = re.findall(r'buy-params="(.*?)"', appInfo)[0]
appParam = appParam.replace('&', '&')
appParamDict = dict((c.split('=') for c in json.loads('"%s"' % appParam).split('&')))
appVer = appParamDict['appExtVrsId']
return appVer

View File

@@ -0,0 +1,18 @@
# Schema Definitions for ipatool-py
In this directory, JSON Schema Definition files are stored in `schema_defs`, with corresponding plist examples in `schema_examples`
## How to generate schema from plist
1. Convert plist to corresponding JSON, using either `plistlib` or online tools
2. Use https://www.liquid-technologies.com/online-json-to-schema-converter to convert JSON to schema
- You have to switch the `Array Rules` option to `List Validation`
3. Merge different request / response body's schema manually
- Usually the "required" field can help you merging the json schema
## Regenerate schema bindings
Run this in current folder:
```
python3 -m schema_defs
```

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
import os
import os.path as path
import subprocess
curpath = path.dirname(__file__)
outpath = path.dirname(curpath)
for p in os.listdir(curpath):
if not p.endswith('.json'):
continue
#subprocess.call(["jsonschema2popo2", "--translate-properties", "--use-types", "-o", path.join(outpath, p.split('.')[0] + '.py'), path.join(curpath, p)])
print("Converting %s" % p)
subprocess.call(["jsonschema2popo2", "--use-types", "-o", path.join(outpath, p.split('.')[0] + '.py'), path.join(curpath, p)])

View File

@@ -0,0 +1,222 @@
{
"title": "iTunes Lookup Resp",
"type": "object",
"properties": {
"resultCount": {
"type": "integer"
},
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"appletvScreenshotUrls": {
"type": "array",
"items": {
"type": ["number","string","boolean","object","array", "null"]
}
},
"screenshotUrls": {
"type": "array",
"items": {
"type": "string"
}
},
"ipadScreenshotUrls": {
"type": "array",
"items": {
"type": "string"
}
},
"artworkUrl60": {
"type": "string"
},
"artworkUrl512": {
"type": "string"
},
"artworkUrl100": {
"type": "string"
},
"artistViewUrl": {
"type": "string"
},
"supportedDevices": {
"type": "array",
"items": {
"type": "string"
}
},
"advisories": {
"type": "array",
"items": {
"type": ["number","string","boolean","object","array", "null"]
}
},
"isGameCenterEnabled": {
"type": "boolean"
},
"kind": {
"type": "string"
},
"features": {
"type": "array",
"items": {
"type": "string"
}
},
"minimumOsVersion": {
"type": "string"
},
"trackCensoredName": {
"type": "string"
},
"languageCodesISO2A": {
"type": "array",
"items": {
"type": "string"
}
},
"fileSizeBytes": {
"type": "string"
},
"formattedPrice": {
"type": "string"
},
"contentAdvisoryRating": {
"type": "string"
},
"averageUserRatingForCurrentVersion": {
"type": "number"
},
"userRatingCountForCurrentVersion": {
"type": "integer"
},
"averageUserRating": {
"type": "number"
},
"trackViewUrl": {
"type": "string"
},
"trackContentRating": {
"type": "string"
},
"releaseDate": {
"type": "string"
},
"genreIds": {
"type": "array",
"items": {
"type": "string"
}
},
"primaryGenreName": {
"type": "string"
},
"trackId": {
"type": "integer"
},
"trackName": {
"type": "string"
},
"sellerName": {
"type": "string"
},
"isVppDeviceBasedLicensingEnabled": {
"type": "boolean"
},
"currentVersionReleaseDate": {
"type": "string"
},
"releaseNotes": {
"type": "string"
},
"primaryGenreId": {
"type": "integer"
},
"currency": {
"type": "string"
},
"version": {
"type": "string"
},
"wrapperType": {
"type": "string"
},
"artistId": {
"type": "integer"
},
"artistName": {
"type": "string"
},
"genres": {
"type": "array",
"items": {
"type": "string"
}
},
"price": {
"type": "number"
},
"description": {
"type": "string"
},
"bundleId": {
"type": "string"
},
"userRatingCount": {
"type": "integer"
}
},
"required": [
"appletvScreenshotUrls",
"screenshotUrls",
"ipadScreenshotUrls",
"artworkUrl60",
"artworkUrl512",
"artworkUrl100",
"artistViewUrl",
"supportedDevices",
"advisories",
"isGameCenterEnabled",
"kind",
"features",
"minimumOsVersion",
"trackCensoredName",
"languageCodesISO2A",
"fileSizeBytes",
"formattedPrice",
"contentAdvisoryRating",
"averageUserRatingForCurrentVersion",
"userRatingCountForCurrentVersion",
"averageUserRating",
"trackViewUrl",
"trackContentRating",
"releaseDate",
"genreIds",
"primaryGenreName",
"trackId",
"trackName",
"sellerName",
"isVppDeviceBasedLicensingEnabled",
"currentVersionReleaseDate",
"releaseNotes",
"primaryGenreId",
"currency",
"version",
"wrapperType",
"artistId",
"artistName",
"genres",
"price",
"description",
"bundleId",
"userRatingCount"
]
}
}
},
"required": [
"resultCount",
"results"
]
}

View File

@@ -0,0 +1,37 @@
{
"title": "Store Authenticate Req",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"appleId": {
"type": "string"
},
"attempt": {
"type": "string"
},
"createSession": {
"type": "string"
},
"guid": {
"type": "string"
},
"password": {
"type": "string"
},
"rmp": {
"type": "string"
},
"why": {
"type": "string"
}
},
"required": [
"appleId",
"attempt",
"createSession",
"guid",
"password",
"rmp",
"why"
]
}

View File

@@ -0,0 +1,324 @@
{
"title": "Store Authenticate Resp",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"pings": {
"type": "array",
"items": {
"type": ["number","string","boolean","object","array", "null"]
}
},
"cancel-purchase-batch": {
"type": "boolean"
},
"customerMessage": {
"type": "string"
},
"failureType": {
"type": "string"
},
"accountInfo": {
"type": "object",
"properties": {
"appleId": {
"type": "string"
},
"address": {
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
}
},
"required": [
"firstName",
"lastName"
]
}
},
"required": [
"appleId",
"address"
]
},
"passwordToken": {
"type": "string"
},
"clearToken": {
"type": "string"
},
"m-allowed": {
"type": "boolean"
},
"is-cloud-enabled": {
"type": "string"
},
"dsPersonId": {
"type": "string"
},
"creditDisplay": {
"type": "string"
},
"creditBalance": {
"type": "string"
},
"freeSongBalance": {
"type": "string"
},
"isManagedStudent": {
"type": "boolean"
},
"action": {
"type": "object",
"properties": {
"kind": {
"type": "string"
}
},
"required": [
"kind"
]
},
"subscriptionStatus": {
"type": "object",
"properties": {
"terms": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"latestTerms": {
"type": "integer"
},
"agreedToTerms": {
"type": "integer"
},
"source": {
"type": "string"
}
},
"required": [
"type",
"latestTerms",
"agreedToTerms",
"source"
]
}
},
"account": {
"type": "object",
"properties": {
"isMinor": {
"type": "boolean"
},
"suspectUnderage": {
"type": "boolean"
}
},
"required": [
"isMinor",
"suspectUnderage"
]
},
"family": {
"type": "object",
"properties": {
"hasFamily": {
"type": "boolean"
}
},
"required": [
"hasFamily"
]
}
},
"required": [
"terms",
"account",
"family"
]
},
"accountFlags": {
"type": "object",
"properties": {
"personalization": {
"type": "boolean"
},
"underThirteen": {
"type": "boolean"
},
"identityLastVerified": {
"type": "integer"
},
"verifiedExpirationDate": {
"type": "integer"
},
"retailDemo": {
"type": "boolean"
},
"autoPlay": {
"type": "boolean"
},
"isDisabledAccount": {
"type": "boolean"
},
"isRestrictedAccount": {
"type": "boolean"
},
"isManagedAccount": {
"type": "boolean"
},
"isInRestrictedRegion": {
"type": "boolean"
},
"accountFlagsVersion": {
"type": "integer"
},
"hasAgreedToTerms": {
"type": "boolean"
},
"hasAgreedToAppClipTerms": {
"type": "boolean"
},
"hasWatchHardwareOffer": {
"type": "boolean"
},
"isInFamily": {
"type": "boolean"
},
"hasSubscriptionFamilySharingEnabled": {
"type": "boolean"
}
},
"required": [
"personalization",
"underThirteen",
"identityLastVerified",
"verifiedExpirationDate",
"retailDemo",
"autoPlay",
"isDisabledAccount",
"isRestrictedAccount",
"isManagedAccount",
"isInRestrictedRegion",
"accountFlagsVersion",
"hasAgreedToTerms",
"hasAgreedToAppClipTerms",
"hasWatchHardwareOffer",
"isInFamily",
"hasSubscriptionFamilySharingEnabled"
]
},
"status": {
"type": "integer"
},
"download-queue-info": {
"type": "object",
"properties": {
"download-queue-item-count": {
"type": "integer"
},
"dsid": {
"type": "integer"
},
"is-auto-download-machine": {
"type": "boolean"
}
},
"required": [
"download-queue-item-count",
"dsid",
"is-auto-download-machine"
]
},
"privacyAcknowledgement": {
"type": "object",
"properties": {
"com.apple.onboarding.appstore": {
"type": "integer"
},
"com.apple.onboarding.applemusic": {
"type": "integer"
},
"com.apple.onboarding.videos": {
"type": "integer"
},
"com.apple.onboarding.itunesstore": {
"type": "integer"
},
"com.apple.onboarding.itunesu": {
"type": "integer"
},
"com.apple.onboarding.applearcade": {
"type": "integer"
}
},
"required": [
"com.apple.onboarding.appstore",
"com.apple.onboarding.applemusic",
"com.apple.onboarding.videos",
"com.apple.onboarding.itunesstore",
"com.apple.onboarding.itunesu",
"com.apple.onboarding.applearcade"
]
},
"dialog": {
"type": "object",
"properties": {
"m-allowed": {
"type": "boolean"
},
"message": {
"type": "string"
},
"explanation": {
"type": "string"
},
"defaultButton": {
"type": "string"
},
"okButtonString": {
"type": "string"
},
"initialCheckboxValue": {
"type": "boolean"
}
},
"required": [
"m-allowed",
"message",
"explanation",
"defaultButton",
"okButtonString",
"initialCheckboxValue"
]
}
},
"required": [
"pings",
"accountInfo",
"passwordToken",
"clearToken",
"m-allowed",
"is-cloud-enabled",
"dsPersonId",
"creditDisplay",
"creditBalance",
"freeSongBalance",
"isManagedStudent",
"action",
"subscriptionStatus",
"accountFlags",
"status",
"download-queue-info",
"privacyAcknowledgement",
"dialog"
]
}

View File

@@ -0,0 +1,120 @@
{
"title": "Store BuyProduct Req",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"ageCheck": {
"type": "string"
},
"appExtVrsId": {
"type": "string"
},
"guid": {
"type": "string"
},
"hasBeenAuthedForBuy": {
"type": "string"
},
"isInApp": {
"type": "string"
},
"kbsync": {
"type": "string"
},
"sbsync": {
"type": "string"
},
"afds": {
"type": "string"
},
"machineName": {
"type": "string"
},
"mtApp": {
"type": "string"
},
"mtClientId": {
"type": "string"
},
"mtEventTime": {
"type": "string"
},
"mtPageId": {
"type": "string"
},
"mtPageType": {
"type": "string"
},
"mtPrevPage": {
"type": "string"
},
"mtRequestId": {
"type": "string"
},
"mtTopic": {
"type": "string"
},
"needDiv": {
"type": "string"
},
"pg": {
"type": "string"
},
"price": {
"type": "string"
},
"pricingParameters": {
"type": "string"
},
"productType": {
"type": "string"
},
"salableAdamId": {
"type": "string"
},
"hasAskedToFulfillPreorder": {
"type": "string"
},
"buyWithoutAuthorization": {
"type": "string"
},
"hasDoneAgeCheck": {
"type": "string"
},
"hasConfirmedPaymentSheet": {
"type": "string"
},
"asn": {
"type": "string"
}
},
"required": [
"guid",
"kbsync",
"price",
"pricingParameters",
"productType",
"salableAdamId",
"appExtVrsId"
],
"optional": [
"ageCheck",
"hasBeenAuthedForBuy",
"hasConfirmedPaymentSheet",
"asn",
"isInApp",
"machineName",
"mtApp",
"mtClientId",
"mtEventTime",
"mtPageId",
"mtPageType",
"mtPrevPage",
"mtRequestId",
"mtTopic",
"needDiv",
"pg"
]
}

View File

@@ -0,0 +1,732 @@
{
"title": "Store BuyProduct Resp",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"pings": {
"type": "array",
"items": {
"type": ["number","string","boolean","object","array", "null"]
}
},
"jingleDocType": {
"type": "string"
},
"jingleAction": {
"type": "string"
},
"status": {
"type": "integer"
},
"dsPersonId": {
"type": "string"
},
"creditDisplay": {
"type": "string"
},
"creditBalance": {
"type": "string"
},
"freeSongBalance": {
"type": "string"
},
"creditDisplayInternal": {
"type": "string"
},
"authorized": {
"type": "boolean"
},
"download-queue-item-count": {
"type": "integer"
},
"songList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"songId": {
"type": "integer"
},
"URL": {
"type": "string"
},
"downloadKey": {
"type": "string"
},
"artworkURL": {
"type": "string"
},
"artwork-urls": {
"type": "object",
"properties": {
"image-type": {
"type": "string"
},
"default": {
"type": "object",
"properties": {
"url": {
"type": "string"
}
},
"required": [
"url"
]
}
},
"required": [
"image-type",
"default"
]
},
"md5": {
"type": "string"
},
"chunks": {
"type": "object",
"properties": {
"chunkSize": {
"type": "integer"
},
"hashes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"chunkSize",
"hashes"
]
},
"isStreamable": {
"type": "boolean"
},
"uncompressedSize": {
"type": "integer"
},
"sinfs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"sinf": {
"type": "string"
}
},
"required": [
"id",
"sinf"
]
}
},
"purchaseDate": {
"type": "string"
},
"download-id": {
"type": "string"
},
"is-in-queue": {
"type": "boolean"
},
"asset-info": {
"type": "object",
"properties": {
"file-size": {
"type": "integer"
},
"flavor": {
"type": "string"
}
},
"required": [
"file-size",
"flavor"
]
},
"metadata": {
"type": "object",
"properties": {
"MacUIRequiredDeviceCapabilities": {
"type": "object",
"properties": {
"arm64": {
"type": "boolean"
}
},
"required": [
"arm64"
]
},
"UIRequiredDeviceCapabilities": {
"type": "object",
"properties": {
"arm64": {
"type": "boolean"
}
},
"required": [
"arm64"
]
},
"WKRunsIndependentlyOfCompanionApp": {
"type": "boolean"
},
"WKWatchOnly": {
"type": "boolean"
},
"appleWatchEnabled": {
"type": "boolean"
},
"artistId": {
"type": "integer"
},
"artistName": {
"type": "string"
},
"bundleDisplayName": {
"type": "string"
},
"bundleShortVersionString": {
"type": "string"
},
"bundleVersion": {
"type": "string"
},
"copyright": {
"type": "string"
},
"fileExtension": {
"type": "string"
},
"gameCenterEnabled": {
"type": "boolean"
},
"gameCenterEverEnabled": {
"type": "boolean"
},
"genre": {
"type": "string"
},
"genreId": {
"type": "integer"
},
"itemId": {
"type": "integer"
},
"itemName": {
"type": "string"
},
"kind": {
"type": "string"
},
"nameTranscriptions": {
"type": "object",
"properties": {
"zh-Hans-CN": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"zh-Hans-CN"
]
},
"playlistName": {
"type": "string"
},
"product-type": {
"type": "string"
},
"rating": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"label": {
"type": "string"
},
"rank": {
"type": "integer"
},
"system": {
"type": "string"
}
},
"required": [
"content",
"label",
"rank",
"system"
]
},
"releaseDate": {
"type": "string"
},
"requiresRosetta": {
"type": "boolean"
},
"runsOnAppleSilicon": {
"type": "boolean"
},
"runsOnIntel": {
"type": "boolean"
},
"s": {
"type": "integer"
},
"software-platform": {
"type": "string"
},
"softwareIcon57x57URL": {
"type": "string"
},
"softwareIconNeedsShine": {
"type": "boolean"
},
"softwareSupportedDeviceIds": {
"type": "array",
"items": {
"type": "integer"
}
},
"softwareVersionBundleId": {
"type": "string"
},
"softwareVersionExternalIdentifier": {
"type": "integer"
},
"softwareVersionExternalIdentifiers": {
"type": "array",
"items": {
"type": "integer"
}
},
"vendorId": {
"type": "integer"
},
"drmVersionNumber": {
"type": "integer"
},
"versionRestrictions": {
"type": "integer"
},
"storeCohort": {
"type": "string"
},
"hasOrEverHasHadIAP": {
"type": "boolean"
}
},
"required": [
"MacUIRequiredDeviceCapabilities",
"UIRequiredDeviceCapabilities",
"WKRunsIndependentlyOfCompanionApp",
"WKWatchOnly",
"appleWatchEnabled",
"artistId",
"artistName",
"bundleDisplayName",
"bundleShortVersionString",
"bundleVersion",
"copyright",
"fileExtension",
"gameCenterEnabled",
"gameCenterEverEnabled",
"genre",
"genreId",
"itemId",
"itemName",
"kind",
"nameTranscriptions",
"playlistName",
"product-type",
"rating",
"releaseDate",
"requiresRosetta",
"runsOnAppleSilicon",
"runsOnIntel",
"s",
"software-platform",
"softwareIcon57x57URL",
"softwareIconNeedsShine",
"softwareSupportedDeviceIds",
"softwareVersionBundleId",
"softwareVersionExternalIdentifier",
"softwareVersionExternalIdentifiers",
"vendorId",
"drmVersionNumber",
"versionRestrictions",
"storeCohort",
"hasOrEverHasHadIAP"
]
}
},
"required": [
"songId",
"URL",
"downloadKey",
"artworkURL",
"artwork-urls",
"md5",
"chunks",
"isStreamable",
"uncompressedSize",
"sinfs",
"purchaseDate",
"download-id",
"is-in-queue",
"asset-info",
"metadata"
]
}
},
"download-queue-info": {
"type": "object",
"properties": {
"download-queue-item-count": {
"type": "integer"
},
"dsid": {
"type": "integer"
},
"is-auto-download-machine": {
"type": "boolean"
}
},
"required": [
"download-queue-item-count",
"dsid",
"is-auto-download-machine"
]
},
"metrics": {
"type": "object",
"properties": {
"itemIds": {
"type": "array",
"items": {
"type": "integer"
}
},
"price": {
"type": "integer"
},
"priceType": {
"type": "string"
},
"productTypes": {
"type": "array",
"items": {
"type": "string"
}
},
"mtApp": {
"type": "string"
},
"mtClientId": {
"type": "string"
},
"mtEventTime": {
"type": "string"
},
"mtPageId": {
"type": "string"
},
"mtPageType": {
"type": "string"
},
"mtPrevPage": {
"type": "string"
},
"mtRequestId": {
"type": "string"
},
"mtTopic": {
"type": "string"
},
"currency": {
"type": "string"
},
"exchangeRateToUSD": {
"type": "number"
},
"commerceEvent_purchase_priceType": {
"type": "string"
},
"commerceEvent_storeFrontId": {
"type": "string"
},
"commerceEvent_result_resultType": {
"type": "integer"
},
"commerceEvent_flowType": {
"type": "integer"
},
"commerceEvent_flowStep": {
"type": "integer"
},
"dialogId": {
"type": "string"
},
"message": {
"type": "string"
},
"messageCode": {
"type": "string"
},
"options": {
"type": "array",
"items": {
"type": "string"
}
},
"actionUrl": {
"type": "string"
},
"asnState": {
"type": "integer"
},
"eventType": {
"type": "string"
}
},
"required": [
"mtApp",
"mtClientId",
"mtEventTime",
"mtPageId",
"mtPageType",
"mtPrevPage",
"mtRequestId",
"mtTopic"
],
"optional": [
"itemIds",
"price",
"priceType",
"productTypes",
"currency",
"exchangeRateToUSD",
"commerceEvent_purchase_priceType",
"commerceEvent_storeFrontId",
"commerceEvent_result_resultType",
"commerceEvent_flowType",
"commerceEvent_flowStep",
"dialogId",
"message",
"messageCode",
"options",
"actionUrl",
"asnState",
"eventType"
]
},
"duAnonymousPings": {
"type": "array",
"items": {
"type": "string"
}
},
"subscriptionStatus": {
"type": "object",
"properties": {
"music": {
"type": "object",
"properties": {
"status": {
"type": "string"
},
"reason": {
"type": "string"
},
"isAdmin": {
"type": "boolean"
},
"isNotEligibleForFreeTrial": {
"type": "boolean"
}
},
"required": [
"status",
"reason",
"isAdmin",
"isNotEligibleForFreeTrial"
]
},
"terms": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"latestTerms": {
"type": "integer"
},
"agreedToTerms": {
"type": "integer"
},
"source": {
"type": "string"
}
},
"required": [
"type",
"latestTerms",
"agreedToTerms",
"source"
]
}
},
"account": {
"type": "object",
"properties": {
"isMinor": {
"type": "boolean"
},
"suspectUnderage": {
"type": "boolean"
}
},
"required": [
"isMinor",
"suspectUnderage"
]
},
"family": {
"type": "object",
"properties": {
"hasFamily": {
"type": "boolean"
}
},
"required": [
"hasFamily"
]
}
},
"required": [
"music",
"terms",
"account",
"family"
]
},
"cancel-purchase-batch": {
"type": "boolean"
},
"failureType": {
"type": "string"
},
"customerMessage": {
"type": "string"
},
"m-allowed": {
"type": "boolean"
},
"dialog": {
"type": "object",
"properties": {
"kind": {
"type": "string"
},
"m-allowed": {
"type": "boolean"
},
"use-keychain": {
"type": "boolean"
},
"isFree": {
"type": "boolean"
},
"message": {
"type": "string"
},
"explanation": {
"type": "string"
},
"defaultButton": {
"type": "string"
},
"okButtonString": {
"type": "string"
},
"okButtonAction": {
"type": "object",
"properties": {
"kind": {
"type": "string"
},
"buyParams": {
"type": "string"
},
"itemName": {
"type": "string"
}
},
"required": [
"kind",
"buyParams",
"itemName"
]
},
"cancelButtonString": {
"type": "string"
},
"initialCheckboxValue": {
"type": "boolean"
}
},
"required": [
"kind",
"m-allowed",
"use-keychain",
"isFree",
"message",
"explanation",
"defaultButton",
"okButtonString",
"okButtonAction",
"cancelButtonString",
"initialCheckboxValue"
]
}
},
"required": [
"pings",
"metrics"
],
"optional": [
"jingleDocType",
"jingleAction",
"status",
"dsPersonId",
"creditDisplay",
"creditBalance",
"freeSongBalance",
"creditDisplayInternal",
"authorized",
"download-queue-item-count",
"songList",
"download-queue-info",
"duAnonymousPings",
"subscriptionStatus",
"failureType",
"customerMessage",
"m-allowed",
"dialog",
"cancel-purchase-batch"
]
}

View File

@@ -0,0 +1,24 @@
{
"title": "Store Download Req",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"creditDisplay": {
"type": "string"
},
"guid": {
"type": "string"
},
"salableAdamId": {
"type": "string"
},
"appExtVrsId": {
"type": "string"
}
},
"required": [
"creditDisplay",
"guid",
"salableAdamId"
]
}

View File

@@ -0,0 +1,497 @@
{
"title": "Store Download Resp",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"pings": {
"type": "array",
"items": {
"type": ["number","string","boolean","object","array", "null"]
}
},
"cancel-purchase-batch": {
"type": "boolean"
},
"customerMessage": {
"type": "string"
},
"failureType": {
"type": "string"
},
"jingleDocType": {
"type": "string"
},
"jingleAction": {
"type": "string"
},
"status": {
"type": "integer"
},
"dsPersonId": {
"type": "string"
},
"creditDisplay": {
"type": "string"
},
"creditBalance": {
"type": "string"
},
"freeSongBalance": {
"type": "string"
},
"authorized": {
"type": "boolean"
},
"download-queue-item-count": {
"type": "integer"
},
"songList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"songId": {
"type": "integer"
},
"URL": {
"type": "string"
},
"downloadKey": {
"type": "string"
},
"artworkURL": {
"type": "string"
},
"artwork-urls": {
"type": "object",
"properties": {
"image-type": {
"type": "string"
},
"default": {
"type": "object",
"properties": {
"url": {
"type": "string"
}
},
"required": [
"url"
]
}
},
"required": [
"image-type",
"default"
]
},
"md5": {
"type": "string"
},
"chunks": {
"type": "object",
"properties": {
"chunkSize": {
"type": "integer"
},
"hashes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"chunkSize",
"hashes"
]
},
"isStreamable": {
"type": "boolean"
},
"uncompressedSize": {
"type": "string"
},
"sinfs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"sinf": {
"type": "string"
}
},
"required": [
"id",
"sinf"
]
}
},
"purchaseDate": {
"type": "string"
},
"download-id": {
"type": "string"
},
"is-in-queue": {
"type": "boolean"
},
"asset-info": {
"type": "object",
"properties": {
"file-size": {
"type": "integer"
},
"flavor": {
"type": "string"
}
},
"required": [
"file-size",
"flavor"
]
},
"metadata": {
"type": "object",
"properties": {
"MacUIRequiredDeviceCapabilities": {
"type": "object",
"properties": {
"arm64": {
"type": "boolean"
},
"gamekit": {
"type": "boolean"
},
"metal": {
"type": "boolean"
}
},
"required": [
"arm64",
"gamekit",
"metal"
]
},
"UIRequiredDeviceCapabilities": {
"type": "object",
"properties": {
"arm64": {
"type": "boolean"
},
"gamekit": {
"type": "boolean"
},
"metal": {
"type": "boolean"
}
},
"required": [
"arm64",
"gamekit",
"metal"
]
},
"artistId": {
"type": "integer"
},
"artistName": {
"type": "string"
},
"bundleDisplayName": {
"type": "string"
},
"bundleShortVersionString": {
"type": "string"
},
"bundleVersion": {
"type": "string"
},
"copyright": {
"type": "string"
},
"fileExtension": {
"type": "string"
},
"gameCenterEnabled": {
"type": "boolean"
},
"gameCenterEverEnabled": {
"type": "boolean"
},
"genre": {
"type": "string"
},
"genreId": {
"type": "integer"
},
"itemId": {
"type": "integer"
},
"itemName": {
"type": "string"
},
"kind": {
"type": "string"
},
"playlistName": {
"type": "string"
},
"product-type": {
"type": "string"
},
"rating": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"label": {
"type": "string"
},
"rank": {
"type": "integer"
},
"system": {
"type": "string"
}
},
"required": [
"content",
"label",
"rank",
"system"
]
},
"releaseDate": {
"type": "string"
},
"requiresRosetta": {
"type": "boolean"
},
"runsOnAppleSilicon": {
"type": "boolean"
},
"runsOnIntel": {
"type": "boolean"
},
"s": {
"type": "integer"
},
"software-platform": {
"type": "string"
},
"softwareIcon57x57URL": {
"type": "string"
},
"softwareIconNeedsShine": {
"type": "boolean"
},
"softwareSupportedDeviceIds": {
"type": "array",
"items": {
"type": "integer"
}
},
"softwareVersionBundleId": {
"type": "string"
},
"softwareVersionExternalIdentifier": {
"type": "integer"
},
"softwareVersionExternalIdentifiers": {
"type": "array",
"items": {
"type": "integer"
}
},
"subgenres": {
"type": "array",
"items": {
"type": "object",
"properties": {
"genre": {
"type": "string"
},
"genreId": {
"type": "integer"
}
},
"required": [
"genre",
"genreId"
]
}
},
"vendorId": {
"type": "integer"
},
"drmVersionNumber": {
"type": "integer"
},
"versionRestrictions": {
"type": "integer"
}
},
"required": [
"MacUIRequiredDeviceCapabilities",
"UIRequiredDeviceCapabilities",
"artistId",
"artistName",
"bundleDisplayName",
"bundleShortVersionString",
"bundleVersion",
"copyright",
"fileExtension",
"gameCenterEnabled",
"gameCenterEverEnabled",
"genre",
"genreId",
"itemId",
"itemName",
"kind",
"playlistName",
"product-type",
"rating",
"releaseDate",
"requiresRosetta",
"runsOnAppleSilicon",
"runsOnIntel",
"s",
"software-platform",
"softwareIcon57x57URL",
"softwareIconNeedsShine",
"softwareSupportedDeviceIds",
"softwareVersionBundleId",
"softwareVersionExternalIdentifier",
"softwareVersionExternalIdentifiers",
"subgenres",
"vendorId",
"drmVersionNumber",
"versionRestrictions"
]
}
},
"required": [
"songId",
"URL",
"downloadKey",
"artworkURL",
"artwork-urls",
"md5",
"chunks",
"isStreamable",
"uncompressedSize",
"sinfs",
"purchaseDate",
"download-id",
"is-in-queue",
"asset-info",
"metadata"
]
}
},
"metrics": {
"type": "object",
"properties": {
"itemIds": {
"type": "array",
"items": {
"type": "integer"
}
},
"currency": {
"type": "string"
},
"exchangeRateToUSD": {
"type": "number"
}
},
"required": [
"itemIds",
"currency",
"exchangeRateToUSD"
]
},
"subscriptionStatus": {
"type": "object",
"properties": {
"terms": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"latestTerms": {
"type": "integer"
},
"agreedToTerms": {
"type": "integer"
},
"source": {
"type": "string"
}
},
"required": [
"type",
"latestTerms",
"agreedToTerms",
"source"
]
}
},
"account": {
"type": "object",
"properties": {
"isMinor": {
"type": "boolean"
},
"suspectUnderage": {
"type": "boolean"
}
},
"required": [
"isMinor",
"suspectUnderage"
]
},
"family": {
"type": "object",
"properties": {
"hasFamily": {
"type": "boolean"
}
},
"required": [
"hasFamily"
]
}
},
"required": [
"terms",
"account",
"family"
]
}
},
"required": [
"pings",
"jingleDocType",
"jingleAction",
"status",
"dsPersonId",
"creditDisplay",
"creditBalance",
"freeSongBalance",
"authorized",
"download-queue-item-count",
"songList",
"metrics",
"subscriptionStatus"
]
}

View File

@@ -0,0 +1,13 @@
{
"resultCount":1,
"results": [
{
"screenshotUrls":["https://is1-ssl.mzstatic.com/image/thumb/Purple123/v4/c7/9d/5a/c79d5ac9-4543-e9d7-acb3-4753704f1488/pr_source.png/392x696bb.png", "https://is5-ssl.mzstatic.com/image/thumb/Purple123/v4/e4/38/3a/e4383af3-d9ed-3d0c-9c80-ca0d413c0f06/pr_source.png/392x696bb.png", "https://is5-ssl.mzstatic.com/image/thumb/Purple123/v4/08/b2/39/08b23995-3c76-3e74-5af4-3edb4914dc4c/pr_source.png/392x696bb.png"],
"ipadScreenshotUrls":["https://is5-ssl.mzstatic.com/image/thumb/Purple113/v4/67/74/39/6774390f-7a12-3d9f-ded7-392b9af90663/pr_source.png/576x768bb.png", "https://is4-ssl.mzstatic.com/image/thumb/Purple123/v4/88/62/85/886285f0-b1c2-ad6b-3ab3-2a5ee70d7c9d/pr_source.png/576x768bb.png", "https://is4-ssl.mzstatic.com/image/thumb/Purple123/v4/29/39/68/29396836-1b94-1561-4bd1-cde929ae5baa/pr_source.png/576x768bb.png"], "appletvScreenshotUrls":[],
"artworkUrl60":"https://is3-ssl.mzstatic.com/image/thumb/Purple123/v4/6b/ed/31/6bed31bd-42d1-5ae9-04fd-a04c865af27d/AppIcon-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/60x60bb.jpg",
"artworkUrl512":"https://is3-ssl.mzstatic.com/image/thumb/Purple123/v4/6b/ed/31/6bed31bd-42d1-5ae9-04fd-a04c865af27d/AppIcon-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/512x512bb.jpg",
"artworkUrl100":"https://is3-ssl.mzstatic.com/image/thumb/Purple123/v4/6b/ed/31/6bed31bd-42d1-5ae9-04fd-a04c865af27d/AppIcon-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/100x100bb.jpg", "artistViewUrl":"https://apps.apple.com/us/developer/potatso-lab-ltd/id1267906737?uo=4",
"supportedDevices":["iPhone5s-iPhone5s", "iPadAir-iPadAir", "iPadAirCellular-iPadAirCellular", "iPadMiniRetina-iPadMiniRetina", "iPadMiniRetinaCellular-iPadMiniRetinaCellular", "iPhone6-iPhone6", "iPhone6Plus-iPhone6Plus", "iPadAir2-iPadAir2", "iPadAir2Cellular-iPadAir2Cellular", "iPadMini3-iPadMini3", "iPadMini3Cellular-iPadMini3Cellular", "iPodTouchSixthGen-iPodTouchSixthGen", "iPhone6s-iPhone6s", "iPhone6sPlus-iPhone6sPlus", "iPadMini4-iPadMini4", "iPadMini4Cellular-iPadMini4Cellular", "iPadPro-iPadPro", "iPadProCellular-iPadProCellular", "iPadPro97-iPadPro97", "iPadPro97Cellular-iPadPro97Cellular", "iPhoneSE-iPhoneSE", "iPhone7-iPhone7", "iPhone7Plus-iPhone7Plus", "iPad611-iPad611", "iPad612-iPad612", "iPad71-iPad71", "iPad72-iPad72", "iPad73-iPad73", "iPad74-iPad74", "iPhone8-iPhone8", "iPhone8Plus-iPhone8Plus", "iPhoneX-iPhoneX", "iPad75-iPad75", "iPad76-iPad76", "iPhoneXS-iPhoneXS", "iPhoneXSMax-iPhoneXSMax", "iPhoneXR-iPhoneXR", "iPad812-iPad812", "iPad834-iPad834", "iPad856-iPad856", "iPad878-iPad878", "iPadMini5-iPadMini5", "iPadMini5Cellular-iPadMini5Cellular", "iPadAir3-iPadAir3", "iPadAir3Cellular-iPadAir3Cellular", "iPodTouchSeventhGen-iPodTouchSeventhGen", "iPhone11-iPhone11", "iPhone11Pro-iPhone11Pro", "iPadSeventhGen-iPadSeventhGen", "iPadSeventhGenCellular-iPadSeventhGenCellular", "iPhone11ProMax-iPhone11ProMax", "iPhoneSESecondGen-iPhoneSESecondGen", "iPadProSecondGen-iPadProSecondGen", "iPadProSecondGenCellular-iPadProSecondGenCellular", "iPadProFourthGen-iPadProFourthGen", "iPadProFourthGenCellular-iPadProFourthGenCellular", "iPhone12Mini-iPhone12Mini", "iPhone12-iPhone12", "iPhone12Pro-iPhone12Pro", "iPhone12ProMax-iPhone12ProMax", "iPadAir4-iPadAir4", "iPadAir4Cellular-iPadAir4Cellular", "iPadEighthGen-iPadEighthGen", "iPadEighthGenCellular-iPadEighthGenCellular", "iPadProThirdGen-iPadProThirdGen", "iPadProThirdGenCellular-iPadProThirdGenCellular", "iPadProFifthGen-iPadProFifthGen", "iPadProFifthGenCellular-iPadProFifthGenCellular", "iPhone13Pro-iPhone13Pro", "iPhone13ProMax-iPhone13ProMax", "iPhone13Mini-iPhone13Mini", "iPhone13-iPhone13", "iPadMiniSixthGen-iPadMiniSixthGen", "iPadMiniSixthGenCellular-iPadMiniSixthGenCellular", "iPadNinthGen-iPadNinthGen", "iPadNinthGenCellular-iPadNinthGenCellular", "iPhoneSEThirdGen-iPhoneSEThirdGen", "iPadAirFifthGen-iPadAirFifthGen", "iPadAirFifthGenCellular-iPadAirFifthGenCellular"], "features":["iosUniversal"], "advisories":[], "isGameCenterEnabled":false, "kind":"software", "minimumOsVersion":"13.0", "trackCensoredName":"Potatso Lite", "languageCodesISO2A":["EN", "ZH"], "fileSizeBytes":"18907136", "sellerUrl":"https://potatso.com/en", "formattedPrice":"Free", "contentAdvisoryRating":"4+", "averageUserRatingForCurrentVersion":4.595620000000000260342858382500708103179931640625, "userRatingCountForCurrentVersion":2923, "averageUserRating":4.595620000000000260342858382500708103179931640625, "trackViewUrl":"https://apps.apple.com/us/app/potatso-lite/id1239860606?uo=4", "trackContentRating":"4+", "trackId":1239860606, "trackName":"Potatso Lite", "bundleId":"com.touchingapp.potatsolite", "primaryGenreName":"Utilities", "releaseDate":"2017-06-01T02:34:35Z", "genreIds":["6002", "6007"], "isVppDeviceBasedLicensingEnabled":true, "sellerName":"Potatso Lab LTD", "currentVersionReleaseDate":"2019-12-16T23:27:27Z",
"releaseNotes":"With this update, we're bringing you some exciting new features and changes. \n\n=====================\n===== What's New =====\n=====================\n\n• The app will support iOS 13+ from now on.\n• We're introducing the brand new logo with clarity and simplicity.\n• We've redeisnged the whole UI to improve your using experience.\n• Some other internal performance improvements and bug fixes.", "primaryGenreId":6002, "currency":"USD", "version":"2.5.0", "wrapperType":"software", "artistId":1267906737, "artistName":"Potatso Lab LTD", "genres":["Utilities", "Productivity"], "price":0.00,
"description":"Potatso Lite is a powerful network tool which empowers your phone to have fully customized network environment. It's friendly for both beginners and power users. \n\nPotatso now supports Shadowsocks, ShadowsocksR, HTTP and Socks5 proxies. You can either setup one by yourself or buy from any proxy providers.\n\nEmbedded smart rouing feature for Chinese users is super helpful which can cost less data in proxy servers and speed up domestic network traffic.\n\n=== Features ===\n- Custom proxy supports Shadowsocks, ShadowsocksR, HTTP and Socks5 \n- Run in the background sustainably without interrupting you\n- Both cellular and Wi-Fi are supported\n- Custom DNS support\n- Smart Routing for Chinese users \n\n=== Privacy ===\nWe respect your privacy so NO confidential data will be uploaded or shared with third parties\n\n=== Feedback ===\nPlease contact on hi@potatso.com", "userRatingCount":2923}]
}

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>appExtVrsId</key>
<string>848463733</string>
<key>guid</key>
<string>22330C8C.C2E39C5C.06C40B91.D0990F95.9A890F9D.AB7F7EB4.56507025</string>
<key>kbsync</key>
<data>
AAQAA5nBc3Q7ETi+TD1x8AM4wbw9sqWglXBaXwuIrlMR9OnAPY89zaoTvbe6PneuS1x1
31NxVIqrAsIZLmxy5be8dQtq8je/rtYTRlxduU9NwW4DBcplBx6vs9qhS3Y8B45Zz4T5
dkmDG4UnS7xnAPwew7jEX/uY38zZhtKu4IN+sl/Whvyh2SkZg/5vGCtjav17CGbP8ZWo
Ci3FhEqAByOL0g6zhPdTHyqF84Apg9fh395tGpzzAWB8mYsRQXJcUHH1cuJjO/qMTkZ4
ZxIJqfMaDJpS20nFq+/Bfg9FvC/83AOPnDfXZTsol3PFKqQ6sLgz6dKIho4Qd2UPABnj
kBx4TFPeYBlm2T6GKfi8tr+rDhsMrbNczpnaUS+3cesIOvDsE3YCX4isOmMtg5yrJ5pi
2GHuofHD2I7Dj6fOh79I7F5OZb71PUvbeABjxvS5b57LGNICSBc/GJ0CEja27kpYals+
bgYG0rVm+vqlAHwRpka5jzeK8DLrvTr22vtBLv62LpTVpVVglr5nbk99BcXG5gA=
</data>
<key>machineName</key>
<string>DESKTOP-697LVJS</string>
<key>mtApp</key>
<string>com.apple.iTunes</string>
<key>mtClientId</key>
<string>3z21abvCzFDuz5CYz9bdz19maFVKge</string>
<key>mtEventTime</key>
<string>1652006678827</string>
<key>mtPageId</key>
<string>ccfce0ef-4ac8-4d5a-8e5f-79876ac474a4</string>
<key>mtPageType</key>
<string>Search</string>
<key>mtPrevPage</key>
<string>Purchases</string>
<key>mtRequestId</key>
<string>3z21abvCzFDuz5CYz9bdz19maFVKgezL2X64FFVz1MGG</string>
<key>mtTopic</key>
<string>xp_its_main</string>
<key>needDiv</key>
<string>0</string>
<key>pg</key>
<string>default</string>
<key>price</key>
<string>0</string>
<key>pricingParameters</key>
<string>STDQ</string>
<key>productType</key>
<string>C</string>
<key>salableAdamId</key>
<string>444934666</string>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>ageCheck</key>
<string>true</string>
<key>appExtVrsId</key>
<string>848463733</string>
<key>guid</key>
<string>22330C8C.C2E39C5C.06C40B91.D0990F95.9A890F9D.AB7F7EB4.56507025</string>
<key>hasBeenAuthedForBuy</key>
<string>true</string>
<key>isInApp</key>
<string>false</string>
<key>kbsync</key>
<data>
AAQAA1c+HfGD4vNLZJYBMpBucSo1bxeaeTEZ3FGUKLq0skmzTxVik6IGoQMGaP6OWsJU
lBoDb3hxaacD57bkiAgRXc/vr21/CipX55hKLoTE53yah3DwBR9tS1cG7oaHFLIh1Vmn
RV7G9LJCQqwSAbr4ugEIVmLULkqaHDfTm8VNDXxYej1p8ghKggMcBT0se5cpDqpVn/bE
qehnOl6QsupUNjjLzDm58bmERm/AjGJVBHQveG+4Y+Y4e1eUO6QQcntmypjmSLDqhI60
31rCV3zwTTZrHmmXEwsZiGgYlSVHR3ne+O9BE+LIPiQxDwIMvjfV6SrzoOUOLlOKvBsk
kI29+6H0QNyMUXojWPQf7bfr+9NBTMgJoDNJd5hEGHqiSKnp9V1ALU8S8QwcYzi3ZDPu
A36lMtgMOFEnYibnGnP5S8i2t43ZSBglExE9LGTGO0/IEWX9gEhKjvMDuIwMt9zdtpye
CXO8siqHY4MtmLlfwZZc/480ZSHfRF8ZQHBa0J0/pgByNQiNe9KMihz+QN7cQI4=
</data>
<key>machineName</key>
<string>DESKTOP-697LVJS</string>
<key>mtApp</key>
<string>com.apple.iTunes</string>
<key>mtClientId</key>
<string>3z21abvCzFDuz5CYz9bdz19maFVKge</string>
<key>mtEventTime</key>
<string>1652006678827</string>
<key>mtPageId</key>
<string>ccfce0ef-4ac8-4d5a-8e5f-79876ac474a4</string>
<key>mtPageType</key>
<string>Search</string>
<key>mtPrevPage</key>
<string>Purchases</string>
<key>mtRequestId</key>
<string>3z21abvCzFDuz5CYz9bdz19maFVKgezL2X64FFVz1MGG</string>
<key>mtTopic</key>
<string>xp_its_main</string>
<key>needDiv</key>
<string>0</string>
<key>pg</key>
<string>default</string>
<key>price</key>
<string>0</string>
<key>pricingParameters</key>
<string>STDQ</string>
<key>productType</key>
<string>C</string>
<key>salableAdamId</key>
<string>444934666</string>
</dict>
</plist>

View File

@@ -0,0 +1,561 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plist version="1.0">
<dict>
<key>pings</key>
<array><string>https://xp.apple.com/report/2/xp_its_main?app=com.apple.iTunes&amp;code=MZCommerce.ASN.ExpiredPasswordToken&amp;buttons=%E8%8E%B7%E5%8F%96%3A%E5%8F%96%E6%B6%88&amp;baseVersion=1&amp;dsId=16916646015&amp;eventVersion=1&amp;storeFrontHeader=143465-19%2C32&amp;eventTime=1652006682067&amp;eventType=dialog&amp;message=%E9%9C%80%E8%A6%81%E7%99%BB%E5%BD%95</string>
</array>
<key>metrics</key>
<dict>
<key>dialogId</key><string>MZCommerce.ASN.ExpiredPasswordToken</string>
<key>message</key><string>需要登录</string>
<key>messageCode</key><string>2072</string>
<key>options</key>
<array>
<string>Get</string>
<string>Cancel</string>
</array>
<key>actionUrl</key><string>p36-buy.itunes.apple.com/WebObjects/MZBuy.woa/wa/buyProduct</string>
<key>asnState</key><integer>2</integer>
<key>mtApp</key><string>com.apple.iTunes</string>
<key>mtClientId</key><string>3z21abvCzFDuz5CYz9bdz19maFVKge</string>
<key>mtEventTime</key><string>2022-05-08 10:44:38 Etc/GMT</string>
<key>mtPageId</key><string>ccfce0ef-4ac8-4d5a-8e5f-79876ac474a4</string>
<key>mtPageType</key><string>Search</string>
<key>mtPrevPage</key><string>Purchases</string>
<key>mtRequestId</key><string>3z21abvCzFDuz5CYz9bdz19maFVKgezL2X64FFVz1MGG</string>
<key>mtTopic</key><string>xp_its_main</string>
<key>eventType</key><string>dialog</string>
</dict>
<key>failureType</key><string>2072</string>
<key>customerMessage</key><string>需要登录</string>
<key>m-allowed</key><true/>
<key>dialog</key>
<dict><key>kind</key><string>authorization</string>
<key>m-allowed</key><true/>
<key>use-keychain</key><true/>
<key>isFree</key><true/>
<key>message</key><string>需要登录</string>
<key>explanation</key><string>如果您有 Apple ID 和密码,请在此处输入。例如,如果您使用过 iTunes Store 或 iCloud,那么您已有 Apple ID。</string>
<key>defaultButton</key><string>ok</string>
<key>okButtonString</key><string>获取</string>
<key>okButtonAction</key><dict><key>kind</key><string>Buy</string>
<key>buyParams</key><string>mtEventTime=1652006678827&amp;salableAdamId=444934666&amp;mtRequestId=3z21abvCzFDuz5CYz9bdz19maFVKgezL2X64FFVz1MGG&amp;appExtVrsId=848463733&amp;mtTopic=xp_its_main&amp;guid=22330C8C.C2E39C5C.06C40B91.D0990F95.9A890F9D.AB7F7EB4.56507025&amp;hasBeenAuthedForBuy=true&amp;isInApp=false&amp;price=0&amp;mtClientId=3z21abvCzFDuz5CYz9bdz19maFVKge&amp;productType=C&amp;mtPageType=Search&amp;mtPageId=ccfce0ef-4ac8-4d5a-8e5f-79876ac474a4&amp;machineName=DESKTOP-697LVJS&amp;ageCheck=true&amp;pg=default&amp;mtApp=com.apple.iTunes&amp;needDiv=0&amp;mtPrevPage=Purchases&amp;pricingParameters=STDQ</string>
<key>itemName</key><string>QQ</string>
</dict>
<key>cancelButtonString</key><string>取消</string>
<key>initialCheckboxValue</key><true/></dict>
<key>cancel-purchase-batch</key><true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plist version="1.0">
<dict>
<key>pings</key>
<array></array>
<key>jingleDocType</key><string>purchaseSuccess</string>
<key>jingleAction</key><string>purchaseProduct</string>
<key>status</key><integer>0</integer>
<key>dsPersonId</key><string>10964418715</string>
<key>creditDisplay</key><string></string>
<key>creditBalance</key><string>1311811</string>
<key>freeSongBalance</key><string>1311811</string>
<key>authorized</key><false/><key>download-queue-item-count</key><integer>0</integer>
<key>songList</key>
<array>
</array>
<key>metrics</key>
<dict>
<key>itemIds</key>
<array>
<integer>580311103</integer>
</array>
<key>price</key><real>0.00</real>
<key>priceType</key><string>STDQ</string>
<key>productTypes</key>
<array>
<string>C</string>
</array>
<key>currency</key><string>JPY</string>
<key>exchangeRateToUSD</key><real>0.0076722418</real>
<key>commerceEvent_purchase_priceType</key><string>STDQ</string>
<key>commerceEvent_storeFrontId</key><string>143462</string>
<key>commerceEvent_result_resultType</key><integer>0</integer>
<key>commerceEvent_flowType</key><integer>4</integer>
<key>commerceEvent_flowStep</key><integer>6</integer>
</dict>
<key>duAnonymousPings</key>
<array>
<string>https://xp.apple.com/report/2/xp_app_buy?clientId=0&amp;sf=143462&amp;adamId=580311103</string>
</array>
<key>subscriptionStatus</key>
<dict>
<key>terms</key>
<array>
<dict>
<key>type</key><string>Store</string>
<key>latestTerms</key><integer>28</integer>
<key>agreedToTerms</key><integer>31</integer>
<key>source</key><string>account</string>
</dict>
</array>
<key>account</key>
<dict>
<key>isMinor</key><false/>
<key>suspectUnderage</key><false/>
</dict>
<key>family</key>
<dict>
<key>hasFamily</key><false/>
</dict>
</dict>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plist version="1.0">
<dict>
<key>pings</key>
<array></array>
<key>jingleDocType</key><string>purchaseSuccess</string>
<key>jingleAction</key><string>purchaseProduct</string>
<key>status</key><integer>0</integer>
<key>dsPersonId</key><string>16916646015</string>
<key>creditDisplay</key><string></string>
<key>creditBalance</key><string>1311811</string>
<key>freeSongBalance</key><string>1311811</string>
<key>creditDisplayInternal</key><string>Â¥0.00+0+0+0+0+0</string>
<key>authorized</key><true/>
<key>download-queue-item-count</key><integer>1</integer>
<key>songList</key>
<array>
<dict>
<key>songId</key><integer>444934666</integer>
<key>URL</key><string>https://iosapps.itunes.apple.com/itunes-assets/Purple112/v4/8c/5d/34/8c5d343a-2132-8690-c6b1-866ec2f6b2f6/extDirwkazoqouvdywwgjk.lc.14519290919268642.5LAVFF7SAES2W.signed.dpkg.ipa?accessKey=1652201151_1282442801256894451_c%2FtMyevC%2FbCtPTcx3kpjPzNcDfSmgpz1CnzuNFgB%2F1n13VEU1IYDwlq1Xie8WXNHq4U4t341RRlyT3J1OI1Doy1%2FKOG8Pk4u38Kn30NHbCnmgCRC2r9lGlND9ZjU7AxGCQeVb5iHc74Vf5i7Exbg3hq5UfUddWq%2BBe7s3VEyvOX9Rikq0Hzj4OkYUkklrks95yuvrEhXjMFYO8YpQAr0tCjKoyU2rvjS%2BwnPYk5U0Hy6DnusEJ3JmJpJKC6EiLvb</string>
<key>downloadKey</key><string></string><key>artworkURL</key><string>https://is5-ssl.mzstatic.com/image/thumb/Purple112/v4/b9/ac/4e/b9ac4ef3-0152-fa92-872f-fe773d799117/AppIcon-1-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/2000x2000bb.jpg</string><key>artwork-urls</key>
<dict>
<key>image-type</key><string>download-queue-item</string>
<key>default</key>
<dict>
<key>url</key>
<string>https://is4-ssl.mzstatic.com/image/thumb/Purple112/v4/b9/ac/4e/b9ac4ef3-0152-fa92-872f-fe773d799117/AppIcon-1-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/57x57bb.jpg</string>
</dict>
</dict>
<key>md5</key><string>cb3a13a60ac4c9f507b0fefa351e0351</string><key>chunks</key>
<dict>
<key>chunkSize</key><integer>10485760</integer>
<key>hashes</key>
<array>
<string>a9c3b17b7fd5ce1380580c6f063c469b</string>
<string>8dfa7efed3cccca58987ec5fb5aad752</string>
<string>c636e4bfcdc17f5ce23a8ef104a44fa3</string>
<string>90911e7b4d63bf8d4fc1c0bb2756211b</string>
<string>0c7ae0bfa13df1a3cb25d18eccf79083</string>
<string>4edbba71a6baabeba209cbe495144017</string>
<string>2b915fa08b532ef007787f3cf9ed68e6</string>
<string>e8ae486763cd40c730a6f2008bb212df</string>
<string>a91b20af08349a115d318a3c1a9ac69c</string>
<string>001a0a9e6f0f779365fd1a9e08993afa</string>
<string>d9c965a523b445f662aac8eb49fa271e</string>
<string>22f61327c32a4569a4d81f29ae93f238</string>
<string>3caf910c1da7640a89a51c2ae33e8a3b</string>
<string>70fcd6e5517144b1298848bd964f4dcc</string>
<string>9fb4924aed5006d2c7037be6532d1652</string>
<string>fb341fcaaf6027182f885628e15542f6</string>
<string>a0999c33fa684fa21cf2d8c8a4d45e27</string>
<string>28025c9522f1dc05360e36a9e6da508b</string>
<string>ea980ee5fae29238778cdd16a1f0a2fa</string>
<string>699c2c8bcd5b4b9353bba25a58bb45f8</string>
<string>10423be39910d01b9e763cc1514fef05</string>
<string>3da83694d61846e91a0a21981e88652a</string>
<string>937391e158c46e385bf1ebd2f17501aa</string>
<string>18a12b305b3a0086d76d4f9c72764a00</string>
<string>c19f2b5c1eeb909db77b5d715e023511</string>
<string>80552d4ed44472cf0f307bc6e6e4180c</string>
<string>9af9bebfb73a15084186032efd64f95b</string>
<string>bdc8305c863637d6031c079f3438b2b2</string>
<string>406fff31a2d714ffa1eb7c417232c478</string>
<string>f29550bd0e718ca8588d13654a14e669</string>
<string>ea916c4a8e8f772610bd4de2549ec891</string>
<string>9ff8f440fb8260ffe7e39e17215e8e9f</string>
<string>b596fe96037d6e0e52401676b87fc6c0</string>
<string>1be6f6b3141c80d2b3ad952db9e92ebb</string>
<string>4a9061c50a209184f7d4a54f80ce61ef</string>
<string>e6505a456ca2273700dcad1dead1f625</string>
<string>9ac28b8e7dd43be5fd309f16403afef8</string>
<string>5088792cdb4928532714a7023df1275d</string>
<string>c0b0d04fd38919c8688c5e793b33d5e4</string>
<string>a87331d5e314e6708f6cc67075e36c56</string>
<string>63ea3257f99d04b44730924cb4a0d553</string>
<string>b3d953d072a3b0e8e264c16d96cebeaf</string>
<string>5eff58a53e7f7e87f57fcb038a4ad0a4</string>
<string>e37467e9f2c7d336c3742b63ee70b4ab</string>
<string>abfcdd0ba248ee9c5bc1b4bf8ab03c15</string>
<string>7c4d4ccfcaaef4708f3d1b0fce994294</string>
<string>927273c03da6f0fcdc674b40224c0a6d</string>
<string>648761edcf4c3d69e147b3671abee7a8</string>
<string>146e363283ed83bfd72a8c4d6b8fa7ac</string>
<string>69c8e188357d463d00bd7f8134786b1c</string>
<string>babbb9b2f0c3d31a4d9e0e0d77852f5e</string>
<string>ae46925c45e689783c38f065a9d1e7ea</string>
<string>c7f4967cb830f008417c02009ae2196a</string>
<string>9b8f17524eb05a512c26bb9e2b89220b</string>
<string>11cdc44dd07fe5d9fa3eaba0a179704c</string>
<string>d0f17891f1c141e39cfcacfb58c1bb3c</string>
<string>3273d004f5971ebee5625868d4978f69</string>
<string>0aa895b7d15ad0760156b3062fb6deeb</string>
<string>7b27b6e73b0731b307399aa4da837df9</string>
</array>
</dict>
<key>isStreamable</key><true/>
<key>uncompressedSize</key><integer>795979776</integer>
<key>sinfs</key><array> <dict> <key>id</key> <integer>0</integer> <key>sinf</key> <data>AAAEIHNpbmYAAAAMZnJtYWdhbWUAAAAUc2NobQAAAABpdHVuAAAAAAAAA3BzY2hpAAAADHVzZXLwT4h/AAAADGNyZHTenU/fAAAADGFzZHQAAAAAAAAADGtleSAAAAACAAAAGGl2aXaD6ySnLt5l3Pdp75fJ0mjxAAAAWHJpZ2h2ZUlEAAEOnHBsYXQAAAABYXZlcgEBAQB0cmFu3p1P33NpbmcAAAAAc29uZxqFKgp0b29sUDYwNG1lZGkAAACAbW9kZQAAIABoaTMyAAAAAwAAAQhuYW1l5q63IOWmueS7jQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcBwcml2eDOeoQvqIT8I9Y9+tU7xixDGAGJI8TvGWPhI2r7kjf9vKy/JunWkBOLN7Ft3eFaFidNSVs3VTlvYSulf3VT0QAc0+3/pFznoHsNC5pMpQ6y0HdBW+8nG+JbiLjeTU3Nj2akunI45wVAiE2IWr1mERJwFG5CavbGOvHM9JBxkHaczFWUUm60zUHuMiBGZiZVDbVI4Oilxdn0vRb3c2P0zDrhOyxez9B7ppEMzJpFkDa2ieFSE0peNxsx8xi+BLWqQ88IZiCpCrLma3P5Wj40hb0nXclQY2t9Zvnw54A2DC/NHEUEDq1T/cZvAi16AdDRB0/GWOTLf7RNf1R8glahArjoD+fddyk9MuVwEN63YqCH/bNh1L7+hpk0Vh2tDGuEy/KDA30kZgF9Z2FED9LAQpCmx1BHUc60NDq++mCImFNiO528OnwirxjZoMWCZWsyCBL+RDTLcNLZOVDwKJcCqP+xLhbbSD8yoQhug/5reFOIUieODiQHGnfVmUmVe9sDuoJmEME3MHMwUHIpGkVfXVE6SPxA2eoN6EReeKwVwbDeLsp/r/dA8jX7BWW9WSjjfAAAAAAAAAAAAAACIc2lnbggl0CkIwRg6tBbdAWQKT2ZlMkYC2bZvWrsyeLzUy+BSYJAs7v2jr1DkRH/xdJbaDjvmkCvS75EUlCXU0oJYT8BydxZzTpJNMALVfwuJNELOkm8sqlCN1/zP1KM3XOeEMu/k6MmtV4nG3zOtLRcKHg5YRz17WcccdTSz251J2Ugn</data> </dict></array><key>purchaseDate</key><string>2022-05-08T10:45:51Z</string>
<key>download-id</key><string>501382282407089488</string>
<key>is-in-queue</key><true/>
<key>asset-info</key>
<dict>
<key>file-size</key><integer>611092999</integer>
<key>flavor</key><string>10:purple</string>
</dict>
<key>metadata</key><dict>
<key>MacUIRequiredDeviceCapabilities</key>
<dict>
<key>arm64</key><true/>
</dict>
<key>UIRequiredDeviceCapabilities</key>
<dict>
<key>arm64</key><true/>
</dict>
<key>WKRunsIndependentlyOfCompanionApp</key><false/>
<key>WKWatchOnly</key><false/>
<key>appleWatchEnabled</key><true/>
<key>artistId</key><integer>292374531</integer>
<key>artistName</key><string>Tencent Technology (Shenzhen) Company Limited</string>
<key>bundleDisplayName</key><string>QQ</string>
<key>bundleShortVersionString</key><string>8.8.88</string>
<key>bundleVersion</key><string>8.8.88.662</string>
<key>copyright</key><string>Copyright &#169; 1998- 2022 Tencent. All Rights Reserved</string>
<key>fileExtension</key><string>.app</string>
<key>gameCenterEnabled</key><false/>
<key>gameCenterEverEnabled</key><false/>
<key>genre</key><string>社交</string>
<key>genreId</key><integer>6005</integer>
<key>itemId</key><integer>444934666</integer>
<key>itemName</key><string>QQ</string>
<key>kind</key><string>software</string>
<key>nameTranscriptions</key>
<dict>
<key>zh-Hans-CN</key>
<array>
<string>QQ</string>
</array>
</dict>
<key>playlistName</key><string>Tencent Technology (Shenzhen) Company Limited</string>
<key>product-type</key><string>ios-app</string>
<key>rating</key>
<dict>
<key>content</key><string>偶尔/轻微的色情内容或裸露 , Advisory.NO.GAMBLING_CONTESTS , 偶尔/轻微的成人或性暗示题材 , Advisory.NO.UNRESTRICTED_WEB_ACCESS and Advisory.NO.TRUE_GAMBLING</string>
<key>label</key><string>12+</string>
<key>rank</key><integer>300</integer>
<key>system</key><string>itunes-games</string>
</dict>
<key>releaseDate</key><string>2011-06-23T03:33:55Z</string>
<key>requiresRosetta</key><false/>
<key>runsOnAppleSilicon</key><true/>
<key>runsOnIntel</key><false/>
<key>s</key><integer>143465</integer>
<key>software-platform</key><string>ios</string>
<key>softwareIcon57x57URL</key><string>https://is4-ssl.mzstatic.com/image/thumb/Purple112/v4/b9/ac/4e/b9ac4ef3-0152-fa92-872f-fe773d799117/AppIcon-1-0-0-1x_U007emarketing-0-0-0-7-0-0-sRGB-0-0-0-GLES2_U002c0-512MB-85-220-0-0.png/114x114bb.jpg</string>
<key>softwareIconNeedsShine</key><false/>
<key>softwareSupportedDeviceIds</key>
<array>
<integer>2</integer>
<integer>9</integer>
<integer>4</integer>
</array>
<key>softwareVersionBundleId</key><string>com.tencent.mqq</string>
<key>softwareVersionExternalIdentifier</key><integer>848463733</integer>
<key>softwareVersionExternalIdentifiers</key>
<array>
<integer>3843900</integer>
<integer>3876776</integer>
<integer>3941034</integer>
<integer>3973775</integer>
<integer>4070873</integer>
<integer>4135846</integer>
<integer>4321059</integer>
<integer>4492645</integer>
<integer>4917185</integer>
<integer>5632593</integer>
<integer>6232232</integer>
<integer>6860432</integer>
<integer>7792605</integer>
<integer>9642362</integer>
<integer>11556077</integer>
<integer>11818464</integer>
<integer>12638046</integer>
<integer>13422327</integer>
<integer>14959445</integer>
<integer>15410008</integer>
<integer>15765932</integer>
<integer>15854719</integer>
<integer>16122679</integer>
<integer>31562763</integer>
<integer>275882650</integer>
<integer>385122645</integer>
<integer>580102645</integer>
<integer>595393136</integer>
<integer>608133076</integer>
<integer>629072654</integer>
<integer>687502658</integer>
<integer>747082669</integer>
<integer>811253584</integer>
<integer>811445779</integer>
<integer>811179715</integer>
<integer>811445780</integer>
<integer>811590055</integer>
<integer>811669050</integer>
<integer>812133257</integer>
<integer>812375519</integer>
<integer>812625692</integer>
<integer>812972631</integer>
<integer>813031156</integer>
<integer>813192464</integer>
<integer>813298393</integer>
<integer>813463229</integer>
<integer>813961231</integer>
<integer>813962159</integer>
<integer>814174262</integer>
<integer>814318376</integer>
<integer>814527796</integer>
<integer>814531991</integer>
<integer>814639613</integer>
<integer>814754396</integer>
<integer>814882132</integer>
<integer>815144899</integer>
<integer>815147083</integer>
<integer>815188393</integer>
<integer>815573881</integer>
<integer>815574602</integer>
<integer>815607136</integer>
<integer>815810968</integer>
<integer>815897122</integer>
<integer>815938087</integer>
<integer>815938591</integer>
<integer>816130933</integer>
<integer>816210673</integer>
<integer>816305041</integer>
<integer>816356364</integer>
<integer>816843896</integer>
<integer>816912335</integer>
<integer>817028549</integer>
<integer>817235792</integer>
<integer>817473714</integer>
<integer>817549698</integer>
<integer>817788181</integer>
<integer>817933532</integer>
<integer>818110324</integer>
<integer>818431910</integer>
<integer>818825180</integer>
<integer>818979113</integer>
<integer>819096686</integer>
<integer>819416223</integer>
<integer>819489902</integer>
<integer>819842838</integer>
<integer>819893353</integer>
<integer>820113905</integer>
<integer>820199943</integer>
<integer>820442929</integer>
<integer>820548304</integer>
<integer>820595060</integer>
<integer>821268583</integer>
<integer>821341311</integer>
<integer>821500924</integer>
<integer>821954014</integer>
<integer>822037007</integer>
<integer>822096329</integer>
<integer>822279520</integer>
<integer>822523036</integer>
<integer>822895308</integer>
<integer>822957820</integer>
<integer>823194852</integer>
<integer>823309872</integer>
<integer>823713346</integer>
<integer>824097583</integer>
<integer>824171129</integer>
<integer>824301257</integer>
<integer>824389600</integer>
<integer>825024981</integer>
<integer>825145808</integer>
<integer>825307653</integer>
<integer>825347730</integer>
<integer>825611268</integer>
<integer>825729315</integer>
<integer>825895542</integer>
<integer>825933124</integer>
<integer>826313718</integer>
<integer>826632543</integer>
<integer>826837026</integer>
<integer>827460275</integer>
<integer>828106847</integer>
<integer>828385681</integer>
<integer>828600919</integer>
<integer>828666943</integer>
<integer>828716670</integer>
<integer>828897691</integer>
<integer>829301009</integer>
<integer>829496800</integer>
<integer>829679760</integer>
<integer>829821912</integer>
<integer>830133231</integer>
<integer>830530856</integer>
<integer>830742895</integer>
<integer>831337375</integer>
<integer>831405629</integer>
<integer>831472755</integer>
<integer>831824011</integer>
<integer>832139548</integer>
<integer>832542612</integer>
<integer>832827329</integer>
<integer>833393416</integer>
<integer>833855517</integer>
<integer>834104017</integer>
<integer>834138755</integer>
<integer>834768091</integer>
<integer>834880993</integer>
<integer>834939578</integer>
<integer>835135459</integer>
<integer>835524672</integer>
<integer>835716180</integer>
<integer>835976856</integer>
<integer>836375483</integer>
<integer>836825545</integer>
<integer>836945925</integer>
<integer>837334930</integer>
<integer>837735298</integer>
<integer>837835768</integer>
<integer>837881604</integer>
<integer>838238560</integer>
<integer>839235987</integer>
<integer>839700113</integer>
<integer>840003771</integer>
<integer>840041841</integer>
<integer>840921423</integer>
<integer>841227891</integer>
<integer>841968948</integer>
<integer>842099251</integer>
<integer>842166600</integer>
<integer>842303496</integer>
<integer>842463280</integer>
<integer>842670770</integer>
<integer>842892434</integer>
<integer>843105491</integer>
<integer>843416604</integer>
<integer>843638409</integer>
<integer>843881653</integer>
<integer>844115468</integer>
<integer>844170367</integer>
<integer>844356613</integer>
<integer>844638728</integer>
<integer>844786323</integer>
<integer>844986204</integer>
<integer>845375859</integer>
<integer>846332674</integer>
<integer>846748317</integer>
<integer>847332305</integer>
<integer>847747163</integer>
<integer>848017318</integer>
<integer>848463733</integer>
</array>
<key>vendorId</key><integer>69276</integer>
<key>drmVersionNumber</key><integer>0</integer>
<key>versionRestrictions</key><integer>16843008</integer>
<key>storeCohort</key><string>10|date=1652005800000&amp;sf=143465&amp;pgtp=Search&amp;pgid=ccfce0ef-4ac8-4d5a-8e5f-79876ac474a4&amp;prpg=Purchases</string>
<key>hasOrEverHasHadIAP</key><true/>
</dict>
</dict>
</array>
<key>download-queue-info</key>
<dict>
<key>download-queue-item-count</key><integer>0</integer>
<key>dsid</key><integer>16916646015</integer>
<key>is-auto-download-machine</key><false/>
</dict>
<key>metrics</key>
<dict>
<key>itemIds</key>
<array>
<integer>444934666</integer>
</array>
<key>price</key><real>0.00</real>
<key>priceType</key><string>STDQ</string>
<key>productTypes</key>
<array>
<string>C</string>
</array>
<key>mtApp</key><string>com.apple.iTunes</string>
<key>mtClientId</key><string>3z21abvCzFDuz5CYz9bdz19maFVKge</string>
<key>mtEventTime</key><string>2022-05-08 10:44:38 Etc/GMT</string>
<key>mtPageId</key><string>ccfce0ef-4ac8-4d5a-8e5f-79876ac474a4</string>
<key>mtPageType</key><string>Search</string>
<key>mtPrevPage</key><string>Purchases</string>
<key>mtRequestId</key><string>3z21abvCzFDuz5CYz9bdz19maFVKgezL2X64FFVz1MGG</string>
<key>mtTopic</key><string>xp_its_main</string>
<key>currency</key><string>CNY</string>
<key>exchangeRateToUSD</key><real>0.1490268546</real>
<key>commerceEvent_purchase_priceType</key><string>STDQ</string>
<key>commerceEvent_storeFrontId</key><string>143465</string>
<key>commerceEvent_result_resultType</key><integer>0</integer>
<key>commerceEvent_flowType</key><integer>4</integer>
<key>commerceEvent_flowStep</key><integer>6</integer>
</dict>
<key>duAnonymousPings</key>
<array>
<string>https://xp.apple.com/report/2/xp_app_buy?clientId=0&amp;sf=143465&amp;adamId=444934666</string>
</array>
<key>subscriptionStatus</key>
<dict>
<key>music</key>
<dict>
<key>status</key><string>Disabled</string>
<key>reason</key><string></string>
<key>isAdmin</key><false/>
<key>isNotEligibleForFreeTrial</key><false/>
</dict>
<key>terms</key>
<array>
<dict>
<key>type</key><string>Store</string>
<key>latestTerms</key><integer>22</integer>
<key>agreedToTerms</key><integer>22</integer>
<key>source</key><string>account</string>
</dict>
</array>
<key>account</key>
<dict>
<key>isMinor</key><false/>
<key>suspectUnderage</key><false/>
</dict>
<key>family</key>
<dict>
<key>hasFamily</key><false/>
</dict>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,250 @@
from reprlib import repr as limitedRepr
class StoreAuthenticateReq:
_types_map = {
"appleId": {"type": str, "subtype": None},
"attempt": {"type": str, "subtype": None},
"createSession": {"type": str, "subtype": None},
"guid": {"type": str, "subtype": None},
"password": {"type": str, "subtype": None},
"rmp": {"type": str, "subtype": None},
"why": {"type": str, "subtype": None},
}
_formats_map = {}
_validations_map = {
"appleId": {
"required": True,
},
"attempt": {
"required": True,
},
"createSession": {
"required": True,
},
"guid": {
"required": True,
},
"password": {
"required": True,
},
"rmp": {
"required": True,
},
"why": {
"required": True,
},
}
def __init__(
self,
appleId: str = None,
attempt: str = None,
createSession: str = None,
guid: str = None,
password: str = None,
rmp: str = None,
why: str = None,
):
pass
self.__appleId = appleId
self.__attempt = attempt
self.__createSession = createSession
self.__guid = guid
self.__password = password
self.__rmp = rmp
self.__why = why
def _get_appleId(self):
return self.__appleId
def _set_appleId(self, value):
if not isinstance(value, str):
raise TypeError("appleId must be str")
self.__appleId = value
appleId = property(_get_appleId, _set_appleId)
def _get_attempt(self):
return self.__attempt
def _set_attempt(self, value):
if not isinstance(value, str):
raise TypeError("attempt must be str")
self.__attempt = value
attempt = property(_get_attempt, _set_attempt)
def _get_createSession(self):
return self.__createSession
def _set_createSession(self, value):
if not isinstance(value, str):
raise TypeError("createSession must be str")
self.__createSession = value
createSession = property(_get_createSession, _set_createSession)
def _get_guid(self):
return self.__guid
def _set_guid(self, value):
if not isinstance(value, str):
raise TypeError("guid must be str")
self.__guid = value
guid = property(_get_guid, _set_guid)
def _get_password(self):
return self.__password
def _set_password(self, value):
if not isinstance(value, str):
raise TypeError("password must be str")
self.__password = value
password = property(_get_password, _set_password)
def _get_rmp(self):
return self.__rmp
def _set_rmp(self, value):
if not isinstance(value, str):
raise TypeError("rmp must be str")
self.__rmp = value
rmp = property(_get_rmp, _set_rmp)
def _get_why(self):
return self.__why
def _set_why(self, value):
if not isinstance(value, str):
raise TypeError("why must be str")
self.__why = value
why = property(_get_why, _set_why)
@staticmethod
def from_dict(d):
v = {}
if "appleId" in d:
v["appleId"] = (
str.from_dict(d["appleId"])
if hasattr(str, "from_dict")
else d["appleId"]
)
if "attempt" in d:
v["attempt"] = (
str.from_dict(d["attempt"])
if hasattr(str, "from_dict")
else d["attempt"]
)
if "createSession" in d:
v["createSession"] = (
str.from_dict(d["createSession"])
if hasattr(str, "from_dict")
else d["createSession"]
)
if "guid" in d:
v["guid"] = (
str.from_dict(d["guid"]) if hasattr(str, "from_dict") else d["guid"]
)
if "password" in d:
v["password"] = (
str.from_dict(d["password"])
if hasattr(str, "from_dict")
else d["password"]
)
if "rmp" in d:
v["rmp"] = (
str.from_dict(d["rmp"]) if hasattr(str, "from_dict") else d["rmp"]
)
if "why" in d:
v["why"] = (
str.from_dict(d["why"]) if hasattr(str, "from_dict") else d["why"]
)
return StoreAuthenticateReq(**v)
def as_dict(self):
d = {}
if self.__appleId is not None:
d["appleId"] = (
self.__appleId.as_dict()
if hasattr(self.__appleId, "as_dict")
else self.__appleId
)
if self.__attempt is not None:
d["attempt"] = (
self.__attempt.as_dict()
if hasattr(self.__attempt, "as_dict")
else self.__attempt
)
if self.__createSession is not None:
d["createSession"] = (
self.__createSession.as_dict()
if hasattr(self.__createSession, "as_dict")
else self.__createSession
)
if self.__guid is not None:
d["guid"] = (
self.__guid.as_dict()
if hasattr(self.__guid, "as_dict")
else self.__guid
)
if self.__password is not None:
d["password"] = (
self.__password.as_dict()
if hasattr(self.__password, "as_dict")
else self.__password
)
if self.__rmp is not None:
d["rmp"] = (
self.__rmp.as_dict() if hasattr(self.__rmp, "as_dict") else self.__rmp
)
if self.__why is not None:
d["why"] = (
self.__why.as_dict() if hasattr(self.__why, "as_dict") else self.__why
)
return d
def __repr__(self):
return "<Class StoreAuthenticateReq. appleId: {}, attempt: {}, createSession: {}, guid: {}, password: {}, rmp: {}, why: {}>".format(
limitedRepr(
self.__appleId[:20]
if isinstance(self.__appleId, bytes)
else self.__appleId
),
limitedRepr(
self.__attempt[:20]
if isinstance(self.__attempt, bytes)
else self.__attempt
),
limitedRepr(
self.__createSession[:20]
if isinstance(self.__createSession, bytes)
else self.__createSession
),
limitedRepr(
self.__guid[:20] if isinstance(self.__guid, bytes) else self.__guid
),
limitedRepr(
self.__password[:20]
if isinstance(self.__password, bytes)
else self.__password
),
limitedRepr(
self.__rmp[:20] if isinstance(self.__rmp, bytes) else self.__rmp
),
limitedRepr(
self.__why[:20] if isinstance(self.__why, bytes) else self.__why
),
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,956 @@
from reprlib import repr as limitedRepr
class StoreBuyproductReq:
_types_map = {
"ageCheck": {"type": str, "subtype": None},
"appExtVrsId": {"type": str, "subtype": None},
"guid": {"type": str, "subtype": None},
"hasBeenAuthedForBuy": {"type": str, "subtype": None},
"isInApp": {"type": str, "subtype": None},
"kbsync": {"type": str, "subtype": None},
"sbsync": {"type": str, "subtype": None},
"afds": {"type": str, "subtype": None},
"machineName": {"type": str, "subtype": None},
"mtApp": {"type": str, "subtype": None},
"mtClientId": {"type": str, "subtype": None},
"mtEventTime": {"type": str, "subtype": None},
"mtPageId": {"type": str, "subtype": None},
"mtPageType": {"type": str, "subtype": None},
"mtPrevPage": {"type": str, "subtype": None},
"mtRequestId": {"type": str, "subtype": None},
"mtTopic": {"type": str, "subtype": None},
"needDiv": {"type": str, "subtype": None},
"pg": {"type": str, "subtype": None},
"price": {"type": str, "subtype": None},
"pricingParameters": {"type": str, "subtype": None},
"productType": {"type": str, "subtype": None},
"salableAdamId": {"type": str, "subtype": None},
"hasAskedToFulfillPreorder": {"type": str, "subtype": None},
"buyWithoutAuthorization": {"type": str, "subtype": None},
"hasDoneAgeCheck": {"type": str, "subtype": None},
"hasConfirmedPaymentSheet": {"type": str, "subtype": None},
"asn": {"type": str, "subtype": None},
}
_formats_map = {}
_validations_map = {
"ageCheck": {
"required": False,
},
"appExtVrsId": {
"required": True,
},
"guid": {
"required": True,
},
"hasBeenAuthedForBuy": {
"required": False,
},
"isInApp": {
"required": False,
},
"kbsync": {
"required": True,
},
"sbsync": {
"required": False,
},
"afds": {
"required": False,
},
"machineName": {
"required": False,
},
"mtApp": {
"required": False,
},
"mtClientId": {
"required": False,
},
"mtEventTime": {
"required": False,
},
"mtPageId": {
"required": False,
},
"mtPageType": {
"required": False,
},
"mtPrevPage": {
"required": False,
},
"mtRequestId": {
"required": False,
},
"mtTopic": {
"required": False,
},
"needDiv": {
"required": False,
},
"pg": {
"required": False,
},
"price": {
"required": True,
},
"pricingParameters": {
"required": True,
},
"productType": {
"required": True,
},
"salableAdamId": {
"required": True,
},
"hasAskedToFulfillPreorder": {
"required": False,
},
"buyWithoutAuthorization": {
"required": False,
},
"hasDoneAgeCheck": {
"required": False,
},
"hasConfirmedPaymentSheet": {
"required": False,
},
"asn": {
"required": False,
},
}
def __init__(
self,
ageCheck: str = None,
appExtVrsId: str = None,
guid: str = None,
hasBeenAuthedForBuy: str = None,
isInApp: str = None,
kbsync: str = None,
sbsync: str = None,
afds: str = None,
machineName: str = None,
mtApp: str = None,
mtClientId: str = None,
mtEventTime: str = None,
mtPageId: str = None,
mtPageType: str = None,
mtPrevPage: str = None,
mtRequestId: str = None,
mtTopic: str = None,
needDiv: str = None,
pg: str = None,
price: str = None,
pricingParameters: str = None,
productType: str = None,
salableAdamId: str = None,
hasAskedToFulfillPreorder: str = None,
buyWithoutAuthorization: str = None,
hasDoneAgeCheck: str = None,
hasConfirmedPaymentSheet: str = None,
asn: str = None,
):
pass
self.__ageCheck = ageCheck
self.__appExtVrsId = appExtVrsId
self.__guid = guid
self.__hasBeenAuthedForBuy = hasBeenAuthedForBuy
self.__isInApp = isInApp
self.__kbsync = kbsync
self.__sbsync = sbsync
self.__afds = afds
self.__machineName = machineName
self.__mtApp = mtApp
self.__mtClientId = mtClientId
self.__mtEventTime = mtEventTime
self.__mtPageId = mtPageId
self.__mtPageType = mtPageType
self.__mtPrevPage = mtPrevPage
self.__mtRequestId = mtRequestId
self.__mtTopic = mtTopic
self.__needDiv = needDiv
self.__pg = pg
self.__price = price
self.__pricingParameters = pricingParameters
self.__productType = productType
self.__salableAdamId = salableAdamId
self.__hasAskedToFulfillPreorder = hasAskedToFulfillPreorder
self.__buyWithoutAuthorization = buyWithoutAuthorization
self.__hasDoneAgeCheck = hasDoneAgeCheck
self.__hasConfirmedPaymentSheet = hasConfirmedPaymentSheet
self.__asn = asn
def _get_ageCheck(self):
return self.__ageCheck
def _set_ageCheck(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("ageCheck must be str")
self.__ageCheck = value
ageCheck = property(_get_ageCheck, _set_ageCheck)
def _get_appExtVrsId(self):
return self.__appExtVrsId
def _set_appExtVrsId(self, value):
if not isinstance(value, str):
raise TypeError("appExtVrsId must be str")
self.__appExtVrsId = value
appExtVrsId = property(_get_appExtVrsId, _set_appExtVrsId)
def _get_guid(self):
return self.__guid
def _set_guid(self, value):
if not isinstance(value, str):
raise TypeError("guid must be str")
self.__guid = value
guid = property(_get_guid, _set_guid)
def _get_hasBeenAuthedForBuy(self):
return self.__hasBeenAuthedForBuy
def _set_hasBeenAuthedForBuy(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("hasBeenAuthedForBuy must be str")
self.__hasBeenAuthedForBuy = value
hasBeenAuthedForBuy = property(_get_hasBeenAuthedForBuy, _set_hasBeenAuthedForBuy)
def _get_isInApp(self):
return self.__isInApp
def _set_isInApp(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("isInApp must be str")
self.__isInApp = value
isInApp = property(_get_isInApp, _set_isInApp)
def _get_kbsync(self):
return self.__kbsync
def _set_kbsync(self, value):
if not isinstance(value, str):
raise TypeError("kbsync must be str")
self.__kbsync = value
kbsync = property(_get_kbsync, _set_kbsync)
def _get_sbsync(self):
return self.__sbsync
def _set_sbsync(self, value):
if not isinstance(value, str):
raise TypeError("sbsync must be str")
self.__sbsync = value
sbsync = property(_get_sbsync, _set_sbsync)
def _get_afds(self):
return self.__afds
def _set_afds(self, value):
if not isinstance(value, str):
raise TypeError("afds must be str")
self.__afds = value
afds = property(_get_afds, _set_afds)
def _get_machineName(self):
return self.__machineName
def _set_machineName(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("machineName must be str")
self.__machineName = value
machineName = property(_get_machineName, _set_machineName)
def _get_mtApp(self):
return self.__mtApp
def _set_mtApp(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtApp must be str")
self.__mtApp = value
mtApp = property(_get_mtApp, _set_mtApp)
def _get_mtClientId(self):
return self.__mtClientId
def _set_mtClientId(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtClientId must be str")
self.__mtClientId = value
mtClientId = property(_get_mtClientId, _set_mtClientId)
def _get_mtEventTime(self):
return self.__mtEventTime
def _set_mtEventTime(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtEventTime must be str")
self.__mtEventTime = value
mtEventTime = property(_get_mtEventTime, _set_mtEventTime)
def _get_mtPageId(self):
return self.__mtPageId
def _set_mtPageId(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtPageId must be str")
self.__mtPageId = value
mtPageId = property(_get_mtPageId, _set_mtPageId)
def _get_mtPageType(self):
return self.__mtPageType
def _set_mtPageType(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtPageType must be str")
self.__mtPageType = value
mtPageType = property(_get_mtPageType, _set_mtPageType)
def _get_mtPrevPage(self):
return self.__mtPrevPage
def _set_mtPrevPage(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtPrevPage must be str")
self.__mtPrevPage = value
mtPrevPage = property(_get_mtPrevPage, _set_mtPrevPage)
def _get_mtRequestId(self):
return self.__mtRequestId
def _set_mtRequestId(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtRequestId must be str")
self.__mtRequestId = value
mtRequestId = property(_get_mtRequestId, _set_mtRequestId)
def _get_mtTopic(self):
return self.__mtTopic
def _set_mtTopic(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("mtTopic must be str")
self.__mtTopic = value
mtTopic = property(_get_mtTopic, _set_mtTopic)
def _get_needDiv(self):
return self.__needDiv
def _set_needDiv(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("needDiv must be str")
self.__needDiv = value
needDiv = property(_get_needDiv, _set_needDiv)
def _get_pg(self):
return self.__pg
def _set_pg(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("pg must be str")
self.__pg = value
pg = property(_get_pg, _set_pg)
def _get_price(self):
return self.__price
def _set_price(self, value):
if not isinstance(value, str):
raise TypeError("price must be str")
self.__price = value
price = property(_get_price, _set_price)
def _get_pricingParameters(self):
return self.__pricingParameters
def _set_pricingParameters(self, value):
if not isinstance(value, str):
raise TypeError("pricingParameters must be str")
self.__pricingParameters = value
pricingParameters = property(_get_pricingParameters, _set_pricingParameters)
def _get_productType(self):
return self.__productType
def _set_productType(self, value):
if not isinstance(value, str):
raise TypeError("productType must be str")
self.__productType = value
productType = property(_get_productType, _set_productType)
def _get_salableAdamId(self):
return self.__salableAdamId
def _set_salableAdamId(self, value):
if not isinstance(value, str):
raise TypeError("salableAdamId must be str")
self.__salableAdamId = value
salableAdamId = property(_get_salableAdamId, _set_salableAdamId)
def _get_hasAskedToFulfillPreorder(self):
return self.__hasAskedToFulfillPreorder
def _set_hasAskedToFulfillPreorder(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("hasAskedToFulfillPreorder must be str")
self.__hasAskedToFulfillPreorder = value
hasAskedToFulfillPreorder = property(
_get_hasAskedToFulfillPreorder, _set_hasAskedToFulfillPreorder
)
def _get_buyWithoutAuthorization(self):
return self.__buyWithoutAuthorization
def _set_buyWithoutAuthorization(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("buyWithoutAuthorization must be str")
self.__buyWithoutAuthorization = value
buyWithoutAuthorization = property(
_get_buyWithoutAuthorization, _set_buyWithoutAuthorization
)
def _get_hasDoneAgeCheck(self):
return self.__hasDoneAgeCheck
def _set_hasDoneAgeCheck(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("hasDoneAgeCheck must be str")
self.__hasDoneAgeCheck = value
hasDoneAgeCheck = property(_get_hasDoneAgeCheck, _set_hasDoneAgeCheck)
def _get_hasConfirmedPaymentSheet(self):
return self.__hasConfirmedPaymentSheet
def _set_hasConfirmedPaymentSheet(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("hasConfirmedPaymentSheet must be str")
self.__hasConfirmedPaymentSheet = value
hasConfirmedPaymentSheet = property(_get_hasConfirmedPaymentSheet, _set_hasConfirmedPaymentSheet)
def _get_asn(self):
return self.__asn
def _set_asn(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("asn must be str")
self.__asn = value
asn = property(_get_asn, _set_asn)
@staticmethod
def from_dict(d):
v = {}
if "ageCheck" in d:
v["ageCheck"] = (
str.from_dict(d["ageCheck"])
if hasattr(str, "from_dict")
else d["ageCheck"]
)
if "appExtVrsId" in d:
v["appExtVrsId"] = (
str.from_dict(d["appExtVrsId"])
if hasattr(str, "from_dict")
else d["appExtVrsId"]
)
if "guid" in d:
v["guid"] = (
str.from_dict(d["guid"]) if hasattr(str, "from_dict") else d["guid"]
)
if "hasBeenAuthedForBuy" in d:
v["hasBeenAuthedForBuy"] = (
str.from_dict(d["hasBeenAuthedForBuy"])
if hasattr(str, "from_dict")
else d["hasBeenAuthedForBuy"]
)
if "isInApp" in d:
v["isInApp"] = (
str.from_dict(d["isInApp"])
if hasattr(str, "from_dict")
else d["isInApp"]
)
if "kbsync" in d:
v["kbsync"] = (
str.from_dict(d["kbsync"]) if hasattr(str, "from_dict") else d["kbsync"]
)
if "sbsync" in d:
v["sbsync"] = (
str.from_dict(d["sbsync"]) if hasattr(str, "from_dict") else d["sbsync"]
)
if "afds" in d:
v["afds"] = (
str.from_dict(d["afds"]) if hasattr(str, "from_dict") else d["afds"]
)
if "machineName" in d:
v["machineName"] = (
str.from_dict(d["machineName"])
if hasattr(str, "from_dict")
else d["machineName"]
)
if "mtApp" in d:
v["mtApp"] = (
str.from_dict(d["mtApp"]) if hasattr(str, "from_dict") else d["mtApp"]
)
if "mtClientId" in d:
v["mtClientId"] = (
str.from_dict(d["mtClientId"])
if hasattr(str, "from_dict")
else d["mtClientId"]
)
if "mtEventTime" in d:
v["mtEventTime"] = (
str.from_dict(d["mtEventTime"])
if hasattr(str, "from_dict")
else d["mtEventTime"]
)
if "mtPageId" in d:
v["mtPageId"] = (
str.from_dict(d["mtPageId"])
if hasattr(str, "from_dict")
else d["mtPageId"]
)
if "mtPageType" in d:
v["mtPageType"] = (
str.from_dict(d["mtPageType"])
if hasattr(str, "from_dict")
else d["mtPageType"]
)
if "mtPrevPage" in d:
v["mtPrevPage"] = (
str.from_dict(d["mtPrevPage"])
if hasattr(str, "from_dict")
else d["mtPrevPage"]
)
if "mtRequestId" in d:
v["mtRequestId"] = (
str.from_dict(d["mtRequestId"])
if hasattr(str, "from_dict")
else d["mtRequestId"]
)
if "mtTopic" in d:
v["mtTopic"] = (
str.from_dict(d["mtTopic"])
if hasattr(str, "from_dict")
else d["mtTopic"]
)
if "needDiv" in d:
v["needDiv"] = (
str.from_dict(d["needDiv"])
if hasattr(str, "from_dict")
else d["needDiv"]
)
if "pg" in d:
v["pg"] = str.from_dict(d["pg"]) if hasattr(str, "from_dict") else d["pg"]
if "price" in d:
v["price"] = (
str.from_dict(d["price"]) if hasattr(str, "from_dict") else d["price"]
)
if "pricingParameters" in d:
v["pricingParameters"] = (
str.from_dict(d["pricingParameters"])
if hasattr(str, "from_dict")
else d["pricingParameters"]
)
if "productType" in d:
v["productType"] = (
str.from_dict(d["productType"])
if hasattr(str, "from_dict")
else d["productType"]
)
if "salableAdamId" in d:
v["salableAdamId"] = (
str.from_dict(d["salableAdamId"])
if hasattr(str, "from_dict")
else d["salableAdamId"]
)
if "hasAskedToFulfillPreorder" in d:
v["hasAskedToFulfillPreorder"] = (
str.from_dict(d["hasAskedToFulfillPreorder"])
if hasattr(str, "from_dict")
else d["hasAskedToFulfillPreorder"]
)
if "buyWithoutAuthorization" in d:
v["buyWithoutAuthorization"] = (
str.from_dict(d["buyWithoutAuthorization"])
if hasattr(str, "from_dict")
else d["buyWithoutAuthorization"]
)
if "hasDoneAgeCheck" in d:
v["hasDoneAgeCheck"] = (
str.from_dict(d["hasDoneAgeCheck"])
if hasattr(str, "from_dict")
else d["hasDoneAgeCheck"]
)
if "hasConfirmedPaymentSheet" in d:
v["hasConfirmedPaymentSheet"] = (
str.from_dict(d["hasConfirmedPaymentSheet"])
if hasattr(str, "from_dict")
else d["hasConfirmedPaymentSheet"]
)
if "asn" in d:
v["asn"] = (
str.from_dict(d["asn"])
if hasattr(str, "from_dict")
else d["asn"]
)
return StoreBuyproductReq(**v)
def as_dict(self):
d = {}
if self.__ageCheck is not None:
d["ageCheck"] = (
self.__ageCheck.as_dict()
if hasattr(self.__ageCheck, "as_dict")
else self.__ageCheck
)
if self.__appExtVrsId is not None:
d["appExtVrsId"] = (
self.__appExtVrsId.as_dict()
if hasattr(self.__appExtVrsId, "as_dict")
else self.__appExtVrsId
)
if self.__guid is not None:
d["guid"] = (
self.__guid.as_dict()
if hasattr(self.__guid, "as_dict")
else self.__guid
)
if self.__hasBeenAuthedForBuy is not None:
d["hasBeenAuthedForBuy"] = (
self.__hasBeenAuthedForBuy.as_dict()
if hasattr(self.__hasBeenAuthedForBuy, "as_dict")
else self.__hasBeenAuthedForBuy
)
if self.__isInApp is not None:
d["isInApp"] = (
self.__isInApp.as_dict()
if hasattr(self.__isInApp, "as_dict")
else self.__isInApp
)
if self.__kbsync is not None:
d["kbsync"] = (
self.__kbsync.as_dict()
if hasattr(self.__kbsync, "as_dict")
else self.__kbsync
)
if self.__sbsync is not None:
d["sbsync"] = (
self.__sbsync.as_dict()
if hasattr(self.__sbsync, "as_dict")
else self.__sbsync
)
if self.__afds is not None:
d["afds"] = (
self.__afds.as_dict()
if hasattr(self.__afds, "as_dict")
else self.__afds
)
if self.__machineName is not None:
d["machineName"] = (
self.__machineName.as_dict()
if hasattr(self.__machineName, "as_dict")
else self.__machineName
)
if self.__mtApp is not None:
d["mtApp"] = (
self.__mtApp.as_dict()
if hasattr(self.__mtApp, "as_dict")
else self.__mtApp
)
if self.__mtClientId is not None:
d["mtClientId"] = (
self.__mtClientId.as_dict()
if hasattr(self.__mtClientId, "as_dict")
else self.__mtClientId
)
if self.__mtEventTime is not None:
d["mtEventTime"] = (
self.__mtEventTime.as_dict()
if hasattr(self.__mtEventTime, "as_dict")
else self.__mtEventTime
)
if self.__mtPageId is not None:
d["mtPageId"] = (
self.__mtPageId.as_dict()
if hasattr(self.__mtPageId, "as_dict")
else self.__mtPageId
)
if self.__mtPageType is not None:
d["mtPageType"] = (
self.__mtPageType.as_dict()
if hasattr(self.__mtPageType, "as_dict")
else self.__mtPageType
)
if self.__mtPrevPage is not None:
d["mtPrevPage"] = (
self.__mtPrevPage.as_dict()
if hasattr(self.__mtPrevPage, "as_dict")
else self.__mtPrevPage
)
if self.__mtRequestId is not None:
d["mtRequestId"] = (
self.__mtRequestId.as_dict()
if hasattr(self.__mtRequestId, "as_dict")
else self.__mtRequestId
)
if self.__mtTopic is not None:
d["mtTopic"] = (
self.__mtTopic.as_dict()
if hasattr(self.__mtTopic, "as_dict")
else self.__mtTopic
)
if self.__needDiv is not None:
d["needDiv"] = (
self.__needDiv.as_dict()
if hasattr(self.__needDiv, "as_dict")
else self.__needDiv
)
if self.__pg is not None:
d["pg"] = (
self.__pg.as_dict() if hasattr(self.__pg, "as_dict") else self.__pg
)
if self.__price is not None:
d["price"] = (
self.__price.as_dict()
if hasattr(self.__price, "as_dict")
else self.__price
)
if self.__pricingParameters is not None:
d["pricingParameters"] = (
self.__pricingParameters.as_dict()
if hasattr(self.__pricingParameters, "as_dict")
else self.__pricingParameters
)
if self.__productType is not None:
d["productType"] = (
self.__productType.as_dict()
if hasattr(self.__productType, "as_dict")
else self.__productType
)
if self.__salableAdamId is not None:
d["salableAdamId"] = (
self.__salableAdamId.as_dict()
if hasattr(self.__salableAdamId, "as_dict")
else self.__salableAdamId
)
if self.__hasAskedToFulfillPreorder is not None:
d["hasAskedToFulfillPreorder"] = (
self.__hasAskedToFulfillPreorder.as_dict()
if hasattr(self.__hasAskedToFulfillPreorder, "as_dict")
else self.__hasAskedToFulfillPreorder
)
if self.__buyWithoutAuthorization is not None:
d["buyWithoutAuthorization"] = (
self.__buyWithoutAuthorization.as_dict()
if hasattr(self.__buyWithoutAuthorization, "as_dict")
else self.__buyWithoutAuthorization
)
if self.__hasDoneAgeCheck is not None:
d["hasDoneAgeCheck"] = (
self.__hasDoneAgeCheck.as_dict()
if hasattr(self.__hasDoneAgeCheck, "as_dict")
else self.__hasDoneAgeCheck
)
if self.__hasConfirmedPaymentSheet is not None:
d["hasConfirmedPaymentSheet"] = (
self.__hasConfirmedPaymentSheet.as_dict()
if hasattr(self.__hasConfirmedPaymentSheet, "as_dict")
else self.__hasConfirmedPaymentSheet
)
if self.__asn is not None:
d["asn"] = (
self.__asn.as_dict()
if hasattr(self.__asn, "as_dict")
else self.__asn
)
return d
def __repr__(self):
return "<Class StoreBuyproductReq. ageCheck: {}, appExtVrsId: {}, guid: {}, hasBeenAuthedForBuy: {}, isInApp: {}, kbsync: {}, sbsync: {}, afds: {}, machineName: {}, mtApp: {}, mtClientId: {}, mtEventTime: {}, mtPageId: {}, mtPageType: {}, mtPrevPage: {}, mtRequestId: {}, mtTopic: {}, needDiv: {}, pg: {}, price: {}, pricingParameters: {}, productType: {}, salableAdamId: {}, hasAskedToFulfillPreorder: {}, buyWithoutAuthorization: {}, hasDoneAgeCheck: {}>".format(
limitedRepr(
self.__ageCheck[:20]
if isinstance(self.__ageCheck, bytes)
else self.__ageCheck
),
limitedRepr(
self.__appExtVrsId[:20]
if isinstance(self.__appExtVrsId, bytes)
else self.__appExtVrsId
),
limitedRepr(
self.__guid[:20] if isinstance(self.__guid, bytes) else self.__guid
),
limitedRepr(
self.__hasBeenAuthedForBuy[:20]
if isinstance(self.__hasBeenAuthedForBuy, bytes)
else self.__hasBeenAuthedForBuy
),
limitedRepr(
self.__isInApp[:20]
if isinstance(self.__isInApp, bytes)
else self.__isInApp
),
limitedRepr(
self.__kbsync[:20]
if isinstance(self.__kbsync, bytes)
else self.__kbsync
),
limitedRepr(
self.__sbsync[:20]
if isinstance(self.__sbsync, bytes)
else self.__sbsync
),
limitedRepr(
self.__afds[:20]
if isinstance(self.__afds, bytes)
else self.__afds
),
limitedRepr(
self.__machineName[:20]
if isinstance(self.__machineName, bytes)
else self.__machineName
),
limitedRepr(
self.__mtApp[:20] if isinstance(self.__mtApp, bytes) else self.__mtApp
),
limitedRepr(
self.__mtClientId[:20]
if isinstance(self.__mtClientId, bytes)
else self.__mtClientId
),
limitedRepr(
self.__mtEventTime[:20]
if isinstance(self.__mtEventTime, bytes)
else self.__mtEventTime
),
limitedRepr(
self.__mtPageId[:20]
if isinstance(self.__mtPageId, bytes)
else self.__mtPageId
),
limitedRepr(
self.__mtPageType[:20]
if isinstance(self.__mtPageType, bytes)
else self.__mtPageType
),
limitedRepr(
self.__mtPrevPage[:20]
if isinstance(self.__mtPrevPage, bytes)
else self.__mtPrevPage
),
limitedRepr(
self.__mtRequestId[:20]
if isinstance(self.__mtRequestId, bytes)
else self.__mtRequestId
),
limitedRepr(
self.__mtTopic[:20]
if isinstance(self.__mtTopic, bytes)
else self.__mtTopic
),
limitedRepr(
self.__needDiv[:20]
if isinstance(self.__needDiv, bytes)
else self.__needDiv
),
limitedRepr(self.__pg[:20] if isinstance(self.__pg, bytes) else self.__pg),
limitedRepr(
self.__price[:20] if isinstance(self.__price, bytes) else self.__price
),
limitedRepr(
self.__pricingParameters[:20]
if isinstance(self.__pricingParameters, bytes)
else self.__pricingParameters
),
limitedRepr(
self.__productType[:20]
if isinstance(self.__productType, bytes)
else self.__productType
),
limitedRepr(
self.__salableAdamId[:20]
if isinstance(self.__salableAdamId, bytes)
else self.__salableAdamId
),
limitedRepr(
self.__hasAskedToFulfillPreorder[:20]
if isinstance(self.__hasAskedToFulfillPreorder, bytes)
else self.__hasAskedToFulfillPreorder
),
limitedRepr(
self.__buyWithoutAuthorization[:20]
if isinstance(self.__buyWithoutAuthorization, bytes)
else self.__buyWithoutAuthorization
),
limitedRepr(
self.__hasDoneAgeCheck[:20]
if isinstance(self.__hasDoneAgeCheck, bytes)
else self.__hasDoneAgeCheck
),
limitedRepr(
self.__hasConfirmedPaymentSheet[:20]
if isinstance(self.__hasConfirmedPaymentSheet, bytes)
else self.__hasConfirmedPaymentSheet
),
limitedRepr(
self.__asn[:20]
if isinstance(self.__asn, bytes)
else self.__asn
),
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,160 @@
from reprlib import repr as limitedRepr
class StoreDownloadReq:
_types_map = {
"creditDisplay": {"type": str, "subtype": None},
"guid": {"type": str, "subtype": None},
"salableAdamId": {"type": str, "subtype": None},
"appExtVrsId": {"type": str, "subtype": None},
}
_formats_map = {}
_validations_map = {
"creditDisplay": {
"required": True,
},
"guid": {
"required": True,
},
"salableAdamId": {
"required": True,
},
"appExtVrsId": {
"required": False,
},
}
def __init__(
self,
creditDisplay: str = None,
guid: str = None,
salableAdamId: str = None,
appExtVrsId: str = None,
):
pass
self.__creditDisplay = creditDisplay
self.__guid = guid
self.__salableAdamId = salableAdamId
self.__appExtVrsId = appExtVrsId
def _get_creditDisplay(self):
return self.__creditDisplay
def _set_creditDisplay(self, value):
if not isinstance(value, str):
raise TypeError("creditDisplay must be str")
self.__creditDisplay = value
creditDisplay = property(_get_creditDisplay, _set_creditDisplay)
def _get_guid(self):
return self.__guid
def _set_guid(self, value):
if not isinstance(value, str):
raise TypeError("guid must be str")
self.__guid = value
guid = property(_get_guid, _set_guid)
def _get_salableAdamId(self):
return self.__salableAdamId
def _set_salableAdamId(self, value):
if not isinstance(value, str):
raise TypeError("salableAdamId must be str")
self.__salableAdamId = value
salableAdamId = property(_get_salableAdamId, _set_salableAdamId)
def _get_appExtVrsId(self):
return self.__appExtVrsId
def _set_appExtVrsId(self, value):
if value is not None and not isinstance(value, str):
raise TypeError("appExtVrsId must be str")
self.__appExtVrsId = value
appExtVrsId = property(_get_appExtVrsId, _set_appExtVrsId)
@staticmethod
def from_dict(d):
v = {}
if "creditDisplay" in d:
v["creditDisplay"] = (
str.from_dict(d["creditDisplay"])
if hasattr(str, "from_dict")
else d["creditDisplay"]
)
if "guid" in d:
v["guid"] = (
str.from_dict(d["guid"]) if hasattr(str, "from_dict") else d["guid"]
)
if "salableAdamId" in d:
v["salableAdamId"] = (
str.from_dict(d["salableAdamId"])
if hasattr(str, "from_dict")
else d["salableAdamId"]
)
if "appExtVrsId" in d:
v["appExtVrsId"] = (
str.from_dict(d["appExtVrsId"])
if hasattr(str, "from_dict")
else d["appExtVrsId"]
)
return StoreDownloadReq(**v)
def as_dict(self):
d = {}
if self.__creditDisplay is not None:
d["creditDisplay"] = (
self.__creditDisplay.as_dict()
if hasattr(self.__creditDisplay, "as_dict")
else self.__creditDisplay
)
if self.__guid is not None:
d["guid"] = (
self.__guid.as_dict()
if hasattr(self.__guid, "as_dict")
else self.__guid
)
if self.__salableAdamId is not None:
d["salableAdamId"] = (
self.__salableAdamId.as_dict()
if hasattr(self.__salableAdamId, "as_dict")
else self.__salableAdamId
)
if self.__appExtVrsId is not None:
d["appExtVrsId"] = (
self.__appExtVrsId.as_dict()
if hasattr(self.__appExtVrsId, "as_dict")
else self.__appExtVrsId
)
return d
def __repr__(self):
return "<Class StoreDownloadReq. creditDisplay: {}, guid: {}, salableAdamId: {}, appExtVrsId: {}>".format(
limitedRepr(
self.__creditDisplay[:20]
if isinstance(self.__creditDisplay, bytes)
else self.__creditDisplay
),
limitedRepr(
self.__guid[:20] if isinstance(self.__guid, bytes) else self.__guid
),
limitedRepr(
self.__salableAdamId[:20]
if isinstance(self.__salableAdamId, bytes)
else self.__salableAdamId
),
limitedRepr(
self.__appExtVrsId[:20]
if isinstance(self.__appExtVrsId, bytes)
else self.__appExtVrsId
),
)

File diff suppressed because it is too large Load Diff

254
src_mac/ipatool-py/reqs/store.py Executable file
View File

@@ -0,0 +1,254 @@
import hashlib
import json
import pickle
import plistlib
import requests
from reqs.schemas.store_authenticate_req import StoreAuthenticateReq
from reqs.schemas.store_authenticate_resp import StoreAuthenticateResp
from reqs.schemas.store_buyproduct_req import StoreBuyproductReq
from reqs.schemas.store_buyproduct_resp import StoreBuyproductResp
from reqs.schemas.store_download_req import StoreDownloadReq
from reqs.schemas.store_download_resp import StoreDownloadResp
class StoreException(Exception):
def __init__(self, req, resp, errMsg, errType=None):
self.req = req
self.resp = resp # type: StoreDownloadResp
self.errMsg = errMsg
self.errType = errType
super().__init__(
"Store %s error: %s" % (self.req, self.errMsg) if not self.errType else
"Store %s error: %s, errorType: %s" % (self.req, self.errMsg, self.errType)
)
#CONFIGURATOR_UA = "Configurator/2.0 (Macintosh; OS X 10.12.6; 16G29) AppleWebKit/2603.3.8"
CONFIGURATOR_UA = 'Configurator/2.0 (Macintosh; OS X 10.12.6; 16G29) AppleWebKit/2603.3.8 iOS/14.2 hwp/t8020'
class StoreClientAuth(object):
def __init__(self, appleId=None, password=None):
self.appleId = appleId
self.password = password
self.guid = None # the guid will not be used in itunes server mode
self.accountName = None
self.authHeaders = None
self.authCookies = None
def __str__(self):
return f"<{self.accountName} [{self.guid}]>"
def _generateGuid(self, appleId):
'''
Derive a GUID for an appleId. For each appleId, the GUID will always remain the same
:param appleId:
:return:
'''
DEFAULT_GUID = '000C2941396B' # this GUID is blocked
# number of chars to use from DEFAULT_GUID as prefix (0..12)
GUID_DEFAULT_PREFIX = 2
# something unique
GUID_SEED = 'CAFEBABE'
# something between 0 and 30
GUID_POS = 10
# generate a unique guid out of the appleId
h = hashlib.sha1((GUID_SEED + appleId + GUID_SEED).encode("utf-8")).hexdigest()
defaultPart = DEFAULT_GUID[:GUID_DEFAULT_PREFIX]
hashPart = h[GUID_POS: GUID_POS + (len(DEFAULT_GUID) - GUID_DEFAULT_PREFIX)]
guid = (defaultPart + hashPart).upper()
return guid
def login(self, sess):
if not self.guid:
self.guid = self._generateGuid(self.appleId)
req = StoreAuthenticateReq(appleId=self.appleId, password=self.password, attempt='4', createSession="true",
guid=self.guid, rmp='0', why='signIn')
url = "https://p46-buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/authenticate?guid=%s" % self.guid
while True:
r = sess.post(url,
headers={
"Accept": "*/*",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": CONFIGURATOR_UA,
}, data=plistlib.dumps(req.as_dict()), allow_redirects=False)
if r.status_code == 302:
url = r.headers['Location']
continue
break
d = plistlib.loads(r.content)
resp = StoreAuthenticateResp.from_dict(d)
if not resp.m_allowed:
raise StoreException("authenticate", d, resp.customerMessage, resp.failureType)
self.authHeaders = {}
self.authHeaders['X-Dsid'] = self.authHeaders['iCloud-Dsid'] = str(resp.download_queue_info.dsid)
self.authHeaders['X-Apple-Store-Front'] = r.headers.get('x-set-apple-store-front')
self.authHeaders['X-Token'] = resp.passwordToken
self.authCookies = pickle.dumps(sess.cookies).hex()
self.accountName = resp.accountInfo.address.firstName + " " + resp.accountInfo.address.lastName
def save(self):
return json.dumps(self.__dict__)
@classmethod
def load(cls, j):
obj = json.loads(j)
ret = cls()
ret.__dict__.update(obj)
return ret
class StoreClient(object):
def __init__(self, sess: requests.Session):
self.sess = sess
self.iTunes_provider = None
self.authInfo = None
def authenticate_load_session(self, sessionContent):
self.authInfo = StoreClientAuth.load(sessionContent)
if self.authInfo.authHeaders is None or self.authInfo.authCookies is None:
raise Exception("invalid auth session")
self.sess.headers = dict(self.authInfo.authHeaders)
self.sess.cookies = pickle.loads(bytes.fromhex(self.authInfo.authCookies))
def authenticate_save_session(self):
return self.authInfo.save()
def authenticate(self, appleId, password):
if not self.authInfo:
self.authInfo = StoreClientAuth(appleId, password)
self.authInfo.login(self.sess)
self.sess.headers = dict(self.authInfo.authHeaders)
self.sess.cookies = pickle.loads(bytes.fromhex(self.authInfo.authCookies))
# ==> 🛠 [Verbose] Performing request: curl -k -X POST \
# -H "iCloud-DSID: 12263680861" \
# -H "Content-Type: application/x-www-form-urlencoded" \
# -H "User-Agent: Configurator/2.0 (Macintosh; OS X 10.12.6; 16G29) AppleWebKit/2603.3.8" \
# -H "X-Dsid: 12263680861" \
# -d '<?xml version="1.0" encoding="UTF-8"?>
# <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
# <plist version="1.0">
# <dict>
# <key>creditDisplay</key>
# <string></string>
# <key>guid</key>
# <string>000C2941396B</string>
# <key>salableAdamId</key>
# <string>1239860606</string>
# </dict>
# </plist>
# ' \
# https://p25-buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/volumeStoreDownloadProduct?guid=000C2941396Bk
def volumeStoreDownloadProduct(self, appId, appVerId=""):
req = StoreDownloadReq(creditDisplay="", guid=self.authInfo.guid, salableAdamId=appId, appExtVrsId=appVerId)
hdrs = {
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": CONFIGURATOR_UA,
}
url = "https://p25-buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/volumeStoreDownloadProduct?guid=%s" % self.authInfo.guid
payload = req.as_dict()
r = self.sess.post(url,
headers=hdrs,
data=plistlib.dumps(payload))
d = plistlib.loads(r.content)
resp = StoreDownloadResp.from_dict(d)
if resp.cancel_purchase_batch:
raise StoreException("volumeStoreDownloadProduct", d, resp.customerMessage, '%s-%s' % (resp.failureType, resp.metrics))
return resp
def buyProduct(self, appId, appVer='', productType='C', pricingParameters='STDQ'):
# STDQ - buy, STDRDL - redownload, SWUPD - update
url = "https://p25-buy.itunes.apple.com/WebObjects/MZBuy.woa/wa/buyProduct"
itunes_internal = self.iTunes_provider(url)
hdrs = itunes_internal.pop('headers')
guid = itunes_internal.pop('guid')
kbsync = itunes_internal.pop('kbsync')
if not appVer:
from reqs.itunes import iTunesClient
iTunes = iTunesClient(self.sess)
appVer = iTunes.getAppVerId(appId, hdrs['X-Apple-Store-Front'])
req = StoreBuyproductReq(
guid=guid,
salableAdamId=str(appId),
appExtVrsId=str(appVer) if appVer else None,
price='0',
productType=productType,
pricingParameters=pricingParameters,
ageCheck='true',
hasBeenAuthedForBuy='true',
isInApp='false',
hasConfirmedPaymentSheet='true',
asn='1',
)
payload = req.as_dict()
payload['kbsync'] = kbsync # kbsync is bytes, but json schema does not support it, so we have to assign it
if 'sbsync' in itunes_internal:
payload['sbsync'] = itunes_internal.pop('sbsync') # sbsync is the same as kbsync
if 'afds' in itunes_internal:
payload['afds'] = itunes_internal.pop('afds')
hdrs = dict(hdrs)
hdrs["Content-Type"] = "application/x-apple-plist"
r = self.sess.post(url,
headers=hdrs,
data=plistlib.dumps(payload)
)
d = plistlib.loads(r.content)
resp = StoreBuyproductResp.from_dict(d)
if resp.cancel_purchase_batch:
raise StoreException("buyProduct", d, resp.customerMessage, '%s-%s' % (resp.failureType, resp.metrics))
return resp
def buyProduct_purchase(self, appId, productType='C'):
url = "https://buy.itunes.apple.com/WebObjects/MZBuy.woa/wa/buyProduct"
req = StoreBuyproductReq(
guid=self.authInfo.guid,
salableAdamId=str(appId),
appExtVrsId='0',
price='0',
productType=productType,
pricingParameters='STDQ',
hasAskedToFulfillPreorder='true',
buyWithoutAuthorization='true',
hasDoneAgeCheck='true',
hasConfirmedPaymentSheet='true',
)
payload = req.as_dict()
r = self.sess.post(url,
headers={
"Content-Type": "application/x-apple-plist",
"User-Agent": "Configurator/2.15 (Macintosh; OS X 11.0.0; 16G29) AppleWebKit/2603.3.8",
},
data=plistlib.dumps(payload))
if r.status_code == 500:
raise StoreException("buyProduct_purchase", None, 'purchased_before')
d = plistlib.loads(r.content)
resp = StoreBuyproductResp.from_dict(d)
if resp.status != 0 or resp.jingleDocType != 'purchaseSuccess':
raise StoreException("buyProduct_purchase", d, resp.customerMessage,
'%s-%s' % (resp.status, resp.jingleDocType))
return resp
def purchase(self, appId):
if self.iTunes_provider:
return None # iTunes mode will automatically purchase the app if not purchased
else:
return self.buyProduct_purchase(appId)
def download(self, appId, appVer='', isRedownload=True):
if self.iTunes_provider:
return self.buyProduct(appId, appVer, pricingParameters='STDRDL' if isRedownload else 'STDQ')
else:
return self.volumeStoreDownloadProduct(appId, appVer)