---
# System prepended metadata

title: Snap Lens Discord Bot

---


# Snap Lens Discord Bot
By Aidan Wolf © 2023

Adds a Discord slash command `/lens url` which generates an embedded Lens Page within Discord from information available at any valid Snap Lens share link. Can be added to an existing Discord bot or packaged as a new one.

### **Result:**
 
Validates the url is a Lens Page link then gathers the Lens name, Lens author, Lens code, and Lens preview video and embeds them in the Discord chat.
 
![Screenshot 2023-12-08 at 12.01.17 PM](https://hackmd.io/_uploads/rklVLe-L6.png)

### Benefit:

* Reduces spam (channel can be limited to just the slash command)
* Double posting can be disallowed as Lens links can be tracked
* Increases bandwidth of content and engagement within community
* Looks cool

### Working Code (NodeJS w/ DiscordJS):
```js
client.on('interactionCreate', async interaction => {
    if (!interaction.isCommand()) return;
    const {commandName} = interaction;

    await interaction.deferReply();

    if (commandName == 'lens') {

        var lensUrl = interaction.options.getString('url')

        if (!isValidUrl(lensUrl,"lens.snapchat.com")) {
            return interaction.editReply({ephemeral:true, content:"Not a valid Lens URL"});
        }

        let domain = (new URL(lensUrl)).hostname;
        let lensId = (new URL(lensUrl)).pathname.split('?')[0].replace("/","");
        
        const config = {
            baseSiteUrl: domain,
            startUrl: lensUrl,
            concurrency: 10,
            maxRetries: 3,
        }

        const scraper = new Scraper(config);
        const root = new Root();

        const lensCode = new CollectContent('.Snapcode_medium__1Raaf', {
            name:"Snapcode_medium__1Raaf",
            getElementContent: (a, b, c) => {
                const svgUrl = c.attr('src');
                return `${svgUrl}`
            }
        });

        const lensName = new CollectContent('.LensInfo_lensName__0mdS8', {
            name:"LensInfo_lensName__0mdS8",
            getElementContent: (a, b, c) => {
                const txt = a.replace(" Lens","");
                return `${txt}`
            }
        });

        const lensLink = new CollectContent('.LensInfo_link__SGlNU', {
            name:"LensInfo_link__SGlNU",
            getElementContent: (a, b, c) => {
                const href = c.attr('href');
                return `${href}`
            },
        });

        const lensVideo = new CollectContent('.LensPreviewCard_previewVideo__tiNEH', {
            name:"LensPreviewCard_previewVideo__tiNEH",
            getElementContent: (a, b, c) => {
                const videoUrl = c.attr('src');
                return `${videoUrl}`
            }
        });

        root.addOperation(lensCode);      
        root.addOperation(lensName);
        root.addOperation(lensLink);
        root.addOperation(lensVideo);

        await scraper.scrape(root);

        const svg = lensCode.getData();
        const title = lensName.getData()[0];
        const creator = lensLink.getData()[0].split('/').pop();
        const video = lensVideo.getData()[0];
        const userId = interaction.user.id;

        const svgBuffer = Buffer.from(await fetch(svg).then(r => r.text()));
        const pngBuffer = await sharp(svgBuffer).png().toBuffer();
        const videoBuffer = await fetch(video).then(v => v.buffer());
        
        var iconAttachment = new AttachmentBuilder(pngBuffer, { name: `${lensId}.png` });
        var videoAttachment = new AttachmentBuilder(videoBuffer, { name: `${lensId}.mp4` });

        await interaction.editReply({content:`${title} by ${creator} (posted by <@${userId}>)`, files:[iconAttachment,videoAttachment]});  
    }
});
```