Skip to content

Latest commit

 

History

History
2322 lines (2079 loc) · 68.8 KB

README.md

File metadata and controls

2322 lines (2079 loc) · 68.8 KB

说明

目标一共有两个,一个是Intel官方地图,另一个是游戏使用的API

本文只做相关API赏析,请不要做违反TOS的事情

已经打包成库

pip3 install ingressAPI

from ingressAPI import IntelMap

Intel Map

获取API

  1. 登录Google账户后,打开intel界面,Chrome打开Network选项卡
  2. 刷新页面来获取一下所有xhr请求 chrome
  3. 这些get*的请求就是ingress的API了,不着急,一个一个看

注意事项

  1. HTTP Request Headers里有一个x-csrftoken,具体释义请翻各类白帽子教程。这个参数的值和Cookie的csrftoken相同csrftoken-same-cookie
  2. HTTP Request Headers里面有一堆以:开头的参数,将之忽略也不要紧
  3. ingress所有API都是POST JSON数据交互,所以HTTP Method和Conten-Type确定,下面不再重复了
  4. 贯穿Intel Map API的参数v相当于Session,至于如何获取,请在登录状态下看Intel主页源码最后,js的名字就包含了v值,即下图打码的部分v

getGameScore

显而易见,这个API用来得到整个游戏的比分

API URL: https://www.ingress.com/r/getGameScore
API Request: v,
API Response: result: [Enl, Res],

example:

getGameScore getGameScore

getRegionScoreDetails

这个API用来得到当前那区域的比分

API URL: https://www.ingress.com/r/getRegionScoreDetails
API Request: latE6, lngE6, v,
API Response: result: {gameScore: [Res, Enl], regionName, regionVertices: [[Res, Enl], ...], scoreHistory: [[id, Enl, Res], ...], timeToEndOfBaseCycleMs, topAgents:[{nick, team}]}

具体latE6,lngE6看下面getEntities API

example: code getRegionScoreDetails getRegionScoreDetails

getEntities

这个是用来获取Entity,也就是link, field, portal的

API URL: https://www.ingress.com/r/getEntities
API Request: tileKeys: [tilename1, tilename2, ...], v,
API Response: result: {map: {tilename1: {gameEntities: [[guid, time, [type, faction, guid1, Lng1, Lat1, ...]], ...]}, ...}}

来解释一下各个变量都是什么意思

tileKeys是一个字符串,表示一个矩形,是一个可控参数的高级MBR(最小单元矩阵),这是典型二维地图的查询参数,具体格式为zoom_x_y_minlevel_maxlevel_health,其中zoom表示区域放大的级别(恰好是Cookie中ingress.intelmap.zoom的值,点一次+或-按钮,地图缩放,值±1,在intel上,这个值得范围是3-21,最大时,显示的portal越少,范围越小);x,y表示当前zoom的区域编号,可以参考tilenames

后面三个就简单了,最小,对应Intel上选择Level和Health的三个值,即最小po等级,最大po等级,最大健康百分比

这是涉及到tilename中的经纬度和实际经纬度的转换,参考github-iitc

下面的代码是进行经纬tile互转的 lat-lng

另外,返回值的Lng_x_, Lat_x_,是6位小数,time是确定到毫秒的Unix时间戳

guid是每一个entity的标识,所有用户,物品,link,portal,...都具有唯一标识guid

type是指这个entity的类型,e: lin(后面直接跟6个元素,两组guid经纬度), r: field(后面是一个list,三组guid经纬度), p: portal(一组guid经纬度,之后是等级,能量(0.0-100.0),脚数,po图,po名,[], false, false, null(这4个不太懂是啥), 更新时间戳)

faction代表阵营,E: Enl, R: Res

example

code 太长了,贴个部分 example

getPortalDetails

用来获取portal的详细信息

API URL: https://www.ingress.com/r/getPortalDetail
API Request: guid, v
API Response: result: [type, faction, lng, lat, level, energy, resonator_nums, picurl, name, [], false, false, null, updatetime, [[agentname, modtype, modlevel, {a: value, b: value}],...], [['agentname', resonator_level, energy],...], belongs, ["", "", []]]

意义很明确了,就是portal的详细信息

{a: value, b: value}表示的是mod的效果,看下面的图很容易理解

example

code example1 example2 example3

getArtifactPortals

猜测是查看是否生成新的portal

API URL: https://www.ingress.com/r/getArtifactPortals
API Request: v
APi Resonse: 同上

getPlexts

用来获得comm信息

