1
0
mirror of https://github.com/tcgdex/cards-database.git synced 2025-08-16 09:08:52 +00:00

Compare commits

...

14 Commits

Author SHA1 Message Date
8b8765206e fix: some more file !
Signed-off-by: Avior <git@avior.me>
2025-05-04 02:01:43 +02:00
e35a91ad4f fix: some cards are now fixed
Signed-off-by: Avior <git@avior.me>
2025-05-04 02:01:43 +02:00
224d9cd1c6 feat: Add openapi explorer (#529) 2025-05-04 01:21:54 +02:00
Khaleeq Ahmad
98bc4db193 Fix: Celestial Guardians corrections (#725)
Co-authored-by: Khaleeq Ahmad <1710642+khaleeqahmad@users.noreply.github.com>
2025-05-03 22:42:16 +00:00
yugi-classic
d169a67833 fix: correct data for sets tk-ex-latia, tk-ex-latio, tk-ex-m, tk-ex-p, tk-bw-e, tk-bw-z (#726)
Co-authored-by: Avior <github@avior.me>
2025-05-04 00:37:30 +02:00
d0c43e5ce6 Update build.yml 2025-05-04 00:31:12 +02:00
61f506ee95 fix: build nor running 2025-05-04 00:28:51 +02:00
651be99b41 fix: build not running on PRs 2025-05-04 00:26:48 +02:00
8a8602da96 fix: url not valid 2025-05-04 00:17:36 +02:00
5b1f0528db fix: use the current user instead of the hardcoded user 2025-05-04 00:15:03 +02:00
2e4e3c25ba fix: change status depending on input 2025-05-04 00:08:53 +02:00
c9021ab8fa fix: comment not made 2025-05-04 00:02:43 +02:00
8feda41809 fix: use another token 2025-05-03 23:48:52 +02:00
1eb4c677a7 chore: Add ability to comment on Prs to simplify checking cards (#729) 2025-05-03 23:33:15 +02:00
280 changed files with 4430 additions and 2122 deletions

34
.github/scripts/.gitignore vendored Normal file
View File

@@ -0,0 +1,34 @@
# dependencies (bun install)
node_modules
# output
out
dist
*.tgz
# code coverage
coverage
*.lcov
# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# caches
.eslintcache
.cache
*.tsbuildinfo
# IntelliJ based IDEs
.idea
# Finder (MacOS) folder config
.DS_Store

15
.github/scripts/README.md vendored Normal file
View File

@@ -0,0 +1,15 @@
# scripts
To install dependencies:
```bash
bun install
```
To run:
```bash
bun run
```
This project was created using `bun init` in bun v1.2.11. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.

106
.github/scripts/bun.lock vendored Normal file
View File

@@ -0,0 +1,106 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "scripts",
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/github": "^6.0.0",
"@tcgdex/sdk": "^2.6.0",
},
"devDependencies": {
"@types/bun": "latest",
},
"peerDependencies": {
"typescript": "^5",
},
},
},
"packages": {
"@actions/core": ["@actions/core@1.11.1", "", { "dependencies": { "@actions/exec": "^1.1.1", "@actions/http-client": "^2.0.1" } }, "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A=="],
"@actions/exec": ["@actions/exec@1.1.1", "", { "dependencies": { "@actions/io": "^1.0.1" } }, "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w=="],
"@actions/github": ["@actions/github@6.0.0", "", { "dependencies": { "@actions/http-client": "^2.2.0", "@octokit/core": "^5.0.1", "@octokit/plugin-paginate-rest": "^9.0.0", "@octokit/plugin-rest-endpoint-methods": "^10.0.0" } }, "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g=="],
"@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="],
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
"@cachex/core": ["@cachex/core@1.0.1", "", { "dependencies": { "@dzeio/object-util": "^1.8.3" } }, "sha512-sHynwjF9hKIvwg8rTUdvA7MOUMcUC5Mq0dpynPBILRS+IPvsHcE4Cb2uRSs0/I2nxO7NQp9p+xHYistdfJJSwg=="],
"@cachex/memory": ["@cachex/memory@1.0.1", "", { "dependencies": { "@cachex/core": "^1" } }, "sha512-KWUTdCCXhIlAkJaVZMhUh9kD0uq8PxC3Z34Q3lMGZOAV6FXP/cOMW89ALrWX3VkoRrrM4R6MIMO+amZNOvEqgw=="],
"@cachex/web-storage": ["@cachex/web-storage@1.0.1", "", { "dependencies": { "@cachex/core": "^1" } }, "sha512-E8Xa9qDZgNgr+lcj3eixowg7PH2CVZbp3huuoc5xVVTtwYrZi5YqbHBG12yG3r6C6Fts/2Yoq6cbVBSm6c8VRA=="],
"@dzeio/object-util": ["@dzeio/object-util@1.9.1", "", {}, "sha512-cLGsjAc7hzSadS57jcMxSPidYabyZXJOFnasScSrE/V5yflhze6T7L5/98josWYrXMvoKu7N+Ivk6vGkIj72UQ=="],
"@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="],
"@octokit/auth-token": ["@octokit/auth-token@4.0.0", "", {}, "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA=="],
"@octokit/core": ["@octokit/core@5.2.1", "", { "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ=="],
"@octokit/endpoint": ["@octokit/endpoint@9.0.6", "", { "dependencies": { "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw=="],
"@octokit/graphql": ["@octokit/graphql@7.1.1", "", { "dependencies": { "@octokit/request": "^8.4.1", "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" } }, "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g=="],
"@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="],
"@octokit/plugin-paginate-rest": ["@octokit/plugin-paginate-rest@9.2.2", "", { "dependencies": { "@octokit/types": "^12.6.0" }, "peerDependencies": { "@octokit/core": "5" } }, "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ=="],
"@octokit/plugin-rest-endpoint-methods": ["@octokit/plugin-rest-endpoint-methods@10.4.1", "", { "dependencies": { "@octokit/types": "^12.6.0" }, "peerDependencies": { "@octokit/core": "5" } }, "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg=="],
"@octokit/request": ["@octokit/request@8.4.1", "", { "dependencies": { "@octokit/endpoint": "^9.0.6", "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw=="],
"@octokit/request-error": ["@octokit/request-error@5.1.1", "", { "dependencies": { "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g=="],
"@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="],
"@tcgdex/sdk": ["@tcgdex/sdk@2.6.0", "", { "dependencies": { "@cachex/memory": "^1", "@cachex/web-storage": "^1", "@dzeio/object-util": "^1", "isomorphic-unfetch": "^3" } }, "sha512-q0O7dNzRRLq38XwqUoHFKo78/NCQW5pEIZ+JnlrVOxp9r9R/LTIQGAMNR96Il0hb1uIm4j5o7WBueBCpuDyomQ=="],
"@types/bun": ["@types/bun@1.2.11", "", { "dependencies": { "bun-types": "1.2.11" } }, "sha512-ZLbbI91EmmGwlWTRWuV6J19IUiUC5YQ3TCEuSHI3usIP75kuoA8/0PVF+LTrbEnVc8JIhpElWOxv1ocI1fJBbw=="],
"@types/node": ["@types/node@22.15.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw=="],
"before-after-hook": ["before-after-hook@2.2.3", "", {}, "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="],
"bun-types": ["bun-types@1.2.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-dbkp5Lo8HDrXkLrONm6bk+yiiYQSntvFUzQp0v3pzTAsXk6FtgVMjdQ+lzFNVAmQFUkPQZ3WMZqH5tTo+Dp/IA=="],
"deprecation": ["deprecation@2.3.1", "", {}, "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="],
"isomorphic-unfetch": ["isomorphic-unfetch@3.1.0", "", { "dependencies": { "node-fetch": "^2.6.1", "unfetch": "^4.2.0" } }, "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q=="],
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
"tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
"tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="],
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
"unfetch": ["unfetch@4.2.0", "", {}, "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA=="],
"universal-user-agent": ["universal-user-agent@6.0.1", "", {}, "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="],
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
"@octokit/plugin-paginate-rest/@octokit/types": ["@octokit/types@12.6.0", "", { "dependencies": { "@octokit/openapi-types": "^20.0.0" } }, "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw=="],
"@octokit/plugin-rest-endpoint-methods/@octokit/types": ["@octokit/types@12.6.0", "", { "dependencies": { "@octokit/openapi-types": "^20.0.0" } }, "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw=="],
"@octokit/plugin-paginate-rest/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@20.0.0", "", {}, "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="],
"@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@20.0.0", "", {}, "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="],
}
}

429
.github/scripts/load-cards.ts vendored Normal file
View File

@@ -0,0 +1,429 @@
import core from "@actions/core";
import github from "@actions/github";
import TCGdex from "@tcgdex/sdk";
// Types
type CardData = {
id: string;
name: string;
image?: string;
rarity?: string;
set: { name: string };
hasImage: boolean;
};
type CardResult = {
file: string;
card?: CardData;
error?: string;
isAsian?: boolean;
usedLanguage?: string;
hasImage?: boolean;
status?: "added" | "removed" | "modified";
};
type CardFetchResult = {
card: any;
usedLanguage: string;
hasImage: boolean;
} | null;
// Constants
const DATA_REGEX = /^data\/([^\/]+)\/([^\/]+)\/([^\/]+)\.ts$/;
const DATA_ASIA_REGEX = /^data-asia\/([^\/]+)\/([^\/]+)\/([^\/]+)\.ts$/;
const INTERNATIONAL_LANGUAGES = ["en", "fr", "es", "es-mx", "it", "pt", "pt-br", "pt-pt", "de", "nl", "pl", "ru"];
const ASIAN_LANGUAGES = ["ja", "ko", "zh-tw", "id", "th", "zh-cn"];
const LANGUAGE_NAMES: Record<string, string> = {
en: "English",
fr: "French",
es: "Spanish",
"es-mx": "Spanish (Mexico)",
it: "Italian",
pt: "Portuguese",
"pt-br": "Portuguese (Brazil)",
"pt-pt": "Portuguese (Portugal)",
de: "German",
nl: "Dutch",
pl: "Polish",
ru: "Russian",
ja: "Japanese",
ko: "Korean",
"zh-tw": "Chinese (Taiwan)",
id: "Indonesian",
th: "Thai",
"zh-cn": "Chinese (China)",
};
// Helper function to sanitize card data
function sanitizeCardData(card: any): CardData | undefined {
if (!card) return undefined;
return {
id: card.id,
name: card.name,
image: card.image,
rarity: card.rarity,
set: card.set ? { name: card.set.name } : { name: "Unknown" },
hasImage: !!card.image,
};
}
// Helper function to try fetching a card with fallback to other languages
async function tryFetchCardWithFallback(
setIdentifier: string,
cardLocalId: string,
primaryLanguage: string,
allLanguages: string[],
isAsianRegion: boolean,
): Promise<CardFetchResult> {
let lastError: Error | unknown = null;
const languagesToTry = [primaryLanguage, ...allLanguages.filter((lang) => lang !== primaryLanguage)];
let foundWithoutImage: { lang: string; card: any } | undefined;
for (const lang of languagesToTry) {
try {
console.log(` Trying language: ${lang}`);
const tcgdex = new TCGdex(lang as any);
let card;
if (!isAsianRegion) {
const set = await tcgdex.set.get(setIdentifier);
card = await tcgdex.card.get(`${set!.id}-${cardLocalId}`);
} else {
card = await tcgdex.card.get(`${setIdentifier}-${cardLocalId}`);
}
if (card && !card.image) {
foundWithoutImage = { lang, card };
continue;
}
if (card && card.image) {
console.log(` Card: ${card.name} (${card.id}) - Found using language: ${lang}`);
return { card, usedLanguage: lang, hasImage: true };
}
} catch (error) {
lastError = error;
console.log(` Failed with language ${lang}: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
if (foundWithoutImage) {
console.log(` Card: ${foundWithoutImage.card.name} (${foundWithoutImage.card.id}) - Found without image`);
return { card: foundWithoutImage.card, usedLanguage: foundWithoutImage.lang, hasImage: false };
}
console.log(
` All languages failed. Last error: ${lastError instanceof Error ? lastError.message : "Unknown error"}`,
);
return null;
}
// Get changed files from GitHub
async function getChangedFiles(
context: typeof github.context,
octokit: ReturnType<typeof github.getOctokit>,
): Promise<{ filename: string; status: string }[]> {
if (context.payload.pull_request) {
const { owner, repo } = context.repo;
const prNumber = context.payload.pull_request.number;
const response = await octokit.rest.pulls.listFiles({
owner,
repo,
pull_number: prNumber,
});
return response.data.map((file) => ({ filename: file.filename, status: file.status }));
} else if (context.payload.commits) {
const files: { filename: string; status: string }[] = [];
for (const commit of context.payload.commits) {
if (commit.added) {
commit.added.forEach((file: string) => files.push({ filename: file, status: "added" }));
}
if (commit.modified) {
commit.modified.forEach((file: string) => files.push({ filename: file, status: "modified" }));
}
if (commit.removed) {
commit.removed.forEach((file: string) => files.push({ filename: file, status: "removed" }));
}
}
return files;
}
return [];
}
// Process a single card file
async function processCardFile(file: { filename: string; status: string }): Promise<CardResult | null> {
console.log(` - ${file.filename} (${file.status})`);
let match = file.filename.match(DATA_REGEX);
const isCardFile = !!(match || file.filename.match(DATA_ASIA_REGEX));
if (!isCardFile) {
return null;
}
// For added files, just return the file info without fetching
if (file.status === "added") {
return {
file: file.filename,
status: "added",
};
}
// For removed files, just return the file info without fetching
if (file.status === "removed") {
return {
file: file.filename,
status: "removed",
};
}
// Only process modified files normally
if (match) {
const [_, , setName, cardLocalId] = match;
const result = await tryFetchCardWithFallback(setName!, cardLocalId!, "en", INTERNATIONAL_LANGUAGES, false);
if (result) {
return {
file: file.filename,
card: sanitizeCardData(result.card),
isAsian: false,
usedLanguage: result.usedLanguage,
hasImage: result.hasImage,
status: "modified",
};
} else {
return {
file: file.filename,
error: "Failed to fetch card information in all available languages",
isAsian: false,
status: "modified",
};
}
}
match = file.filename.match(DATA_ASIA_REGEX);
if (match) {
const [_, , setId, cardLocalId] = match;
const result = await tryFetchCardWithFallback(setId!, cardLocalId!, "ja", ASIAN_LANGUAGES, true);
if (result) {
return {
file: file.filename,
card: sanitizeCardData(result.card),
isAsian: true,
usedLanguage: result.usedLanguage,
hasImage: result.hasImage,
status: "modified",
};
} else {
return {
file: file.filename,
error: "Failed to fetch card information in all available languages",
isAsian: true,
status: "modified",
};
}
}
return null;
}
// Generate comment body for PR
function generateCommentBody(
cardResults: CardResult[],
changedFiles: { filename: string; status: string }[],
repoFullName: string,
contextSha: string,
): string {
const newCards = cardResults.filter((r) => r.status === "added").length;
const deletedCards = cardResults.filter((r) => r.status === "removed").length;
const modifiedCards = cardResults.filter((r) => r.status === "modified" && r.card).length;
const errorCards = cardResults.filter((r) => r.status === "modified" && r.error).length;
const cardsWithoutImages = cardResults.filter((r) => r.card && !r.hasImage).length;
let commentBody = `## 🃏 ${cardResults.length} Card${cardResults.length !== 1 ? "s" : ""} Changed\n\n`;
if (cardResults.length === 0) {
commentBody +=
changedFiles.length > 0
? "No recognized card files were changed in this PR.\n"
: "No files were changed in this PR.\n";
return commentBody;
}
// Add summary
commentBody += `**Details:** `;
const details = [];
if (newCards > 0) {
details.push(`${newCards} new`);
}
if (deletedCards > 0) {
details.push(`${deletedCards} deleted`);
}
if (modifiedCards > 0) {
details.push(`${modifiedCards} modified`);
}
if (errorCards > 0) {
details.push(`${errorCards} with errors`);
}
if (cardsWithoutImages > 0) {
details.push(`${cardsWithoutImages} without images`);
}
commentBody += details.join(", ") + "\n\n";
// Generate detailed card information
for (const item of cardResults) {
const fileUrl = `https://github.com/${repoFullName}/blob/${contextSha}/${item.file}`;
const fileName = item.file.split("/").pop();
if (item.status === "added") {
commentBody += `<details><summary> <strong>New card: ${fileName}</strong></summary>\n\n`;
commentBody += `**File:** [${encodeURI(item.file)}](${encodeURI(fileUrl)}) \n\n`;
commentBody += "</details>\n\n";
} else if (item.status === "removed") {
commentBody += `<details><summary>🗑️ <strong>Deleted card: ${fileName}</strong></summary>\n\n`;
commentBody += `**File:** [${encodeURI(item.file)}](${encodeURI(fileUrl)}) \n\n`;
commentBody += "</details>\n\n";
} else if (item.card) {
const langInfo = item.usedLanguage ? ` (found using ${item.usedLanguage})` : "";
const imageStatus = !item.hasImage ? ` <em>(no images)</em>` : "";
commentBody += `<details><summary><strong>${item.card.name}</strong> (${item.card.id})${langInfo}${imageStatus}</summary>\n\n`;
if (item.card.image) {
const languages = item.isAsian ? ASIAN_LANGUAGES : INTERNATIONAL_LANGUAGES;
commentBody += renderCardImageTable(item.card, languages);
} else {
commentBody += `<p align="center"><em>No images available for this card</em></p>\n\n`;
}
commentBody += `**File:** [${item.file}](${fileUrl}) \n`;
commentBody += `**Set:** ${item.card.set?.name || "Unknown"} \n`;
commentBody += `**Rarity:** ${item.card.rarity || "Unknown"}\n\n`;
commentBody += "</details>\n\n";
} else if (item.error) {
commentBody += `<details><summary>⚠️ <strong>Error processing ${fileName}</strong></summary>\n\n`;
commentBody += `**File:** [${encodeURI(item.file)}](${encodeURI(fileUrl)}) \n\n`;
commentBody += `**Error:** ${item.error}\n\n`;
commentBody += "</details>\n\n";
}
}
return commentBody;
}
// Helper to render the card image table
function renderCardImageTable(card: CardData, languages: string[]): string {
let tableMarkdown = `<div align="center">\n\n`;
tableMarkdown += `| Language | Language | Language |\n`;
tableMarkdown += `|:-------:|:-------:|:-------:|\n`;
for (let i = 0; i < languages.length; i += 3) {
tableMarkdown += `|`;
for (let j = 0; j < 3; j++) {
const langIndex = i + j;
if (langIndex < languages.length) {
const lang = languages[langIndex];
const langName = LANGUAGE_NAMES[lang as keyof typeof LANGUAGE_NAMES] || lang;
const localizedImageUrl = card.image!.replace(/\/[a-z]{2}(-[a-z]{2})?\//, `/${lang}/`);
tableMarkdown += ` <strong>${langName} (${lang})</strong><br><img src="${localizedImageUrl}/high.webp" alt="${card.name} (${langName})" width="200"/> |`;
} else {
tableMarkdown += ` |`;
}
}
tableMarkdown += `\n`;
}
tableMarkdown += `\n</div>\n\n`;
return tableMarkdown;
}
// Post or update PR comment
async function postOrUpdatePRComment(
octokit: ReturnType<typeof github.getOctokit>,
owner: string,
repo: string,
prNumber: number,
commentBody: string,
): Promise<void> {
// Get authenticated user info to identify our bot
const { data: authenticatedUser } = await octokit.rest.users.getAuthenticated();
console.log(`Authenticated as user: ${authenticatedUser.login}`);
const commentsResponse = await octokit.rest.issues.listComments({
owner,
repo,
issue_number: prNumber,
});
// Look for existing comments from our authenticated bot user
const existingComment = commentsResponse.data.find(
(comment) => comment.user?.login === authenticatedUser.login && comment.body?.includes("## 🃏"),
);
if (existingComment) {
await octokit.rest.issues.updateComment({
owner,
repo,
comment_id: existingComment.id,
body: commentBody,
});
console.log(`Updated existing comment #${existingComment.id} on PR #${prNumber} as ${authenticatedUser.login}`);
} else {
await octokit.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: commentBody,
});
console.log(`Posted new comment to PR #${prNumber} as ${authenticatedUser.login}`);
}
}
async function run() {
try {
// Initialize GitHub client
const token = core.getInput("github-token", { required: true });
const octokit = github.getOctokit(token);
const context = github.context;
const { owner, repo } = context.repo;
const repoFullName = `${owner}/${repo}`;
// Get changed files
const changedFiles = await getChangedFiles(context, octokit);
// Process card files
const cardResults: CardResult[] = [];
for (const file of changedFiles) {
const result = await processCardFile(file);
if (result) cardResults.push(result);
}
// Generate comment body
const commentBody = generateCommentBody(cardResults, changedFiles, repoFullName, context.sha);
// Post or update the comment in the PR
if (context.payload.pull_request) {
const prNumber = context.payload.pull_request.number;
await postOrUpdatePRComment(octokit, owner, repo, prNumber, commentBody);
}
// Store the generated comment for the workflow
core.setOutput("pr_comment", commentBody);
core.setOutput("files", changedFiles.map(f => f.filename).join(","));
core.setOutput("cardFiles", JSON.stringify(cardResults));
} catch (error) {
if (error instanceof Error) {
core.setFailed(error.message);
} else {
core.setFailed("An unknown error occurred");
}
}
}
run();

15
.github/scripts/package.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "scripts",
"private": true,
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5"
},
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/github": "^6.0.0",
"@tcgdex/sdk": "^2.6.0"
}
}

