wikimasters-cli 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +125 -2
- package/dist/cli/config.js +47 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/main.js +10 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/output.js +297 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/pasted-session.js +49 -0
- package/dist/cli/pasted-session.js.map +1 -0
- package/dist/cli/program.js +334 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/session.js +30 -0
- package/dist/cli/session.js.map +1 -0
- package/dist/core/auction-bids.js +31 -0
- package/dist/core/auction-bids.js.map +1 -0
- package/dist/core/auction-cancel.js +17 -0
- package/dist/core/auction-cancel.js.map +1 -0
- package/dist/core/auction-create.js +40 -0
- package/dist/core/auction-create.js.map +1 -0
- package/dist/core/auction-list.js +16 -0
- package/dist/core/auction-list.js.map +1 -0
- package/dist/core/auction-search.js +38 -0
- package/dist/core/auction-search.js.map +1 -0
- package/dist/core/auction.js +79 -0
- package/dist/core/auction.js.map +1 -0
- package/dist/core/auth-cookie.js +50 -0
- package/dist/core/auth-cookie.js.map +1 -0
- package/dist/core/browser-login.js +81 -0
- package/dist/core/browser-login.js.map +1 -0
- package/dist/core/card-id.js +5 -0
- package/dist/core/card-id.js.map +1 -0
- package/dist/core/card-search.js +51 -0
- package/dist/core/card-search.js.map +1 -0
- package/dist/core/card-value.js +43 -0
- package/dist/core/card-value.js.map +1 -0
- package/dist/core/collection-list.js +44 -0
- package/dist/core/collection-list.js.map +1 -0
- package/dist/core/collection.js +46 -0
- package/dist/core/collection.js.map +1 -0
- package/dist/core/entry-id.js +4 -0
- package/dist/core/entry-id.js.map +1 -0
- package/dist/core/errors.js +28 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/favourite.js +27 -0
- package/dist/core/favourite.js.map +1 -0
- package/dist/core/global-collection.js +58 -0
- package/dist/core/global-collection.js.map +1 -0
- package/dist/core/index.js +26 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/integer.js +15 -0
- package/dist/core/integer.js.map +1 -0
- package/dist/core/label.js +39 -0
- package/dist/core/label.js.map +1 -0
- package/dist/core/notification-list.js +32 -0
- package/dist/core/notification-list.js.map +1 -0
- package/dist/core/page.js +22 -0
- package/dist/core/page.js.map +1 -0
- package/dist/core/profile-collection.js +45 -0
- package/dist/core/profile-collection.js.map +1 -0
- package/dist/core/session.js +49 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/site.js +52 -0
- package/dist/core/site.js.map +1 -0
- package/dist/core/supabase.js +5 -0
- package/dist/core/supabase.js.map +1 -0
- package/dist/core/table-query.js +21 -0
- package/dist/core/table-query.js.map +1 -0
- package/dist/core/tag.js +25 -0
- package/dist/core/tag.js.map +1 -0
- package/dist/core/transient.js +40 -0
- package/dist/core/transient.js.map +1 -0
- package/dist/core/uuid.js +10 -0
- package/dist/core/uuid.js.map +1 -0
- package/dist/core/wishlist.js +66 -0
- package/dist/core/wishlist.js.map +1 -0
- package/package.json +42 -4
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { WikiMastersError, apiFailure } from "./errors.js";
|
|
2
|
+
import { parseStrictlyPositiveInteger } from "./integer.js";
|
|
3
|
+
import { siteCookie, siteRequest } from "./site.js";
|
|
4
|
+
import { parseUuid } from "./uuid.js";
|
|
5
|
+
export const AUCTION_LIMIT = 50;
|
|
6
|
+
export const AUCTION_COLUMNS = "status, end_at, seller_id, base_amount, current_bid, current_bidder_id, snapshot_rarity, is_shiny, cards(wikipedia_title)";
|
|
7
|
+
export function parseAuctionId(raw) {
|
|
8
|
+
return parseUuid(raw, "auction");
|
|
9
|
+
}
|
|
10
|
+
export function parseAuctionLimit(raw) {
|
|
11
|
+
return parseStrictlyPositiveInteger(raw, {
|
|
12
|
+
subject: "limit",
|
|
13
|
+
untouched: "nothing was read",
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function parseBidAmount(raw) {
|
|
17
|
+
return parseStrictlyPositiveInteger(raw, {
|
|
18
|
+
subject: "bid amount",
|
|
19
|
+
unit: "wikibidous",
|
|
20
|
+
untouched: "nothing was bid",
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export function auctionedTitle(auctionId, { cards }) {
|
|
24
|
+
if (!cards) {
|
|
25
|
+
throw new WikiMastersError(`Auction ${auctionId} has no readable card details`);
|
|
26
|
+
}
|
|
27
|
+
return cards.wikipedia_title;
|
|
28
|
+
}
|
|
29
|
+
export function leads(session, { current_bidder_id }) {
|
|
30
|
+
return current_bidder_id === session.userId;
|
|
31
|
+
}
|
|
32
|
+
async function readAuction(session, auctionId) {
|
|
33
|
+
const { data, error, status } = await session.client
|
|
34
|
+
.from("auctions")
|
|
35
|
+
.select(AUCTION_COLUMNS)
|
|
36
|
+
.eq("id", auctionId)
|
|
37
|
+
.maybeSingle()
|
|
38
|
+
.overrideTypes();
|
|
39
|
+
if (error) {
|
|
40
|
+
throw apiFailure("Reading the auction", status, error.message);
|
|
41
|
+
}
|
|
42
|
+
if (!data)
|
|
43
|
+
throw new WikiMastersError(`Auction ${auctionId} not found`);
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
46
|
+
export function toAuction(session, auctionId, row) {
|
|
47
|
+
return {
|
|
48
|
+
auctionId,
|
|
49
|
+
title: auctionedTitle(auctionId, row),
|
|
50
|
+
rarity: row.snapshot_rarity,
|
|
51
|
+
shiny: row.is_shiny,
|
|
52
|
+
status: row.status,
|
|
53
|
+
endsAt: row.end_at,
|
|
54
|
+
startingPrice: row.base_amount,
|
|
55
|
+
currentBid: row.current_bid,
|
|
56
|
+
leading: leads(session, row),
|
|
57
|
+
selling: row.seller_id === session.userId,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export async function showAuction(session, auctionId) {
|
|
61
|
+
return toAuction(session, auctionId, await readAuction(session, auctionId));
|
|
62
|
+
}
|
|
63
|
+
function isBidResponse(body) {
|
|
64
|
+
return (typeof body === "object" &&
|
|
65
|
+
body !== null &&
|
|
66
|
+
"current_bid" in body &&
|
|
67
|
+
typeof body.current_bid === "number" &&
|
|
68
|
+
"bidder_balance" in body &&
|
|
69
|
+
typeof body.bidder_balance === "number");
|
|
70
|
+
}
|
|
71
|
+
export async function placeBid(session, auctionId, amount) {
|
|
72
|
+
const action = "Placing the bid";
|
|
73
|
+
const body = await siteRequest(session, await siteCookie(session), action, `/marketplace/${auctionId}`, `/api/marketplace/${auctionId}/bid`, { method: "POST", body: { amount } });
|
|
74
|
+
if (!isBidResponse(body)) {
|
|
75
|
+
throw new WikiMastersError(`${action} returned an unexpected response: ${JSON.stringify(body)}`);
|
|
76
|
+
}
|
|
77
|
+
return { auctionId, amount: body.current_bid, balance: body.bidder_balance };
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=auction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auction.js","sourceRoot":"","sources":["../../src/core/auction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { WikiMastersError } from "./errors.js";
|
|
2
|
+
import { SUPABASE_PROJECT_REF } from "./supabase.js";
|
|
3
|
+
export const AUTH_COOKIE_NAME = `sb-${SUPABASE_PROJECT_REF}-auth-token`;
|
|
4
|
+
const BASE64_PREFIX = "base64-";
|
|
5
|
+
function authCookieChunks(cookies) {
|
|
6
|
+
const byName = new Map(cookies.map(({ name, value }) => [name, value]));
|
|
7
|
+
const whole = byName.get(AUTH_COOKIE_NAME);
|
|
8
|
+
if (whole)
|
|
9
|
+
return [whole];
|
|
10
|
+
const chunks = [];
|
|
11
|
+
for (let index = 0; byName.has(`${AUTH_COOKIE_NAME}.${index}`); index++) {
|
|
12
|
+
chunks.push(byName.get(`${AUTH_COOKIE_NAME}.${index}`) ?? "");
|
|
13
|
+
}
|
|
14
|
+
return chunks.length > 0 ? chunks : undefined;
|
|
15
|
+
}
|
|
16
|
+
function decodeSession(raw) {
|
|
17
|
+
const json = raw.startsWith(BASE64_PREFIX)
|
|
18
|
+
? Buffer.from(raw.slice(BASE64_PREFIX.length), "base64url").toString("utf8")
|
|
19
|
+
: decodeURIComponent(raw);
|
|
20
|
+
return JSON.parse(json);
|
|
21
|
+
}
|
|
22
|
+
export function refreshTokenFromAuthCookies(cookies) {
|
|
23
|
+
const chunks = authCookieChunks(cookies);
|
|
24
|
+
return chunks === undefined
|
|
25
|
+
? undefined
|
|
26
|
+
: refreshTokenFromAuthCookieChunks(chunks);
|
|
27
|
+
}
|
|
28
|
+
export function refreshTokenFromAuthCookieChunks(chunks) {
|
|
29
|
+
let session;
|
|
30
|
+
try {
|
|
31
|
+
session = decodeSession(chunks.join(""));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
session = undefined;
|
|
35
|
+
}
|
|
36
|
+
if (typeof session !== "object" ||
|
|
37
|
+
session === null ||
|
|
38
|
+
!("refresh_token" in session) ||
|
|
39
|
+
typeof session.refresh_token !== "string" ||
|
|
40
|
+
session.refresh_token === "") {
|
|
41
|
+
throw new WikiMastersError(`The ${AUTH_COOKIE_NAME} cookie holds no refresh token: check that every chunk is there, in order`);
|
|
42
|
+
}
|
|
43
|
+
return session.refresh_token;
|
|
44
|
+
}
|
|
45
|
+
// @supabase/ssr reads the unchunked cookie before any `.N` chunk; its 3180-byte chunk limit only matters to browsers.
|
|
46
|
+
export function authCookieHeader(session) {
|
|
47
|
+
const encoded = Buffer.from(JSON.stringify(session), "utf8").toString("base64url");
|
|
48
|
+
return `${AUTH_COOKIE_NAME}=${BASE64_PREFIX}${encoded}`;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=auth-cookie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-cookie.js","sourceRoot":"","sources":["../../src/core/auth-cookie.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,aAAa,CAAC;AAExE,MAAM,aAAa,GAAG,SAAS,CAAC;AAOhC,SAAS,gBAAgB,CAAC,OAA0B;IAClD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC3C,IAAI,KAAK;QAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAE1B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,gBAAgB,IAAI,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACxE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,gBAAgB,IAAI,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC;QACxC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC5E,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,OAA0B;IAE1B,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,gCAAgC,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC9C,MAAyB;IAEzB,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,SAAS,CAAC;IACtB,CAAC;IACD,IACE,OAAO,OAAO,KAAK,QAAQ;QAC3B,OAAO,KAAK,IAAI;QAChB,CAAC,CAAC,eAAe,IAAI,OAAO,CAAC;QAC7B,OAAO,OAAO,CAAC,aAAa,KAAK,QAAQ;QACzC,OAAO,CAAC,aAAa,KAAK,EAAE,EAC5B,CAAC;QACD,MAAM,IAAI,gBAAgB,CACxB,OAAO,gBAAgB,2EAA2E,CACnG,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,aAAa,CAAC;AAC/B,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CACnE,WAAW,CACZ,CAAC;IACF,OAAO,GAAG,gBAAgB,IAAI,aAAa,GAAG,OAAO,EAAE,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { copyFileSync, existsSync, mkdtempSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { DatabaseSync } from "node:sqlite";
|
|
6
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
7
|
+
import { AUTH_COOKIE_NAME, refreshTokenFromAuthCookies, } from "./auth-cookie.js";
|
|
8
|
+
import { WikiMastersError } from "./errors.js";
|
|
9
|
+
import { SITE_URL } from "./supabase.js";
|
|
10
|
+
export const FIREFOX_BINARY = "/Applications/Firefox.app/Contents/MacOS/firefox";
|
|
11
|
+
const COOKIES_DB = "cookies.sqlite";
|
|
12
|
+
const PROFILE_PREFS = [
|
|
13
|
+
'user_pref("browser.shell.checkDefaultBrowser", false);',
|
|
14
|
+
'user_pref("browser.aboutwelcome.enabled", false);',
|
|
15
|
+
'user_pref("browser.startup.homepage_override.mstone", "ignore");',
|
|
16
|
+
'user_pref("datareporting.policy.dataSubmissionPolicyBypassNotification", true);',
|
|
17
|
+
];
|
|
18
|
+
export function readRefreshTokenFromFirefoxProfile(profileDir) {
|
|
19
|
+
const database = join(profileDir, COOKIES_DB);
|
|
20
|
+
if (!existsSync(database))
|
|
21
|
+
return undefined;
|
|
22
|
+
const snapshot = mkdtempSync(join(tmpdir(), "wikimasters-cookies-"));
|
|
23
|
+
try {
|
|
24
|
+
for (const suffix of ["", "-wal"]) {
|
|
25
|
+
if (existsSync(database + suffix))
|
|
26
|
+
copyFileSync(database + suffix, join(snapshot, COOKIES_DB + suffix));
|
|
27
|
+
}
|
|
28
|
+
const db = new DatabaseSync(join(snapshot, COOKIES_DB));
|
|
29
|
+
try {
|
|
30
|
+
const cookies = db
|
|
31
|
+
.prepare("SELECT name, value FROM moz_cookies WHERE host LIKE '%wiki-masters.com' AND name LIKE ? || '%'")
|
|
32
|
+
.all(AUTH_COOKIE_NAME)
|
|
33
|
+
.map(({ name, value }) => ({
|
|
34
|
+
name: String(name),
|
|
35
|
+
value: String(value),
|
|
36
|
+
}));
|
|
37
|
+
return refreshTokenFromAuthCookies(cookies);
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
db.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
rmSync(snapshot, { recursive: true, force: true });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function loginInBrowser({ firefoxBinary = FIREFOX_BINARY, timeoutMs = 5 * 60_000, pollIntervalMs = 1000, } = {}) {
|
|
51
|
+
const profileDir = mkdtempSync(join(tmpdir(), "wikimasters-firefox-"));
|
|
52
|
+
writeFileSync(join(profileDir, "user.js"), `${PROFILE_PREFS.join("\n")}\n`);
|
|
53
|
+
const firefox = spawn(firefoxBinary, ["--no-remote", "--profile", profileDir, `${SITE_URL}/login`], { stdio: "ignore" });
|
|
54
|
+
let exited = false;
|
|
55
|
+
const exit = new Promise((resolve) => firefox.once("close", () => resolve()));
|
|
56
|
+
void exit.then(() => (exited = true));
|
|
57
|
+
const launchFailure = new Promise((_, reject) => firefox.once("error", (error) => reject(new WikiMastersError(`Cannot start Firefox at ${firefoxBinary}: ${error.message}`))));
|
|
58
|
+
try {
|
|
59
|
+
return await Promise.race([launchFailure, pollForSession()]);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
if (!exited)
|
|
63
|
+
firefox.kill();
|
|
64
|
+
await exit;
|
|
65
|
+
rmSync(profileDir, { recursive: true, force: true });
|
|
66
|
+
}
|
|
67
|
+
async function pollForSession() {
|
|
68
|
+
const deadline = Date.now() + timeoutMs;
|
|
69
|
+
while (Date.now() < deadline) {
|
|
70
|
+
const closed = exited;
|
|
71
|
+
const refreshToken = readRefreshTokenFromFirefoxProfile(profileDir);
|
|
72
|
+
if (refreshToken)
|
|
73
|
+
return refreshToken;
|
|
74
|
+
if (closed)
|
|
75
|
+
throw new WikiMastersError("Firefox was closed before signing in");
|
|
76
|
+
await sleep(pollIntervalMs);
|
|
77
|
+
}
|
|
78
|
+
throw new WikiMastersError(`No sign-in within ${Math.round(timeoutMs / 1000)} s`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=browser-login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-login.js","sourceRoot":"","sources":["../../src/core/browser-login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card-id.js","sourceRoot":"","sources":["../../src/core/card-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,SAAS,CAAC,GAAG,EAAE,MAAM,CAAW,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { apiFailure, WikiMastersError } from "./errors.js";
|
|
2
|
+
export const CARD_SEARCH_LIMIT = 50;
|
|
3
|
+
export const CARD_SEARCH_FIELDS = ["title", "category", "summary"];
|
|
4
|
+
const SEARCHED_COLUMNS = {
|
|
5
|
+
title: "wikipedia_title",
|
|
6
|
+
category: "category",
|
|
7
|
+
summary: "summary",
|
|
8
|
+
};
|
|
9
|
+
function isCardSearchField(raw) {
|
|
10
|
+
return CARD_SEARCH_FIELDS.includes(raw);
|
|
11
|
+
}
|
|
12
|
+
export function parseCardSearchField(raw) {
|
|
13
|
+
if (!isCardSearchField(raw)) {
|
|
14
|
+
throw new WikiMastersError(`Invalid field: ${JSON.stringify(raw)} is not one of ${CARD_SEARCH_FIELDS.join(", ")}; nothing was read`);
|
|
15
|
+
}
|
|
16
|
+
return raw;
|
|
17
|
+
}
|
|
18
|
+
// PostgREST turns every `*` of a like pattern into `%`, escaped or not
|
|
19
|
+
// (https://docs.postgrest.org/en/stable/references/api/tables_views.html#operators).
|
|
20
|
+
function likePattern(text) {
|
|
21
|
+
return text.replace(/[\\%_]/g, "\\$&").replaceAll("*", "_");
|
|
22
|
+
}
|
|
23
|
+
function regexLiteral(text) {
|
|
24
|
+
return text.replace(/[\\^$.|?*+()[\]{}]/g, "\\$&");
|
|
25
|
+
}
|
|
26
|
+
export async function searchCards(session, text, field) {
|
|
27
|
+
const column = SEARCHED_COLUMNS[field];
|
|
28
|
+
const { data, error, status } = await session.client
|
|
29
|
+
.from("cards")
|
|
30
|
+
.select("id, wikipedia_title, rarity")
|
|
31
|
+
.ilike(column, `%${likePattern(text)}%`)
|
|
32
|
+
.filter(column, "imatch", regexLiteral(text))
|
|
33
|
+
.order("wikipedia_title")
|
|
34
|
+
.order("id")
|
|
35
|
+
.limit(CARD_SEARCH_LIMIT + 1)
|
|
36
|
+
.overrideTypes();
|
|
37
|
+
if (error) {
|
|
38
|
+
throw apiFailure("Searching the card catalogue", status, error.message);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
cards: data
|
|
42
|
+
.slice(0, CARD_SEARCH_LIMIT)
|
|
43
|
+
.map(({ id, wikipedia_title, rarity }) => ({
|
|
44
|
+
id: id,
|
|
45
|
+
title: wikipedia_title,
|
|
46
|
+
rarity,
|
|
47
|
+
})),
|
|
48
|
+
truncated: data.length > CARD_SEARCH_LIMIT,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=card-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card-search.js","sourceRoot":"","sources":["../../src/core/card-search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAEpC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AAI5E,MAAM,gBAAgB,GAAG;IACvB,KAAK,EAAE,iBAAiB;IACxB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;CACgC,CAAC;AAErD,SAAS,iBAAiB,CAAC,GAAW;IACpC,OAAQ,kBAAwC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,gBAAgB,CACxB,kBAAkB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CACzG,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAmBD,uEAAuE;AACvE,qFAAqF;AACrF,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAgB,EAChB,IAAY,EACZ,KAAsB;IAEtB,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,MAAM;SACjD,IAAI,CAAC,OAAO,CAAC;SACb,MAAM,CAAC,6BAA6B,CAAC;SACrC,KAAK,CAAC,MAAM,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;SACvC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;SAC5C,KAAK,CAAC,iBAAiB,CAAC;SACxB,KAAK,CAAC,IAAI,CAAC;SACX,KAAK,CAAC,iBAAiB,GAAG,CAAC,CAAC;SAC5B,aAAa,EAA+B,CAAC;IAChD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,CAAC,8BAA8B,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO;QACL,KAAK,EAAE,IAAI;aACR,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC;aAC3B,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;YACzC,EAAE,EAAE,EAAY;YAChB,KAAK,EAAE,eAAe;YACtB,MAAM;SACP,CAAC,CAAC;QACL,SAAS,EAAE,IAAI,CAAC,MAAM,GAAG,iBAAiB;KAC3C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { COLLECTION_PAGE } from "./collection.js";
|
|
2
|
+
import { WikiMastersError } from "./errors.js";
|
|
3
|
+
import { siteCookie, siteRequest } from "./site.js";
|
|
4
|
+
function isRarityAverage(value) {
|
|
5
|
+
return (typeof value === "object" &&
|
|
6
|
+
value !== null &&
|
|
7
|
+
"average" in value &&
|
|
8
|
+
typeof value.average === "number");
|
|
9
|
+
}
|
|
10
|
+
function isSalesSummaryResponse(body) {
|
|
11
|
+
return (typeof body === "object" &&
|
|
12
|
+
body !== null &&
|
|
13
|
+
"wikipedia_title" in body &&
|
|
14
|
+
typeof body.wikipedia_title === "string" &&
|
|
15
|
+
"summary" in body &&
|
|
16
|
+
typeof body.summary === "object" &&
|
|
17
|
+
body.summary !== null &&
|
|
18
|
+
Object.values(body.summary).every(isRarityAverage));
|
|
19
|
+
}
|
|
20
|
+
async function readCardValue(session, cookie, cardId) {
|
|
21
|
+
const action = `Reading the sales of card ${cardId}`;
|
|
22
|
+
const body = await siteRequest(session, cookie, action, COLLECTION_PAGE, `/api/marketplace/cards/${cardId}/sales?scope=summary`, { method: "GET" });
|
|
23
|
+
if (!isSalesSummaryResponse(body)) {
|
|
24
|
+
throw new WikiMastersError(`${action} returned an unexpected response: ${JSON.stringify(body)}`);
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
id: cardId,
|
|
28
|
+
title: body.wikipedia_title,
|
|
29
|
+
averages: Object.fromEntries(Object.entries(body.summary).map(([rarity, { average }]) => [
|
|
30
|
+
rarity,
|
|
31
|
+
average,
|
|
32
|
+
])),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export async function readCardValues(session, cardIds) {
|
|
36
|
+
const cookie = await siteCookie(session);
|
|
37
|
+
const values = [];
|
|
38
|
+
for (const cardId of cardIds) {
|
|
39
|
+
values.push(await readCardValue(session, cookie, cardId));
|
|
40
|
+
}
|
|
41
|
+
return values;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=card-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card-value.js","sourceRoot":"","sources":["../../src/core/card-value.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAapD,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,SAAS,IAAI,KAAK;QAClB,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAClC,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAa;IAC3C,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,iBAAiB,IAAI,IAAI;QACzB,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ;QACxC,SAAS,IAAI,IAAI;QACjB,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;QAChC,IAAI,CAAC,OAAO,KAAK,IAAI;QACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CACnD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,OAAgB,EAChB,MAAc,EACd,MAAc;IAEd,MAAM,MAAM,GAAG,6BAA6B,MAAM,EAAE,CAAC;IACrD,MAAM,IAAI,GAAG,MAAM,WAAW,CAC5B,OAAO,EACP,MAAM,EACN,MAAM,EACN,eAAe,EACf,0BAA0B,MAAM,sBAAsB,EACtD,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAC;IACF,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,gBAAgB,CACxB,GAAG,MAAM,qCAAqC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CACrE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,IAAI,CAAC,eAAe;QAC3B,QAAQ,EAAE,MAAM,CAAC,WAAW,CAC1B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1D,MAAM;YACN,OAAO;SACR,CAAC,CACH;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,OAA0B;IAE1B,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,MAAM,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { WikiMastersError, apiFailure } from "./errors.js";
|
|
2
|
+
import { isFullPage, pageRange } from "./page.js";
|
|
3
|
+
function labelsOf({ card_id, user_card_tags }) {
|
|
4
|
+
return user_card_tags
|
|
5
|
+
.map(({ tags }) => {
|
|
6
|
+
if (!tags) {
|
|
7
|
+
throw new WikiMastersError(`A label of card ${card_id} has no readable name`);
|
|
8
|
+
}
|
|
9
|
+
return tags.name;
|
|
10
|
+
})
|
|
11
|
+
.sort((a, b) => a.localeCompare(b));
|
|
12
|
+
}
|
|
13
|
+
export async function listCollection(session, request, { rarity } = {}) {
|
|
14
|
+
let query = session.client
|
|
15
|
+
.from("user_cards")
|
|
16
|
+
.select("id, card_id, snapshot_title, snapshot_rarity, count, starred, is_shiny, obtained_at, user_card_tags(tags(name))")
|
|
17
|
+
.eq("user_id", session.userId)
|
|
18
|
+
.gt("count", 0);
|
|
19
|
+
if (rarity !== undefined)
|
|
20
|
+
query = query.eq("snapshot_rarity", rarity);
|
|
21
|
+
const [from, to] = pageRange(request);
|
|
22
|
+
const { data, error, status } = await query
|
|
23
|
+
.order("obtained_at")
|
|
24
|
+
.order("id")
|
|
25
|
+
.range(from, to)
|
|
26
|
+
.overrideTypes();
|
|
27
|
+
if (error)
|
|
28
|
+
throw apiFailure("Listing the collection", status, error.message);
|
|
29
|
+
return {
|
|
30
|
+
cards: data.map((row) => ({
|
|
31
|
+
entryId: row.id,
|
|
32
|
+
id: row.card_id,
|
|
33
|
+
title: row.snapshot_title,
|
|
34
|
+
rarity: row.snapshot_rarity,
|
|
35
|
+
copies: row.count,
|
|
36
|
+
starred: row.starred,
|
|
37
|
+
shiny: row.is_shiny,
|
|
38
|
+
labels: labelsOf(row),
|
|
39
|
+
obtainedAt: row.obtained_at,
|
|
40
|
+
})),
|
|
41
|
+
full: isFullPage(data, request.limit),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=collection-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-list.js","sourceRoot":"","sources":["../../src/core/collection-list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAoB,MAAM,WAAW,CAAC;AAoCpE,SAAS,QAAQ,CAAC,EAAE,OAAO,EAAE,cAAc,EAAgB;IACzD,OAAO,cAAc;SAClB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;QAChB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,gBAAgB,CACxB,mBAAmB,OAAO,uBAAuB,CAClD,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,OAAoB,EACpB,EAAE,MAAM,EAAE,GAAqB,EAAE;IAEjC,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM;SACvB,IAAI,CAAC,YAAY,CAAC;SAClB,MAAM,CACL,iHAAiH,CAClH;SACA,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC;SAC7B,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAClB,IAAI,MAAM,KAAK,SAAS;QAAE,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACtE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK;SACxC,KAAK,CAAC,aAAa,CAAC;SACpB,KAAK,CAAC,IAAI,CAAC;SACX,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;SACf,aAAa,EAAoC,CAAC;IACrD,IAAI,KAAK;QAAE,MAAM,UAAU,CAAC,wBAAwB,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAE7E,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACxB,OAAO,EAAE,GAAG,CAAC,EAAE;YACf,EAAE,EAAE,GAAG,CAAC,OAAiB;YACzB,KAAK,EAAE,GAAG,CAAC,cAAc;YACzB,MAAM,EAAE,GAAG,CAAC,eAAe;YAC3B,MAAM,EAAE,GAAG,CAAC,KAAK;YACjB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,KAAK,EAAE,GAAG,CAAC,QAAQ;YACnB,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC;YACrB,UAAU,EAAE,GAAG,CAAC,WAAW;SAC5B,CAAC,CAAC;QACH,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC;KACtC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { asEntryId } from "./entry-id.js";
|
|
2
|
+
import { WikiMastersError } from "./errors.js";
|
|
3
|
+
import { siteCookie, siteRequest } from "./site.js";
|
|
4
|
+
export const COLLECTION_PAGE = "/collection";
|
|
5
|
+
const WIKIBIDOUS_PER_DISCARD = 1;
|
|
6
|
+
function isBulkDiscardResponse(body) {
|
|
7
|
+
return (typeof body === "object" &&
|
|
8
|
+
body !== null &&
|
|
9
|
+
"balance" in body &&
|
|
10
|
+
typeof body.balance === "number" &&
|
|
11
|
+
"discarded_count" in body &&
|
|
12
|
+
typeof body.discarded_count === "number" &&
|
|
13
|
+
"failed" in body &&
|
|
14
|
+
Array.isArray(body.failed) &&
|
|
15
|
+
body.failed.every((failure) => typeof failure === "object" &&
|
|
16
|
+
failure !== null &&
|
|
17
|
+
"card_id" in failure &&
|
|
18
|
+
typeof failure.card_id === "string" &&
|
|
19
|
+
"error" in failure &&
|
|
20
|
+
typeof failure.error === "string"));
|
|
21
|
+
}
|
|
22
|
+
function accountsForEntriesSent(entryIds, response) {
|
|
23
|
+
const sent = new Set(entryIds);
|
|
24
|
+
return (response.discarded_count + response.failed.length === entryIds.length &&
|
|
25
|
+
response.failed.every(({ card_id }) => sent.has(card_id)));
|
|
26
|
+
}
|
|
27
|
+
export async function discardEntries(session, entryIds) {
|
|
28
|
+
if (entryIds.length === 0) {
|
|
29
|
+
throw new WikiMastersError("No entry to discard was given");
|
|
30
|
+
}
|
|
31
|
+
const action = "Discarding entries";
|
|
32
|
+
const body = await siteRequest(session, await siteCookie(session), action, COLLECTION_PAGE, "/api/user-cards/bulk-discard", { method: "POST", body: { card_ids: entryIds } });
|
|
33
|
+
if (!isBulkDiscardResponse(body) || !accountsForEntriesSent(entryIds, body)) {
|
|
34
|
+
throw new WikiMastersError(`${action} returned an unexpected response, which may have discarded some of the ${entryIds.length} entries sent: ${JSON.stringify(body)}`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
discarded: body.discarded_count,
|
|
38
|
+
gained: body.discarded_count * WIKIBIDOUS_PER_DISCARD,
|
|
39
|
+
balance: body.balance,
|
|
40
|
+
failed: body.failed.map(({ card_id, error }) => ({
|
|
41
|
+
entryId: asEntryId(card_id),
|
|
42
|
+
reason: error,
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.js","sourceRoot":"","sources":["../../src/core/collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;AAE7C,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAoBjC,SAAS,qBAAqB,CAAC,IAAa;IAC1C,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,SAAS,IAAI,IAAI;QACjB,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;QAChC,iBAAiB,IAAI,IAAI;QACzB,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ;QACxC,QAAQ,IAAI,IAAI;QAChB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,CAAC,OAAgB,EAAE,EAAE,CACnB,OAAO,OAAO,KAAK,QAAQ;YAC3B,OAAO,KAAK,IAAI;YAChB,SAAS,IAAI,OAAO;YACpB,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;YACnC,OAAO,IAAI,OAAO;YAClB,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CACpC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,QAA4B,EAC5B,QAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,CAAC;IACvC,OAAO,CACL,QAAQ,CAAC,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QACrE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,QAA4B;IAE5B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,gBAAgB,CAAC,+BAA+B,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,MAAM,GAAG,oBAAoB,CAAC;IACpC,MAAM,IAAI,GAAG,MAAM,WAAW,CAC5B,OAAO,EACP,MAAM,UAAU,CAAC,OAAO,CAAC,EACzB,MAAM,EACN,eAAe,EACf,8BAA8B,EAC9B,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CACjD,CAAC;IACF,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,gBAAgB,CACxB,GAAG,MAAM,0EAA0E,QAAQ,CAAC,MAAM,kBAAkB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC3I,CAAC;IACJ,CAAC;IACD,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,eAAe;QAC/B,MAAM,EAAE,IAAI,CAAC,eAAe,GAAG,sBAAsB;QACrD,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YAC/C,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC;YAC3B,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-id.js","sourceRoot":"","sources":["../../src/core/entry-id.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,GAAc,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describeTransientStatus, isTransientStatus } from "./transient.js";
|
|
2
|
+
export class WikiMastersError extends Error {
|
|
3
|
+
name = "WikiMastersError";
|
|
4
|
+
}
|
|
5
|
+
export class AuthRequiredError extends WikiMastersError {
|
|
6
|
+
name = "AuthRequiredError";
|
|
7
|
+
}
|
|
8
|
+
export class ApiUnavailableError extends WikiMastersError {
|
|
9
|
+
name = "ApiUnavailableError";
|
|
10
|
+
}
|
|
11
|
+
export function apiUnavailable(status) {
|
|
12
|
+
return new ApiUnavailableError(`WikiMasters API unavailable (HTTP ${status}: ${describeTransientStatus(status)}), retry later`);
|
|
13
|
+
}
|
|
14
|
+
export function outcomeUnknown(action, status) {
|
|
15
|
+
return new ApiUnavailableError(`WikiMasters API unavailable (HTTP ${status}: ${describeTransientStatus(status)}) after the request was sent: ${action} may have taken effect, check before running the command again`);
|
|
16
|
+
}
|
|
17
|
+
export function isUniqueViolation(error) {
|
|
18
|
+
return error?.code === "23505";
|
|
19
|
+
}
|
|
20
|
+
export function apiFailure(action, status, message) {
|
|
21
|
+
if (status === 401) {
|
|
22
|
+
return new AuthRequiredError(`${action} was rejected: the session is no longer valid`);
|
|
23
|
+
}
|
|
24
|
+
if (isTransientStatus(status))
|
|
25
|
+
return apiUnavailable(status);
|
|
26
|
+
return new WikiMastersError(`${action} failed (HTTP ${status}): ${message}`);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE5E,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,GAAG,kBAAkB,CAAC;CACpC;AAED,MAAM,OAAO,iBAAkB,SAAQ,gBAAgB;IAC5C,IAAI,GAAG,mBAAmB,CAAC;CACrC;AAED,MAAM,OAAO,mBAAoB,SAAQ,gBAAgB;IAC9C,IAAI,GAAG,qBAAqB,CAAC;CACvC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO,IAAI,mBAAmB,CAC5B,qCAAqC,MAAM,KAAK,uBAAuB,CAAC,MAAM,CAAC,gBAAgB,CAChG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,MAAc;IAEd,OAAO,IAAI,mBAAmB,CAC5B,qCAAqC,MAAM,KAAK,uBAAuB,CAAC,MAAM,CAAC,iCAAiC,MAAM,gEAAgE,CACvL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAA+B;IAC/D,OAAO,KAAK,EAAE,IAAI,KAAK,OAAO,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,MAAc,EACd,MAAc,EACd,OAAe;IAEf,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,OAAO,IAAI,iBAAiB,CAC1B,GAAG,MAAM,+CAA+C,CACzD,CAAC;IACJ,CAAC;IACD,IAAI,iBAAiB,CAAC,MAAM,CAAC;QAAE,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7D,OAAO,IAAI,gBAAgB,CAAC,GAAG,MAAM,iBAAiB,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { WikiMastersError, apiFailure } from "./errors.js";
|
|
2
|
+
async function setEntryStarred(session, entryId, starred) {
|
|
3
|
+
const action = starred
|
|
4
|
+
? `Marking entry ${entryId} as favourite`
|
|
5
|
+
: `Removing entry ${entryId} from the favourites`;
|
|
6
|
+
const update = await session.client
|
|
7
|
+
.from("user_cards")
|
|
8
|
+
.update({ starred }, { count: "exact" })
|
|
9
|
+
.eq("id", entryId);
|
|
10
|
+
if (update.error) {
|
|
11
|
+
throw apiFailure(action, update.status, update.error.message);
|
|
12
|
+
}
|
|
13
|
+
if (update.count === null) {
|
|
14
|
+
throw new WikiMastersError(`${action} returned no row count (HTTP ${update.status})`);
|
|
15
|
+
}
|
|
16
|
+
if (update.count === 0) {
|
|
17
|
+
throw new WikiMastersError(`${action} changed no entry: the entry is unknown or not yours; nothing was changed`);
|
|
18
|
+
}
|
|
19
|
+
return { entryId, starred };
|
|
20
|
+
}
|
|
21
|
+
export function starEntry(session, entryId) {
|
|
22
|
+
return setEntryStarred(session, entryId, true);
|
|
23
|
+
}
|
|
24
|
+
export function unstarEntry(session, entryId) {
|
|
25
|
+
return setEntryStarred(session, entryId, false);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=favourite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"favourite.js","sourceRoot":"","sources":["../../src/core/favourite.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQ3D,KAAK,UAAU,eAAe,CAC5B,OAAgB,EAChB,OAAgB,EAChB,OAAgB;IAEhB,MAAM,MAAM,GAAG,OAAO;QACpB,CAAC,CAAC,iBAAiB,OAAO,eAAe;QACzC,CAAC,CAAC,kBAAkB,OAAO,sBAAsB,CAAC;IACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM;SAChC,IAAI,CAAC,YAAY,CAAC;SAClB,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;SACvC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,gBAAgB,CACxB,GAAG,MAAM,gCAAgC,MAAM,CAAC,MAAM,GAAG,CAC1D,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,gBAAgB,CACxB,GAAG,MAAM,2EAA2E,CACrF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,OAAgB,EAChB,OAAgB;IAEhB,OAAO,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,OAAgB,EAChB,OAAgB;IAEhB,OAAO,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { WikiMastersError } from "./errors.js";
|
|
2
|
+
import { siteCookie, siteRequest } from "./site.js";
|
|
3
|
+
function isObject(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function isGlobalCollectionResponse(body) {
|
|
7
|
+
return (isObject(body) &&
|
|
8
|
+
Array.isArray(body.cards) &&
|
|
9
|
+
(body.total === null || ["number", "string"].includes(typeof body.total)) &&
|
|
10
|
+
typeof body.searchHasMore === "boolean" &&
|
|
11
|
+
(body.rarityCounts === null || isObject(body.rarityCounts)) &&
|
|
12
|
+
isObject(body.friendOwners) &&
|
|
13
|
+
Array.isArray(body.ownedCardIds) &&
|
|
14
|
+
Array.isArray(body.wishlistCardIds) &&
|
|
15
|
+
Array.isArray(body.friendPendingOfferKeys));
|
|
16
|
+
}
|
|
17
|
+
function queryString({ text, page, sort, rarities = [], wishlist = false, }) {
|
|
18
|
+
const query = new URLSearchParams();
|
|
19
|
+
if (page !== undefined)
|
|
20
|
+
query.set("page", page);
|
|
21
|
+
if (text !== undefined)
|
|
22
|
+
query.set("q", text);
|
|
23
|
+
for (const rarity of rarities)
|
|
24
|
+
query.append("rarity", rarity);
|
|
25
|
+
if (sort !== undefined)
|
|
26
|
+
query.set("sort", sort);
|
|
27
|
+
if (wishlist)
|
|
28
|
+
query.set("wishlist", "1");
|
|
29
|
+
return query;
|
|
30
|
+
}
|
|
31
|
+
export async function searchGlobalCollection(session, query) {
|
|
32
|
+
const action = "Searching the global collection";
|
|
33
|
+
const body = await siteRequest(session, await siteCookie(session), action, "/global-collection", `/api/cards?${queryString(query)}`, { method: "GET" });
|
|
34
|
+
if (!isGlobalCollectionResponse(body)) {
|
|
35
|
+
throw new WikiMastersError(`${action} returned an unexpected response: ${JSON.stringify(body)}`);
|
|
36
|
+
}
|
|
37
|
+
const owned = new Set(body.ownedCardIds);
|
|
38
|
+
const wishlisted = new Set(body.wishlistCardIds);
|
|
39
|
+
return {
|
|
40
|
+
cards: body.cards.map(({ id, wikipedia_title, rarity }) => ({
|
|
41
|
+
id,
|
|
42
|
+
title: wikipedia_title,
|
|
43
|
+
rarity,
|
|
44
|
+
owned: owned.has(id),
|
|
45
|
+
wishlisted: wishlisted.has(id),
|
|
46
|
+
friends: (body.friendOwners[id] ?? []).map(({ id: friendId, username, rarities }) => ({
|
|
47
|
+
id: friendId,
|
|
48
|
+
username,
|
|
49
|
+
rarities,
|
|
50
|
+
})),
|
|
51
|
+
})),
|
|
52
|
+
total: body.total === null ? null : Number(body.total),
|
|
53
|
+
rarityCounts: body.rarityCounts,
|
|
54
|
+
pendingOfferKeys: body.friendPendingOfferKeys,
|
|
55
|
+
hasMore: body.searchHasMore,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=global-collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-collection.js","sourceRoot":"","sources":["../../src/core/global-collection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { SITE_URL } from "./supabase.js";
|
|
2
|
+
export { listRunningBids, } from "./auction-bids.js";
|
|
3
|
+
export { cancelAuction } from "./auction-cancel.js";
|
|
4
|
+
export { createAuction, parseAuctionDuration, parseStartingPrice, } from "./auction-create.js";
|
|
5
|
+
export { listAuctions } from "./auction-list.js";
|
|
6
|
+
export { parseAuctionSearchPage, searchAuctions, } from "./auction-search.js";
|
|
7
|
+
export { AUCTION_LIMIT, parseAuctionId, parseAuctionLimit, parseBidAmount, placeBid, showAuction, } from "./auction.js";
|
|
8
|
+
export { AUTH_COOKIE_NAME, refreshTokenFromAuthCookieChunks, refreshTokenFromAuthCookies, } from "./auth-cookie.js";
|
|
9
|
+
export { FIREFOX_BINARY, loginInBrowser, readRefreshTokenFromFirefoxProfile, } from "./browser-login.js";
|
|
10
|
+
export { parseCardId } from "./card-id.js";
|
|
11
|
+
export { asEntryId } from "./entry-id.js";
|
|
12
|
+
export { CARD_SEARCH_FIELDS, parseCardSearchField, searchCards, } from "./card-search.js";
|
|
13
|
+
export { readCardValues } from "./card-value.js";
|
|
14
|
+
export { asLabelId, createLabel, deleteLabel, listLabels, } from "./label.js";
|
|
15
|
+
export { NOTIFICATION_LIMIT, listNotifications, } from "./notification-list.js";
|
|
16
|
+
export { PAGE_LIMIT, parsePageLimit, parsePageNumber, } from "./page.js";
|
|
17
|
+
export { listCollection, } from "./collection-list.js";
|
|
18
|
+
export { discardEntries, } from "./collection.js";
|
|
19
|
+
export { ApiUnavailableError, AuthRequiredError, WikiMastersError, } from "./errors.js";
|
|
20
|
+
export { starEntry, unstarEntry, } from "./favourite.js";
|
|
21
|
+
export { searchGlobalCollection, } from "./global-collection.js";
|
|
22
|
+
export { readProfileCollection, } from "./profile-collection.js";
|
|
23
|
+
export { resumeSession, } from "./session.js";
|
|
24
|
+
export { tagEntry, untagEntry, } from "./tag.js";
|
|
25
|
+
export { addToWishlist, listWishlist, removeFromWishlist, } from "./wishlist.js";
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,eAAe,GAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAyB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,kBAAkB,GAInB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAsB,MAAM,mBAAmB,CAAC;AACrE,OAAO,EACL,sBAAsB,EACtB,cAAc,GAGf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,QAAQ,EACR,WAAW,GAMZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gBAAgB,EAChB,gCAAgC,EAChC,2BAA2B,GAE5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,cAAc,EACd,kCAAkC,GAEnC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAe,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,SAAS,EAAgB,MAAM,eAAe,CAAC;AACxD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,GAIZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAkB,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,UAAU,GAIX,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,GAIlB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,UAAU,EACV,cAAc,EACd,eAAe,GAIhB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,GAIf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,cAAc,GAGf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,SAAS,EACT,WAAW,GAEZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,sBAAsB,GAKvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,qBAAqB,GAItB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,aAAa,GAGd,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,QAAQ,EACR,UAAU,GAGX,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,aAAa,EACb,YAAY,EACZ,kBAAkB,GAInB,MAAM,eAAe,CAAC"}
|