API URL: https://www.ingress.com/r/getPlexts
API Request: ascendingTimestampOrder, maxLatE6, maxLngE6, minLatE6 , minLngE6, maxTimestampMs, minTimestampMs, tab, v
API Response: result: [[guid, updatetime, {plext: {categories, plextType, team, text, markup: [#]}}],...]
根据不同的categories(1=all, 2=faction),不同plextType,markup的list不同,说明一下#的内容
SYSTEM_BROADCAST:
	[PLATER: {plain, team}], [TEXT: {plain}], [PORTAL: {name, address, latE6, lngE6, name, plain, team}], [TEXT: {plain}], [TEXT: {plain}], [TEXT: {plain}]
	后面三个是消息尾部,比如 '-' '28' 'Mus'
	也有可能是2个尾部,比如[TEXT] [PORTAL]
	也有可能没有消息尾部,比如destroyed行为
PLAYER_GENERATED:
	[SECURE: {plain}]
	[SENDER: {plain, team}], [TEXT: {plain}] [AT_PLAYER: {plain, team}]

显然[SECURE]是可选的
每出现一个@,就会导致[AT_PLAYER]出现并把文字用[TEXT]填上,因此这个list不定长(我猜的,2333)

解释一下E6,明显这是4个点,确定了一个矩形区域,那么捕获的消息就来自这个区域

ascendingTimestampOrder(Bool)表示是否按照时间asc输出

code example

发出消息

API URL:
API Request: latE6, lngE6, message, tab, v,
API Response: result

这个API,看上边接收消息的就可以了,注意tab的值是all或faction

redeemReward

使用passcode

API URL: https://www.ingress.com/r/redeemReward
API Request: passcode, v,
API Response:
	1. error

sendInviteEmail

邀请

API URL: https://www.ingress.com/r/sendInviteEmail
API Request: inviteeEmailAddress, v
API Response: result

第一部分结束

代码

Game API(iOS)

获取API

  1. 使用Charles作为中转,iPhone转发到Charles,之后转到ss
  2. 安装HTTPS证书

注意事项

  1. 在HTTP Request Headers中,同样有X-XsrfToken
  2. 还有固定值User-Agent: Nemesis (gzip), Accept-Encoding: gzip, Accept-Language: 你自己设置的语言
  3. 还需要Authorization在HTTP Request Headers中
  4. 身份认证:
  5. 没特殊说明的,都是POST请求
  6. API用到的域名:(gstatic)|(upsight-api)|(appspot.com)|(google-analytics.com)
  7. google-analytics一会就一个,都是GET请求,在游戏过程中的这种包懒得写了

Google数据统计

在此期间 User-Agent是Ingress/1.110.0 CFNetwork/808.2.16 Darwin/16.3.0

Start

在打开游戏时,第一个请求是发向https://www.googleadservices.com/pagead/conversion/999636601/的

说下参数

appversion: 1.110.0
auto: 1
bundleid: com.google.ingress
lat: 1
muid: n4nISlWfVzY2pH_42u0NMw
osversion: 10.2
sdkversion: ct-sdk-i-v3.1.1
timestamp: 1457613595.596337
usage_tracking_enabled: 1

只有timestamp是变化的

Config

之后是POST请求配置文件,https://bootstrap.upsight-api.com/config/v1/f1f4c1b2962446b38f72d5a456aac73c/

注意这里开始,Headers里带了一个X-US-Ref-Id(当向upsight-api.com请求的时候都要有,其他几个API站用X-XsrfToken), 每次启动APP值不容

这个请求的内容很多,

{
	"sdk.version": "4.0.2",
	"device.manufacturer": "Apple",
	"screen.width": 375,
	"app.token": "f1f4c1b2962446b38f72d5a456aac73c",
	"app.version": "1.110.0",
	"device.limit_ad_tracking": true,
	"screen.height": 667,
	"bundle.hash": *,
	"ids.idfv": *,
	"sdk.build": "+release.91a51d8",
	"request_ts": 1481902230,
	"device.carrier": "中国联通",
	"device.hardware": "iPhone8,1",
	"locale": "zh_CN",
	"app.bundleid": "com.google.ingress",
	"sid": "622357641234265637",
	"location.tz": "+0800",
	"device.connection": "Wifi",
	"device.os_version": "10.2",
	"device.type": "phone",
	"identifiers": "pub",
	"opt_out": false,
	"device.jailbroken": false,
	"screen.scale": 2,
	"device.os": "ios",
	"sessions": [{
		"session_num": 5558,
		"install_ts": 1457609995,
		"session_start": 1481901886,
		"events": [{
			"ts": 1481902230,
			"seq_id": 252628,
			"type": "upsight.config.expired",
			"user_attributes": {
				"days_inactive": -1,
				"hashed_user_id": *,
				"player_approx_lat": 30.76,
				"player_approx_lng": 103.93,
				"language": "zh_CN",
				"faction": "ALIENS",
				"distance_to_portal": -1,
				"agent_level": 13
			}
		}],
		"past_session_time": 2873649
	}]
}```

可以看到这里实际上是上传了session的备份,设备信息,APP信息

会返回一个配置

```json
{
	"errobj": null,
	"response": [{
		"content": {
			"configurationList": [{
				"configuration": {
					"queues": [{
						"max_age": 120,
						"count_network_fail_retries": false,
						"name": "batch",
						"retry_interval": 60,
						"host": "batch.upsight-api.com",
						"max_retry_count": 3,
						"url_fmt": "{protocol}://{host}/batch/{version}/{app_token}/",
						"protocol": "https",
						"max_size": 50
					}, {
						"max_age": 0,
						"count_network_fail_retries": true,
						"name": "immediate",
						"retry_interval": 5,
						"host": "single.upsight-api.com",
						"max_retry_count": 1,
						"url_fmt": "{protocol}://{host}/sdk/{version}/events/{app_token}/",
						"protocol": "https",
						"max_size": 1
					}, {
						"max_age": 0,
						"count_network_fail_retries": true,
						"name": "config",
						"retry_interval": 15,
						"host": "bootstrap.upsight-api.com",
						"max_retry_count": 2,
						"url_fmt": "{protocol}://{host}/config/{version}/{app_token}/",
						"protocol": "https",
						"max_size": 1
					}],
					"identifiers": [{
						"ids": ["ids.idfv", "ids.android_id"],
						"name": "pub"
					}, {
						"ids": ["ids.idfa", "ids.aid"],
						"name": "ad"
					}],
					"route_filters": [{
						"filter": "*",
						"queues": ["batch", "trash"]
					}, {
						"filter": "upsight.*",
						"queues": ["batch", "trash"]
					}, {
						"filter": "upsight.milestone",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.uxm.enumerate",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.content.unrendered",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.campaign.*",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.content.*",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.comm.register",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.comm.unregister",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.session.start",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "pub.RequestContentSize.*",
						"queues": ["trash"]
					}, {
						"filter": "pub.RequestDuration.*",
						"queues": ["trash"]
					}, {
						"filter": "pub.RequestPayloadSize.*",
						"queues": ["trash"]
					}, {
						"filter": "upsight.config.expired",
						"queues": ["config", "trash"]
					}, {
						"filter": "upsight.monetization.iap",
						"queues": ["immediate", "batch", "trash"]
					}, {
						"filter": "upsight.data_collection",
						"queues": ["immediate", "batch", "trash"]
					}],
					"identifier_filters": [{
						"filter": "*",
						"identifiers": "pub"
					}]
				},
				"type": "upsight.configuration.dispatcher"
			}, {
				"configuration": {
					"retryMultiplier": 120,
					"requestInterval": 3600,
					"retryPowerBase": 1.61,
					"retryPowerExponentMax": 10
				},
				"type": "upsight.configuration.configurationManager"
			}, {
				"configuration": {
					"push_token_ttl": 604800,
					"auto_register": true
				},
				"type": "upsight.configuration.push"
			}]
		},
		"type": "upsight.configuration"
	}],
	"error": null
}

这里就不细说了

batch

这个是POST给https://batch.upsight-api.com/batch/v1/f1f4c1b2962446b38f72d5a456aac73c/

{
	"sdk.version": "4.0.2",
	"device.manufacturer": "Apple",
	"screen.width": 375,
	"app.token": "*",
	"app.version": "1.110.0",
	"device.limit_ad_tracking": true,
	"screen.height": 667,
	"bundle.hash": "*",
	"ids.idfv": "*",
	"sdk.build": "+release.91a51d8",
	"request_ts": 1481902232,
	"device.carrier": "中国联通",
	"device.hardware": "iPhone8,1",
	"locale": "zh_CN",
	"app.bundleid": "com.google.ingress",
	"sid": *,
	"location.tz": "+0800",
	"device.connection": "Wifi",
	"device.os_version": "10.2",
	"device.type": "phone",
	"identifiers": "pub",
	"opt_out": false,
	"device.jailbroken": false,
	"screen.scale": 2,
	"device.os": "ios",
	"sessions": [{
		"session_num": 5558,
		"install_ts": 1457609995,
		"session_start": 1481901886,
		"events": [{
			"ts": 1481902146,
			"seq_id": 252627,
			"type": "upsight.session.pause",
			"user_attributes": {
				"days_inactive": -1,
				"hashed_user_id": "*",
				"player_approx_lat": *,
				"player_approx_lng": *,
				"language": "zh_CN",
				"faction": "ALIENS",
				"distance_to_portal": -1,
				"agent_level": 13
			}
		}, {
			"ts": 1481902230,
			"seq_id": 252629,
			"type": "upsight.session.resume",
			"user_attributes": {
				"days_inactive": -1,
				"hashed_user_id": "*",
				"player_approx_lat": *,
				"player_approx_lng": *,
				"language": "zh_CN",
				"faction": "ALIENS",
				"distance_to_portal": -1,
				"agent_level": 13
			}
		}, {
			"ts": 1481902230,
			"pub_data": {
				"ui_type": "FOREGROUND",
				"GL_MAX_TEXTURE_SIZE": 4096
			},
			"seq_id": 252630,
			"type": "pub.Stats.GL_MAX_TEXTURE_SIZE",
			"user_attributes": {
				"days_inactive": -1,
				"hashed_user_id": "*",
				"player_approx_lat": *,
				"player_approx_lng": *,
				"language": "zh_CN",
				"faction": "ALIENS",
				"distance_to_portal": -1,
				"agent_level": 13
			}
		}],
		"past_session_time": 2873649
	}]
}

和上面的差别在于event, 有兴趣的diff一下

返回什么呢:

{
	"errobj": null,
	"error": null,
	"response": []
}

OAuth2登录

这里是OAuth2的认证,不是重点,都略去

最后一个API是POST到https://www.googleapis.com/oauth2/v4/token,**form**包含了

client_id
code
grant_type
redirect_uri
verifier

然后仍然是返回一个JSON,

{
	"access_token": *,
	"token_type": "Bearer",
	"expires_in": 3600,
	"refresh_token": *,
	"id_token": *
}

从这里之后就要带上Authorizatoin了 (向appspot请求时)

其格式就是 Bearer access_token

collect

之后,ingress会发送一个统计信息,GET传参到https://ssl.google-analytics.com/collect

这里的User-Agent被设置为GoogleAnalytics/3.10 (iPhone; U; CPU iPhone OS 10.2 like Mac OS X; zh-hans-cn-cn)

下面说一下参数

an: niantic-ingress
av: 1.110.0
a: 1360117771
tid: UA-30116200-4
cd: NiOSAuthenticationInfoViewController
t: screenview
cid: *
ul: zh-hans-cn
aid: com.google.ingress
ds: app
_u: *
sr: 375x667
v: 1
_crc: 0
_v: mi3.1.0
sf: 100
ht: 1481901425098
qt: 155026
z: *

hanshake

URL: https://m-dot-betaspike.appspot.com/handshake

这里仍然是POST form提交,但是内容是JSON的,怀疑是设置错了

{
"nemesisSoftwareVersion": "2016-11-18T13:44:21Z+c90631584ea7-i+opt",
"deviceSoftwareVersion": "10.2",
"a": *,
"reason": "SUP"
}

返回的东西很重要 首先是一个crack串)]}' 然后是一个巨大的JSON,返回了:

{
    "result": {
        "playerEntity": [user_guid, 1481899737145, {
            "playerPersonal": {
                "ap": "14031060",
                "energy": 10255,
                "allowNicknameEdit": false,
                "allowFactionChoice": false,
                "verifiedLevel": 13,
                "mediaHighWaterMarks": {
                    "General": 1809,
                    "RESISTANCE": 1328,
                    "ALIENS": 1327
                },
                "energyState": "XM_OK",
                "notificationSettings": {
                    "shouldSendEmail": false,
                    "maySendPromoEmail": false,
                    "shouldPushNotifyForAtPlayer": true,
                    "shouldPushNotifyForPortalAttacks": true,
                    "shouldPushNotifyForInvitesAndFactionInfo": true,
                    "shouldPushNotifyForNewsOfTheDay": true,
                    "shouldPushNotifyForEventsAndOpportunities": true,
                    "locale": "zh-Hans-CN"
                },
                "profileSettings": {
                    "areMetricsPublic": false
                },
                "verificationState": "UNVERIFIED",
                "extraXmTankEnergy": 0
            },
            "controllingTeam": {
                "team": "RESISTANCE"
            },
            "avatar": {
                "foreground": {
                    "layerId": "foreground4",
                    "tintColor": 16249235,
                    "imageUrl": "http://lh3.googleusercontent.com/COPtJLf8PEP0dgeehOg425-ASLkkQtrphoViG6Hy19mbHtyBDvanqWB4a6jPCaHhYpLYNaw9Ot9-0cfYm0Qc"
                },
                "background": {
                    "layerId": "background3",
                    "tintColor": 481625,
                    "imageUrl": "http://lh3.googleusercontent.com/WorWGSonh3XJrC7RWpVuBkTKcHoF2QtsolzqhmNUrZcaHKmfRgpTO_5QmpYTbBvkLkbTlF5LRW9gS_xDmTdY"
                }
            }
        }],
        "nickname": *,
        "xsrfToken": *,
        "storage": {
            "tutorial_complete_scanner_intro": "true:delim:1481895477261:delim:true",
            "game_intro_has_played": "true:delim:1457410095779:delim:true",
            "mission_complete_7": "ENDED_BY_NAGGING:delim:1457876587760:delim:true",
            "mission_complete_6": "ENDED_BY_NAGGING:delim:1457876587759:delim:true",
            "mission_complete_5": "ENDED_BY_NAGGING:delim:1457876587758:delim:true",
            "mission_complete_4": "SUCCESS:delim:1457876587753:delim:true",
            "mission_complete_3": "ENDED_BY_NAGGING:delim:1457876587757:delim:true",
            "mission_complete_0": "ENDED_BY_NAGGING:delim:1457876587754:delim:true",
            "mission_complete_1": "ENDED_BY_NAGGING:delim:1457876587755:delim:true",
            "mission_complete_2": "ENDED_BY_NAGGING:delim:1457876587756:delim:true",
            "all_missions_complete_announcement_made": "true:delim:1457410237730:delim:true",
            "tutorial_complete_hack": "true:delim:1457410237722:delim:true",
            "training_portal_photo_url": "http://lh6.ggpht.com/xZU07oPfUpRDnz_2og2L1E3O4T74iMUyCVtB5lL6m16lh0PnZPtBMf8XjkpYbq8Veby0eHNhCGNRwQrYNg:delim:1457439507178:delim:true",
            "training_portal_lng_degrees": *,
            "training_portal_lat_degrees": *,
            "training_portal_title": "本科9栋:delim:1457439507178:delim:true",
            "tutorial_complete_xm": "true:delim:1457412143790:delim:true",
            "tutorial_complete_xmp": "true:delim:1457412131239:delim:true",
            "tutorial_complete_profile_link": "true:delim:1457422332944:delim:true",
            "tutorial_complete_deploy": "true:delim:1457488741871:delim:true"
        },
        "pregameStatus": {
            "action": "NO_ACTIONS_REQUIRED",
            "dialogText": ""
        },
        "initialKnobs": {
            "bundleMap": {
                "ClientFeatureKnobs": {
                    "enableEmbeddedYouTubePlayback": true,
                    "showGlobalMap": true,
                    "logSkipRegex": "\\b\\B",
                    "enableParticleFilter": true,
                    "enableGAViolationReporting": false,
                    "portalKeyCardRefreshIntervalSecs": 5,
                    "portalInfoRefreshIntervalSecs": 2,
                    "enableInviteNag": true,
                    "inviteNagDelayDays": 14,
                    "enableVerificationNag": false,
                    "verificationNagDelayDays": 3,
                    "refreshTimeMs": "-1",
                    "playerProfileCacheExpirationSecs": "60",
                    "enableDelayGpsPause": true,
                    "enableAdvancedAnalytics": true,
                    "playerVerificationEnabled": 0,
                    "enableExtraNativeRenderedText": -1,
                    "enableShareMission": 10740,
                    "profileUrlFormat": "http://plus.google.com/%s",
                    "profileUrlFormatApp": "gplus://plus.google.com/%s",
                    "factionChoiceBeforeSpaceToFace": true,
                    "minGlobBundleSizeXm": 1500,
                    "enableMissions": 10610,
                    "enableBadAnalyticsTrackingEventLogging": 10570,
                    "enableIOSPushNotifications": 10640,
                    "iOSPortalDiscoveryProcessIntervalMS": "200000",
                    "enableMissionsConnectivityRecovery": 10610,
                    "enableMissionsStatePolling": 10610,
                    "enableHackLongPressIndicator": 10612,
                    "enableIOSNativeYoutubePlayer": 10620,
                    "enableIOSPortalDetailPanel": 10630,
                    "enableIOSMultiPhotoViewer": 10640,
                    "enableIOSPhotoSubmission": 10640,
                    "enableIOSGridPhotoViewer": 10650,
                    "enableCommunityTab": 10740,
                    "enableBoostRechargeV2": 10760,
                    "enableSetLocale": 10771,
                    "disableNewPortalSubmissions": -1,
                    "enableLocalLinkChecks": 10790,
                    "enableStore": 10851,
                    "enableRecycleConfirmationDialog": 0,
                    "enableGlyphCommandChannel": 10900,
                    "enableGlyphRedoButton": 10910,
                    "upsightLocationDecimalPlacesToRound": 2,
                    "enableExtendedFireMenu": 11010
                },
                "SmartNotificationsClientKnobs": {
                    "enableSmartNotifications": 10670,
                    "maximumCachedHandshakeResultAgeMs": "43200000",
                    "enableR": 10691,
                    "enableRIOS": 10700,
                    "playerRProbabilityE6": 1000000,
                    "rLPlayerMs": "864000000",
                    "rMinPollingDelayMs": "900000",
                    "maximumPortalCacheSize": 5000,
                    "portalCacheEntryExpirationTimeMs": "1209600000",
                    "nearbyPortalDistanceM": 200,
                    "loiteringMs": "300000",
                    "noLongerNearbyDistanceM": 100,
                    "rNearbyPortalDistanceGrowthRate": 50,
                    "rMaxGrownNearbyPortalDistanceM": 1000,
                    "rWaitPeriodsMs": ["86400000", "172800000", "259200000", "432000000"],
                    "rIOSAlwaysLocationAccessMinIntervalMs": "5256000000",
                    "amSessionLengthMs": "1800000",
                    "enableAm": 10700,
                    "playerAmProbabilityE6": 1000000,
                    "amNearbyPortalDistanceM": 37,
                    "amNoLongerNearbyDistanceM": 40,
                    "amAndroidLocationRequestPriority": 102,
                    "amAndroidLocationRequestIntervalMs": "30000",
                    "amAndroidLocationRequestFastestIntervalMs": "5000",
                    "amAndroidLocationRequestSmallestDisplacementM": 0
                },
                "TranslationClientKnobs": {
                    "enableCloudTranslations": 10860,
                    "translationUrls": {
                        "zh_TW.json": "http://storage.googleapis.com/ingress-translations/2016.11.04/zh_TW.json",
                        "ru": "http://storage.googleapis.com/ingress-translations/2016.11.04/ru.json",
                        "fr": "http://storage.googleapis.com/ingress-translations/2016.11.04/fr.json",
                        "en": "http://storage.googleapis.com/ingress-translations/2016.11.04/en.json",
                        "nl": "http://storage.googleapis.com/ingress-translations/2016.11.04/nl.json",
                        "pt": "http://storage.googleapis.com/ingress-translations/2016.11.04/pt.json",
                        "no": "http://storage.googleapis.com/ingress-translations/2016.11.04/no.json",
                        "de": "http://storage.googleapis.com/ingress-translations/2016.11.04/de.json",
                        "ko": "http://storage.googleapis.com/ingress-translations/2016.11.04/ko.json",
                        "it": "http://storage.googleapis.com/ingress-translations/2016.11.04/it.json",
                        "sv": "http://storage.googleapis.com/ingress-translations/2016.11.04/sv.json",
                        "pl": "http://storage.googleapis.com/ingress-translations/2016.11.04/pl.json",
                        "cs": "http://storage.googleapis.com/ingress-translations/2016.11.04/cs.json",
                        "zh_CN.json": "http://storage.googleapis.com/ingress-translations/2016.11.04/zh_CN.json",
                        "ja": "http://storage.googleapis.com/ingress-translations/2016.11.04/ja.json",
                        "es": "http://storage.googleapis.com/ingress-translations/2016.11.04/es.json"
                    }
                },
                "GlyphCommandClientKnobs": {
                    "commands": {
                        "ikj": "GLYPH_ACCEPT_MORE_KEYS",
                        "jkgh": "GLYPH_ACCEPT_COMPLEX_HACK",
                        "hkg": "GLYPH_ACCEPT_LESS_KEYS",
                        "ji": "GLYPH_ACCEPT_SIMPLE_HACK"
                    },
                    "hints": ["GLYPH_HINT_LESS_KEYS", "GLYPH_HINT_MORE_KEYS", "GLYPH_HINT_SIMPLE_HACK"]
                },
                "StagingKnobs": {
                    "playerStoreProbabilityE6": 1000000,
                    "oldAnalyticsProbabilityE6": 1000000,
                    "newAnalyticsProbabilityE6": 1000000
                },
                "InventoryKnobs": {
                    "maxInventoryItems": 2000,
                    "resourceLimits": {
                        "KEY_CAPSULE": 5
                    },
                    "cmuRestockItemId": "ingress.cmu.large",
                    "itemRestockResourceToId": {},
                    "powerupRestockToId": {
                        "LOOK": "ingress.beacon.look",
                        "RES": "ingress.beacon.res",
                        "NIA": "ingress.beacon.nia",
                        "ENL": "ingress.beacon.enl",
                        "FRACK": "ingress.fracker",
                        "MEET": "ingress.beacon.meet"
                    }
                },
                "PortalKnobs": {
                    "resonatorLimits": {
                        "bands": [{
                            "remaining": 1,
                            "applicableLevels": [8]
                        }, {
                            "remaining": 4,
                            "applicableLevels": [2]
                        }, {
                            "remaining": 8,
                            "applicableLevels": [1]
                        }, {
                            "remaining": 2,
                            "applicableLevels": [5]
                        }, {
                            "remaining": 4,
                            "applicableLevels": [3]
                        }, {
                            "remaining": 2,
                            "applicableLevels": [6]
                        }, {
                            "remaining": 4,
                            "applicableLevels": [4]
                        }, {
                            "remaining": 1,
                            "applicableLevels": [7]
                        }]
                    },
                    "maxModsPerPlayer": 2,
                    "radiusParamsSet": [],
                    "allowRegionSpecificSubmissions": false,
                    "minLevelForSubmission": 2
                },
                "recycleKnobs": {
                    "recycleValuesMap": {
                        "BOOSTED_POWER_CUBE": [160, 160, 160, 160, 160, 160, 160, 160],
                        "MULTIHACK": [20, 40, 60, 80, 100, 120, 140, 160],
                        "EMP_BURSTER": [20, 40, 60, 80, 100, 120, 140, 160],
                        "INTEREST_CAPSULE": [20, 40, 60, 80, 100, 120, 140, 160],
                        "TURRET": [20, 40, 60, 80, 100, 120, 140, 160],
                        "MEDIA": [20, 40, 60, 80, 100, 120, 140, 160],
                        "EXTRA_SHIELD": [20, 40, 60, 80, 100, 120, 140, 160],
                        "ULTRA_STRIKE": [20, 40, 60, 80, 100, 120, 140, 160],
                        "POWER_CUBE": [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000],
                        "FLIP_CARD": [20, 40, 60, 80, 100, 120, 140, 160],
                        "ULTRA_LINK_AMP": [20, 40, 60, 80, 100, 120, 140, 160],
                        "CAPSULE": [20, 40, 60, 80, 100, 120, 140, 160],
                        "HEATSINK": [20, 40, 60, 80, 100, 120, 140, 160],
                        "RES_SHIELD": [20, 40, 60, 80, 100, 120, 140, 160],
                        "PORTAL_POWERUP": [20, 40, 60, 80, 100, 120, 140, 160],
                        "LINK_AMPLIFIER": [20, 40, 60, 80, 100, 120, 140, 160],
                        "EMITTER_A": [20, 40, 60, 80, 100, 120, 140, 160],
                        "PORTAL_LINK_KEY": [500, 500, 500, 500, 500, 500, 500, 500],
                        "KEY_CAPSULE": [20, 40, 60, 80, 100, 120, 140, 160],
                        "FORCE_AMP": [20, 40, 60, 80, 100, 120, 140, 160]
                    }
                },
                "WeaponRangeKnobs": {
                    "xmpDamageRangeMap": {
                        "1": 42,
                        "3": 58,
                        "2": 48,
                        "5": 90,
                        "4": 72,
                        "7": 138,
                        "6": 112,
                        "8": 168
                    },
                    "ultraStrikeDamageRangeMap": {
                        "1": 10,
                        "3": 16,
                        "2": 13,
                        "5": 21,
                        "4": 18,
                        "7": 27,
                        "6": 24,
                        "8": 30
                    },
                    "maxPowerBoostPercentage": 20,
                    "powerBoostPeriodHardS": 0.6,
                    "powerBoostPeriodEasyS": 1.5,
                    "powerBoostWindowHardS": 0.06,
                    "powerBoostWindowEasyS": 0.1,
                    "powerBoostPowAnimation": 1.0,
                    "powerBoostPowScore": 1.0,
                    "maxFireRateSeconds": 1.5
                },
                "XmCostKnobs": {
                    "xmpFiringCostByLevel": [50, 100, 150, 200, 250, 300, 350, 400],
                    "shieldDeployCostByLevel": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                    "linkAmplifierDeployCostByLevel": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                    "forceAmplifierDeployCostByLevel": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                    "heatsinkDeployCostByLevel": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                    "multihackDeployCostByLevel": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                    "turretDeployCostByLevel": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                    "resonatorDeployCostByLevel": [50, 100, 150, 200, 250, 300, 350, 400],
                    "resonatorUpgradeCostByLevel": [50, 100, 150, 200, 250, 300, 350, 400],
                    "portalHackFriendlyCostByLevel": [50, 100, 150, 200, 250, 300, 350, 400],
                    "portalHackNeutralCostByLevel": [50, 100, 150, 200, 250, 300, 350, 400],
                    "portalHackEnemyCostByLevel": [50, 100, 150, 200, 250, 300, 350, 400],
                    "flipCardCostByLevel": [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000],
                    "portalModByLevel": {
                        "MULTIHACK": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                        "HEATSINK": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                        "TURRET": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                        "EXTRA_SHIELD": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                        "FORCE_AMP": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                        "ULTRA_LINK_AMP": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                        "RES_SHIELD": [200, 400, 600, 800, 1000, 1200, 1400, 1600],
                        "LINK_AMPLIFIER": [200, 400, 600, 800, 1000, 1200, 1400, 1600]
                    },
                    "powerupByLevel": {
                        "PORTAL_POWERUP": [200, 400, 600, 800, 1000, 1200, 1400, 1600]
                    },
                    "boostRechargeResonatorsCost": 15000
                },
                "ScannerKnobs": {
                    "updateIntervalMs": 30000,
                    "updateDistanceM": 10,
                    "maxUpdateIntervalMs": 30000,
                    "minUpdateIntervalMs": 5000,
                    "updateIntervalThrottlingTriggerVelocityMps": 3.0,
                    "updateIntervalThrottlingRate": 0.65,
                    "rangeM": 300,
                    "missionsUpdateIntervalMs": 60000,
                    "missionsUpdateDistanceM": 500,
                    "maxLinkAutoCheckRangeM": 200000,
                    "reportRequestPerformancePercentE6": 0,
                    "crittercismSendPerfDataProbabilityE6": 0,
                    "crittercismSendLogcatProbabilityE6": 0
                },
                "PortalModSharedKnobs": {
                    "diminishingValues": {
                        "FORCE_AMPLIFIER": [1000, 250, 125, 125],
                        "ATTACK_FREQUENCY": [1000, 250, 125, 125],
                        "LINK_RANGE_MULTIPLIER": [1000, 250, 125, 125],
                        "TEMP_LINK_RANGE_MULTIPLIER_SORTED": [1000, 250, 125, 125],
                        "TEMP_ATTACK_FREQUENCY_SORTED": [1000, 250, 125, 125],
                        "BURNOUT_INSULATION": [1000, 500, 500, 500],
                        "HACK_SPEED": [1000, 500, 500, 500],
                        "TEMP_FORCE_AMPLIFIER_SORTED": [1000, 250, 125, 125]
                    },
                    "directValues": {
                        "OUTGOING_LINKS_BONUS": [8, 8, 8, 8]
                    }
                },
                "NearbyPortalKnobs": {
                    "repopulateDistanceMeters": 500.0,
                    "repopulateTimeMilliseconds": "30000"
                },
                "PlayerAnnounceSharedKnobs": {
                    "featureActivationDate": "1377241200000"
                },
                "PlayerVerificationSharedKnobs": {
                    "unverifiedXmCapacity": 3000,
                    "unverifiedInventoryCapacity": 100,
                    "unverifiedApCapacity": 19999,
                    "enableVerificationFeature": false,
                    "enableVerifiedGameActions": false,
                    "numPinCodeDigits": 4
                },
                "PlayerLevelKnobs": {
                    "levelUpRequirements": {
                        "11": {
                            "apRequired": "6000000",
                            "achievementsRequired": {
                                "SILVER": 6,
                                "GOLD": 4
                            }
                        },
                        "10": {
                            "apRequired": "4000000",
                            "achievementsRequired": {
                                "SILVER": 5,
                                "GOLD": 2
                            }
                        },
                        "13": {
                            "apRequired": "12000000",
                            "achievementsRequired": {
                                "PLATINUM": 1,
                                "GOLD": 7
                            }
                        },
                        "12": {
                            "apRequired": "8400000",
                            "achievementsRequired": {
                                "SILVER": 7,
                                "GOLD": 6
                            }
                        },
                        "15": {
                            "apRequired": "24000000",
                            "achievementsRequired": {
                                "PLATINUM": 3
                            }
                        },
                        "14": {
                            "apRequired": "17000000",
                            "achievementsRequired": {
                                "PLATINUM": 2
                            }
                        },
                        "16": {
                            "apRequired": "40000000",
                            "achievementsRequired": {
                                "PLATINUM": 4,
                                "BLACK": 2
                            }
                        },
                        "1": {
                            "apRequired": "0",
                            "achievementsRequired": {}
                        },
                        "3": {
                            "apRequired": "20000",
                            "achievementsRequired": {}
                        },
                        "2": {
                            "apRequired": "2500",
                            "achievementsRequired": {}
                        },
                        "5": {
                            "apRequired": "150000",
                            "achievementsRequired": {}
                        },
                        "4": {
                            "apRequired": "70000",
                            "achievementsRequired": {}
                        },
                        "7": {
                            "apRequired": "600000",
                            "achievementsRequired": {}
                        },
                        "6": {
                            "apRequired": "300000",
                            "achievementsRequired": {}
                        },
                        "9": {
                            "apRequired": "2400000",
                            "achievementsRequired": {
                                "SILVER": 4,
                                "GOLD": 1
                            }
                        },
                        "8": {
                            "apRequired": "1200000",
                            "achievementsRequired": {}
                        }
                    },
                    "maxPlayerLevel": 16,
                    "xmCapacityByLevel": {
                        "11": 14500,
                        "10": 13000,
                        "13": 17500,
                        "12": 16000,
                        "15": 20500,
                        "14": 19000,
                        "16": 22000,
                        "1": 3000,
                        "3": 5000,
                        "2": 4000,
                        "5": 7000,
                        "4": 6000,
                        "7": 9000,
                        "6": 8000,
                        "9": 11500,
                        "8": 10000
                    },
                    "boostedPowerCubeCapacityByLevel": {
                        "11": 40800,
                        "10": 38400,
                        "13": 45600,
                        "12": 43200,
                        "15": 50400,
                        "14": 48000,
                        "16": 52800,
                        "1": 18000,
                        "3": 22500,
                        "2": 20250,
                        "5": 27000,
                        "4": 24750,
                        "7": 31500,
                        "6": 29250,
                        "9": 36000,
                        "8": 33750
                    }
                },
                "MapCompositionRootKnobs": {
                    "mapAreas": [{
                        "description": "S Korea",
                        "epoch": 1,
                        "mapProvider": "OSM",
                        "boundingRects": [{
                            "north": 37.69547616496338,
                            "south": 34.83562779241368,
                            "east": 131.16790087890627,
                            "west": 124.44700830078114
                        }, {
                            "north": 37.69547616496338,
                            "south": 33.025620228813466,
                            "east": 128.76189501953127,
                            "west": 124.44700830078114
                        }, {
                            "north": 37.84094374831599,
                            "south": 37.561299473030594,
                            "east": 126.86126025390627,
                            "west": 126.18010156249989
                        }, {
                            "north": 38.358197906100926,
                            "south": 37.62589818166485,
                            "east": 129.34966357421877,
                            "west": 126.65800683593739
                        }, {
                            "north": 38.634814820135226,
                            "south": 38.358197906100926,
                            "east": 128.55040820312502,
                            "west": 128.14116113281239
                        }]
                    }, {
                        "description": "World",
                        "epoch": -1,
                        "mapProvider": "GMM",
                        "mapProviderName": "",
                        "boundingRects": [{
                            "north": 90.0,
                            "south": -90.0,
                            "east": 180.0,
                            "west": -180.0
                        }]
                    }],
                    "mapProviders": [{
                        "name": "GMM",
                        "baseUrl": "http://mobilemaps.clients.google.com/glm/mmap",
                        "queryFormat": ""
                    }, {
                        "name": "OSM",
                        "baseUrl": "http://maps.nianticlabs.com",
                        "queryFormat": "ntp-maptiles/epoch-%04d/%s.gmm"
                    }]
                }
            },
            "syncTimestamp": "1481903753065"
        }
    }
}

这里的东西可以做一个教程了,基本上,各种物品的效果,升级的要求都在里面写的很清楚,欢迎其他同学做个统计

比如ultraStrikeDamageRangeMap里说明了各个级别的US作用距离

这里大概是为了热更新,把设置放在服务端(反正跑的又不是我的流量,gg)

setLocale

然后是POST到https://m-dot-betaspike.appspot.com/rpc/emptyBasket/setLocale

直接form内容简单暴力

{"params":["zh-Hans-CN"]}

返回也是一个空的{}

globalRegionMap

这次是GET到https://m-dot-betaspike.appspot.com/globalRegionMap获取游戏开始那张转动的地球的图

Response是一张256*128的黑绿红图

batch 第二次

又触发一次设备信息上传,除了request_ts更新了,有一点不同,在events中

"pub_data": {
	"type": "upsight.session.pause",
	"ui_type": "FOREGROUND"
},
...,
"type": "pub.StartupWheelsOfAdaSubActivity",

这之前都是在点击我明白了按钮之前的请求

Game API

getGameScore

显然是用来获取游戏的比分的

API URL: https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/getGameScore
API Request: params: []
API Response:
{
	"result": {
		"alienScore": "569243223",
		"resistanceScore": "723155462"
	},
	"gameBasket": {
		"gameEntities": [],
		"inventory": [],
		"deletedEntityGuids": []
	}
}

懒得解释了,直接贴返回的包吧

getObjectsInCells

用来获得地图元素

API URL: https://m-dot-betaspike.appspot.com/rpc/gameplay/getObjectsInCells
API Request: params: {clientBasket: {clientBlob}, knobSyncTimestamp, energyGlobGuids: [], playerLocation: value, dates: [value], cellsAsHex: [...], cells}

这里clientBasket是验证信息,整个过程中不会变,大概要逆一下知道算法

playerLocation是'hex,hex'这样的串,纬度经度(保留6位小数后去掉小数点)转成16进制后空格连接

dates是20个0组成的list(不确定)

cellsAsHex是cell分片的token,20个16位hex值组成的list

API Response:
{
	"result": "1481906071300",
	"gameBasket": {
		"gameEntities": [
			[guid, time, {
				"capturedRegion": {
					"vertexA": {
						"guid": guid,
						"location": {
							"latE6": *,
							"lngE6": *
						}
					},
					"vertexB": {
						...
					},
					"vertexC": {
						...
					}
				},
				"entityScore": {
					"entityScore": "8"
				},
				"creator": {
					"creatorGuid": user_guid,
					"creationTime": time
				},
				"controllingTeam": {
					"team": "RESISTANCE"
				}
			}],
			...,
			[guid, time, {
				"photoStreamInfo": {
					"coverPhoto": {
						"portalImageGuid": *,
						"imageUrl": *,
						"attributionMarkup": ["PLAYER", {
							"plain": agent_name,
							"guid": guid,
							"team": "ALIENS"
						}],
						"voteCount": 0
					},
					"photoCount": 1
				},
				"locationE6": {
					"latE6": *,
					"lngE6": *
				},
				"discoverer": {
					"playerMarkupArgSet": {
						"plain": agent_name,
						"guid": *,
						"team": "ALIENS"
					}
				},
				"resonatorArray": {
					"resonators": [{
						"level": 3,
						"distanceToPortal": 28,
						"ownerGuid": agent_guid,
						"energyTotal": 1327,
						"slot": 0,
						"id": uuid
					}, ...]
				},
				"descriptiveText": {
					"map": {
						"TITLE": *,
						"ADDRESS": *
					}
				},
				"turret": {},
				"portalV2": {
					"linkedEdges": [],
					"linkedModArray": [{
						"installingUser": agent_guid,
						"stats": {
							"MITIGATION": "30",
							"REMOVAL_STICKINESS": "0"
						},
						"rarity": "COMMON",
						"displayName": "Portal Shield",
						"type": "RES_SHIELD"
					}, ...],
					"missionStartPoint": false
				},
				"controllingTeam": {
					"team": "RESISTANCE"
				},
				"captured": {
					"capturingPlayerId": agent_guid
				},
				"defaultActionRange": {}
			}],
			...,

			[guide, time, {
				"edge": {
					"originPortalGuid": guid,
					"destinationPortalGuid": guid,
					"originPortalLocation": {
						"latE6": *,
						"lngE6": *
					},
					"destinationPortalLocation": {
						"latE6": *,
						"lngE6": *
					}
				},
				"creator": {
					"creatorGuid": *,
					"creationTime": *
				},
				"controllingTeam": {
					"team": "RESISTANCE"
				}
			}],
			...,
			[guid, time, {
				"imageByUrl": {
					"imageUrl": *
				},
				"photoStreamInfo": {
					"coverPhoto": {
						"portalImageGuid": guid,
						"imageUrl": *,
						"attributionMarkup": ["PLAYER", {
							"plain": agent_name,
							"guid": guid,
							"team": "ALIENS"
						}],
						"voteCount": 5
					},
					"photoCount": 1
				},
				"locationE6": {
					"latE6": *,
					"lngE6": *
				},
				"discoverer": {
					"playerMarkupArgSet": {
						"plain": agent_name,
						"guid": *,
						"team": "ALIENS"
					}
				},
				"resonatorArray": {
					"resonators": [...]
				},
				"descriptiveText": {
					"map": {
						"TITLE": *,
						"DESCRIPTION": *,
						"ADDRESS": *
					}
				},
				"turret": {},
				"portalV2": {
					"linkedEdges": [{
						"edgeGuid": guid,
						"otherPortalGuid": guid",
						"isOrigin": false
					}, ...],
					"linkedModArray": [..., null],
					"missionStartPoint": false
				},
				"controllingTeam": {
					"team": "RESISTANCE"
				},
				"captured": {
					"capturingPlayerId": agent_guid
				},
				"defaultActionRange": {}
			}],
			...,
			[guid, time, {
				"timedPowerupSet": {
					"powerUpItems": []
				},
				"imageByUrl": {
					"imageUrl": *
				},
				"photoStreamInfo": {
					"coverPhoto": {
						"portalImageGuid": guid,
						"imageUrl": *,
						"attributionMarkup": ["PLAYER", {
							"plain": agent_user,
							"guid": guid,
							"team": "ALIENS"
						}],
						"voteCount": 2
					},
					"photoCount": 1
				},
				"locationE6": {
					"latE6": *,
					"lngE6": *
				},
				"discoverer": {
					"playerMarkupArgSet": {
						"plain": agent_user,
						"guid": guid,
						"team": "ALIENS"
					}
				},
				"resonatorArray": {
					"resonators": [...]
				},
				"descriptiveText": {
					"map": {
						"ADDRESS": *,
						"TITLE": (
					}
				},
				"turret": {},
				"portalV2": {
					"linkedEdges": [...],
					"linkedModArray": [null, null, null, null],
					"missionStartPoint": false
				},
				"controllingTeam": {
					"team": "RESISTANCE"
				},
				"captured": {
					"capturingPlayerId": agent_guid
				},
				"defaultActionRange": {}
			}],
			...,
		}],
		"apGains": [],
		"inventory": [],
		"deletedEntityGuids": [],
		"energyGlobGuids": [guid, ...],
		"energyGlobTimestamp": "1481906071300",
		"refreshEntityGuids": [guid, ...]
	}
}

很清楚。。。不说了

getCurrentMission

API URL: https://m-dot-betaspike.appspot.com/rpc/gameplay/getCurrentMission
API Request: params: {clientBasket: {clientBlob}, knobSyncTimestamp, energyGlobGuids: [], playerLocation: value}
API Response: 任务和gameBasket,这里因为我没当前任务,略掉

getNewsOfTheDay

API URL:https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/getNewsOfTheDay
API Request: params: [value]

这个value是一个不造什么鬼的串

API Response:  gameBasket: {gameEntities: [], inventory: [], deletedEntityGuids: [] }

这个API得等有活动的时候测试

getPaginatedPlexts

获得comm消息

API URL: https://m-dot-betaspike.appspot.com/rpc/gameplay/getPaginatedPlexts

API Request:
{
	"params": {
		"clientBasket": {
			"clientBlob": *
		},
		"knobSyncTimestamp": *,
		"energyGlobGuids": [],
		"playerLocation": value,
		"categories": -1,
		"ascendingTimestampOrder": false,
		"desiredNumItems": 100,
		"maxTimestampMs": -1,
		"minTimestampMs": 1481900888021,
		"cellsAsHex": [...],
		"factionOnly": false
	}
}

这个的参数可以参考Intel Map的

API Response:
{
	"result": [
		[guid, time, {
			"locationE6": {
				"latE6": *,
				"lngE6": *
			},
			"plext": {
				"text": *,
				"team": "ALIENS",
				"markup": [
					["SENDER", {
						"plain": agent_name,
						"guid": *,
						"team": "ALIENS"
					}],
					["TEXT", {
						"plain": ""
					}],
					["AT_PLAYER", {
						"plain": *,
						"guid": guid,
						"team": "ALIENS"
					}],
					["TEXT", {
						"plain": *
					}]
				],
				"plextType": "PLAYER_GENERATED",
				"categories": 1
			}
		}]
	],
	"gameBasket": {
		"gameEntities": [],
		"playerEntity": [...],
		"apGains": [],
		"inventory": [],
		"deletedEntityGuids": [],
		"serverBlob": *
	}
}

省略了一些重复的,这里也可以参考Intel Map的API

getInventory

API URL: https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/getInventory
API Request:
{
	"params": {
		"lastQueryTimestamp": timestamp
	}
}
API Response:(只返回更新的物品)
{
	"result": "1481911112158",
	"gameBasket": {
		"gameEntities": [],
		"inventory": [
		["56b24e20197240d2a2330e7fb60fa6a1.5", 1473951636802, {
						"inInventory": {
							"playerId": *,
							"acquisitionTimestampMs": *
						},
						"modResource": {
							"displayName": "Heat Sink",
							"stats": {
								"REMOVAL_STICKINESS": "0",
								"HACK_SPEED": "200000"
							},
							"rarity": "COMMON",
							"resourceType": "HEATSINK"
						},
						"displayName": {
							"displayName": "Heat Sink",
							"displayDescription": "Mod that reduces cooldown time between Portal hacks."
						}
				}],...,
		],
		"deletedEntityGuids": []
	}
}

inventory能看到更新的物品是什么,强制同步后,这个里面就是所有东西,非常大。。(毕竟每个物品一个list...)

registerForApn

API URL: https://m-dot-betaspike.appspot.com/rpc/emptyBasket/registerForApn
API Request: params: [key, "com.google.ingress", "2048"]
API Response: {}

用来注册token

unregisterForApn

API URL: https://m-dot-betaspike.appspot.com/rpc/emptyBasket/unregisterForApn
API Request:
API Response: {}

getInviteInfo

API URL: https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/getInviteInfo
API Request: params: []
API Response:
{
	"result": {
		"numAvailableInvites": 298,
		"inviteeToStatusMap": {
			email: status,
			...
		},
		"apGainOnInviteAccepted": "3000"
	},
	"gameBasket": {
		"gameEntities": [],
		"inventory": [
		],
		"deletedEntityGuids": []
	}
}

这个API不错,能看到自己邀请的所有人和状态,甚至是ACCEPTED_ANOTHER_PLAYERS_INVITE

putBulkPlayerStorage

API URL:https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/putBulkPlayerStorage
API Request: prams: [{tutorial_complete_scanner_intro: value}]

这个value是一个true:delim:1481912306360:delim:true格式的串

API Response:
{
	"result": "SUCCESS",
	"gameBasket": {
		"gameEntities": [],
		"inventory": [],
		"deletedEntityGuids": []
	}
}

getPlayerProfile2

这个是用来获取自己的信息的

API URL: https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/getPlayerProfile2
API Request: params: [agent_name]
API Response: result: {team, avatar: {foregroundLayer: {id, imageURL, layer}, backgroundLayer: {id, imageUrl, layer}, avatarColorForeground, avatarColorBackground}, metrics: [{metricName, metricCategory, formattedValueAllTime, formattedValue30Days, formattedValue7Days}, ...], highlightedAchievements: [title, description, group, tiers: [{value, badgeImageUrl, locked}, ...], timestampAwarded], firstAchievementContinuationToken, ap, verifiedLeve, achievementCounts: {SILVER, GOLD, BLACK, PLATINUM, BRONZE}, gPlusId, highlightedMissionBadges: [{missionGuid, missionTitle, missionDescription, imageUrl}, ...], firstMissionBadgeContinuationToken}, gameBasket: {gameEntities, inventory, deletedEntityGuids}

都是自注释

metrics是数据统计,例如Unique Portals Visite

highlightedAchievements是牌子信息

highlightedMissionBadges是任务信息

getPaginatedMissionBadges

API URL: https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/getPaginatedMissionBadges
API Request: params: [{continuationToken, nickname}]

这个continuationToken是上面那个API返回的firstMissionBadgeContinuationToken或者是自己返回的continuationToken

API Response:
{
	"result": {
		"missionBadges": [{
			"missionGuid": guid,
			"missionTitle": *,
			"missionDescription": *,
			"imageUrl": *
		}, ...],
		"continuationToken": *
	},
	"gameBasket": {
		"gameEntities": [],
		"inventory": [],
		"deletedEntityGuids": []
	}
}

这个API是用来获取任务图标和详情的

getNearbyMissions

API URL: https://m-dot-betaspike.appspot.com/rpc/gameplay/getNearbyMissions
API Request:
{
	"params": {
		"clientBasket": {
			"clientBlob": *
		},
		"knobSyncTimestamp": *,
		"energyGlobGuids": [],
		"location": value,
		"continuationToken": value
	}
}

这里的value也是逗号分隔的两个hex

continueationToken为null表示第一次查看任务,之后值为这个API自己返回的continuationToken

API Response:
{
	"result": {
		"missionSnippets": [{
			"header": {
				"guid": guid,
				"title": *,
				"logoUrl": *,
				"startLocation": value,
				"badgeUrl": *,
				"stats": {
					"ratingE6": "0",
					"medianCompletionTimeMs": "0",
					"numUniqueCompletedPlayers": "0"
				},
				"status": "NOT_STARTED",
				"authorNickname": agent_name,
				"authorTeam": "ALIENS"
			},
			"version": "2"
		},...],
		"continuationToken": value
	},
	"gameBasket": {
		"gameEntities": [],
		"playerEntity": [guid, 1481912305897, {
			"avatar": {
				"foreground": {
					"layerId": "foreground4",
					"tintColor": 16249235,
					"imageUrl": *
				},
				"background": {
					"layerId": "background3",
					"tintColor": 481625,
					"imageUrl": *
				}
			},
			"playerPersonal": {
				"ap": "14031060",
				"energy": 17500,
				"allowNicknameEdit": false,
				"allowFactionChoice": false,
				"verifiedLevel": 13,
				"mediaHighWaterMarks": {
					"General": 1809,
					"RESISTANCE": 1328,
					"ALIENS": 1327
				},
				"energyState": "XM_OK",
				"notificationSettings": {
					"shouldSendEmail": false,
					"maySendPromoEmail": false,
					"shouldPushNotifyForAtPlayer": true,
					"shouldPushNotifyForPortalAttacks": true,
					"shouldPushNotifyForInvitesAndFactionInfo": true,
					"shouldPushNotifyForNewsOfTheDay": true,
					"shouldPushNotifyForEventsAndOpportunities": true,
					"locale": "zh-Hans-CN"
				},
				"profileSettings": {
					"areMetricsPublic": false
				},
				"verificationState": "UNVERIFIED",
				"extraXmTankEnergy": 0
			},
			"controllingTeam": {
				"team": "RESISTANCE"
			}
		}],
		"apGains": [],
		"inventory": [],
		"deletedEntityGuids": [],
		"serverBlob": *,
		"refreshEntityGuids": [guid, ...]
	}
}

getNickNamesFromPlayerIds

API URL: https://m-dot-betaspike.appspot.com/rpc/playerUndecorated/getNickNamesFromPlayerIds
API Request: params: [agent_guid]
API Response: result: [agent_name], gameBasket: {gameEntities: , inventory: , deletedEntityGuids: }

collectItemsOrGlyphsFromPortal

API URL: https://m-dot-betaspike.appspot.com/rpc/gameplay/collectItemsOrGlyphsFromPortal

Without Glyphs

API Request:
{
	"params": {
		"glyphGameRequested": false,
		"spewInfluenceGlyphSequence": null,
		"userInputGlyphSequence": null,
		"clientBasket": {
			"clientBlob": *
		},
		"knobSyncTimestamp": *,
		"energyGlobGuids": [],
		"portalGuid": guid,
		"location": value
	}
}
API Response:
{
	"result": {
		"items": {
			"addedGuids": [guid, ...],
			"baseHackMultiplier": "1"
		}
	},
	"gameBasket": {
		"playerDamages": [],
		"gameEntities": [],
		"playerEntity": [guid, 1481913704637, {
			"playerPersonal": {
				...,
				"energyState": "XM_OK",
				"notificationSettings": ...,
				"profileSettings": {
					"areMetricsPublic": false
				},
				"verificationState": "UNVERIFIED",
				"extraXmTankEnergy": 0
			},
			"controllingTeam": {
				"team": "RESISTANCE"
			},
			"avatar": {
				...
			}
		}],
		"apGains": [],
		"inventory": [
			[guid, 1481913704513, {
				"modResource": {
					"displayName": "Portal Shield",
					"stats": {
						"REMOVAL_STICKINESS": "0",
						"MITIGATION": "30"
					},
					"rarity": "COMMON",
					"resourceType": "RES_SHIELD"
				},
				"displayName": {
					"displayName": "Portal Shield",
					"displayDescription": "Mod which shields Portal from attacks."
				},
				"inInventory": {
					"playerId": agent_guid,
					"acquisitionTimestampMs": *
				}
			}],
			...
		],
		"deletedEntityGuids": [],
		"serverBlob": *,
		"refreshEntityGuids": [guid]
	}
}

With Glyphs

API Request:
{
	"params": {
		"glyphGameRequested": true,
		"spewInfluenceGlyphSequence": null,
		"userInputGlyphSequence": null,
		"clientBasket": {
			"clientBlob": *
		},
		"knobSyncTimestamp": 1481912295011,
		"energyGlobGuids": [],
		"portalGuid": guid,
		"location": value
	}
}
```json

	API Response:

```json
{
	"result": {
		"glyphs": {
			"glyphSequence": [{
				"glyphOrder": "ejgahic"
			}, {
				"glyphOrder": "ga"
			}, {
				"glyphOrder": "jkgh"
			}, {
				"glyphOrder": "ejka"
			}, {
				"glyphOrder": "gkhijd"
			}],
			"isPrompted": false,
			"maxInputTimeMs": "15000",
			"timeToDemoMs": "500"
		}
	},
	"gameBasket": {
		*
	}
}

collectItemsFromPortalWithGlyphResponse

API URL: https://m-dot-betaspike.appspot.com/rpc/gameplay/collectItemsFromPortalWithGlyphResponse
API Request:
{
	"params": {
		"glyphGameRequested": false,
		"spewInfluenceGlyphSequence": {
			"inputTimeMs": 1233,
			"bypassed": false,
			"glyphSequence": [{
				"glyphOrder": "hgkj"
			}, {
				"glyphOrder": "gkh"
			}]
		},
		"userInputGlyphSequence": {
			"inputTimeMs": 8683,
			"bypassed": false,
			"glyphSequence": [{
				"glyphOrder": "fgah"
			}, {
				"glyphOrder": "egjihc"
			}, {
				"glyphOrder": "egahc"
			}, {
				"glyphOrder": "ega"
			}, {
				"glyphOrder": "efabhkjd"
			}]
		},
		"clientBasket": {
			"clientBlob": *
		},
		"knobSyncTimestamp": 1481912295011,
		"energyGlobGuids": [],
		"portalGuid": "3e2bcc15c58d486fae24e2ade2bf7327.16",
		"location": "01d553fe,0631e166"
	}
}
API Response:
{
	"result": {
		"addedGuids": ["a4f754d8e8f0448c88a6fe349f303ebc.5", "c07c542b6e0c4fea9b66b66fcc110c37.5", "c7995bba88c4442eac1ac2c8008d419c.5", "3264136a3f414efba8e88a401786bc25.5", "4d928a839c3546658abc025fb8170981.5", "65916b9be8944fe986abe47433ad4c75.5", "0e9b7f761b8f41d8b149447dfd10ca0d.5", "995fddb948bf41caab25ad1d0496e57a.5", "36ecac7a73ba43bfb21f6d4dbdd84a1f.5", "afe79b3bd18941b995557eb0d0bcef41.5"],
		"glyphResponse": {
			"glyphResponses": [true, true, true, true, true],
			"powerBoostInMillion": 1630000,
			"timeBonusBoostInMillion": 421133,
			"displayNames": ["PURSUE", "CONFLICT", "WAR", "ADVANCE", "CHAOS"],
			"bonusGuids": ["a4f754d8e8f0448c88a6fe349f303ebc.5", "c07c542b6e0c4fea9b66b66fcc110c37.5", "3264136a3f414efba8e88a401786bc25.5", "4d928a839c3546658abc025fb8170981.5", "65916b9be8944fe986abe47433ad4c75.5", "afe79b3bd18941b995557eb0d0bcef41.5"]
		},
		"baseHackMultiplier": "1"
	},
	"gameBasket": {
		"playerDamages": [],
		"gameEntities": [],
		"playerEntity": [*, 1481914255972, {
			"avatar": {
				*
			},
			"playerPersonal": {
				"ap": "14031565",
				"energy": 17100,
				"allowNicknameEdit": false,
				"allowFactionChoice": false,
				"verifiedLevel": 13,
				"mediaHighWaterMarks": {
					"General": 1809,
					"RESISTANCE": 1328,
					"ALIENS": 1327
				},
				"energyState": "XM_OK",
				"notificationSettings": {
					"shouldSendEmail": false,
					"maySendPromoEmail": false,
					"shouldPushNotifyForAtPlayer": true,
					"shouldPushNotifyForPortalAttacks": true,
					"shouldPushNotifyForInvitesAndFactionInfo": true,
					"shouldPushNotifyForNewsOfTheDay": true,
					"shouldPushNotifyForEventsAndOpportunities": true,
					"locale": "zh-Hans-CN"
				},
				"profileSettings": {
					"areMetricsPublic": false
				},
				"verificationState": "UNVERIFIED",
				"extraXmTankEnergy": 0
			},
			"controllingTeam": {
				"team": "RESISTANCE"
			}
		}],
		"apGains": [{
			"apTrigger": "GLYPH_HACK",
			"apGainAmount": "405"
		}],
		"inventory": [
			["a4f754d8e8f0448c88a6fe349f303ebc.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMITTER_A",
					"level": 8
				},
				"displayName": {
					"displayName": "Resonator",
					"displayDescription": "XM object used to power-up a Portal and align it to a Faction."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255794"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				}
			}],
			["c07c542b6e0c4fea9b66b66fcc110c37.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMP_BURSTER",
					"level": 8
				},
				"displayName": {
					"displayName": "Xmp Burster",
					"displayDescription": "Exotic Matter Pulse weapons which can destroy enemy Resonators and Mods and neutralize enemy Portals."
				},
				"empWeapon": {
					"level": 8,
					"ammo": 1
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255779"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				}
			}],
			["c7995bba88c4442eac1ac2c8008d419c.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMITTER_A",
					"level": 7
				},
				"displayName": {
					"displayName": "Resonator",
					"displayDescription": "XM object used to power-up a Portal and align it to a Faction."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255777"
				},
				"accessLevel": {
					"requiredLevel": 7,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 7
					}
				}
			}],
			["3264136a3f414efba8e88a401786bc25.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMP_BURSTER",
					"level": 7
				},
				"displayName": {
					"displayName": "Xmp Burster",
					"displayDescription": "Exotic Matter Pulse weapons which can destroy enemy Resonators and Mods and neutralize enemy Portals."
				},
				"empWeapon": {
					"level": 7,
					"ammo": 1
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255794"
				},
				"accessLevel": {
					"requiredLevel": 7,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 7
					}
				}
			}],
			["4d928a839c3546658abc025fb8170981.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMITTER_A",
					"level": 8
				},
				"displayName": {
					"displayName": "Resonator",
					"displayDescription": "XM object used to power-up a Portal and align it to a Faction."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255779"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				}
			}],
			["65916b9be8944fe986abe47433ad4c75.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMITTER_A",
					"level": 8
				},
				"displayName": {
					"displayName": "Resonator",
					"displayDescription": "XM object used to power-up a Portal and align it to a Faction."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255780"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				}
			}],
			["0e9b7f761b8f41d8b149447dfd10ca0d.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMITTER_A",
					"level": 8
				},
				"displayName": {
					"displayName": "Resonator",
					"displayDescription": "XM object used to power-up a Portal and align it to a Faction."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255778"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				}
			}],
			["995fddb948bf41caab25ad1d0496e57a.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "POWER_CUBE",
					"level": 8
				},
				"displayName": {
					"displayName": "Power Cube",
					"displayDescription": "Store of XM which can be used to recharge Scanner."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255778"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				},
				"powerCube": {
					"energy": 8000
				}
			}],
			["36ecac7a73ba43bfb21f6d4dbdd84a1f.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "EMITTER_A",
					"level": 8
				},
				"displayName": {
					"displayName": "Resonator",
					"displayDescription": "XM object used to power-up a Portal and align it to a Faction."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255778"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				}
			}],
			["afe79b3bd18941b995557eb0d0bcef41.5", 1481914255823, {
				"resourceWithLevels": {
					"resourceType": "POWER_CUBE",
					"level": 8
				},
				"displayName": {
					"displayName": "Power Cube",
					"displayDescription": "Store of XM which can be used to recharge Scanner."
				},
				"inInventory": {
					"playerId": *,
					"acquisitionTimestampMs": "1481914255779"
				},
				"accessLevel": {
					"requiredLevel": 8,
					"failure": {
						"isAllowed": false,
						"requiredLevel": 8
					}
				},
				"powerCube": {
					"energy": 8000
				}
			}]
		],
		"deletedEntityGuids": [],
		"serverBlob": *,
		"refreshEntityGuids": [guid]
	}
}

这里把所有提交和得到的参数都列明了,说明一下画图的字母代表哪个位置:

从上到下,从左到右依次是

a
fb
gh
k
ejic
d

也就是 ALL命令从最上方顶点顺时针依次是abcd(最下面)dfa; Strong命令从左上角开始顺时针ghij;中心是k

#结语

用了两个晚上统计了下API。
本来打算也写一份Game API的库,但是因为不能生成客户端blob并没有意义,以后用到再说,Intel Map已经ok了。
在游戏过程中,batch会在移动的时候触发
获取地图更新是定时轮询:getInventory(毕竟还可以passcode获取物品,所有得一直get),getPaginatedPlexts,getObjectsInCells