poi-plugin-mcp 0.2.12 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,7 @@
1
+ const { createPoiActionEvents } = require('./poi-action-events')
2
+
1
3
  const QUEST_LIST_PATH = '/kcsapi/api_get_member/questlist'
4
+ const UNSET_SLOT_PATH = '/kcsapi/api_get_member/unsetslot'
2
5
  const QUEST_ACTION_PATHS = new Set([
3
6
  '/kcsapi/api_req_quest/start',
4
7
  '/kcsapi/api_req_quest/stop',
@@ -40,12 +43,15 @@ const BATTLE_PATHS = new Set([
40
43
 
41
44
  function createPoiTelemetry(options = {}) {
42
45
  const now = options.now || (() => new Date())
46
+ const actionEvents = createPoiActionEvents({ now })
43
47
  let questGeneration = 0
44
48
  let questList = null
45
49
  let questActionGeneration = 0
46
50
  let questAction = null
47
51
  let equipmentActionGeneration = 0
48
52
  let equipmentAction = null
53
+ let unsetSlotGeneration = 0
54
+ let unsetSlot = null
49
55
  let fleetActionGeneration = 0
50
56
  let fleetAction = null
51
57
  let battleGeneration = 0
@@ -54,21 +60,26 @@ function createPoiTelemetry(options = {}) {
54
60
  function handleGameResponse(event) {
55
61
  const detail = event && event.detail
56
62
  if (!detail || typeof detail.path !== 'string') return
63
+ const actionEvent = actionEvents.capture(detail)
57
64
 
58
65
  if (detail.path === QUEST_LIST_PATH) {
59
- captureQuestList(detail)
66
+ captureQuestList(detail, actionEvent)
67
+ return
68
+ }
69
+ if (detail.path === UNSET_SLOT_PATH) {
70
+ captureUnsetSlot(detail, actionEvent)
60
71
  return
61
72
  }
62
73
  if (QUEST_ACTION_PATHS.has(detail.path)) {
63
- captureQuestAction(detail)
74
+ captureQuestAction(detail, actionEvent)
64
75
  return
65
76
  }
66
77
  if (EQUIPMENT_ACTION_PATHS.has(detail.path)) {
67
- captureEquipmentAction(detail)
78
+ captureEquipmentAction(detail, actionEvent)
68
79
  return
69
80
  }
70
81
  if (detail.path === FLEET_ACTION_PATH) {
71
- captureFleetAction(detail)
82
+ captureFleetAction(detail, actionEvent)
72
83
  return
73
84
  }
74
85
  if (BATTLE_RESULT_PATHS.has(detail.path)) {
@@ -80,7 +91,7 @@ function createPoiTelemetry(options = {}) {
80
91
  }
81
92
  }
82
93
 
83
- function captureQuestList(detail) {
94
+ function captureQuestList(detail, actionEvent) {
84
95
  const body = detail.body
85
96
  const postBody = detail.postBody
86
97
  const tabId = toInteger(postBody && postBody.api_tab_id)
@@ -105,7 +116,9 @@ function createPoiTelemetry(options = {}) {
105
116
  questList = {
106
117
  available: true,
107
118
  generation: questGeneration,
108
- capturedAt: now().toISOString(),
119
+ capturedAt: actionEvent
120
+ ? actionEvent.capturedAt
121
+ : now().toISOString(),
109
122
  tabId,
110
123
  pageNo: nonNegativeInteger(body.api_disp_page),
111
124
  pageCount: nonNegativeInteger(body.api_page_count),
@@ -116,7 +129,11 @@ function createPoiTelemetry(options = {}) {
116
129
  }
117
130
  }
118
131
 
119
- function captureQuestAction(detail) {
132
+ function captureQuestAction(detail, actionEvent) {
133
+ const apiResult = actionEvent
134
+ ? actionEvent.apiResult
135
+ : equipmentApiResult(detail)
136
+ if (apiResult !== 1) return
120
137
  const postBody = detail.postBody
121
138
  const questId = toInteger(postBody && postBody.api_quest_id)
122
139
  if (questId == null || questId <= 0) return
@@ -125,15 +142,20 @@ function createPoiTelemetry(options = {}) {
125
142
  questAction = {
126
143
  available: true,
127
144
  generation: questActionGeneration,
128
- capturedAt: now().toISOString(),
129
- path: detail.path,
145
+ capturedAt: actionEvent
146
+ ? actionEvent.capturedAt
147
+ : now().toISOString(),
148
+ path: actionEvent ? actionEvent.path : detail.path,
130
149
  questId,
131
150
  flag: toInteger(postBody && postBody.api_quest_flag),
151
+ apiResult,
132
152
  }
133
153
  }
134
154
 
135
- function captureEquipmentAction(detail) {
136
- const apiResult = equipmentApiResult(detail)
155
+ function captureEquipmentAction(detail, actionEvent) {
156
+ const apiResult = actionEvent
157
+ ? actionEvent.apiResult
158
+ : equipmentApiResult(detail)
137
159
  if (apiResult === 0) return
138
160
  const postBody = normalizeEquipmentPostBody(detail.path, detail.postBody)
139
161
  if (!postBody) return
@@ -142,15 +164,37 @@ function createPoiTelemetry(options = {}) {
142
164
  equipmentAction = {
143
165
  available: true,
144
166
  generation: equipmentActionGeneration,
145
- capturedAt: now().toISOString(),
146
- path: detail.path,
167
+ capturedAt: actionEvent
168
+ ? actionEvent.capturedAt
169
+ : now().toISOString(),
170
+ path: actionEvent ? actionEvent.path : detail.path,
147
171
  apiResult,
148
172
  postBody,
149
173
  }
150
174
  }
151
175
 
152
- function captureFleetAction(detail) {
153
- const apiResult = equipmentApiResult(detail)
176
+ function captureUnsetSlot(detail, actionEvent) {
177
+ const bySlotType = normalizeUnsetSlotBody(detail.body)
178
+ if (bySlotType == null) return
179
+
180
+ unsetSlotGeneration += 1
181
+ unsetSlot = {
182
+ available: true,
183
+ generation: unsetSlotGeneration,
184
+ capturedAt: actionEvent
185
+ ? actionEvent.capturedAt
186
+ : now().toISOString(),
187
+ bySlotType,
188
+ equipmentIds: Object.values(bySlotType)
189
+ .flatMap((groups) => Object.values(groups))
190
+ .flat(),
191
+ }
192
+ }
193
+
194
+ function captureFleetAction(detail, actionEvent) {
195
+ const apiResult = actionEvent
196
+ ? actionEvent.apiResult
197
+ : equipmentApiResult(detail)
154
198
  if (apiResult === 0) return
155
199
  const postBody = normalizeFleetPostBody(detail.postBody)
156
200
  if (!postBody) return
@@ -159,8 +203,10 @@ function createPoiTelemetry(options = {}) {
159
203
  fleetAction = {
160
204
  available: true,
161
205
  generation: fleetActionGeneration,
162
- capturedAt: now().toISOString(),
163
- path: detail.path,
206
+ capturedAt: actionEvent
207
+ ? actionEvent.capturedAt
208
+ : now().toISOString(),
209
+ path: actionEvent ? actionEvent.path : detail.path,
164
210
  apiResult,
165
211
  postBody,
166
212
  }
@@ -231,15 +277,51 @@ function createPoiTelemetry(options = {}) {
231
277
  getEquipmentAction() {
232
278
  return equipmentAction || { available: false, generation: 0 }
233
279
  },
280
+ getUnsetSlot() {
281
+ return unsetSlot || { available: false, generation: 0 }
282
+ },
234
283
  getFleetAction() {
235
284
  return fleetAction || { available: false, generation: 0 }
236
285
  },
286
+ getActionEvents(options) {
287
+ return actionEvents.read(options)
288
+ },
237
289
  getBattleTelemetry() {
238
290
  return battleTelemetry || { available: false, generation: 0 }
239
291
  },
240
292
  }
241
293
  }
242
294
 
295
+ function normalizeUnsetSlotBody(body) {
296
+ if (!body || typeof body !== 'object' || Array.isArray(body)) return null
297
+ const source = body.api_data &&
298
+ typeof body.api_data === 'object' &&
299
+ !Array.isArray(body.api_data)
300
+ ? body.api_data
301
+ : body
302
+ const output = {}
303
+ let totalIds = 0
304
+
305
+ for (const [slotType, groups] of Object.entries(source)) {
306
+ if (!/^api_slottype\d+$/.test(slotType)) continue
307
+ if (!groups || typeof groups !== 'object' || Array.isArray(groups)) continue
308
+ const normalizedGroups = {}
309
+ for (const [groupId, ids] of Object.entries(groups)) {
310
+ if (!/^\d+$/.test(groupId) || !Array.isArray(ids)) continue
311
+ const normalizedIds = ids
312
+ .map(positiveIntegerOrNull)
313
+ .filter((id) => id != null)
314
+ totalIds += normalizedIds.length
315
+ if (totalIds > 10000) return null
316
+ normalizedGroups[groupId] = normalizedIds
317
+ }
318
+ if (Object.keys(normalizedGroups).length > 0) {
319
+ output[slotType] = normalizedGroups
320
+ }
321
+ }
322
+ return Object.keys(output).length > 0 ? output : null
323
+ }
324
+
243
325
  function normalizeFleetPostBody(postBody) {
244
326
  if (!postBody || typeof postBody !== 'object') return null
245
327
  const fleetId = boundedInteger(postBody.api_id, 1, 4)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poi-plugin-mcp",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "description": "Poi data, WebView capture, and opt-in authenticated input bridge for local KanColle tools.",
5
5
  "main": "index.js",
6
6
  "keywords": [