28
.github/scripts/tsconfig.json vendored Normal file
View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}

View File

@@ -8,7 +8,6 @@ on:
branches:
- master
env:
REGISTRY_IMAGE: |
ghcr.io/tcgdex/server
@@ -65,7 +64,7 @@ jobs:
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Pre build server
run: |
bun install --frozen-lockfile
@@ -88,4 +87,3 @@ jobs:
cache-from: type=gha
push: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }}
cache-to: type=gha,mode=max

36
.github/workflows/comment-pr.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: Card Info Comment
on:
pull_request_target:
types: [opened, synchronize]
paths:
- 'data/**/*.ts'
- 'data-asia/**/*.ts'
jobs:
card-info-comment:
runs-on: ubuntu-latest
continue-on-error: true
defaults:
run:
working-directory: .github/scripts
permissions:
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun i --frozen-lockfile
- name: Run load-cards script
id: load-cards
run: bun load-cards.js
env:
INPUT_GITHUB-TOKEN: ${{ secrets.TCGDEX_BOT }}

View File

@@ -1,5 +1,4 @@
<!-- omit in toc -->
# Contributing to TCGdex
First off, thanks for taking the time to contribute! ❤️
@@ -7,26 +6,23 @@ First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
>
> - Star the project
> - Tweet about it
> - Refer this project in your project's readme
> - Mention the project at local meetups and tell your friends/colleagues
<!-- omit in toc -->
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
- [Reporting Issues](#reporting-issues)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)
- [Improving The Documentation](#improving-the-documentation)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)
- [Improving The Documentation](#improving-the-documentation)
- [Styleguides](#styleguides)
- [Coding Guidlines](#coding-guidelines)
- [Commit Messages](#commit-messages)
- [Commit Messages](#commit-messages)
- [Join The Project Team](#join-the-project-team)
## Code of Conduct
@@ -37,7 +33,7 @@ By participating, you are expected to uphold this code. Please report unacceptab
## I Have a Question
> If you want to ask a question, we assume that you have read the available Documentation at <https://www.tcgdex.dev>.
> If you want to ask a question, we assume that you have read the available [Documentation](https://tcgdex.dev).
The best way to ask questions is to join our Discord server at <https://discord.gg/NehYTAhsZE>.
@@ -69,38 +65,36 @@ Depending on how large the project is, you may want to outsource the questioning
## I Want To Contribute
> ### Legal Notice <!-- omit in toc -->
>
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project licence.
### Reporting Issues
### Reporting Bugs
<!-- omit in toc -->
#### Before Submitting a Bug Report
#### Before Submitting an Issue Report
A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
A good issue report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
- Determine if your issue is not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://www.tcgdex.dev). If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already an issue report existing for your bug or error in the [bug tracker](https://github.com/tcgdex/cards-database/issues).
- Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://tcgdex.dev). If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https:/github.com/tcgdex/cards-database/issues?q=label%3Abug).
- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
- Collect information about the bug:
- Stack trace (Traceback)
- OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
- Possibly your input and the output
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
- Stack trace (Traceback)
- OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
- Possibly your input and the output
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
<!-- omit in toc -->
#### How Do I Submit a Good Bug Report?
> You must never report security related issues, vulnerabilities or bugs to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to <security@tcgdex.net>.
> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to <security@tcgdex.net>.
<!-- You may add a PGP key to allow the messages to be sent encrypted as well. -->
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
- Open an [Issue](https://github.com/tcgdex/cards-databaseissues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
- Open an [Issue](https://github.com/tcgdex/cards-database/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
- Explain the behavior you would expect and the actual behavior.
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
- Provide the information you collected in the previous section.
@@ -122,20 +116,19 @@ This section guides you through submitting an enhancement suggestion for TCGdex,
#### Before Submitting an Enhancement
- Make sure that you are using the latest version.
- Read the [documentation](https://www.tcgdex.dev) carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](https://github.com/tcgdex/cards-databaseissues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Read the [documentation](https://tcgdex.dev) carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](https://github.com/tcgdex/cards-database/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.
<!-- omit in toc -->
#### How Do I Submit a Good Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://github.com/tcgdex/cards-databaseissues).
Enhancement suggestions are tracked as [GitHub issues](https:/github.com/tcgdex/cards-database/issues).
- Use a **clear and descriptive title** for the issue to identify the suggestion.
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you.
- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. <!-- this should only be included if the project has a GUI -->
- You may want to **include screenshots or screen recordings** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [LICEcap](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and the built-in [screen recorder in GNOME](https://help.gnome.org/users/gnome-help/stable/screen-shot-record.html.en) or [SimpleScreenRecorder](https://github.com/MaartenBaert/ssr) on Linux. <!-- this should only be included if the project has a GUI -->
- **Explain why this enhancement would be useful** to most TCGdex users. You may also want to point out the other projects that solved it better and which could serve as inspiration.
<!-- You might want to create an issue template for enhancement suggestions that can be used as a guide and that defines the structure of the information to be included. If you do so, reference it here in the description. -->
@@ -150,6 +143,11 @@ _note: Follow the different styleguides listed below when contributing_
- we don't like ❌, so if your pull request has its automated checks ending with the red cross, please double check your changes until it show the awesome 🟢, or ask for help !
- If your pull request is ready for review remove WIP: put it s ready for review and we will handle the rest !
folders :
- `data`: the database for the internationnal cards
- `data-asia`: the database for the asian cards
- `server`: The server behind the API
### Improving The Documentation
The documentation is updated in the Documentation repository at <https://github.com/tcgdex/documentation>
@@ -160,8 +158,8 @@ The documentation is updated in the Documentation repository at <https://github.
Install the plugin `.editorconfig` in your dev environment if it's not already done and thats it !
for those who don't want to install it the basic are these:
- Indent using the `tab` or `\t` character
for those who don't want to install it, the basics are these:
- Indent using the <xkb>tab</xkb> (`\t`) character
- the line feed character is `\n`
- only use `;` when necessary and at the start of the line
- use double quotes `"` when editing files in the `data/` folder and single quote `'` in other files
@@ -195,6 +193,6 @@ In short, please name your Pull Requests/Commits following this format
- use the imperative, present tense: "Change" not "Changed" nor "Changes"
- `<footer>` and `<body>` are both optional
<!-- omit in toc -->
## Attribution
This guide is based on [Contribution Gen]((https://github.com/bttger/contributing-gen)) and was adapted by the TCGdex community !
This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)!

View File

@@ -10,8 +10,8 @@ RUN apk add git\
USER bun
ADD --chown=bun:bun package.json bun.lockb ./
ADD --chown=bun:bun server/package.json server/bun.lockb ./server/
ADD --chown=bun:bun package.json bun.lock ./
ADD --chown=bun:bun server/package.json server/bun.lock ./server/
# install dependencies
RUN bun install --frozen-lockfile && \

View File

@@ -8,7 +8,7 @@ RUN chown -R bun:bun .
USER bun
ADD --chown=bun:bun server/package.json server/bun.lockb ./server/
ADD --chown=bun:bun server/package.json server/bun.lock ./server/
# install prod deps dependencies
RUN cd server && \

13
bun.lock Normal file
View File

@@ -0,0 +1,13 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"devDependencies": {
"typescript": "^5",
},
},
},
"packages": {
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
}
}

BIN
bun.lockb

Binary file not shown.

View File

@@ -29,9 +29,11 @@ const card: Card = {
type: "Ability",
name: {
en: "Intuition",
fr: "Intuition"
},
effect: {
en: "When you play this Pokémon from your hand to evolve 1 of your Pokémon, you may draw 2 cards.",
fr: "Lorsque vous jouez ce Pokémon de votre main pour faire évoluer 1 de vos Pokémon, vous pouvez piocher 2 cartes."
},
},
],
@@ -44,28 +46,13 @@ const card: Card = {
],
name: {
en: "Fast Punch",
fr: "{Ability] Intuition",
},
effect: {
en: "Flip a coin. If heads, this attack does 30 more damage.",
fr: "Lorsque vous jouez ce Pokémon de votre main pour faire évoluer 1 de vos Pokémon, vous pouvez piocher 2 cartes.",
},
damage: 60,
},
{
cost: [
"Fighting",
"Colorless",
"Colorless",
],
name: {
fr: "Poing Rapide",
},
effect: {
en: "Flip a coin. If heads, this attack does 30 more damage.",
fr: "Lancez une pièce. Si c'est face, cette attaque inflige 30 dégâts supplémentaires.",
},
damage: "60+",
damage: 60,
},
],

View File

@@ -38,6 +38,7 @@ const card: Card = {
attacks: [{
name: {
en: 'Peck',
fr: "Picpic",
de: "Schnabel"
},
@@ -47,11 +48,13 @@ const card: Card = {
cost: ["Water", "Colorless"],
name: {
en: 'Water Splash',
fr: "Éclaboussure",
de: "Wasserplatscher"
},
effect: {
en: 'Flip a coin. If heads, this attack does 20 damage plus 10 more damage.',
fr: "Lancez une pièce. Si c'est face, cette attaque inflige 20 dégâts plus 10 dégâts supplémentaires.",
de: "Wirf 1 Münze. Bei \"Kopf\" fügt dieser Angriff 20 Schadenspunkte plus 10 weitere Schadenspunkte zu."
},

View File

@@ -37,12 +37,14 @@ const card: Card = {
attacks: [{
name: {
en: 'Splash About',
de: "Herumspritzen"
},
damage: "10+",
effect: {
en: 'If buizel has less Energy attached to it than the Defending Pokémon, this attack does 10 damage plus 10 more damage.',
de: "Wenn an das Verteidigende Pokémon mehr Energie angelegt ist als an Bamelin, fügt dieser Angriff 10 Schadenspunkte plus 10 weitere Schadenspunkte zu."
},

View File

@@ -14,6 +14,7 @@ const card: Card = {
set: Set,
effect: {
en: "Attach this card to 1 of your Pokémon in play. That Pokémon may use this card's attack instead of its own.",
fr: "Attachez cette carte à 1 de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne.",
de: "Lege diese Karte an 1 deiner Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstelle seiner eigenen Angriffe benutzen."
},
@@ -22,10 +23,14 @@ const card: Card = {
attacks: [{
name: {
en: "Evoluter",
fr: "Évolutionneur",
de: "Evoluter"
},
effect: {
en: "Search your deck for a card that evolves from 1 of you Pokémon and put it onto that Pokémon. (This counts as evolving that Pokémon.) Shuffle your deck afterward.",
fr: "Cherchez dans votre deck une carte évoluant d'1 de vos Pokémon et placez-la sur ce Pokémon. (Vous le faites ainsi évoluer.) Ensuite, mélangez votre deck.",
de: "Durchsuche dein Deck nach 1 Karte, die sich aus 1 deiner Pokémon entwickelt, und lege sie auf dieses Pokémon. (Dies zählt als Entwickeln von diesem Pokémon.) Mische dein Deck danach."
}
}]

View File

@@ -14,6 +14,7 @@ const card: Card = {
set: Set,
effect: {
en: "Attach this card to 1 of your Pokémon in play. That Pokémon may use this card's attack instead of its own.",
fr: "Attachez cette carte à 1 de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne.",
de: "Lege diese Karte an 1 deiner Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstelle seiner eigenen Angriffe benutzen."
},
@@ -22,10 +23,14 @@ const card: Card = {
attacks: [{
name: {
en: "Devoluter",
fr: "Dés-Évolutionneur",
de: "Devoluter"
},
effect: {
en: "Choose 1 of your opponent's Evolved Pokémon (Excluding Pokémon LV.X). Remove the highest Stage Evolution card from that Pokémon and put that card back into your opponent's hand.",
fr: "Choisizzes 1 des Pokémon Évolués de votre adversaire (Pokémon LV.X exclus). Retirez à ce Pokémon sa carte au niveau d'Évolution le plus élevé et replacez cette carte dans la main de votre adversaire.",
de: "Wähle 1 entwickeltes Pokémon deines Gegners (außer Pokémon LV.X). Entferne die höchste Evolutionskarte vom gewählten Pokémon, dein Gegner nimmt diese Karte auf seine Hand zurück."
}
}]

View File

@@ -10,7 +10,7 @@ const card: Card = {
illustrator: "Masakazu Fukuda",
rarity: "Common",
category: "Trainer",
category: "Pokemon",
set: Set,
dexId: [
@@ -32,31 +32,38 @@ const card: Card = {
},
],
retreat: 1,
level: 15,
weight: 3.9,
height: 0.5,
effect: {
en: "Search your deck for a Basic Pokémon and put it onto your Bench. Shuffle your deck afterward.",
fr: "Choisissez dans votre deck un Pokémon de base et placez-le sur votre Banc. Ensuite, mélangez votre deck.",
},
retreat: 1,
attacks: [{
name: {
en: 'Call for Family',
fr: 'Appel à la famille',
de: "Familienruf"
},
effect: {
fr: 'Choisissez dans votre deck un Pokémon de base et placez-le sur botre Banc. Ensuite, mélangez votre deck.',
en: 'Search your deck for a Basic Pokémon and put it onto your Bench. Shuffle your deck afterward',
de: "Durchsuche dein Deck nach 1 Basis-Pokémon-Karte und lege sie auf diene Bank. Mische dein Deck danach."
},
cost: ["Colorless"]
}, {
name: {
en: 'Rip Claw',
fr: 'Griffe déchirante',
de: "Reißklaue"
},
damage: 10,
effect: {
fr: "Lancez une pièce, Si c'est face, défaussez une Énergie attachée au Pokémon Défenseur.",
en: 'Flip a coin. If heads, discard an Energy attached to the Defending Pokémon.',
de: "Wirf 1 Münze. Bei 'Kopf' entferne 1 Energie, die an das Verteidigende Pokémon angelegt ist, und lege sie auf den Ablagestapel deines Gegners."
},

View File

@@ -8,25 +8,31 @@ const card: Card = {
de: "Unlicht Würfel 01"
},
illustrator: undefined,
illustrator: '"Big Mama" Tagawa',
trainerType: 'Technical Machine',
rarity: "Uncommon",
category: "Trainer",
set: Set,
effect: {
fr: "Attachez cette carte à l'un de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube d'obscurité 01.",
de: "Lege diese Karte an 1 deiner -Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seiner eigenen verwenden. Lege am Ende deines Zuges Unlicht-Würfel 01 auf deinen Ablagestapel."
en: 'Attach this card to 1 of your {D} Pokémon in play. That Pokémon may use this card\'s attack instead of its own. At the end of your turn, discard Darkness Cube 01.',
fr: "Attachez cette carte à l'un de vos Pokémon {D} en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube d'obscurité 01.",
de: "Lege diese Karte an 1 deiner {D} - Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seiner eigenen verwenden. Lege am Ende deines Zuges Unlicht-Würfel 01 auf deinen Ablagestapel."
},
attacks: [{
name: {
de: "Plunder"
en: 'Plunder',
de: "Plunder",
fr: 'Pillage'
},
damage: 10,
effect: {
de: "Before doing damage, discard any Trainer cards attached to the Defending Pokémon."
fr: "Avant d'infliger les dégâts, défaussez toutes les cartes Dresseur attachées au Pokémon Défenseur.",
en: 'Before doing damage, discard any Trainer cards attached to the Defending Pokémon.',
de: "Lege alle Trainerkarten, die an das Verteidigende Pokémon angelegt sind, auf den Ablagestapel deines Gegners, bevor des Schaden zugefügt wird."
},
cost: ["Darkness"]

View File

@@ -8,24 +8,31 @@ const card: Card = {
de: "Kampf-Würfel 01"
},
illustrator: undefined,
illustrator: '"Big Mama" Tagawa',
rarity: "Uncommon",
category: "Trainer",
set: Set,
trainerType: 'Technical Machine',
effect: {
fr: "Attachez cette carte à l'un de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube de combat 01.",
en: "Attach this card to 1 of your {F} Pokémon in play. That Pokémon may use this card's attack instead of its own. At the end of your turn, discard Fighting Cube 01.",
fr: "Attachez cette carte à l'un de vos Pokémon {F} en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube de combat 01.",
de: "Lege diese Karte an 1 deiner -Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seiner eigenen verwenden. Lege am Ende deines Zuges Kampf-Würfel 01 auf deinen Ablagestapel."
},
attacks: [{
name: {
en: 'Violent Rage',
fr: "Rage violente",
de: "Rasende Wut"
},
damage: "10x",
effect: {
fr: "Lancez un nombre de pièces égal au nombre de marqueurs de dégâts sur ce Pokémon. Cette attaque inflige 10 dégâts multipliés par le nombre de faces.",
en: 'Flip a number of coins equal to the number of damage counters on this Pokémon. This attack does 10 damage times the number of heads.',
de: "Wirf so viele Münzen, wie Schadensmarken auf diesem Pokémon liegen. Dieser Angriff fügt 10 Schadenspunkte mal der Anzahl \"Kopf\" zu."
},

View File

@@ -10,21 +10,27 @@ const card: Card = {
illustrator: "\"Big Mama\" Tagawa",
rarity: "Uncommon",
trainerType: 'Technical Machine',
category: "Trainer",
set: Set,
effect: {
fr: "Attachez cette carte à l'un de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube de feu 01.",
en: "Attach this card to 1 of your {R} Pokémon in play. That Pokémon may use this card's attack instead of its own. At the end of your turn, discard Fire Cube 01.",
fr: "Attachez cette carte à l'un de vos Pokémon {R} en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube de feu 01.",
de: "Lege diese Karte an 1 deiner -Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seiner eigenen verwenden. Lege am Ende deines Zuges Feuer-Würfel 01 auf deinen Ablagestapel."
},
attacks: [{
name: {
de: "Versengung"
de: "Versengung",
en: "Singe",
fr: "Rousir"
},
effect: {
de: "Das Verteidigende Pokémon ist jetzt verbrannt."
de: "Das Verteidigende Pokémon ist jetzt verbrannt.",
en: "The Defending Pokémon is now Burned.",
fr: "Le Pokémon Defenseur est maintenant Brûlé."
},
cost: ["Fire"]

View File

@@ -10,20 +10,26 @@ const card: Card = {
illustrator: "\"Big Mama\" Tagawa",
rarity: "Uncommon",
trainerType: 'Technical Machine',
category: "Trainer",
set: Set,
effect: {
fr: "Attachez cette carte à l'un de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube de plante 01.",
en: "Attach this card to 1 of your {G} Pokémon in play. That Pokémon may use this card's attack instead of its own. At the end of your turn, discard Fire Cube 01.",
fr: "Attachez cette carte à l'un de vos Pokémon {G} en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube de plante 01.",
de: "Lege diese Karte an 1 deiner -Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seiner eigenen verwenden. Lege am Ende deines Zuges Gras-Würfel 01 auf deinen Ablagestapel."
},
attacks: [{
name: {
fr: "Poison dodo",
en: "Sleep Poison",
de: "Schlafgift"
},
effect: {
en: "The Defending Pokémon is now Asleep and Poisoned.",
fr: "Le Pokémon Défenseur est maintenant Endormi et Empoisonné.",
de: "Das Verteidigende Pokémon ist jetzt vergiftet und schläft."
},

View File

@@ -14,16 +14,21 @@ const card: Card = {
set: Set,
effect: {
en: "Attach this card to 1 of your Water Pokémon in play. That Pokémon may use this card's attack instead of its own. At the end of your turn, discord Water Cube 01.",
fr: "Attachez cette carte à l'un de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Cube d'eau 01.",
de: "Lege diese Karte an 1 deiner -Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seiner eigenen verwenden. Lege am Ende deines Zuges Wasser-Würfel 01 auf deinen Ablagestapel."
},
attacks: [{
name: {
en: "Splatter",
fr: "Crépitement",
de: "Verspritzer"
},
effect: {
en: "Choose 1 of your oppenent's Pokémon. This attack does 20 damage to that Pokémon. Don't apply Weakness or Resistance.",
fr: "Choisissez un des Pokémon de votre adversaire. Cette attaque inflige 20 dégâts à ce Pokémon. N'appliquez ni la Faiblesse, ni la Résistance.",
de: "Wähle 1 der Pokémon deines Gegners. Dieser Angriff fügt diesem Pokémon 20 Schadenspunkte zu. Wende Schwäche und Resistenz nicht an."
},

View File

@@ -24,31 +24,17 @@ const card: Card = {
attacks: [{
cost: ["Water", "Colorless", "Colorless"],
cost: ["Grass"],
name: {
en: "Sleep Powder",
fr: "Poudre dodo",
de: "Dornkanone"
de: "Schlafpuder"
},
effect: {
en: "Flip a coin. If heads, the Defending Pokémon is now Asleep.",
fr: "Le Pokémon Défenseur est maintenant Endormi.",
de: "Wirf 3 Münzen. Dieser Angriff fügt 20 Schadenspunkte mal der Anzahl 'Kopf' zu."
},
damage: "20x",
}, {
name: {
de: "Schlafpuder"
},
damage: 10,
effect: {
de: "Das Verteidigende Pokémon schläft jetzt."
},
cost: ["Grass"]
}],
weaknesses: [
{

View File

@@ -14,16 +14,21 @@ const card: Card = {
set: Set,
effect: {
en: "Attach this card to 1 of you Pokémon in play, That Pokémon may use this card's attack instead of its own. At the end of your turn, discard Multi Technical Machine 01.",
fr: "Attachez cette carte à l'un de vos Pokémon en jeu. Ce Pokémon peut utiliser l'attaque de cette carte à la place de la sienne. À la fin de votre tour, défaussez-vous de Machine multi-technique 01.",
de: "Lege diese Karte an 1 deiner Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seiner eigenen verwenden. Lege am Ende deines Zuges Vielzweckmaschine 01 auf deinen Ablagestapel."
},
attacks: [{
name: {
en: "Paralyzing Gaze",
fr: "Regard paralysant",
de: "Lähmender Blick"
},
effect: {
en: "The Defending Pokémon is now Paralyzed.",
fr: "Le Pokémon Défenseur est maintenant Paralysé.",
de: "Das Verteidigende Pokémon ist jetzt gelähmt."
},

View File

@@ -14,10 +14,12 @@ const card: Card = {
attacks: [{
name: {
en: "Healing Oasis",
de: "Heilungsoase"
},
effect: {
en: "If your opponent has 5 or more Prizes, search your deck for up to 3 basic Energy cards, show them to your opponent, and put them into your hand, Shuffle your deck afterward. If your opponent has exactly 2 Prizes, remove all damage counters from 1 of your Pokémon.",
de: "Hat dein Gegner 5 oder mehr Preise, durchsuche dein Deck nach bis zu 3 Basis-Energiekarten, zeige sie deinem Gegner und nimm sie auf deine Hand. Mische dein Deck danach. Hat dein Gegner 2 Preise, entferne alle Schadensmarken von 1 deiner Pokémon."
},
@@ -25,6 +27,7 @@ const card: Card = {
}],
effect: {
en: "Attach this card to 1 of your Pokémon in play. That Pokémon may use this card's attack instead of its own. At the end of your turn, discard Mystry Plate Delta",
de: "Lege diese Karte an 1 deiner Pokémon im Spiel an. Dieses Pokémon kann den Angriff dieser Karte anstatt seines eigenen verwenden. Lege am Ende deines Zuges das Geheimnis Schild S auf deinen Ablagestapel."
}
}

View File

@@ -5,12 +5,12 @@ const set: Set = {
id: "A3",
name: {
// de: "Unschlagbare Gene",
de: "Hüter des Firmaments",
en: "Celestial Guardians",
// es: "Genes Formidables",
// fr: "Puissance Génétique",
// it: "Geni Supremi",
// pt: "Dominação Genética"
es: "Guardianes Celestiales",
fr: "Gardiens Astraux",
it: "Guardiani Astrali",
pt: "Guardiões Celestiais"
},
serie: serie,

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Quick Attack"
},
damage: 10,
damage: "10+",
cost: ["Colorless"],
effect: {
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Double Spin"
},
damage: 30,
damage: "30x",
cost: ["Grass"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Three Kick Combo"
},
damage: 50,
damage: "50x",
cost: ["Grass"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "First Impression"
},
damage: 60,
damage: "60+",
cost: ["Grass", "Grass", "Grass"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Burning Bonemerang"
},
damage: 70,
damage: "70x",
cost: ["Fire", "Fire", "Colorless"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -37,7 +37,7 @@ const card: Card = {
en: "Scar-Charged Smash"
},
damage: 80,
damage: "80+",
cost: ["Fire", "Fire", "Colorless"],
effect: {
@@ -53,4 +53,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
cost: ["Fire", "Fire", "Colorless"],
effect: {
en: "Discard a Energy from this Pokémon."
en: "Discard a Fire Energy from this Pokémon."
}
}],
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 4
}
export default card
export default card

View File

@@ -28,7 +28,7 @@ const card: Card = {
cost: ["Water"],
effect: {
en: "Take a Energy from your Energy Zone and attach it to this Pokémon."
en: "Take a Water Energy from your Energy Zone and attach it to this Pokémon."
}
}],
@@ -40,4 +40,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -32,7 +32,7 @@ const card: Card = {
},
effect: {
en: "Once during your turn, you may heal 30 damage from each of your Pokémon."
en: "Once during your turn, you may heal 30 damage from each of your Water Pokémon."
}
}],
@@ -53,4 +53,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -21,7 +21,7 @@ const card: Card = {
en: "School Storm"
},
damage: 30,
damage: "30+",
cost: ["Water", "Water", "Water"],
effect: {
@@ -37,4 +37,4 @@ const card: Card = {
retreat: 3
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Dangerous Claws"
},
damage: 60,
damage: "60+",
cost: ["Water", "Water", "Colorless"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -26,7 +26,7 @@ const card: Card = {
en: "Psychic"
},
damage: 60,
damage: "60+",
cost: ["Colorless", "Colorless", "Colorless"],
effect: {
@@ -42,4 +42,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -33,7 +33,7 @@ const card: Card = {
cost: ["Lightning", "Lightning", "Colorless", "Colorless"],
effect: {
en: "Discard 2 Energy from this Pokémon."
en: "Discard 2 Lightning Energy from this Pokémon."
}
}],
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 4
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Electrosmash"
},
damage: 20,
damage: "20+",
cost: ["Lightning"],
effect: {
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
cost: ["Lightning", "Lightning", "Lightning"],
effect: {
en: "Switch this Pokémon with 1 of your Benched Pokémon."
en: "Switch this Pokémon with 1 of your Benched Lightning Pokémon."
}
}],
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -28,7 +28,7 @@ const card: Card = {
cost: ["Psychic"],
effect: {
en: "Take a Energy from your Energy Zone and attach it to this Pokémon."
en: "Take a Psychic Energy from your Energy Zone and attach it to this Pokémon."
}
}],
@@ -40,4 +40,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Spiteful Dance"
},
damage: 20,
damage: "20+",
cost: ["Psychic"],
effect: {
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -28,7 +28,7 @@ const card: Card = {
},
effect: {
en: "Each of your Pokémon that has any Energy attached recovers from all Special Conditions and can't be affected by any Special Conditions."
en: "Each of your Pokémon that has any Psychic Energy attached recovers from all Special Conditions and can't be affected by any Special Conditions."
}
}],
@@ -49,4 +49,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
},
effect: {
en: "Once during your turn, you may move all Energy from 1 of your Benched Pokémon to your Active Pokémon."
en: "Once during your turn, you may move all Psychic Energy from 1 of your Benched Psychic Pokémon to your Active Pokémon."
}
}],
@@ -50,4 +50,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Blood Fang"
},
damage: 50,
damage: "50+",
cost: ["Fighting", "Fighting"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -24,7 +24,7 @@ const card: Card = {
},
effect: {
en: "If this Pokémon is in the Active Spot and is Knocked Out by damage from an attack from your opponent's Pokémon, move all Energy from this Pokémon to 1 of your Benched Pokémon."
en: "If this Pokémon is in the Active Spot and is Knocked Out by damage from an attack from your opponent's Pokémon, move all Fighting Energy from this Pokémon to 1 of your Benched Pokémon."
}
}],
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Unseen Claw"
},
damage: 20,
damage: "20+",
cost: ["Darkness", "Colorless"],
effect: {
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Spike Cannon"
},
damage: 20,
damage: "20x",
cost: ["Darkness"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Iron Head"
},
damage: 70,
damage: "70x",
cost: ["Metal", "Metal"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Silver Cannon"
},
damage: 40,
damage: "40+",
cost: ["Metal", "Metal"],
effect: {
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Berserk"
},
damage: 20,
damage: "20+",
cost: ["Colorless", "Colorless"],
effect: {
@@ -33,12 +33,7 @@ const card: Card = {
}
}],
weaknesses: [{
type: "Colorless",
value: "+20"
}],
retreat: 2
}
export default card
export default card

View File

@@ -29,12 +29,7 @@ const card: Card = {
cost: ["Colorless"]
}],
weaknesses: [{
type: "Colorless",
value: "+20"
}],
retreat: 1
}
export default card
export default card

View File

@@ -33,12 +33,7 @@ const card: Card = {
cost: ["Lightning", "Fighting"]
}],
weaknesses: [{
type: "Colorless",
value: "+20"
}],
retreat: 2
}
export default card
export default card

View File

@@ -37,12 +37,7 @@ const card: Card = {
}
}],
weaknesses: [{
type: "Colorless",
value: "+20"
}],
retreat: 2
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Rising Lunge"
},
damage: 50,
damage: "50+",
cost: ["Colorless", "Colorless", "Colorless"],
effect: {
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -33,7 +33,7 @@ const card: Card = {
cost: ["Colorless"],
effect: {
en: "Take a Energy from your Energy Zone and attach it to 1 of your Benched Pokémon."
en: "Take a Colorless Energy from your Energy Zone and attach it to 1 of your Benched Pokémon."
}
}],
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -25,11 +25,11 @@ const card: Card = {
en: "Justified Press"
},
damage: 20,
damage: "20+",
cost: ["Colorless"],
effect: {
en: "If your opponent's Active Pokémon is a Pokémon, this attack does 30 more damage."
en: "If your opponent's Active Pokémon is a Darkness Pokémon, this attack does 30 more damage."
}
}],
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
cost: ["Colorless", "Colorless"],
effect: {
en: "During your opponent's next turn, attacks used by the Defending Pokémon cost 1 more, and its Retreat Cost is 1 more."
en: "During your opponent's next turn, attacks used by the Defending Pokémon cost 1 Colorless more, and its Retreat Cost is 1 Colorless more."
}
}],
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Put a random Basic Pokémon from your discard pile into your hand."
en: "Put a random Basic Water Pokémon from your discard pile into your hand."
},
trainerType: "Item"
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "The Pokémon this card is attached to gets +30 HP."
en: "The Grass Pokémon this card is attached to gets +30 HP."
},
trainerType: "Tool"
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Put 1 of your Pokémon that has damage on it into your hand."
en: "Put 1 of your Colorless Pokémon that has damage on it into your hand."
},
trainerType: "Supporter"
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Choose 1 of your Alolan Marowak or Turtonator. Take 2 Energy from your Energy Zone and attach it to that Pokémon. Your turn ends."
en: "Choose 1 of your Alolan Marowak or Turtonator. Take 2 Fire Energy from your Energy Zone and attach it to that Pokémon. Your turn ends."
},
trainerType: "Supporter"
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Heal 60 damage from 1 of your Two Pokémon."
en: "Heal 60 damage from 1 of your Stage 2 Pokémon."
},
trainerType: "Supporter"
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Three Kick Combo"
},
damage: 50,
damage: "50x",
cost: ["Grass"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Burning Bonemerang"
},
damage: 70,
damage: "70x",
cost: ["Fire", "Fire", "Colorless"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
cost: ["Fire", "Fire", "Colorless"],
effect: {
en: "Discard a Energy from this Pokémon."
en: "Discard a Fire Energy from this Pokémon."
}
}],
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 4
}
export default card
export default card

View File

@@ -28,7 +28,7 @@ const card: Card = {
cost: ["Water"],
effect: {
en: "Take a Energy from your Energy Zone and attach it to this Pokémon."
en: "Take a Water Energy from your Energy Zone and attach it to this Pokémon."
}
}],
@@ -40,4 +40,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
cost: ["Lightning", "Lightning", "Lightning"],
effect: {
en: "Switch this Pokémon with 1 of your Benched Pokémon."
en: "Switch this Pokémon with 1 of your Benched Lightning Pokémon."
}
}],
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -28,7 +28,7 @@ const card: Card = {
},
effect: {
en: "Each of your Pokémon that has any Energy attached recovers from all Special Conditions and can't be affected by any Special Conditions."
en: "Each of your Pokémon that has any Psychic Energy attached recovers from all Special Conditions and can't be affected by any Special Conditions."
}
}],
@@ -49,4 +49,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Silver Cannon"
},
damage: 40,
damage: "40+",
cost: ["Metal", "Metal"],
effect: {
@@ -41,4 +41,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -25,7 +25,7 @@ const card: Card = {
en: "Berserk"
},
damage: 20,
damage: "20+",
cost: ["Colorless", "Colorless"],
effect: {
@@ -33,12 +33,7 @@ const card: Card = {
}
}],
weaknesses: [{
type: "Colorless",
value: "+20"
}],
retreat: 2
}
export default card
export default card

View File

@@ -21,7 +21,7 @@ const card: Card = {
en: "School Storm"
},
damage: 30,
damage: "30+",
cost: ["Water", "Water", "Water"],
effect: {
@@ -37,4 +37,4 @@ const card: Card = {
retreat: 3
}
export default card
export default card

View File

@@ -26,7 +26,7 @@ const card: Card = {
en: "Psychic"
},
damage: 60,
damage: "60+",
cost: ["Colorless", "Colorless", "Colorless"],
effect: {
@@ -42,4 +42,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
},
effect: {
en: "Once during your turn, you may move all Energy from 1 of your Benched Pokémon to your Active Pokémon."
en: "Once during your turn, you may move all Psychic Energy from 1 of your Benched Psychic Pokémon to your Active Pokémon."
}
}],
@@ -50,4 +50,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -24,7 +24,7 @@ const card: Card = {
},
effect: {
en: "If this Pokémon is in the Active Spot and is Knocked Out by damage from an attack from your opponent's Pokémon, move all Energy from this Pokémon to 1 of your Benched Pokémon."
en: "If this Pokémon is in the Active Spot and is Knocked Out by damage from an attack from your opponent's Pokémon, move all Fighting Energy from this Pokémon to 1 of your Benched Pokémon."
}
}],
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Put 1 of your Pokémon that has damage on it into your hand."
en: "Put 1 of your Colorless Pokémon that has damage on it into your hand."
},
trainerType: "Supporter"
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Choose 1 of your Alolan Marowak or Turtonator. Take 2 Energy from your Energy Zone and attach it to that Pokémon. Your turn ends."
en: "Choose 1 of your Alolan Marowak or Turtonator. Take 2 Fire Energy from your Energy Zone and attach it to that Pokémon. Your turn ends."
},
trainerType: "Supporter"
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Heal 60 damage from 1 of your Two Pokémon."
en: "Heal 60 damage from 1 of your Stage 2 Pokémon."
},
trainerType: "Supporter"
}
export default card
export default card

View File

@@ -21,7 +21,7 @@ const card: Card = {
en: "School Storm"
},
damage: 30,
damage: "30+",
cost: ["Water", "Water", "Water"],
effect: {
@@ -37,4 +37,4 @@ const card: Card = {
retreat: 3
}
export default card
export default card

View File

@@ -26,7 +26,7 @@ const card: Card = {
en: "Psychic"
},
damage: 60,
damage: "60+",
cost: ["Colorless", "Colorless", "Colorless"],
effect: {
@@ -42,4 +42,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
},
effect: {
en: "Once during your turn, you may move all Energy from 1 of your Benched Pokémon to your Active Pokémon."
en: "Once during your turn, you may move all Psychic Energy from 1 of your Benched Psychic Pokémon to your Active Pokémon."
}
}],
@@ -50,4 +50,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -24,7 +24,7 @@ const card: Card = {
},
effect: {
en: "If this Pokémon is in the Active Spot and is Knocked Out by damage from an attack from your opponent's Pokémon, move all Energy from this Pokémon to 1 of your Benched Pokémon."
en: "If this Pokémon is in the Active Spot and is Knocked Out by damage from an attack from your opponent's Pokémon, move all Fighting Energy from this Pokémon to 1 of your Benched Pokémon."
}
}],
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -13,10 +13,10 @@ const card: Card = {
category: "Trainer",
effect: {
en: "Heal 60 damage from 1 of your Two Pokémon."
en: "Heal 60 damage from 1 of your Stage 2 Pokémon."
},
trainerType: "Supporter"
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
en: "Psychic"
},
damage: 80,
damage: "80+",
cost: ["Grass", "Colorless", "Colorless", "Colorless"],
effect: {
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 3
}
export default card
export default card

