game: ingress api
Python
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
dist 0.21 dist Apr 6, 2018
ingressAPI remove default proxy Apr 6, 2018
LICENSE.txt pypi Dec 16, 2016
MANIFEST update Dec 16, 2016
README.md update readme Dec 16, 2016
requirements.txt init Dec 15, 2016
setup.cfg pypi Dec 16, 2016
setup.py 0.2 dist Apr 6, 2018

README.md

说明

目标一共有两个,一个是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

https://www.ingress.com/r/sendPlext

发出消息

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