Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ Entry structure must be as follows:

This field is needed because some addresses in TON have to be in other format (UQ vs EQ). The address itself can be in any format, just set the correct `type`.

## Adding images
Use the `avatars` directory to add images to addresses. The image name must be a TON address in any format. Acceptable image extensions: `jpg`, `jpeg`, `png`, `webp`

After the build, the images will be available in the `/build/img` folder in three address formats (raw/bounced/non-bounced).


## Building
```bash
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 88 additions & 1 deletion index.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { readdir, readFile, writeFile } from 'node:fs/promises';
import { readdir, readFile, writeFile, mkdir } from 'node:fs/promises';
import { parseAllDocuments } from 'yaml'
import TonWeb from 'tonweb';
import { join, extname, basename } from 'node:path';
import sharp from 'sharp';

const CONTRACT_TYPES = [
'wallet',
Expand All @@ -11,6 +13,8 @@ const CONTRACT_TYPES = [

const YAML_DIRECTORY = './source/';
const BUILD_DIRECTORY = './build/';
const AVATARS_DIRECTORY = './avatars/';
const IMG_DIRECTORY = './build/img/';

/**
* @param {String} address
Expand Down Expand Up @@ -121,10 +125,93 @@ const saveAddressbook = async function createAndWriteAddressbookJson(directory =
return addresses;
};

/**
* @param {String} addressString
* @return {Object}
*/
const generateAddressVariants = function generateRawBouncedNonBouncedAddresses(addressString) {
try {
const address = new TonWeb.utils.Address(addressString);

// Raw
const raw = address.toString(false);

// Bounced (EQ...)
const bounced = address.toString(true, true, true, false);

// Non-bounced (UQ...)
const nonBounced = address.toString(true, true, false, false);

return { raw, bounced, nonBounced };
} catch (error) {
throw new Error(`Invalid address format: ${addressString} - ${error.message}`);
}
};

/**
* @return {Promise<void>}
*/
const copyAvatars = async function copyAvatarsToBuildImgWithoutExtension() {
try {
await mkdir(IMG_DIRECTORY, { recursive: true });

const files = await readdir(AVATARS_DIRECTORY);

// Filter only images
const imageExtensions = ['.jpg', '.jpeg', '.png', '.webp', '.svg'];
const imageFiles = files.filter(file => {
const ext = extname(file).toLowerCase();
return imageExtensions.includes(ext);
});

let processedCount = 0;

for (const imageFile of imageFiles) {
const imagePath = join(AVATARS_DIRECTORY, imageFile);
const addressString = basename(imageFile, extname(imageFile));

try {
// Generating raw/bounced/non-bounced forms of address
const variants = generateAddressVariants(addressString);

const image = sharp(imagePath);

for (const variant of Object.values(variants)) {
const outputFileName = `${variant}.w200.webp`;
const outputPath = join(IMG_DIRECTORY, outputFileName);

await image
.resize(200, 200, {
fit: 'cover',
position: 'center'
})
.webp({ quality: 85 })
.toFile(outputPath);
}

processedCount++;
} catch (error) {
console.warn(`Failed to process ${imageFile}: ${error.message}`);
}
}

console.log(`Successfully processed ${processedCount} images, generated ${processedCount * 3} variants to ${IMG_DIRECTORY}`);
} catch (error) {
if (error.code === 'ENOENT') {
console.log('Avatars directory not found, skipping image copy');
} else {
throw error;
}
}
};

// Save addressbook if command line has build argument:
if (process.argv.slice(2).includes('build')) {
const addresses = await saveAddressbook();
console.log(`Successfully created addressbook with ${addresses.size} addresses`);

// Create images directory and copy avatars to it
await copyAvatars();

// Just test otherwise:
} else {
Expand Down
Loading