koishi-plugin-warframe 1.6.7 → 1.7.1

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.
package/lib/index.js CHANGED
@@ -733,11 +733,11 @@ var require_LocalDatastore = __commonJS({
733
733
  return _this6._done;
734
734
  })();
735
735
  }
736
- __groupCheck__(time) {
736
+ __groupCheck__(time2) {
737
737
  var _this7 = this;
738
738
  return _asyncToGenerator2(function* () {
739
739
  yield _this7.yieldLoop();
740
- return _this7._nextRequest + _this7.timeout < time;
740
+ return _this7._nextRequest + _this7.timeout < time2;
741
741
  })();
742
742
  }
743
743
  computeCapacity() {
@@ -2323,14 +2323,14 @@ var require_Group = __commonJS({
2323
2323
  clearInterval(this.interval);
2324
2324
  return typeof (base = this.interval = setInterval(
2325
2325
  /* @__PURE__ */ _asyncToGenerator2(function* () {
2326
- var e, k, ref, results, time, v;
2327
- time = Date.now();
2326
+ var e, k, ref, results, time2, v;
2327
+ time2 = Date.now();
2328
2328
  ref = _this3.instances;
2329
2329
  results = [];
2330
2330
  for (k in ref) {
2331
2331
  v = ref[k];
2332
2332
  try {
2333
- if (yield v._store.__groupCheck__(time)) {
2333
+ if (yield v._store.__groupCheck__(time2)) {
2334
2334
  results.push(_this3.deleteKey(k));
2335
2335
  } else {
2336
2336
  results.push(void 0);
@@ -4208,7 +4208,7 @@ function HotRivenComponent(data) {
4208
4208
  }
4209
4209
  __name(HotRivenComponent, "HotRivenComponent");
4210
4210
 
4211
- // src/messages.ts
4211
+ // src/i18n.ts
4212
4212
  var messages = {
4213
4213
  "common.fetchFailed": "内部错误,获取最新信息失败",
4214
4214
  "relic.invalidName": "请提供正确的遗物名称",
@@ -4560,7 +4560,8 @@ async function getWorldState(json) {
4560
4560
  throw new Error("获取游戏信息失败");
4561
4561
  }
4562
4562
  const WorldStateParser = await import("warframe-worldstate-parser");
4563
- return WorldStateParser.WorldState.build(json);
4563
+ return WorldStateParser.WorldState.build(json, { locale: "en", logger: { debug: /* @__PURE__ */ __name(() => {
4564
+ }, "debug") } });
4564
4565
  }
4565
4566
  __name(getWorldState, "getWorldState");
4566
4567
  async function getVoidTraderHistory(data) {
@@ -4853,23 +4854,27 @@ function getVoidTraderItemName(sourceKey) {
4853
4854
  __name(getVoidTraderItemName, "getVoidTraderItemName");
4854
4855
 
4855
4856
  // src/warframe/data/wf/globalWorldState.ts
4857
+ async function adaptFissure(fissure) {
4858
+ const nodeKey = await getSolNodeKey(fissure.nodeKey);
4859
+ const tierName = fissure.tierNum in fissureTierName ? import_warframe_public_export_plus3.dict_zh[fissureTierName[fissure.tierNum]] : fissure.tierNum;
4860
+ return {
4861
+ category: fissure.isStorm ? "rj-fissures" : fissure.isHard ? "sp-fissures" : "fissures",
4862
+ hard: fissure.isHard,
4863
+ activation: fissure.activation?.getTime() ?? 0,
4864
+ expiry: fissure.expiry?.getTime() ?? 0,
4865
+ node: regionToShort(import_warframe_public_export_plus3.ExportRegions[nodeKey], import_warframe_public_export_plus3.dict_zh),
4866
+ tier: String(tierName),
4867
+ tierNum: fissureTierNumToNumber(fissure.tierNum)
4868
+ };
4869
+ }
4870
+ __name(adaptFissure, "adaptFissure");
4856
4871
  var globalWorldState = createAsyncCache(async () => {
4857
4872
  const worldState = await getWorldState();
4858
4873
  const fissures = [];
4859
4874
  const rjFissures = [];
4860
4875
  const spFissures = [];
4861
4876
  for (const fissure of worldState.fissures) {
4862
- const nodeKey = await getSolNodeKey(fissure.nodeKey);
4863
- const tierName = fissure.tierNum in fissureTierName ? import_warframe_public_export_plus3.dict_zh[fissureTierName[fissure.tierNum]] : fissure.tierNum;
4864
- const obj = {
4865
- category: fissure.isStorm ? "rj-fissures" : fissure.isHard ? "sp-fissures" : "fissures",
4866
- hard: fissure.isHard,
4867
- activation: fissure.activation?.getTime() ?? 0,
4868
- expiry: fissure.expiry?.getTime() ?? 0,
4869
- node: regionToShort(import_warframe_public_export_plus3.ExportRegions[nodeKey], import_warframe_public_export_plus3.dict_zh),
4870
- tier: String(tierName),
4871
- tierNum: fissureTierNumToNumber(fissure.tierNum)
4872
- };
4877
+ const obj = await adaptFissure(fissure);
4873
4878
  if (fissure.isStorm) {
4874
4879
  rjFissures.push(obj);
4875
4880
  } else if (fissure.isHard) {
@@ -4882,7 +4887,7 @@ var globalWorldState = createAsyncCache(async () => {
4882
4887
  spFissures.sort((a, b) => a.tierNum - b.tierNum);
4883
4888
  rjFissures.sort((a, b) => a.tierNum - b.tierNum);
4884
4889
  return { raw: worldState, fissures, spFissures, rjFissures };
4885
- }, 12e4);
4890
+ }, -1);
4886
4891
 
4887
4892
  // src/warframe/data/wf/relics.ts
4888
4893
  var import_warframe_public_export_plus4 = require("warframe-public-export-plus");
@@ -6585,6 +6590,144 @@ var primedModHistory = createAsyncCache(async () => {
6585
6590
  return result;
6586
6591
  }, 432e5);
6587
6592
 
6593
+ // src/warframe/services/world-state-refresh.ts
6594
+ function time(value) {
6595
+ return value?.getTime() ?? 0;
6596
+ }
6597
+ __name(time, "time");
6598
+ function fissureId(value) {
6599
+ return value.id ?? [
6600
+ time(value.activation),
6601
+ time(value.expiry),
6602
+ value.node,
6603
+ value.tier,
6604
+ value.isHard,
6605
+ value.isStorm
6606
+ ].join(":");
6607
+ }
6608
+ __name(fissureId, "fissureId");
6609
+ function dailyDealId(value) {
6610
+ return value.id ?? [
6611
+ time(value.activation),
6612
+ time(value.expiry),
6613
+ value.uniqueName ?? value.item
6614
+ ].join(":");
6615
+ }
6616
+ __name(dailyDealId, "dailyDealId");
6617
+ function alertId(value) {
6618
+ return value.id ?? [
6619
+ time(value.activation),
6620
+ time(value.expiry),
6621
+ value.mission?.nodeKey ?? value.mission?.node ?? "",
6622
+ value.tag ?? ""
6623
+ ].join(":");
6624
+ }
6625
+ __name(alertId, "alertId");
6626
+ function traderId(value) {
6627
+ return value.id ?? [
6628
+ time(value.activation),
6629
+ value.character,
6630
+ value.location
6631
+ ].join(":");
6632
+ }
6633
+ __name(traderId, "traderId");
6634
+ function alertReward(alert) {
6635
+ const reward = alert.mission?.reward;
6636
+ if (!reward) {
6637
+ return "";
6638
+ }
6639
+ const values = [
6640
+ ...reward.items,
6641
+ ...reward.countedItems.map((item) => `${item.key} x${item.count}`)
6642
+ ];
6643
+ if (reward.credits) {
6644
+ values.push(`${reward.credits} 现金`);
6645
+ }
6646
+ return values.join("、");
6647
+ }
6648
+ __name(alertReward, "alertReward");
6649
+ async function diffWorldStates(previous, current) {
6650
+ const notifications = [];
6651
+ const previousFissures = new Set(previous.raw.fissures.map(fissureId));
6652
+ for (const fissure of current.raw.fissures) {
6653
+ const id = fissureId(fissure);
6654
+ if (!previousFissures.has(id)) {
6655
+ const mapped = await adaptFissure(fissure);
6656
+ notifications.push({
6657
+ type: "fissure",
6658
+ id,
6659
+ tier: mapped.tier,
6660
+ tierNum: mapped.tierNum,
6661
+ node: mapped.node,
6662
+ hard: mapped.hard,
6663
+ category: fissure.isStorm ? "railjack" : fissure.isHard ? "steel-path" : "normal",
6664
+ expiry: time(fissure.expiry)
6665
+ });
6666
+ }
6667
+ }
6668
+ const previousTimestamp = previous.raw.timestamp.getTime();
6669
+ const currentTimestamp = current.raw.timestamp.getTime();
6670
+ for (const trader of current.raw.voidTraders) {
6671
+ const activation = time(trader.activation);
6672
+ if (activation > previousTimestamp && activation <= currentTimestamp) {
6673
+ notifications.push({
6674
+ type: "void-trader",
6675
+ id: traderId(trader),
6676
+ character: trader.character,
6677
+ location: trader.location,
6678
+ expiry: time(trader.expiry)
6679
+ });
6680
+ }
6681
+ }
6682
+ const previousDeals = new Set(previous.raw.dailyDeals.map(dailyDealId));
6683
+ for (const deal of current.raw.dailyDeals) {
6684
+ const id = dailyDealId(deal);
6685
+ if (!previousDeals.has(id)) {
6686
+ notifications.push({
6687
+ type: "daily-deal",
6688
+ id,
6689
+ item: deal.item,
6690
+ originalPrice: deal.originalPrice,
6691
+ salePrice: deal.salePrice,
6692
+ discount: deal.discount,
6693
+ expiry: time(deal.expiry)
6694
+ });
6695
+ }
6696
+ }
6697
+ const previousAlerts = new Set(previous.raw.alerts.map(alertId));
6698
+ for (const alert of current.raw.alerts) {
6699
+ const id = alertId(alert);
6700
+ if (!previousAlerts.has(id)) {
6701
+ notifications.push({
6702
+ type: "alert",
6703
+ id,
6704
+ description: alert.description,
6705
+ node: alert.mission?.node ?? "",
6706
+ missionType: alert.mission?.type ?? "",
6707
+ reward: alertReward(alert),
6708
+ expiry: time(alert.expiry)
6709
+ });
6710
+ }
6711
+ }
6712
+ return notifications;
6713
+ }
6714
+ __name(diffWorldStates, "diffWorldStates");
6715
+ function createWorldStateRefresher(source = globalWorldState) {
6716
+ let previous;
6717
+ return async () => {
6718
+ const current = await source.update();
6719
+ if (!previous) {
6720
+ previous = current;
6721
+ return [];
6722
+ }
6723
+ const notifications = await diffWorldStates(previous, current);
6724
+ previous = current;
6725
+ return notifications;
6726
+ };
6727
+ }
6728
+ __name(createWorldStateRefresher, "createWorldStateRefresher");
6729
+ var refreshWorldState = createWorldStateRefresher();
6730
+
6588
6731
  // src/commands/miscs.ts
6589
6732
  function inDevelopment() {
6590
6733
  return t("miscs.inDevelopment");
@@ -8942,50 +9085,7 @@ function createWfmCommands(deps) {
8942
9085
  }
8943
9086
  __name(createWfmCommands, "createWfmCommands");
8944
9087
 
8945
- // src/index.ts
8946
- var import_reflect_metadata = __toESM(require_Reflect());
8947
- var name = "warframe";
8948
- var inject = {
8949
- required: ["puppeteer"]
8950
- };
8951
- var Config = import_koishi2.Schema.object({
8952
- developerMode: import_koishi2.Schema.boolean().default(false),
8953
- ocrAPISecret: import_koishi2.Schema.object({
8954
- id: import_koishi2.Schema.string(),
8955
- key: import_koishi2.Schema.string()
8956
- }).description("OCR API 密钥")
8957
- });
8958
- function apply(ctx) {
8959
- const deps = {
8960
- config: ctx.config,
8961
- logger: ctx.logger("koishi-plugin-warframe"),
8962
- render: /* @__PURE__ */ __name(async (e) => generateImageOutput(ctx.puppeteer, e), "render")
8963
- };
8964
- setupHooks(ctx, deps);
8965
- setupCommands(ctx, deps);
8966
- }
8967
- __name(apply, "apply");
8968
- function setupHooks(ctx, deps) {
8969
- const { config, logger } = deps;
8970
- ctx.on("message", (session) => {
8971
- if (config.developerMode) {
8972
- logger.info(
8973
- `Koishi recieved message: ${session.content}
8974
- Platform: ${session.platform}
8975
- User: ${session.author.name}`
8976
- );
8977
- }
8978
- });
8979
- ctx.on("command/before-execute", (action) => {
8980
- if (config.developerMode) {
8981
- logger.info(
8982
- `WFM Plugin received command ${action.command?.name}
8983
- arguments: ${JSON.stringify(action.args)}`
8984
- );
8985
- }
8986
- });
8987
- }
8988
- __name(setupHooks, "setupHooks");
9088
+ // src/commands/index.ts
8989
9089
  function setupCommands(ctx, deps) {
8990
9090
  const wf = createWfCommands(deps);
8991
9091
  const wfm = createWfmCommands(deps);
@@ -9017,6 +9117,153 @@ function setupCommands(ctx, deps) {
9017
9117
  ctx.command("pmod-history", "Primed MOD 历史").alias("pmodhistory").alias("pmod").alias("P卡").alias("p卡").alias("P卡历史").alias("p卡历史").action(wfm.pmodhistoryCommand);
9018
9118
  }
9019
9119
  __name(setupCommands, "setupCommands");
9120
+
9121
+ // src/hooks/index.ts
9122
+ function setupHooks(ctx, deps) {
9123
+ const { config, logger } = deps;
9124
+ ctx.on("message", (session) => {
9125
+ if (config.developerMode) {
9126
+ logger.info(
9127
+ `Koishi recieved message: ${session.content}
9128
+ Platform: ${session.platform}
9129
+ User: ${session.author.name}`
9130
+ );
9131
+ }
9132
+ });
9133
+ ctx.on("command/before-execute", (action) => {
9134
+ if (config.developerMode) {
9135
+ logger.info(
9136
+ `WFM Plugin received command ${action.command?.name}
9137
+ arguments: ${JSON.stringify(action.args)}`
9138
+ );
9139
+ }
9140
+ });
9141
+ }
9142
+ __name(setupHooks, "setupHooks");
9143
+
9144
+ // src/schedules/pmod-history.ts
9145
+ function setupPrimedModHistorySchedule(ctx, deps, refresh = async () => primedModHistory.update()) {
9146
+ const run = /* @__PURE__ */ __name(async () => {
9147
+ try {
9148
+ await refresh();
9149
+ } catch (error) {
9150
+ deps.logger.warn("刷新 Primed MOD 历史缓存失败", error);
9151
+ }
9152
+ }, "run");
9153
+ ctx.cron("0 0 0,6,12,18 * * *", () => {
9154
+ void run();
9155
+ });
9156
+ }
9157
+ __name(setupPrimedModHistorySchedule, "setupPrimedModHistorySchedule");
9158
+
9159
+ // src/messages/world-state.tsx
9160
+ var import_jsx_runtime5 = require("@satorijs/element/jsx-runtime");
9161
+ function formatExpiry(expiry) {
9162
+ if (!expiry) {
9163
+ return "";
9164
+ }
9165
+ return new Date(expiry).toLocaleString("zh-CN", {
9166
+ hour12: false,
9167
+ timeZone: "Asia/Shanghai"
9168
+ });
9169
+ }
9170
+ __name(formatExpiry, "formatExpiry");
9171
+ function suffixWithExpiry(expiry) {
9172
+ const formatted = formatExpiry(expiry);
9173
+ return formatted ? `,截止 ${formatted}` : "";
9174
+ }
9175
+ __name(suffixWithExpiry, "suffixWithExpiry");
9176
+ function suffixWithTimeRemaining(expiry) {
9177
+ return expiry > Date.now() ? `剩余${msToHumanReadable(expiry - Date.now())}` : "";
9178
+ }
9179
+ __name(suffixWithTimeRemaining, "suffixWithTimeRemaining");
9180
+ async function createWorldStateMessages(items) {
9181
+ const messages2 = [];
9182
+ const push = /* @__PURE__ */ __name(async (title, lines) => {
9183
+ if (lines.length) {
9184
+ messages2.push(/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("message", { children: [
9185
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: `${title}
9186
+ ` }),
9187
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: lines.join("\n") })
9188
+ ] }));
9189
+ }
9190
+ }, "push");
9191
+ await push("新的虚空裂隙已出现:", items.filter((item) => item.type === "fissure").map((item) => {
9192
+ const category = item.category === "steel-path" ? "[钢铁]" : item.category === "railjack" ? "[九重天]" : "[普通]";
9193
+ const faction = item.node.faction ? `${item.node.faction}` : "";
9194
+ return `${category}${item.tier} - ${item.node.system} (${item.node.type}) ${faction} ${item.node.name} | ${suffixWithTimeRemaining(item.expiry)}`;
9195
+ }));
9196
+ await push("虚空商人到达", items.filter((item) => item.type === "void-trader").map((item) => `${item.character} 已到达 ${item.location}${suffixWithExpiry(item.expiry)}`));
9197
+ await push("新每日特惠", items.filter((item) => item.type === "daily-deal").map((item) => `${item.item}:${item.salePrice} 白金(-${item.discount}%,原价 ${item.originalPrice})${suffixWithExpiry(item.expiry)}`));
9198
+ await push("新警报", items.filter((item) => item.type === "alert").map((item) => {
9199
+ const reward = item.reward ? ` | 奖励:${item.reward}` : "";
9200
+ return `${item.description} | ${item.node} ${item.missionType}${reward}${suffixWithExpiry(item.expiry)}`;
9201
+ }));
9202
+ return messages2;
9203
+ }
9204
+ __name(createWorldStateMessages, "createWorldStateMessages");
9205
+
9206
+ // src/schedules/world-state.ts
9207
+ function setupWorldStateSchedule(ctx, deps, refresh = refreshWorldState) {
9208
+ let running = false;
9209
+ const run = /* @__PURE__ */ __name(async () => {
9210
+ if (running) {
9211
+ return;
9212
+ }
9213
+ running = true;
9214
+ try {
9215
+ const messages2 = await createWorldStateMessages(await refresh());
9216
+ const channels = Object.values(deps.config.channelIds);
9217
+ if (!channels.length) {
9218
+ return;
9219
+ }
9220
+ for (const message of messages2) {
9221
+ await ctx.broadcast(channels, message);
9222
+ }
9223
+ } catch (error) {
9224
+ deps.logger.warn(error, "刷新 Warframe 世界状态失败");
9225
+ } finally {
9226
+ running = false;
9227
+ }
9228
+ }, "run");
9229
+ ctx.cron("0 */5 * * * *", () => {
9230
+ void run();
9231
+ });
9232
+ }
9233
+ __name(setupWorldStateSchedule, "setupWorldStateSchedule");
9234
+
9235
+ // src/schedules/index.ts
9236
+ function setupSchedules(ctx, deps) {
9237
+ setupWorldStateSchedule(ctx, deps);
9238
+ setupPrimedModHistorySchedule(ctx, deps);
9239
+ }
9240
+ __name(setupSchedules, "setupSchedules");
9241
+
9242
+ // src/index.ts
9243
+ var import_reflect_metadata = __toESM(require_Reflect());
9244
+ var name = "warframe";
9245
+ var inject = {
9246
+ required: ["cron", "database", "puppeteer"]
9247
+ };
9248
+ var Config = import_koishi2.Schema.object({
9249
+ channelIds: import_koishi2.Schema.dict(import_koishi2.Schema.string()).default({}).description("用于接收推送的`channelId`列表, 需携带平台前缀, 如:`qq:123456789`"),
9250
+ developerMode: import_koishi2.Schema.boolean().default(false),
9251
+ ocrAPISecret: import_koishi2.Schema.object({
9252
+ id: import_koishi2.Schema.string(),
9253
+ key: import_koishi2.Schema.string()
9254
+ }).description("OCR API 密钥")
9255
+ });
9256
+ function apply(ctx) {
9257
+ const deps = {
9258
+ config: ctx.config,
9259
+ logger: ctx.logger("koishi-plugin-warframe"),
9260
+ render: /* @__PURE__ */ __name(async (e) => generateImageOutput(ctx.puppeteer, e), "render")
9261
+ };
9262
+ setupHooks(ctx, deps);
9263
+ setupCommands(ctx, deps);
9264
+ setupSchedules(ctx, deps);
9265
+ }
9266
+ __name(apply, "apply");
9020
9267
  // Annotate the CommonJS export names for ESM import in node:
9021
9268
  0 && (module.exports = {
9022
9269
  Config,