View File

@@ -29,11 +29,11 @@ const card: Card = {
en: "Power Press"
},
damage: 70,
damage: "70+",
cost: ["Fighting", "Fighting"],
effect: {
en: "If this Pokémon has at least 2 extra Energy attached, this attack does 50 more damage."
en: "If this Pokémon has at least 2 extra Fighting Energy attached, this attack does 50 more damage."
}
}],
@@ -45,4 +45,4 @@ const card: Card = {
retreat: 2
}
export default card
export default card

View File

@@ -26,7 +26,7 @@ const card: Card = {
en: "Tropical Swing"
},
damage: 40,
damage: "40+",
cost: ["Grass"],
effect: {
@@ -42,4 +42,4 @@ const card: Card = {
retreat: 3
}
export default card
export default card

View File

@@ -33,11 +33,11 @@ const card: Card = {
en: "Hydro Bazooka"
},
damage: 100,
damage: "100+",
cost: ["Water", "Water", "Colorless"],
effect: {
en: "If this Pokémon has at least 2 extra Energy attached, this attack does 60 more damage."
en: "If this Pokémon has at least 2 extra Water Energy attached, this attack does 60 more damage."
}
}],
@@ -49,4 +49,4 @@ const card: Card = {
retreat: 3
}
export default card
export default card

