diff --git a/app/Dockerfile b/app/Dockerfile index ddac9ee..3d8dbca 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -8,8 +8,6 @@ COPY . . # build RUN npx prisma generate RUN npm run build -# remove dev dependencies -RUN npm prune --production FROM node:alpine @@ -23,6 +21,7 @@ COPY --from=build /app/.next ./.next COPY --from=build /app/public ./public COPY --from=build /app/tools ./tools COPY --from=build /app/data ./data +COPY --from=build /app/prisma ./prisma EXPOSE 3000 CMD ["npm","run","start"] diff --git a/app/app/account/signin/page.tsx b/app/app/account/signin/page.tsx index b4eba82..c9b4f45 100644 --- a/app/app/account/signin/page.tsx +++ b/app/app/account/signin/page.tsx @@ -52,7 +52,7 @@ export default function Signin() { Connectez vous - + diff --git a/app/tools/createUser.mjs b/app/tools/createUser.mjs new file mode 100644 index 0000000..061b56d --- /dev/null +++ b/app/tools/createUser.mjs @@ -0,0 +1,51 @@ +import { PrismaClient } from '@prisma/client' +import { createHmac } from "crypto" +import 'dotenv/config' + +const secret = process.env.PASSWORD_SECRET ? process.env.PASSWORD_SECRET : "" + +const db = new PrismaClient() + +const users = [ + "zuma", + "nicolo", + "gororeznor", + "ragdub", + "onenleir", + "triskell", + "anubis", + "asmolith", + "izameh", + "lucie", + "kellaubz", + "bertrand", + "tibalt", + "jean", + "mercant", + "axel", + "aeddis", + "demo_a", + "demo_b", + "demo_c", + "demode", +] + +async function createUser(username) { + const email = username + "@example.com" + const password = username + "123" + const hashed_password = createHmac('sha256',secret).update(password).digest('hex') + const admin = true + + const user = await db.utilisateurice.create({ + data: { + username, + password: hashed_password, + email, + admin, + } + }) + + console.log(user.username) +} + +users.forEach(createUser) diff --git a/app/tools/updateDatabase.mjs b/app/tools/updateDatabase.mjs index 3d8c80c..3dc5526 100644 --- a/app/tools/updateDatabase.mjs +++ b/app/tools/updateDatabase.mjs @@ -1,15 +1,28 @@ import 'dotenv/config' import 'https' import fs from 'fs' +import { Readable } from 'stream' +import { finished } from 'stream/promises' import pg from 'pg' const { Client } = pg +console.log("Fetching latest Scryfall Bulk Data URL...") +const bulkDataApi = await fetch('https://api.scryfall.com/bulk-data') +const bulkDataApiJson = await bulkDataApi.json() +const bulkDataDownloadUrl = bulkDataApiJson.data.filter((obj) => obj.type == "unique_artwork")[0].download_uri + +console.log("Downloading latest Scryfall Bulk Data...") +const stream = fs.createWriteStream(import.meta.dirname + '/data/scryfall_data.json'); +const { body } = await fetch(bulkDataDownloadUrl); +await finished(Readable.fromWeb(body).pipe(stream)); + +console.log("Fetching latest sets list from Scryfall...") const scryfallSets = await fetch('https://api.scryfall.com/sets'); console.log('Status Code:', scryfallSets.status); - const sets = await scryfallSets.json(); // Read the data from the exported fr_cards.json extracted from Scryfall Bulk Data +console.log("Reading Bulk Data...") const fileBytes = fs.readFileSync(import.meta.dirname + '/data/scryfall_data.json') let scryfallData = JSON.parse(fileBytes) @@ -25,6 +38,7 @@ await client.connect() const two_faced_layouts = ["transform","modal_dfc","double_faced_token","reversible_card"] +console.log("Starting updating database...") try { const setRes = await client.query('SELECT id FROM set') const preUpdateSetRows = setRes.rows @@ -35,7 +49,7 @@ try { for (const set of sets.data) { if(!preUpdateSetIds.includes(set.id)){ - const addingSetQuery = await client.query('INSERT INTO set(id, name_en, sanitized_name, code, set_type, released_at, icon_svg_uri) VALUES($1, $2, $3, $4, $5, $6, $7)', [set.id, set.name, set.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), set.code, set.set_type, set.released_at, set.icon_svg_uri]) + await client.query('INSERT INTO set(id, name_en, sanitized_name, code, set_type, released_at, icon_svg_uri) VALUES($1, $2, $3, $4, $5, $6, $7)', [set.id, set.name, set.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), set.code, set.set_type, set.released_at, set.icon_svg_uri]) } } @@ -51,60 +65,77 @@ try { // Define counter for logging let total_inserted = 0 let total_skipped = 0 + let total_updated = 0 + + const total_cards = scryfallData.length // For each card check if we need to upload it to the database for (const carte of scryfallData) { - if(!preUpdateCardsIds.includes(carte.id) && carte.legalities.commander != "not_legal"){ - let type = "" - const layout = carte.layout - const card_type = (carte.type_line == undefined) ? carte.card_faces[0].type_line.toLowerCase() : carte.type_line.toLowerCase() - - let promo = (carte.promo_types == undefined) ? false : true - let can_be_commander = (card_type.includes("legendary") && (card_type.includes("creature") || card_type.includes("planeswalker"))) ? true : false - - - - if(card_type.includes("creature")){ - type = "creature" - } else if (card_type.includes("planeswalker")) { - type = "planeswalker" - } else if (card_type.includes("artifact")) { - type = "artifact" - } else if (card_type.includes("instant")) { - type = "instant" - } else if (card_type.includes("enchantment")) { - type = "enchantment" - } else if (card_type.includes("sorcery")) { - type = "sorcery" - } else if (card_type.includes("land")) { - type = "land" - } - - try { - if(two_faced_layouts.includes(layout)) { - const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, small_image_back, normal_image, normal_image_back, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)', [carte.id, carte.name, carte.released_at, carte.card_faces[0].image_uris.small, carte.card_faces[1].image_uris.small, carte.card_faces[0].image_uris.normal, carte.card_faces[0].image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander]) - - } else { - const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, normal_image, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)', [carte.id, carte.name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander]) - - } - total_inserted = total_inserted + 1 - } catch (err) { - console.log(carte.uri) - console.log(carte.layout) - console.log(err) - total_skipped = total_skipped + 1 - } - - // Add the card to the database - } else { - total_skipped = total_skipped + 1 - + const total_processed = total_skipped + total_updated + total_inserted + if ((total_processed) % 1000 == 0) { + console.log(total_processed + "/" + total_cards) } + if(carte.legalities.commander != "not_legal") { + if(!preUpdateCardsIds.includes(carte.id)){ + let type = "" + const layout = carte.layout + const card_type = (carte.type_line == undefined) ? carte.card_faces[0].type_line.toLowerCase() : carte.type_line.toLowerCase() + + let promo = (carte.promo_types == undefined) ? false : true + let can_be_commander = (card_type.includes("legendary") && (card_type.includes("creature") || card_type.includes("planeswalker"))) ? true : false + + + + if(card_type.includes("creature")){ + type = "creature" + } else if (card_type.includes("planeswalker")) { + type = "planeswalker" + } else if (card_type.includes("artifact")) { + type = "artifact" + } else if (card_type.includes("instant")) { + type = "instant" + } else if (card_type.includes("enchantment")) { + type = "enchantment" + } else if (card_type.includes("sorcery")) { + type = "sorcery" + } else if (card_type.includes("land")) { + type = "land" + } + + try { + if(two_faced_layouts.includes(layout)) { + const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, small_image_back, normal_image, normal_image_back, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)', [carte.id, carte.name, carte.released_at, carte.card_faces[0].image_uris.small, carte.card_faces[1].image_uris.small, carte.card_faces[0].image_uris.normal, carte.card_faces[0].image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander]) + + } else { + const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, normal_image, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)', [carte.id, carte.name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander]) + + } + total_inserted = total_inserted + 1 + } catch (err) { + console.log(carte.uri) + console.log(carte.layout) + console.log(err) + total_skipped = total_skipped + 1 + } + } else { + const query = 'UPDATE "carte" SET "price" = $1 WHERE "id" = $2' + try { + const updateQuery = await client.query(query, [carte.prices.eur, carte.id]) + total_updated = total_updated + 1 + } catch (err) { + total_skipped = total_skipped + 1 + console.log(err) + console.log(query) + } + } + } else { + total_skipped = total_skipped + 1 + } } console.log("Un total de " + total_inserted + " cartes ont été insérées.") console.log("Un total de " + total_skipped + " cartes ont été ignorées.") + console.log("Un total de " + total_updated + " cartes ont été mises à jour.") } catch (err) { console.error(err); } finally {