DEV Community

Cover image for Working alone is so exhausting so I created my own assistant

Working alone is so exhausting so I created my own assistant

Min on March 15, 2022

Working alone is great... but... I am so tired of dealing with all of these.. these shitty uninspiring, repetitive, tedious tasks... I didn't real...
Collapse
 
lionelrowe profile image
lionel-rowe • Edited

As I understand is what Puppeteer gives me is not an HTML element but something else.. ( is there anybody explain a bit easy for me? i am helpless lol)

The function passed as a callback runs in the context of the headless browser, with all the relevant web APIs available. So within that function, document.querySelector gives a real live DOM element that you can manipulate however you like:

const isItARealDiv = await page.evaluate(() => {
    return document.querySelector("div") instanceof HTMLDivElement
})

isItARealDiv // true
Enter fullscreen mode Exit fullscreen mode

The problem is that when passing the return value back to the parent script, everything is serialized and then deserialized again — something similar to JSON.parse(JSON.serialize(result)). DOM elements can't be properly serialized, getting converted to undefined, so you need to return only the serializable data that you need (text content, specific attributes, inner/outer HTML, etc).

Collapse
 
happping_min profile image
Min

Thank you Lionel-rowe! ( Still confused lol)

Collapse
 
ctsstc profile image
Cody Swartz • Edited

I think Puppeteer and Selenium both suffer from the same problem -- Selenium has been around longer, likely before websites were more complicated with single page magic and dynamic content. The last thing I remembered is that if you query for something before it exists/mounts/renders you'll get nothing back, so you need to wait/poll for it to be available. I thought Puppeteer has helpers around this, or this is why people start to reach for additional libraries on top of these tools to help with this problem. It's been a while since I've touched Puppeteer or Selenium, but I do remember the pains of working with them in single page applications.

Edit: puppeteer.github.io/puppeteer/docs...

Thread Thread
 
lionelrowe profile image
lionel-rowe

@ctsstc yeah, Puppeteer gives you various APIs, such as page.waitForSelector, to deal with that, but it can be finnicky knowing exactly what you need to wait for and avoiding race conditons.

Collapse
 
lionelrowe profile image
lionel-rowe

The parent puppeteer script runs in the Node.JS runtime, whereas the callback to page.evaluate runs in the Chromium browser runtime, headlessly by default ("headless" basically just means that it runs in the background, so you can't visibly see it running). Passing complex data between runtimes is often not possible, because the different runtimes don't know how to interpret it, and DOM elements (DOM is the way the browser interprets HTML) are internally very complex. So to simplify the message passing, Puppeteer uses a serialized format that both runtimes can easily understand. The drawback is that any data that can't be converted to this serialized format is lost.

You can think of "serialized" as meaning something like flat, like a string of letters or binary digits. JSON is a typical serialization format and is useful because it allows the "flattening" of "deep" structures. For example, the JavaScript object { a: { b: 1 } } nests b within a, yet it can be serialized to the JSON string {"a":{"b":1}}. Why is this flat? Well, it's simply the character {, followed by ", followed by a, etc., so it can be read left-to-right; even though the object it represents is a tree structure.

Puppeteer does much of this JSON serialization "under the hood", so you often don't need to worry about it; but JSON can't serialize DOM nodes, because they contain circular structures, e.g. *{ a: { b: *{ a: ... } } } (where * represents a reference to the exact same object). So you need to return only things that JSON can represent — strings, numbers, booleans, null, arrays, and objects containing other JSON-able stuff.

const elementData = await page.evaluate(() => {
    const el = document.querySelector('h1')

    return {
        textContent: el.textContent, // string — OK
        childElementCount: el.childElementCount, // number — OK
        className: el.className, // string — OK
        outerHTML: el.outerHTML, // string — OK
    }
})

console.log(elementData)
// {
//     textContent: 'Posted on Mar 15'
//     childElementCount: 1,
//     className: 'fs-xs color-base-60'
//     outerHTML: '<p class="fs-xs color-base-60">Posted on <time datetime="2022-03-15T02:18:47Z" class="date-no-year" title="Tuesday, March 15, 2022, 2:18:47 AM">Mar 15</time></p>',
// }
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
happping_min profile image
Min

Omg @lionelrowe
Big thank you to explain this with full of kind detail!
This is really easy to understand! You are the best!👍👍👍👍👍

Collapse
 
joncojonathan profile image
Jonathan Haddock

Thanks for sharing this, I've contemplated making an assistant for years. Sure, I could use Google, but something more custom like you've made is more useful I feel. Maybe when I have some free time (!!!) I'll give something similar a go.

Collapse
 
happping_min profile image
Min

haha I tried siri and google assitant. They sucks because there no way to customize.
I am glad to hear you found this is useful. show your progress when you make any progress. I am sure you can make it better one!

Collapse
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

Love it 😂 i did a discord weekend project in the past and just for fun and this seems more like a month project.
Did you published it? Can i get a link to include it to my discord server? 🤩

Collapse
 
happping_min profile image
Min

It's not published because I didn't set the notion authentification per user.
it would be so embarrasing if people manage their tasks on my notion. lol

Collapse
 
joelbonetr profile image
JoelBonetR 🥇

Hahaha and what about the fun? 😅

Thread Thread
 
happping_min profile image
Min

I will consider to publish it :)

Collapse
 
atulcodex profile image
🚩 Atul Prajapati 🇮🇳

Wow my you are the Tony stark

Collapse
 
happping_min profile image
Min

Actually I considered to name it as Jarvis 😂

Collapse
 
