Skip to content

Instantly share code, notes, and snippets.

@lucaronca
Last active March 27, 2018 09:50
Show Gist options
  • Save lucaronca/1d3964362d82a001c27af1e4a62bea50 to your computer and use it in GitHub Desktop.
Save lucaronca/1d3964362d82a001c27af1e4a62bea50 to your computer and use it in GitHub Desktop.
Script to get the stickers configuration reading from a given folder containing them
/**
*
* Install global modules: yarn global add typescript ts-node
* Install image utility libraries: npm i svgson calipers calipers-png
* Launch with ts-node ex:
* curl -sL <script_shortlink> -o ./c.ts && ts-node <path_to_sticker_folder> && rm ./c.ts
*
**/
const { promisify } = require('util')
const { resolve, extname, basename } = require('path')
const {
readdir: nodeReaddir,
readFile: nodeReadFile,
writeFile: nodeWriteFile,
stat: nodeStat,
lstatSync,
} = require('fs')
const svgson = require('svgson')
const calipers = require('calipers')('png');
const readdir = promisify(nodeReaddir)
const readFile = promisify(nodeReadFile)
const writeFile = promisify(nodeWriteFile)
const stat = promisify(nodeStat)
const stickerFolder = process.argv[2]
const destinationFile = resolve('./stickers.js')
const folderNames = {
base: 'SVG',
thumb: '1x',
}
interface Images {
mediaThumb: {
uri: String
width: 244
height: 165
}
mediaBase: {
uri: String
width: Number
height: Number
}
}
interface Sticker {
identifier: String
defaultName: String
images: Images
}
interface Category {
identifier: String
defaultName: String
stickers: Array<Sticker>
}
interface StickerConfig {
categories: Array<Category>
replaceCategories: true
}
async function listSVGsForCategory(category: string): Promise<Array<string>> {
try {
const SVGFolder = resolve(stickerFolder, category, folderNames.base)
return readdir(SVGFolder)
} catch (e) {
console.log(`can't read folder for ${category} category`);
throw e
}
}
function labelify(string: string): string {
const capitalized: string = string.charAt(0).toUpperCase() + string.slice(1)
return capitalized.replace(new RegExp('-', 'g'), ' ')
}
async function listCategories(folder: string): Promise<Array<string>> {
try {
const items: Array<string> = await readdir(folder)
return items.filter((item): boolean => lstatSync(resolve(folder, item)).isDirectory())
} catch (e) {
throw e
}
}
function getFileName(file: string): string {
return basename(file, extname(file))
}
function isNotCategoryBadge(stickerName: string): boolean {
return !getFileName(stickerName).endsWith('-0-cover')
}
async function getSticker(category: string, svgName: string): Promise<Sticker> {
try {
const filePath: string = resolve(stickerFolder, category, folderNames.base, svgName)
const stickerName: string = getFileName(filePath)
const svgContent: string = await readFile(filePath, 'utf8')
let viewBox: Array<number>
try {
viewBox = await new Promise<Array<number>>((res) => {
svgson(svgContent, {}, result => {
res(result.attrs.viewBox.split(' ').map((dimension): number => parseInt(dimension)))
})
})
} catch(e) {
// can't retrieve viewBox, maybe sticker file is just a png (this could happen with PE default stickers)
// read dimensions and put it in a mocked viewBox
const result = await calipers.measure(filePath)
viewBox = [0, 0, result.pages[0].width, result.pages[0].height]
}
return <Sticker> {
identifier: stickerName,
defaultName: labelify(stickerName),
images: {
mediaThumb: {
uri: `stickers/${category}/${folderNames.thumb}/${stickerName}.png`,
width: 244,
height: 165,
},
mediaBase: {
uri: `stickers/${category}/${folderNames.base}/${stickerName}${extname(filePath)}`,
width: viewBox[2],
height: viewBox[3],
}
}
}
} catch (e) {
console.log(`can't read svg: ${svgName} in ${category} category`)
throw e
}
}
(async (): Promise<void> => {
try {
const categoriesList: Array<string> = await listCategories(stickerFolder)
const categories: Array<Category> = await Promise.all(
categoriesList.map(async (category): Promise<Category> => {
const SVGs: Array<string> = await listSVGsForCategory(category)
const stickers: Array<Sticker> = await Promise.all(
SVGs
.filter(isNotCategoryBadge)
.map(async (svgName): Promise<Sticker> => getSticker(category, svgName))
)
return <Category> {
identifier: category,
defaultName: labelify(category),
stickers,
}
})
)
const configuration: StickerConfig = {
categories,
replaceCategories: true,
}
const stickerFileContent: string = `export default ${JSON.stringify(configuration, null, 2)}`
await writeFile(destinationFile, stickerFileContent)
console.log('Sticker configuration written in:', destinationFile)
} catch (e) {
throw e
}
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment