New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

canvacard

Package Overview
Dependencies
Maintainers
0
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

canvacard - npm Package Compare versions

Comparing version 6.0.4 to 6.0.5-dev.1733492009-c2f8775.0

2

package.json
{
"name": "canvacard",
"version": "6.0.4",
"version": "6.0.5-dev.1733492009-c2f8775.0",
"description": "Powerful image manipulation package for beginners.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -6,2 +6,3 @@ const { createCanvas, loadImage } = require("@napi-rs/canvas");

const parseSvg = require("./utils/parseSvg.utils");
const formatAndValidateHex = require("./utils/formatAndValidateHex.utils");

@@ -33,6 +34,7 @@ /**

constructor() {
this.token = "f4a26b940ef54a9a4238cef040bd08fa9001cd6c";
this.token = ""; // Requiere token válido
this.textHeader = "FORTNITE ITEMS SHOP";
this.textFooter = "Generated with canvascard";
this.options = { lang: "es", dateFormat: "dddd, MMMM Do YYYY" };
this.rows = 8;
}

@@ -55,2 +57,16 @@

/**
* @method setRows
* @name setRows
* @description Set the number of rows for the Fortnite Shop card
* @param {number} value Number of rows to set for the card
* @returns {FortniteShop} The current instance of FortniteShop
* @throws {APIError} If the value is not a number
*/
setRows(value) {
if (!value || typeof value !== "number") throw new APIError("Please provide a valid number of rows for fortnite-api.com!");
this.rows = value;
return this;
}
/**
* @method setText

@@ -81,3 +97,3 @@ * @name setText

const shopRequest = await fetch("https://fortnite-api.com/v2/shop/br/combined?language=es", {
const shopRequest = await fetch("https://fortnite-api.com/v2/shop?language=es", {
headers: { "x-api-key": this.token }

@@ -89,234 +105,211 @@ });

const shopData = await shopRequest.json();
const entries = shopData.data.featured.entries;
const entries = shopData.data.entries || [];
// Create a new arrangement for the items
// Process items same as before
let items = [];
const existingItemsSet = new Set(); // Use Set to avoid duplicates
for (const entry of entries) {
if (entry.bundle) {
// If it's a bundle, get the first item in the bundle for the rarity
const bundle = entry.bundle;
const firstItem = entry.items[0]; // Get the first item
// Add the batch to the array, using the rarity of the first item
items.push({
name: bundle.name,
type: bundle.info,
images: bundle.image,
regularPrice: entry.regularPrice,
finalPrice: entry.finalPrice,
rarity: firstItem?.rarity || { backendValue: 'EFortRarity::Common' } // Add first item rarity or default value
type: "bundle",
name: entry.bundle.name,
image: entry.bundle.image,
price: entry.finalPrice,
section: entry.section?.name || "Featured",
colors: entry.colors // Colors for gradient
});
} else {
// If it is a loose item, add only the item
entry.items.forEach(item => {
if (!existingItemsSet.has(item.name)) {
existingItemsSet.add(item.name);
items.push({
name: item.name,
type: "Article",
rarity: item.rarity,
images: item.images?.icon || item.images?.smallIcon || item.images?.featured,
finalPrice: entry.finalPrice // Add price to item object
});
}
});
} else if (entry.brItems) {
const itemData = entry.brItems.map(item => ({
type: "item",
name: item.name,
description: item.description,
rarity: item.rarity?.backendValue || "Common",
image: item.images?.featured || item.images?.icon || item.images?.smallIcon || "",
price: entry.finalPrice,
section: entry.section?.name || "Daily",
colors: item?.series?.colors // Array of colors for gradient
}));
items = items.concat(itemData);
}
}
// Sort items by finalPrice (lowest to highest)
items.sort((a, b) => b.finalPrice - a.finalPrice);
// Group items by section
const sections = {};
items.forEach(item => {
if (!sections[item.section]) sections[item.section] = [];
sections[item.section].push(item);
});
const itemsPerRow = 8; // Maximum 8 items per row
const maxRows = 10; // Maximum 10 rows
const itemWidth = 384; // Width of each item
const itemHeight = 384; // Height of each item
const padding = 15; // Space between items
const canvasWidth = itemsPerRow * itemWidth + (itemsPerRow - 1) * padding;
const canvasHeight = maxRows * itemHeight + (maxRows - 1) * padding + 300; // Extra adjustment for header
// Canvas setup with new dimensions
const itemsPerRow = this.rows;
const itemWidth = 512;
const itemHeight = 512;
const padding = 20;
const headerHeight = 100;
const sectionPadding = 60;
// Calculate total width based on sections
const canvasWidth = itemsPerRow * (itemWidth + padding) + padding;
// Calculate total height based on sections
const rows = Math.ceil(items.filter(i => i.type === "item").length / itemsPerRow) + Math.ceil(items.filter(i => i.type === "bundle").length / itemsPerRow);
const canvasHeight = rows * (itemHeight + padding) + (headerHeight + sectionPadding) + 300;
const canvas = createCanvas(canvasWidth, canvasHeight);
const ctx = canvas.getContext("2d");
// Create a blue circular radial gradient
const gradient = ctx.createRadialGradient(
canvasWidth / 2, // X center of gradient
canvasHeight / 2, // Y center of gradient
0, // Start radius (0 to start at a point)
canvasWidth / 2, // X center of gradient
canvasHeight / 2, // Y center of gradient
canvasWidth // Final radius set to canvas width
);
gradient.addColorStop(0, '#0064BD'); // Light Blue (SkyBlue)
gradient.addColorStop(1, '#001E8E'); // Dark blue
// Apply gradient as background
// Create gradient background
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, '#1e3c72');
gradient.addColorStop(1, '#2a5298');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw header
ctx.fillStyle = "#ffffff";
ctx.font = `70px ${font}`;
ctx.textAlign = "center";
ctx.fillText(this.textHeader, canvas.width / 2, 100);
ctx.fillStyle = '#ffffff';
ctx.font = `bold 60px ${font}`;
ctx.textAlign = 'center';
ctx.fillText(this.textHeader.toUpperCase(), canvas.width / 2, 70);
// Initialize position variables
let currentRow = 0;
let currentColumn = 0;
// Draw date
const date = new Date().toLocaleDateString('en-US', {
weekday: 'long',
month: 'long',
day: 'numeric',
year: 'numeric'
});
ctx.font = `30px ${font}`;
ctx.fillText(date, canvas.width / 2, 110);
// Iterate over the items and draw them on the canvas
for (const item of items) {
try {
const { name, type, rarity, images, finalPrice } = item;
// Draw sections
let currentY = headerHeight + padding;
// Calculate item position based on current column and row
const x = currentColumn * (itemWidth + padding);
const y = 200 + currentRow * (itemHeight + padding);
for (const [sectionName, sectionItems] of Object.entries(sections)) {
// Section header
ctx.font = `bold 40px ${font}`;
ctx.fillStyle = '#ffffff';
ctx.textAlign = 'left';
ctx.fillText(sectionName.toUpperCase(), padding, currentY + 40);
currentY += 60;
// Get colors by rarity
const rarityColors = this.getRarityColors(rarity.backendValue || 'EFortRarity::Common');
// Draw items in grid
let currentX = padding;
let maxRowHeight = 0;
// Draw the item background
ctx.fillStyle = rarityColors.colorCenter;
for (let i = 0; i < sectionItems.length; i++) {
const item = sectionItems[i];
ctx.fillRect(x, y, itemWidth, itemHeight); // Background for the article
if (currentX + itemWidth > canvas.width - padding) {
currentX = padding;
currentY += maxRowHeight + padding;
maxRowHeight = 0;
}
ctx.beginPath();
// Draw item card
await this.drawItemCard(ctx, item, currentX, currentY, itemWidth, itemHeight, font);
// Upload and draw the image of the item or lot
const itemIcon = await loadImage(images);
currentX += itemWidth + padding;
maxRowHeight = Math.max(maxRowHeight, itemHeight);
// If it is a loose item
ctx.drawImage(itemIcon, x, y, itemWidth, itemHeight);
ctx.globalAlpha = 1;
ctx.closePath();
ctx.save();
ctx.beginPath();
const overlay = await loadImage(`${__dirname}/../assets/images/fortnite/shop/SmallOverlay.png`);
ctx.drawImage(overlay, x, y, itemWidth, itemHeight);
ctx.closePath();
ctx.save();
ctx.globalAlpha = 1;
// Adjust the item name (lot or article)
this.drawItemName(ctx, name, x + 196, y + 310, 375, font);
// Adjust the price within the card area
await this.drawItemPrice(ctx, finalPrice, x + 192, y + 340, 200, font);
currentColumn++;
// If we reach the maximum number of columns, move to the next row
if (currentColumn >= itemsPerRow) {
currentColumn = 0;
currentRow++;
// If we reach the maximum number of rows, we are done.
if (currentRow >= maxRows) break;
if (i === sectionItems.length - 1) {
currentY += maxRowHeight + padding;
}
} catch (error) {
console.error("Error al procesar el ítem:", item, error);
// Skip the item that has an error and continue with the next one
continue;
}
currentY += sectionPadding;
}
// Footer
ctx.font = `50px ${font}`;
ctx.fillText(this.textFooter, canvas.width / 2, canvas.height - 50);
// Draw footer
ctx.fillStyle = '#ffffff';
ctx.font = `30px ${font}`;
ctx.textAlign = 'center';
ctx.fillText(this.textFooter, canvas.width / 2, canvas.height - 30);
// Save Image
const outputPath = `${__dirname}/../assets/images/fortnite/shop/output.png`;
const buffer = canvas.toBuffer("image/png");
fs.writeFileSync(outputPath, buffer);
return canvas.toBuffer("image/png");
}
// Function to obtain a numerical value according to the rarity of the item
getRarityValue(rarity) {
const rarityValues = {
"EFortRarity::Legendary": 5,
"EFortRarity::Epic": 4,
"EFortRarity::Rare": 3,
"EFortRarity::Uncommon": 2,
"EFortRarity::Common": 1
};
return rarityValues[rarity] || 0; // Use 0 by default if not found
// New method to draw colored rounded rectangles
getItemColors(item) {
if (item.type === "bundle") {
// Validar los colores a hexadecimal
const color1 = formatAndValidateHex(item.colors.color1);
const color2 = formatAndValidateHex(item.colors.color2);
return [color1, color2];
} else if (item.type === "item") {
if (item.colors) {
// Si tiene colores, toma los dos primeros y los valida
const color1 = formatAndValidateHex(item.colors[0]);
const color2 = formatAndValidateHex(item.colors[1]);
return [color1, color2];
} else {
// Si no tiene series.colors, obtiene los colores por rareza
return this.getRarityColors(item.rarity);
}
}
// Si no hay colores definidos, usa un gradiente por defecto
return ["#ffffff", "#000000"];
}
// Function to get colors based on item rarity
getRarityColors(rarity) {
const rarities = {
"EFortRarity::Legendary": { colorBorder: "#e98d4b", colorCenter: "#ea8d23" },
"EFortRarity::Epic": { colorBorder: "#e95eff", colorCenter: "#c359ff" },
"EFortRarity::Rare": { colorBorder: "#37d1ff", colorCenter: "#2cc1ff" },
"EFortRarity::Uncommon": { colorBorder: "#87e339", colorCenter: "#69bb1e" },
"EFortRarity::Common": { colorBorder: "#b1b1b1", colorCenter: "#bebebe" }
};
return rarities[rarity] || rarities.common; // Use common by default
}
// New method to draw individual item cards
async drawItemCard(ctx, item, x, y, width, height, font) {
// Function to split the name into two lines if necessary
drawItemName(ctx, text, x, y, maxWidth, font) {
ctx.font = `30px ${font}`;
ctx.fillStyle = "#ffffff";
const colors = this.getItemColors(item);
const words = text.split(' ');
let line = '';
let lineHeight = 30;
let lineCount = 0;
const maxLines = 2; // Maximum 2 lines
// Draw card background with gradient
const cardGradient = ctx.createLinearGradient(x, y, x, y + height);
cardGradient.addColorStop(0, colors[0]);
cardGradient.addColorStop(1, colors[1]);
for (let i = 0; i < words.length; i++) {
const testLine = line + words[i] + ' ';
const metrics = ctx.measureText(testLine);
const testWidth = metrics.width;
// Card shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 15;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 5;
if (testWidth > maxWidth && lineCount < maxLines - 1) {
ctx.fillText(line, x, y);
line = words[i] + ' ';
y += lineHeight;
lineCount++;
} else {
line = testLine;
}
}
// Draw the last line
ctx.fillText(line, x, y);
}
// Draw rounded rectangle
ctx.beginPath();
ctx.roundRect(x, y, width, height, 15);
ctx.fillStyle = cardGradient;
ctx.fill();
// Function to adjust the price within the card
async drawItemPrice(ctx, price, x, y, maxWidth, font) {
const vbuckIcon = await loadImage(parseSvg(`${__dirname}/../assets/images/fortnite/shop/vBucks.svg`));
const iconSize = 20;
// Reset shadow
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
// Draw the V-Bucks icon
ctx.drawImage(vbuckIcon, x - 40, y + 10, iconSize, iconSize);
// Draw item image
try {
const image = await loadImage(item.image);
const imageSize = Math.min(width - 40, height - 100);
const imageX = x + (width - imageSize) / 2;
const imageY = y + 20;
// Draw the price adjusted to the available width
ctx.font = `30px ${font}`;
ctx.fillStyle = "#ffffff";
let priceText = `${price}`;
const priceWidth = ctx.measureText(priceText).width;
// If the price exceeds the available space, adjust the font size
if (priceWidth > maxWidth - iconSize - 10) {
let fontSize = 30;
do {
fontSize -= 1;
ctx.font = `${fontSize}px ${font}`;
} while (ctx.measureText(priceText).width > maxWidth - iconSize - 10);
ctx.drawImage(image, imageX, imageY, imageSize, imageSize);
} catch (error) {
console.error(`Error loading image for ${item.name}:`, error);
}
// Draw the price text
ctx.fillText(priceText, x + iconSize, y + 30);
// Draw item name
ctx.fillStyle = '#ffffff';
ctx.font = `bold 20px ${font}`;
ctx.textAlign = 'center';
ctx.fillText(item.name, x + width / 2, y + height - 60, width - 20);
// Draw price with V-Bucks icon
ctx.font = `bold 24px ${font}`;
ctx.fillText(`${item.price} V-Bucks`, x + width / 2, y + height - 20);
}
// Updated rarity colors method
getRarityColors(rarity) {
const rarities = {
"EFortRarity::Legendary": ['#ea8d23', 'rgba(233, 141, 75, 0.9)'],
"EFortRarity::Epic": ['#c359ff', 'rgba(233, 94, 255, 0.9)'],
"EFortRarity::Rare": ['#2cc1ff', 'rgba(55, 209, 255, 0.9)'],
"EFortRarity::Uncommon": ['#69bb1e', 'rgba(135, 227, 57, 0.9)'],
"EFortRarity::Common": ['#bebebe', 'rgba(177, 177, 177, 0.9)'],
};
return rarities[rarity] || rarities["EFortRarity::Uncommon"];
}
}
module.exports = FortniteShop;

@@ -16,9 +16,11 @@ const APIError = require("./error.utils");

// Validar longitud y expandir si es necesario
if (hex.length === 3) {
// Si el código hexadecimal es menor a 6 caracteres, duplicar los caracteres
if (hex.length < 6) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
// Validar que el código tenga 6 caracteres
if (hex.length !== 6) return alt;
// Si el código hexadecimal es mayor a 6 caracteres, cortar a 6 caracteres
if (hex.length > 6) {
hex = hex.slice(0, 6);
}

@@ -25,0 +27,0 @@ // Regex para validar caracteres válidos

@@ -31,9 +31,9 @@ import Canvacard = require("./src/Canvacard");

export declare namespace MSX {
let Brightness: (img: any, amount: any) => Promise<Buffer>;
let Convolute: (img: any, matrix: any, opaque: any, lvl: any) => Promise<Buffer>;
let Darkness: (img: any, amount: any) => Promise<Buffer>;
let Greyscale: (img: any) => Promise<Buffer>;
let Invert: (img: any) => Promise<Buffer>;
let Sepia: (img: any) => Promise<Buffer>;
let Threshold: (img: any, amount?: number) => Promise<Buffer>;
let Brightness: (img: any, amount: any) => Promise<Buffer<ArrayBufferLike>>;
let Convolute: (img: any, matrix: any, opaque: any, lvl: any) => Promise<Buffer<ArrayBufferLike>>;
let Darkness: (img: any, amount: any) => Promise<Buffer<ArrayBufferLike>>;
let Greyscale: (img: any) => Promise<Buffer<ArrayBufferLike>>;
let Invert: (img: any) => Promise<Buffer<ArrayBufferLike>>;
let Sepia: (img: any) => Promise<Buffer<ArrayBufferLike>>;
let Threshold: (img: any, amount?: number) => Promise<Buffer<ArrayBufferLike>>;
let Trigger: (image: any, TRIGGERED: any) => Promise<any>;

@@ -40,0 +40,0 @@ }

@@ -1,3 +0,3 @@

declare function _exports(img: any, amount: any): Promise<Buffer>;
declare function _exports(img: any, amount: any): Promise<Buffer<ArrayBufferLike>>;
export = _exports;
//# sourceMappingURL=Brightness.d.ts.map

@@ -1,3 +0,3 @@

declare function _exports(img: any, matrix: any, opaque: any, lvl: any): Promise<Buffer>;
declare function _exports(img: any, matrix: any, opaque: any, lvl: any): Promise<Buffer<ArrayBufferLike>>;
export = _exports;
//# sourceMappingURL=Convolute.d.ts.map

@@ -1,3 +0,3 @@

declare function _exports(img: any, amount: any): Promise<Buffer>;
declare function _exports(img: any, amount: any): Promise<Buffer<ArrayBufferLike>>;
export = _exports;
//# sourceMappingURL=Darkness.d.ts.map

@@ -1,3 +0,3 @@

declare function _exports(img: any): Promise<Buffer>;
declare function _exports(img: any): Promise<Buffer<ArrayBufferLike>>;
export = _exports;
//# sourceMappingURL=Greyscale.d.ts.map

@@ -1,3 +0,3 @@

declare function _exports(img: any): Promise<Buffer>;
declare function _exports(img: any): Promise<Buffer<ArrayBufferLike>>;
export = _exports;
//# sourceMappingURL=Invert.d.ts.map

@@ -1,3 +0,3 @@

declare function _exports(img: any): Promise<Buffer>;
declare function _exports(img: any): Promise<Buffer<ArrayBufferLike>>;
export = _exports;
//# sourceMappingURL=Sepia.d.ts.map

@@ -1,3 +0,3 @@

declare function _exports(img: any, amount?: number): Promise<Buffer>;
declare function _exports(img: any, amount?: number): Promise<Buffer<ArrayBufferLike>>;
export = _exports;
//# sourceMappingURL=Threshold.d.ts.map

@@ -33,2 +33,3 @@ export = FortniteShop;

};
rows: number;
/**

@@ -44,2 +45,11 @@ * @method setToken

/**
* @method setRows
* @name setRows
* @description Set the number of rows for the Fortnite Shop card
* @param {number} value Number of rows to set for the card
* @returns {FortniteShop} The current instance of FortniteShop
* @throws {APIError} If the value is not a number
*/
setRows(value: number): FortniteShop;
/**
* @method setText

@@ -62,7 +72,6 @@ * @name setText

build(font?: string): Promise<Buffer>;
getRarityValue(rarity: any): any;
getItemColors(item: any): any;
drawItemCard(ctx: any, item: any, x: any, y: any, width: any, height: any, font: any): Promise<void>;
getRarityColors(rarity: any): any;
drawItemName(ctx: any, text: any, x: any, y: any, maxWidth: any, font: any): void;
drawItemPrice(ctx: any, price: any, x: any, y: any, maxWidth: any, font: any): Promise<void>;
}
//# sourceMappingURL=FortniteShop.d.ts.map

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc