common-tags#stripIndents TypeScript Examples

The following examples show how to use common-tags#stripIndents. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Ping.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
@constantly
    public async exec(msg: Message): Promise<Message> {
        const now = Date.now();
        const m = await msg.ctx.send("? Ping..");
        const embed = new MessageEmbed()
            .setColor("RANDOM")
            .setDescription(stripIndents`
                ⏱️ **RoundTrip:** \`${Math.round(Date.now()-now)}ms\`
                ⏳ **Latency:** \`${m.createdTimestamp - msg.createdTimestamp}ms\`
                ? **API:** \`${this.client.ws.ping}ms\`
            `);
        return m.edit("? Pong", embed);
    }
Example #2
Source File: CodeLinter.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
export function lint(content: string, ecmaVersion: Linter.ParserOptions["ecmaVersion"], rules: Partial<Linter.RulesRecord> ): Linter.LintMessage[] {
    if (/\bawait\b/i.test(content)) content = stripIndents`
        (async function () {
            ${content}
        })()
    `;
    const errors = linter.verify(content, {
        extends: "eslint:recommended",
        parserOptions: {
            ecmaVersion,
            sourceType: "module"
        },
        env: {
            es6: true,
            node: true
        },
        rules
    });
    return errors;
}
Example #3
Source File: Logger.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public write (head: string, value: string): void {
        const date = this.date();
        const log = stripIndents`
            ${this.equal(chalk.bold(head))}
            ${value}
            ${this.equal(chalk.grey(date))}
            \u200B
        `;
        process.stdout.write(log);
    }
Example #4
Source File: Ready.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
@constantly
    public exec (): void {
        assignDB(this.client);
        this.client.log.info(stripIndents`
            ${this.client.log.color(this.client.user!.tag, "FFFFFF")} is Ready to play. ${this.client.shard ? this.client.shard.ids.map(x => this.client.log.color(`#${x + 1}`, "00FFFF")).join(", ") : ""}
        `);
        this.client.lavalink.userID = this.client.user!.id;
        presence.call(null, this.client);
        setInterval(presence.bind(null, this.client), 60000);
    }
Example #5
Source File: Weather.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public async exec(msg: Message, { location }: { location: string }): Promise<Message> {
        const weather = await this.getWeather(location);
        if (!weather) return msg.ctx.send("? No result found");
        const embed = new MessageEmbed()
            .setColor(this.client.config.color)
            .setAuthor(`${weather.skytext}`, weather.icon)
            .setDescription(stripIndents`
                Location: **${weather.observationpoint}**
                Temprature: **${weather.temperature} ${weather.degree}**
                Feels Like: **${weather.feelslike} ${weather.degree}**
                Humidity: **${weather.humidity}**
                Precip: **${weather.precip}**
                Windspeed: **${weather.windspeed}**
            `);
        return msg.ctx.send(embed);
    }
Example #6
Source File: Lint.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public exec(msg: Message, { script, ecma }: { script: TypeCodeReturn; ecma: Linter.ParserOptions["ecmaVersion"]}, send = true): MessageEmbed|boolean {
        const embed = new MessageEmbed().setColor("RED");
        if (script.lang === "json") {
            try {
                JSON.parse(script.code);
                msg.react("734220684825329775");
                return true;
            } catch (e) {
                embed.setDescription(stripIndents`
                    ⛔ **Error**
                    ${codeBlock("js", String(e))}
                `);
                if (send) msg.ctx.send(embed);
                return embed;
            }
        }
        const errors = lint(script.code, ecma, { "no-console": 0 });
        if (!errors.length) {
            msg.react("734220684825329775");
            return true;
        }
        embed.setDescription(stripIndents`
            ⛔ **Errors**
            ${codeBlock("js", errors.map(x => `- [${x.line}:${x.column}] ${x.message}`).join("\n"))}
            ? **Annotated**
            ${codeBlock("js", this.anotate(script.code, errors))}
        `);
        if (send) msg.ctx.send(embed);
        return embed;
    }
Example #7
Source File: Jisho.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public async exec(msg: Message, { word }: { word: string }): Promise<Message|void> {
        const definition = await this.getDefinition(word);
        if (!definition) return msg.ctx.send("? No result found");
        const embed = new MessageEmbed()
            .setColor("#47DB27")
            .setAuthor(definition.form, "https://assets.jisho.org/assets/touch-icon-017b99ca4bfd11363a97f66cc4c00b1667613a05e38d08d858aa5e2a35dce055.png")
            .setDescription(stripIndents`
                Tags: ${definition.tags.length ? definition.tags.map((x: string) => `\`${x}\``).join(" ") : "None"}
                Forms: **${definition.otherforms.length ? definition.otherforms.join(", ") : "None"}**
                ${definition.senses.map((x: any) => `${x.name}: **${x.value}**`).join("\n")}
            `);
        if (definition.kanjis.length) embed.addField("Kanjis", definition.kanjis.map((x: any) => stripIndents`
            > Kanji: **${x.kanji}**
            > Means: **${x.definition}**
            > Kun: **${x.kun.length ? x.kun.join(", ") : "..."}**
            > On: **${x.on.length ? x.on.join(", ") : "..."}**
        `).join("\n\n"));
        if (definition.audio) {
            const { raw: attachment } = await request.get(`https:${definition.audio}`);
            embed.attachFiles([{ attachment, name: "pronounce.mp3" }]);
        }
        msg.ctx.send(embed);
    }
Example #8
Source File: Google.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public async exec(msg: Message, { query }: { query: string }): Promise<Message|void> {
        const results = await this.getResults(query, (msg.channel as TextChannel).nsfw);
        const pages = chunk(results.map(x => stripIndents`
            [${x.title}](${x.link})
            ${x.snippet}
        `), 4).map(x => x.join("\n\n"));
        if (!results.length) return msg.ctx.send("? **| No result**");
        const embed = new MessageEmbed()
            .setColor("#E1FAFF")
            .setAuthor(`Result for ${query}`, "http://i.imgur.com/b7k7puJ.jpg");
        await new Pagination(msg, {
            pages, embed,
            edit: (index, emb, page): MessageEmbed => emb.setDescription(page)
                .setFooter(`Page ${index+1} of ${pages.length}`)
        }).start();
    }
Example #9
Source File: Stats.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
@constantly
    public async exec(msg: Message): Promise<Message> {
        const [usersSize, channelsSize, serversSize] = this.client.shard ?
            this.parseSizeEvaluate(await this.client.shard.broadcastEval(`[
                this.users.cache.map(x => x.id),
                this.channels.cache.size,
                this.guilds.cache.size
            ]`)) : [this.client.users.cache.size, this.client.channels.cache.size, this.client.guilds.cache.size];
        const usage = process.memoryUsage();
        const embed = new MessageEmbed()
            .setColor(this.client.config.color)
            .setTitle("♪ My Current Statistic")
            .setThumbnail(this.client.user!.displayAvatarURL())
            .setDescription(codeBlock("ascii", stripIndents`
                Shard          : ${Number(msg.guild!.shardID) + 1} / ${this.client.shard ? this.client.shard.count : 1}
                Memory Usage   : ${(usage.heapUsed / 1024 / 1024).toFixed(2)} / ${Math.round(100 * (usage.heapTotal / 1048576)) / 100} MB
                Uptime         : ${moment.duration(this.client.uptime).format("YY [years] MM [month] DD [days], hh:mm:ss")}
                CPU            : ${Math.round(loadavg()[0] * 100) / 100}%
                Users          : ${usersSize.toLocaleString()}
                Channels       : ${channelsSize.toLocaleString()}
                Servers        : ${serversSize.toLocaleString()}
                WS ping        : ${this.client.ws.ping.toFixed(2)}ms
                Node           : ${process.version}
            `));
        const owners: string[] = [];
        for (const own of this.client.config.owners) {
            const owner = this.client.users.cache.get(own) || await this.client.users.fetch(own, true).catch(() => undefined);
            if (!owner) continue;
            owners.push(`• ${msg.guild!.members.cache.has(owner.id) ? owner : owner.username} (${owner.id})`);
        }
        embed.addField("? Owners", owners.join("\n"))
            .addField("\u200B", "[Github](https://github.com/youKnowOwO) | [Repository](https://github.com/youKnowOwO/yumeko)");
        return msg.ctx.send(embed);
    }
Example #10
Source File: Help.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
@constantly
    public exec(msg: Message, { command }: { command?: Command }): Promise<Message> {
        if (command) {
            const { name: category } = this.collector.categories.find(x => x.type === command.option.category)!;
            const { option } = command;
            const desc: [string, string[], number] = [
                `${msg.prefix}${option.description.usage}`,
                option.aliases.length > 1 ? option.aliases.slice(1) : ["No Aliases"],
                option.cooldown ? option.cooldown : 5
            ];
            const embed = new MessageEmbed()
                .setColor(this.client.config.color)
                .setThumbnail("https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/320/twitter/31/black-question-mark-ornament_2753.png")
                .setDescription(stripIndents`
                    __**${category} -> ${firstUpperCase(command.identifier)}**__ ${option.disable ? "**[DISABLE]**" : ""}
                    ${codeBlock("", typeof option.description.content === "string" ? option.description.content : option.description.content(msg))}
                    ${msg.ctx.lang("COMMAND_HELP_PARSE_DESC", ...desc)}
                `)
                .setFooter(msg.ctx.lang("COMMAND_HELP_INFO_ARGS"));
            if (option.description.examples.length) embed
                .addField(msg.ctx.lang("COMMAND_HELP_PARSE_EXAMPLES"), codeBlock("", option.description.examples.map(x => `${msg.prefix}${x}`).join("\n")));
            return msg.ctx.send(embed);
        }
        const embed = new MessageEmbed()
            .setColor(this.client.config.color)
            .setFooter(msg.ctx.lang("COMMAND_HELP_INFO_EXPLAIN", msg.prefix!));
        for (const category of this.collector.categories) {
            let commands = msg.author.isDev ? category.commands : category.commands.filter(x => !x.option.devOnly);
            commands = commands.filter(x => x.option.aliases.length);
            if (!commands.length) continue;
            embed.addField(category.name, commands.map(x => `\`${x.identifier}\``).join(", "));
        }
        embed.fields = embed.fields.sort((a, b) => b.value.length - a.value.length);
        return msg.ctx.send(embed);
    }
Example #11
Source File: Trivia.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public async exec(msg: Message): Promise<Message> {
        const { body }: any = await request.get("https://opentdb.com/api.php")
            .query({ amount: 1 } as any);
        let selections: string[] = body.results[0].incorrect_answers;
        const rightAnswer = body.results[0].correct_answer;
        selections.push(rightAnswer);
        selections = shuffle(selections);
        const embed = new MessageEmbed()
            .setColor("#87C5F1")
            .setAuthor("Trivia", "https://cdn.discordapp.com/emojis/449753526592208907.png")
            .setDescription(stripIndents`
                ${body.results[0].question.split("\n").map((x: string) => `> **${x}**`).join("\n")}
                ${selections.map((x, i) => `${emojis[i]} ${x}`).join("\n")}
            `);
        const result = await new SelectionPage(msg, {
            selections, emojis, embed,
            cancelEmo: "❌"
        }).start();
        if (!result) msg.channel.send(msg.ctx.lang("COMMAND_GAME_LIST_TIMEOUT"));
        if (result === rightAnswer) return msg.ctx.send(msg.ctx.lang("COMMAND_GAME_LIST_RIGHT", rightAnswer));
        return msg.ctx.send(msg.ctx.lang("COMMAND_GAME_LIST_WRONG", rightAnswer));
    }
Example #12
Source File: TicTacToe.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
@verifyWantChallange("opponent", true)
    public async exec(msg: Message, { opponent }: { opponent: User }): Promise<Message> {
        const message = await msg.channel.send(msg.ctx.lang("COMMAND_GAME_LIST_PREPARING"));
        for (const num of numbers) await message.react(num);
        const ttt = new TicTacToe();
        while (!ttt.isEnd()) {
            const user = ttt.turn ? msg.author : opponent;
            await message.edit(stripIndents`
                <:tictactoe:736370109073063946> **| ${msg.ctx.lang("COMMAND_GAME_LIST_TURN", user)}**
                > ${ttt.toString().replace(/\n/g, "\n> ")}
            `);
            if (user.bot) {
                await Util.delayFor(1000);
                ttt.placeAI(8);
                continue;
            }
            const filter = (m: MessageReaction, usr: User): boolean => numbers.includes(m.emoji.name)
                &&  usr.id === user.id
                && ttt.canPlace(...ttt.parsePosition(numbers.indexOf(m.emoji.name) + 1));
            const responses = await message.awaitReactions(filter, { max: 1, time: 30000 });
            if (!responses.size) {
                ttt.giveUp();
                break;
            }
            const index = numbers.indexOf(responses.first()!.emoji.name);
            ttt.place(...ttt.parsePosition(index + 1));
        }
        return message.edit(stripIndents`
        ${msg.ctx.lang(ttt.winner ? "COMMAND_GAME_LIST_CONGRATS" : "COMMAND_GAME_LIST_DRAW", ttt.turn ? msg.author : opponent)}
            > ${ttt.toString().replace(/\n/g, "\n> ")}
        `);
    }
Example #13
Source File: Hangman.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public getHangedMan(passes: number): string {
        return stripIndents`
            > .┌─────┐
            > .┃................┋
            > .┃................┋
            > .┃${passes > 0 ? `..............${passes > 5 ? "?" : "?"}` : ""}
            > .┃${passes > 1 ? "............../": ""} ${passes > 2 ? "|" : ""} ${passes > 3 ? "\\" : ""}
            > .┃${passes > 4 ? ".............../" : ""} ${passes > 5 ? "\\" : ""}
            > /-\\
        `;
    }
Example #14
Source File: Hangman.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public async exec(msg: Message): Promise<Message> {
        const { body }: any = await request.get("https://emilia-api.xyz/api/hangman")
            .set("Authorization", `Bearer ${process.env.EMIAPI}`);
        const word: string[] = body.word.split("");
        const guessedWords: string[] = [];
        const failedWords: string[] = [];
        let passes = 0;
        while(guessedWords.length !== new Set(word).size && passes < 7) {
            await msg.channel.send(stripIndents`
                <:hangman:736148147038060554> **| Hangman**
                ${codeBlock("", word.map(x => guessedWords.includes(x.toLowerCase()) ? x : "◯").join(" "))}
                ${this.getHangedMan(passes)}
                ${codeBlock("", failedWords.join(" "))}
            `);
            const filter = (m: Message): boolean => m.content.length < 2
                 && words.includes(m.content.toLowerCase())
                 && !guessedWords.includes(m.content.toLowerCase())
                 && !failedWords.includes(m.content.toLowerCase())
                 && msg.author.id === m.author.id;
            const responses = await msg.channel.awaitMessages(filter, { max: 1, time: 30000 });
            if (!responses.size) {
                passes = 8;
                msg.channel.send("⏱️ **| Timeout**");
                break;
            }
            const alphabet = responses.first()!.content.toLowerCase();
            if (word.includes(alphabet)) guessedWords.push(alphabet);
            else {
                failedWords.push(alphabet);
                passes++;
            }
        }
        if (passes < 7) return msg.ctx.send(msg.ctx.lang("COMMAND_GAME_LIST_RIGHT", word.join("")));
        return msg.ctx.send(msg.ctx.lang("COMMAND_GAME_LIST_WRONG", words.join("")));
    }
Example #15
Source File: GameList.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
public async exec(msg: Message, { game } : { game?: Command }): Promise<Message> {
        if (game) {
            if (this.session.has(`${msg.channel.id}/${game.identifier}`)) {
                msg.ctx.send(msg.ctx.lang("COMMAND_GAME_LIST_ONLY_ONE"));
                throw new CustomError("CANCELED");
            }
            this.session.add(`${msg.channel.id}/${game.identifier}`);
            await this.collector.runner.runCommand(msg, game);
            this.session.delete(`${msg.channel.id}/${game.identifier}`);
            return msg;
        }
        const list = this.collector.commands.filter(x => x.identifier.includes("game-"));
        const embed = new MessageEmbed()
            .setColor(this.client.config.color)
            .setDescription(list.map(x => {
                const [name, ...cmds] = x.option.description.adionalInfo!;
                return stripIndents`
                    **${name}**
                    > ${typeof x.option.description.content === "string" ? x.option.description.content : x.option.description.content(msg)}
                    *cmds: ${cmds.map(x => `\`${x}\``).join(", ")}*
                `;
            }).join("\n\n"))
            .setFooter(msg.ctx.lang("COMMAND_GAME_LIST_INFO", msg.prefix!));
        return msg.ctx.send(embed);
    }
Example #16
Source File: Connect4.ts    From yumeko with GNU Affero General Public License v3.0 6 votes vote down vote up
@verifyWantChallange("opponent", true)
    public async exec(msg: Message, { opponent }: { opponent: User }): Promise<Message> {
        const message = await msg.channel.send(msg.ctx.lang("COMMAND_GAME_LIST_PREPARING"));
        for (const num of numbers) await message.react(num);
        const c4 = new Connect4();
        while(!c4.isEnd()) {
            const user = c4.turn ? msg.author : opponent;
            await message.edit(stripIndents`
                <:connect4:745791911218118706> **| ${msg.ctx.lang("COMMAND_GAME_LIST_TURN", user)}**
                > ${c4.toString().replace(/\n/g, "\n> ")}
                > ${numbers.join("")}
            `);
            if (user.bot) {
                await Util.delayFor(1000);
                c4.placeAI(5);
                continue;
            }
            const filter = (m: MessageReaction, usr: User): boolean => usr.id === user.id
                && numbers.includes(m.emoji.name)
                && c4.canPlace(numbers.indexOf(m.emoji.name));
            const responses = await message.awaitReactions(filter, { max: 1, time: 30000 });
            if (!responses.size) {
                c4.giveUp();
                break;
            }
            const index = numbers.indexOf(responses.first()!.emoji.name);
            c4.place(index);
        }
        return message.edit(stripIndents`
            ${msg.ctx.lang(c4.winner ? "COMMAND_GAME_LIST_CONGRATS" : "COMMAND_GAME_LIST_DRAW", c4.turn ? msg.author : opponent)}
            > ${c4.toString().replace(/\n/g, "\n> ")}
            > ${numbers.join("")}
        `);
    }
Example #17
Source File: Doujin.ts    From yumeko with GNU Affero General Public License v3.0 5 votes vote down vote up
public async handleDoujinSelect(msg: Message, doujins: DoujinResponse[]): Promise<Message> {
        let index = 0;
        const embedDoujin = (doujin: DoujinResponse): MessageEmbed => {
            const tags: string[] = [];
            const desc: {[key: string]: string[] | void} = {};
            for (const tag of doujin.tags) {
                if (tag.type === "tag") tags.push(`[${tag.name}](https://nhentai.net${tag.url})`);
                else {
                    if (!desc[tag.type]) desc[tag.type] = [];
                    (desc[tag.type] as string[]).push(`[${tag.name}](https://nhentai.net${tag.url})`);
                }
            }
            const embed = new MessageEmbed()
                .setColor(0x1F1F1F)
                .setURL(`https://nhentai.net/g/${doujin.id}`)
                .setAuthor(doujin.title.english, "https://i.imgur.com/uLAimaY.png")
                .setTitle(doujin.title.japanese)
                .setDescription(stripIndents`
                    ${Object.keys(desc).map(x => `${firstUpperCase(x)}: ${(desc[x] as string[]).join(", ")}`).join("\n")}
                    Pages: \`${doujin.num_pages}\`
                    Favorites: \`${doujin.num_favorites}\`
                    Created: \`${moment(Date.now() - doujin.upload_date).format("MMMM Do YYYY, h:mm:ss a")}\`
                `)
                .setImage(`https://t.nhentai.net${doujin.images.cover.u}`);
            if (tags.length) embed.addField("Tags", tags.join(", "));
            return embed;
        };
        const list = chunk(doujins.map((x, i) => `\`${i + 1}.\` **${x.title.english}**`), 10).map(x => x.join("\n"));
        const embed = new MessageEmbed()
            .setColor(0x1F1F1F)
            .setAuthor("Search Result", "https://i.imgur.com/uLAimaY.png")
            .setDescription(list[index])
            .setFooter(`Page ${index + 1} / ${list.length} • if you wannt to see detail of the doujin just type the number`);
        let selectedDoujin: DoujinResponse | undefined;
        if (doujins.length < 2) selectedDoujin = doujins[0];
        const message = await msg.channel.send(selectedDoujin ? embedDoujin(selectedDoujin) : embed);
        const emojis = ["⏪", "⬅️", "➡️", "⏩"];
        await message.react("?");
        if (list.length > 1) for (const emoji of emojis) await message.react(emoji);
        if (selectedDoujin) await message.react("?");
        return new Promise(resolve => {
            const reactionCollectorFilter = (react: MessageReaction, usr: User): boolean => (["?", ...(selectedDoujin ? ["?", "?"] : emojis)].includes(react.emoji.name)) && usr.id === msg.author.id;
            const messageCollectorFilter = (mess: Message): boolean => !selectedDoujin && !isNaN(Number(mess.content)) && msg.author.id === mess.author.id;
            const messageCollector = msg.channel.createMessageCollector(messageCollectorFilter)
                .on("collect", col => {
                    const num = parseInt(col.content);
                    if (num < 1 && num > doujins.length) return undefined;
                    selectedDoujin = doujins[num - 1];
                    message.edit(embedDoujin(selectedDoujin));
                    message.react("?").then(() => message.react("?"));
                });
            const reactionCollector = message.createReactionCollector(reactionCollectorFilter)
                .on("collect", col => {
                    if (col.emoji.name === "?") {
                        (messageCollector as Collector<string, Message>).stop();
                        (reactionCollector as Collector<string, MessageReaction>).stop();
                        return resolve(msg);
                    } else if (col.emoji.name === "?") {
                        (messageCollector as Collector<string, Message>).stop();
                        (reactionCollector as Collector<string, MessageReaction>).stop();
                        message.delete();
                        return resolve(this.handleRead(msg, selectedDoujin!));
                    } else if (col.emoji.name === "?") {
                        if (doujins.length < 2) return undefined;
                        selectedDoujin = undefined;
                        embed.setDescription(list[index]).setFooter(`Page ${index + 1} / ${list.length} • if you wannt to see detail of the doujin just type the number`);
                        message.edit(embed);
                    } else {
                        if (!list.length) return undefined;
                        index += [-10, -1, 1, 10][emojis.indexOf(col.emoji.name)];
                        index = ((index % list.length) + list.length) % list.length;
                        embed.setDescription(list[index]).setFooter(`Page ${index + 1} / ${list.length} • if you wannt to see detail of the doujin just type the number`);
                        message.edit(embed);
                    }
                });
        });
    }
Example #18
Source File: Minesweeper.ts    From yumeko with GNU Affero General Public License v3.0 5 votes vote down vote up
public async exec(msg: Message): Promise<Message> {
        const message = await msg.channel.send("?️ Preparing...");
        for (const alphabet of alphabets) await message.react(alphabet);
        for (const num of numbers) await message.react(num);
        const minesweeper = new Minesweeper();
        let isFlag = false as boolean;
        const flagListener = message.createReactionCollector((react: MessageReaction, usr: User): boolean => react.emoji.name === "?" && !!minesweeper.board.length && usr.id === msg.author.id)
            .on("collect", () => {
                isFlag = !isFlag;
                message.edit(stripIndents`
                    ? **| Minesweeper**
                    > ${isFlag ? "?" : "⬛"}${alphabets.map((_, i) => `:regional_indicator_${String.fromCharCode(97 + i)}:`).join("")}
                    ${minesweeper.toString().split("\n").map((x, i) => `> ${numbers[i]}${x}`).join("\n")}
                `);
            });
        while(!minesweeper.isEnd()) {
            await message.edit(stripIndents`
                ? **| Minesweeper**
                > ${isFlag ? "?" : "⬛"}${alphabets.map((_, i) => `:regional_indicator_${String.fromCharCode(97 + i)}:`).join("")}
                ${minesweeper.toString().split("\n").map((x, i) => `> ${numbers[i]}${x}`).join("\n")}
            `);
            let alphaSelect = true;
            const filter = (react: MessageReaction, usr: User): boolean => {
                if (usr.id !== msg.author.id) return false;
                if (!(alphaSelect ? alphabets : numbers).includes(react.emoji.name)) return false;
                alphaSelect = !alphaSelect;
                return true;
            };
            const responses = await message.awaitReactions(filter, { max: 2, time: 30000 });
            if (!responses.size) break;
            const [col, line] = responses.map(x => alphabets.includes(x.emoji.name) ? alphabets.indexOf(x.emoji.name) : numbers.indexOf(x.emoji.name));
            minesweeper[isFlag ? "flag" : "dig"](line, col);
            if (minesweeper.board.length) await message.react("?");
        }
        (flagListener as Collector<string, MessageReaction>).stop();
        return message.edit(stripIndents`
            ${msg.ctx.lang(minesweeper.isEnd() ? (minesweeper.isDoughBomb ? "COMMAND_GAME_MINESWEEPER_DOUGH_BOMB" : "COMMAND_GAME_MINESWEEPER_WIN") : "COMMAND_GAME_LIST_TIMEOUT")}
            > ⬛${alphabets.map((_, i) => `:regional_indicator_${String.fromCharCode(97 + i)}:`).join("")}
            ${minesweeper.toString().split("\n").map((x, i) => `> ${numbers[i]}${x}`).join("\n")}
        `);
    }
Example #19
Source File: MetaManager.ts    From obsidian-banners with MIT License 5 votes vote down vote up
// Upsert banner data into a file's frontmatter
  async upsertBannerData(fileOrPath: TFile | string, data: Partial<IBannerMetadata>) {
    const file = (fileOrPath instanceof TFile) ? fileOrPath : this.getFileByPath(fileOrPath);
    if (!file) { return }

    // Get banner data based on the designated prefix for banner data fields
    const { src, x, y, icon, lock } = data;
    const baseName = this.plugin.getSettingValue('frontmatterField');
    const trueFields: Partial<IBannerMetadata> = {
      ...(src !== undefined && { [baseName]: src }),
      ...(x !== undefined && { [`${baseName}_x`]: x }),
      ...(y !== undefined && { [`${baseName}_y`]: y }),
      ...(icon !== undefined && { [`${baseName}_icon`]: icon }),
      ...(lock !== undefined && { [`${baseName}_lock`]: lock })
    };

    const fieldsArr = Object.keys(trueFields) as Array<keyof IBannerMetadata>;
    const content = await this.vault.read(file);
    const lines = content.split('\n');
    const yamlStartLine = lines.indexOf('---');
    const hasYaml = yamlStartLine !== -1 && lines.slice(0, yamlStartLine).every(l => !l);
    let changed = false;
    if (hasYaml) {
      // Search through the frontmatter to update target fields if they exist
      let i;
      for (i = yamlStartLine + 1; i < lines.length && fieldsArr.length; i++) {
        if (lines[i].startsWith('---')) { break }

        const [key, val] = lines[i].split(': ') as [keyof IBannerMetadata, string];
        const targetIndex = fieldsArr.indexOf(key);
        if (targetIndex === -1) { continue }

        const newVal = trueFields[key];
        if (val !== newVal) {
          lines[i] = `${key}: ${newVal}`;
          changed = true;
        }
        // lines[i] = `${key}: ${trueFields[key]}`;
        fieldsArr.splice(targetIndex, 1);
      }

      // Create new fields with their value if it didn't exist before
      if (fieldsArr.length) {
        lines.splice(i, 0, ...this.formatYamlFields(fieldsArr, trueFields));
        i += fieldsArr.length;
        changed = true;
      }

      // Add YAML ending separator if needed
      const end = lines.indexOf('---', i);
      if (end === -1) {
        lines.splice(i, 0, '---');
        changed = true;
      }
    } else {
      // Create frontmatter structure if none is found
      lines.unshift(stripIndents`
        ---
        ${this.formatYamlFields(fieldsArr, trueFields).join('\n')}
        ---
      `);
      changed = true;
    }

    // Skip write if no change was made
    if (!changed) { return }

    const newContent = lines.join('\n');
    await this.vault.modify(file, newContent);
  }
Example #20
Source File: compileBreakpointsCssVarsDeclaration.ts    From vkui-tokens with MIT License 4 votes vote down vote up
/**
 * Компилирует медиаквери переходы между переменными
 * @param sourceTheme
 * @param type
 */
// eslint-disable-next-line sonarjs/cognitive-complexity
export function compileBreakpointsCssVarsDeclaration<T = Theme>(
	sourceTheme: ThemeCssVarsWide<T, Extract<keyof T, 'breakpoints'>>,
	type: DeclarationType = 'default',
): string | null {
	if (!('breakpoints' in sourceTheme)) {
		return null;
	}
	const breakpoints = sourceTheme['breakpoints'];
	const customMedia = processCustomMedia(sourceTheme as any);

	const theme: ThemeCssVarsWide<T> =
		type === 'onlyColors' ? getOnlyColors(sourceTheme) : sourceTheme;

	const {adaptiveValues} = accumulateValues<any>({
		theme,
	});

	let result = '';

	if (!Object.keys(adaptiveValues.auto).length) {
		return null;
	}

	result += stripIndent`
	:root {
${getVarString({valuesObject: adaptiveValues.auto, prefix: '\t\t'})}
	}`;

	const adaptivityStatesLength = Object.keys(adaptiveValues).length;

	// только regular и auto
	if (adaptivityStatesLength === 2) {
		return result;
	}

	let regularValues = '';
	let mediaValues = '';

	Object.entries(adaptiveValues)
		.sort(([a]) => (a === 'regular' ? 1 : -1))
		.forEach(([adaptivityState, valuesObject]) => {
			const isRegular = adaptivityState === 'regular';

			if (adaptivityState === 'auto') {
				return;
			}

			const usedViewport = findViewportByAdaptivityState(
				breakpoints,
				adaptivityState as keyof Adaptive<any>,
			);

			mediaValues += stripIndent`
			@media ${customMedia[`width${capitalize(usedViewport)}`]} {
				:root, .vkui--force-auto {
					${stripIndents(
						isRegular
							? regularValues
							: getVarString({
									valuesObject,
									prefix: '',
									callback: (name) => {
										if (isRegular) {
											return;
										}

										const regularName = name.replace(
											new RegExp(`${adaptivityState}$`),
											'regular',
										);
										const regularValue =
											adaptiveValues.regular[regularName];
										if (regularValue) {
											regularValues += `${regularName}: ${regularValue};\n`;
										}
									},
							  }),
					)}
				}
			}

			.vkui--force-${convertCamelToSnake(usedViewport)} {
				${stripIndents(
					isRegular
						? regularValues
						: getVarString({
								valuesObject,
								prefix: '',
						  }),
				)}
			}
			`;

			mediaValues += '\n\n';
		});

	return stripIndent(`${result}\n\n${mediaValues}`);
}