View File

@@ -26,7 +26,7 @@ const card: Card = {
en: "Bonemerang"
},
damage: 80,
damage: "80x",
cost: ["Fighting", "Fighting"],
effect: {
@@ -42,4 +42,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -29,7 +29,7 @@ const card: Card = {
},
effect: {
en: "Once during your turn, you may move all Energy from 1 of your Benched Pokémon to your Active Pokémon."
en: "Once during your turn, you may move all Psychic Energy from 1 of your Benched Psychic Pokémon to your Active Pokémon."
}
}],
@@ -50,4 +50,4 @@ const card: Card = {
retreat: 1
}
export default card
export default card

View File

@@ -25,10 +25,12 @@ const card: Card = {
en: "Domed Armor",
it: "Domocorazza",
pt: "Armadura Cupular",
de: "Domrüstung"
de: "Domrüstung",
es: "Caparzón Domo",
},
effect: {
es: "Losataques hacen 30 puntos de daño menos a este Pokémon (después de aplicar Debilidad y Resistencia).",
fr: "Ce Pokémon subit 30 dégâts de moins provenant des attaques (après application de la Faiblesse et de la Résistance).",
en: "This Pokémon takes 30 less damage from attacks (after applying Weakness and Resistance).",
it: "Questo Pokémon subisce 30 danni in meno dagli attacchi, dopo aver applicato debolezza e resistenza.",
@@ -49,19 +51,9 @@ const card: Card = {
trainerType: "Item",
regulationMark: "G",
attacks: [{
name: {
es: "Caparazón Domo"
},
effect: {
es: "Los ataques hacen 30 puntos de daño menos a este Pokémon (después de aplicar Debilidad y Resistencia)."
}
}],
variants: {
holo: false
}
}
export default card
export default card

View File

@@ -25,10 +25,12 @@ const card: Card = {
en: "Helical Swell",
it: "Helixonda",
pt: "Maré Espiralada",
de: "Helixschwall"
de: "Helixschwall",
es: "Oleaje Helicoidal",
},
effect: {
es: "Mientras este Pokémon esté en el Puesto Activo, tu rival no puede jugar ninguna carta de Estadio de su mano.",
fr: "Tant que ce Pokémon est sur le Poste Actif, votre adversaire ne peut pas jouer de cartes Stade de sa main.",
en: "As long as this Pokémon is in the Active Spot, your opponent can't play any Stadium cards from their hand.",
it: "Fintanto che questo Pokémon è in posizione attiva, il tuo avversario non può giocare le carte Stadio che ha in mano.",
@@ -49,19 +51,9 @@ const card: Card = {
trainerType: "Item",
regulationMark: "G",
attacks: [{
name: {
es: "Oleaje Helicoidal"
},
effect: {
es: "Mientras este Pokémon esté en el Puesto Activo, tu rival no puede jugar ninguna carta de Estadio de su mano."
}
}],
variants: {
holo: false
}
}
export default card
export default card

View File

@@ -24,6 +24,7 @@ const card: Card = {
fr: "Protection Ambre",
en: "Amber Protection",
it: "Ambradifesa",
es: "Protección Ámbar",
pt: "Proteção Âmbar",
de: "Bernsteinschutz"
},
@@ -33,6 +34,7 @@ const card: Card = {
en: "Prevent all effects of your opponent's Pokémon's Abilities done to this Pokémon.",
it: "Previeni tutti gli effetti delle abilità dei Pokémon del tuo avversario inflitti a questo Pokémon.",
pt: "Previna todos os efeitos de Habilidades dos Pokémon do seu oponente causados a este Pokémon.",
es: "Se evitan todos los efectos de las habilidades de los Pokémon de tu rival infligidos a este Pokémon.",
de: "Verhindere alle Effekte von Fähigkeiten der Pokémon deines Gegners, die diesem Pokémon zugefügt werden."
}
}],
@@ -49,19 +51,9 @@ const card: Card = {
trainerType: "Item",
regulationMark: "G",
attacks: [{
name: {
es: "Protección Ámbar"
},
effect: {
es: "Se evitan todos los efectos de las habilidades de los Pokémon de tu rival infligidos a este Pokémon."
}
}],
variants: {
holo: false
}
}
export default card
export default card