atulcodex profile image
🚩 Atul Prajapati 🇮🇳

that's how we inspire

Collapse
 
timmortal profile image
Timmortal

To make a "Jarvis" that follows you from conception to birth and before you merge back in to the universe, is my dream

Collapse
 
incrementis profile image
Akin C.

Hello Min,

thank you for your article.
I've never looked into implementing chatbots, so this is interesting for me.
I like your creative but simple idea of ​​having a digital companion. I don't think that's sad, it's wise, because like you said
"I am so tired of dealing with all of these.. these shitty uninspiring, repetitive, tedious tasks...".

Collapse
 
happping_min profile image
Min

hehe thank you to saying that! Akin!
very glad to hear i inspire somebody with my idea 🥰

Collapse
 
tqbit profile image
tq-bit

I love the idea. If you're into shares, you might as well give the Yahoon finance API a shot. It gives you 100 free requests per day, that's more than enough for a single person. For instance, I've built a telegram bot earlier that tells me when is a good time to buy & sell

yahoofinanceapi.com/

Collapse
 
happping_min profile image
Min

Ah-ha! that’s nice idea. Maybe i can add that!

Collapse
 
jacksonkasi profile image
Jackson Kasi

wow, that's cool...

Collapse
 
happping_min profile image
Min

Thank you for saying that🥰

Collapse
 
tomaszs2 profile image
Tom Smykowski

Congrats on your project. It is extremely epic. Now please monetize it :-)

Collapse
 
happping_min profile image
Min

Thanks for saying it's epic haha

Collapse
 
tomaszs2 profile image
Tom Smykowski

Hobby money Good money :)

Collapse
 
marissab profile image
Marissa B

Good job on learning so much new stuff! That was a lot of steps and your story from start to finish was clear. I might have to make one of these.

Collapse
 
happping_min profile image
Min

Really fun project, you should try and let me know your progress!

Collapse
 
ashwinv profile image
Ashwin V

Nice, I learned many terms from this post! Keep going!😊

Collapse
 
happping_min profile image
Min

Thank you! 🥰

Collapse
 
dhravya profile image
Dhravya • Edited

Damn, this is an amazing project! Great work. Amazing discord bot!

Collapse
 
happping_min profile image
Min

Thank you for saying that🥰

Collapse
 
twitmyreview profile image
Priyab Dash

Hell I love this idea, now I need to implement it in Python and slack

Collapse
 
happping_min profile image
Min • Edited

Thank you very much! I want to see your version! please share the progress! 😊

Collapse
 
danwalsh profile image
Dan Walsh

Super impressive feat! It’s one thing to build something new; it’s a whole other thing to learn several libraries/systems in the process. Great work, never stop learning! 😇

Collapse
 
happping_min profile image
Min

hehe thank you very much Dan!

Collapse
 
dandyandy22 profile image
Andras Mihaly

Wow, I really enjoyed reading through your article! Great work on the project, this is pretty impressive! Thanks for sharing @happping_min !

Collapse
 
happping_min profile image
Min

Thank you very much Andras!😊

Collapse
 
nebocoder profile image
nebocoder

Thank you for this wonderful post. I planned on learning Discord.js to build a personal bot eventually, and I'm so glad I discovered this!

Collapse
 
happping_min profile image
Min

Please show what you make 😀

Collapse
 
billraymond profile image
Bill Raymond

This was an inspiring and well written article. Thank you!

Collapse
 
happping_min profile image
Min

Thank you very much Bill!

Collapse
 
svgatorapp profile image
SVGator • Edited

Impressive, to say the least!

Collapse
 
happping_min profile image
Min

Thank you!

Collapse
 
annetawamono profile image
Anneta Wamono

This is a great project! And I've been meaning to make a discord bot and you've really broken the process down quite well.

Collapse
 
happping_min profile image
Min

Haha thanks! Great to hear my article helps others!

Collapse
 
happping_min profile image
Min

Thanks Leonid! Yeah I like what I am doing haha

Collapse
 
fumaga_xyz profile image
Fumagalli

This project is incredible!

Collapse
 
happping_min profile image
Min

Thank you for saying that!🤗

Collapse
 
tythos profile image
Brian Kirkpatrick

This is great stuff! I love the way you approached an under-constrained problem and found a value-added approach that contributed real help to your workflow.

One thing I found when going through your steps was, of course, that different developers might want different things from an automated assistant. How did you decide what you wanted an "assistant" to do for you--that is, what were your objectives? Are there specific tedious things you seek to automate for your own workflow versus collaborative tools that support team-based efforts?

Two thumbs up!

Collapse
 
marcomoscatelli profile image
Marco Moscatelli

What node js library did you use for NPL?

Collapse
 
happping_min profile image
Min
Collapse
 
moses_110_94_111 profile image
Moses • Edited

1- great work, you built it using different languages than we did.
2-i see photo of that indian hot chick. dream about it to be your assitant. :)
3- we did it differently, ajax, js, prolog, aiml used in our bot. she has intelligence
check it out in our website. lots of videos there.
4- send me a link to go and talk with her to see how she is doing.
email: support at robot-hosting.com
have a happy time
Moses

Collapse
 
andrewbaisden profile image
Andrew Baisden

What a cool concept!

Collapse
 
cindy_bahl profile image
Cindy Bahl

Wow. Impressive. I was going to ask if you tried Character.AI for this but 'duh' it isn't meant for this type of thing. But, wow, this is cool!

Collapse
 
prodsllc profile image
Prodsllc

Thank you as well Lionel-rowe.

Collapse
 
fariddarmaji98 profile image
darmaji.code.v • Edited