View File

@@ -27,6 +27,7 @@ const card: Card = {
en: "Rob-'n'-Run",
fr: "Vol à la Volée",
es: "Robo y Huida",
de: "Rauben und rennen",
it: "Frega e Fuggi",
pt: "Surrupiar e Sumir"
},
@@ -35,6 +36,7 @@ const card: Card = {
en: "When you play this Pokémon from your hand to evolve 1 of your Pokémon during your turn, you may have your opponent reveal their hand, and then you choose 2 Energy cards you find there and shuffle them into your opponent's deck.",
fr: "Lorsque vous jouez ce Pokémon de votre main pour faire évoluer l'un de vos Pokémon pendant votre tour, vous pouvez demander à votre adversaire de montrer sa main. Choisissez ensuite 2 cartes Énergie que vous y trouvez et mélangez-les avec le deck de votre adversaire.",
es: "Cuando juegas este Pokémon de tu mano para hacer evolucionar a uno de tus Pokémon durante tu turno, puedes hacer que tu rival enseñe las cartas de su mano. Después, elige 2 cartas de Energía que encuentres entre ellas, ponlas en la baraja de tu rival y barájalas todas.",
de: "Wenn du dieses Pokémon aus deiner Hand spielst, um 1 deiner Pokémon während deines Zuges zu entwickeln, kannst du deinen Gegner dazu veranlassen, dir seine Handkarten zu zeigen. Wähle anschließend 2 Energiekarten, die du dort findest, und mische sie in das Deck deines Gegners.",
it: "Quando giochi questo Pokémon dalla tua mano per far evolvere uno dei tuoi Pokémon durante il tuo turno, puoi far mostrare al tuo avversario le carte che ha in mano, poi scegli due carte Energia presenti tra esse e le rimischi nel suo mazzo.",
pt: "Quando você jogar este Pokémon da sua mão para evoluir 1 dos seus Pokémon durante o seu turno, você poderá fazer com que o seu oponente revele a mão dele e, em seguida, você escolhe 2 cartas de Energia que encontrar lá e as embaralha no baralho do seu oponente."
}
@@ -49,18 +51,6 @@ const card: Card = {
es: "Cuchillada Garra",
it: "Lacerartiglio",
pt: "Golpe de Garra",
de: "Rauben und rennen"
},
damage: 60,
effect: {
de: "Wenn du dieses Pokémon aus deiner Hand spielst, um 1 deiner Pokémon während deines Zuges zu entwickeln, kannst du deinen Gegner dazu veranlassen, dir seine Handkarten zu zeigen. Wähle anschließend 2 Energiekarten, die du dort findest, und mische sie in das Deck deines Gegners."
}
}, {
cost: ["Colorless", "Colorless"],
name: {
de: "Klauenschlitzer"
},
@@ -70,10 +60,28 @@ const card: Card = {
retreat: 1,
regulationMark: "G",
illustrator: 'SIE NANAHARA',
weaknesses: [{
type: 'Grass',
value: 'x2'
}],
weight: 19.9,
height: 1.2,
evolveFrom: {
en: 'Nickit',
fr: 'Goupilou',
es: 'Nickit',
de: 'Kleptifux',
it: 'Nickit',
pt: 'Nickit'
},
variants: {
reverse: false,
normal: false
}
}
export default card
export default card

View File

@@ -90,20 +90,6 @@ const card: Card = {
}
},
{
cost: [
"Colorless",
"Colorless",
"Colorless",
],
name: {
fr: "Plante Solaire-GX",
},
effect: {
fr: "Cette attaque inflige 50 dégâts à chacun des Pokémon de votre adversaire. Si au moins 2 Énergies supplémentaires sont attachées à ce Pokémon (en plus du coût de cette attaque), soignez tous les dégâts de vos Pokémon. (Nappliquez ni la Faiblesse ni la Résistance aux Pokémon de Banc.) (Vous ne pouvez utiliser quune attaque GX par partie.)",
},
},
],
weaknesses: [
{

View File

@@ -97,19 +97,6 @@ const card: Card = {
damage: 50,
},
{
cost: [
"Grass",
],
name: {
fr: "Explosion Allergène-GX",
},
effect: {
fr: "Le Pokémon Actif de votre adversaire est maintenant Brûlé, Empoisonné et Paralysé. (Vous ne pouvez utiliser quune attaque GX par partie.)",
},
damage: 50,
},
],
weaknesses: [
{

View File

@@ -75,18 +75,6 @@ const card: Card = {
},
},
{
cost: [
"Fire",
],
name: {
fr: "Colonne de Flamme Écarlate-GX",
},
effect: {
fr: "Attachez 5 cartes Énergie de base de votre pile de défausse à vos Pokémon, de la manière que vous voulez. Si au moins une Énergie supplémentaire est attachée à ce Pokémon (en plus du coût de cette attaque), le Pokémon Actif de votre adversaire est maintenant Brûlé et Confus. (Vous ne pouvez utiliser quune attaque GX par partie.)",
},
},
],
weaknesses: [
{

View File

@@ -77,21 +77,6 @@ const card: Card = {
damage: "100+",
},
{
cost: [
"Water",
"Water",
"Colorless",
],
name: {
fr: "Lance-Bulles-GX",
},
effect: {
fr: "Le Pokémon Actif de votre adversaire est maintenant Paralysé. Si au moins 3 Énergies Water supplémentaires sont attachées à ce Pokémon (en plus du coût de cette attaque), cette attaque inflige 150 dégâts supplémentaires. (Vous ne pouvez utiliser quune attaque GX par partie.)",
},
damage: "100+",
},
],
weaknesses: [
{

Some files were not shown because too many files have changed in this diff Show More