Jump to content

Photo

Toady :)


  • Please log in to reply
25 replies to this topic

#1
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
So in my couple free hours at night, I've been entertaining an obsession called Toady.

Toady is an IRC bot. Big whoop, right? Sure. Until you change Toady's code and it takes effect without a restart, or even reconnecting it to the server. Or until you go to install a new third-party Toady mod, and you realize that Toady's entire public package manager for mods is only about 200 lines long, and half of that is jsdoc.

Obviously, Toady is written in Node.js, but recently I've been digging deeper into the core to see what I could make Node do that hasn't been widely explored yet. Things like editing the require() cache in a running application, resolving module keys, selectively rerouting stdout and stderr, and using npm programmatically to turn it into a package manager just for Toady mods.

It's nothing Earth-shattering; I mean, it's all in the Node.js docs, so it's not like I'm hacking the node source or anything. It's just that so much of it hasn't been touched in mainstream Node applications -- ESPECIALLY the concept of reloading modules without restarting the application -- that I had to play with it. And it's turned into a pretty solid and easily extensible IRC bot, to boot :). Right now there aren't a ton of third-party mods to make it fun (actually, at the time of this posting, there's exactly one), but I hope to write a few more once I can convince myself to stop tweaking the framework ;-).

Check it out: https://github.com/TomFrost/Toady

#2
Lemon

Lemon
  • Members
  • 850 posts
  • Joined: 24-February 11
  • Expertise:HTML, CSS, PHP, Javascript, Node.js, SQL
Witchcraft!

That's certainly something I never ever thought to attempt in Node and, judging by what I've seen, nobody else has really. Now you've got me trying to think of ways this could be a useful technique in anything I've built and I'm drawing a blank at the moment <_< .

#3
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL

Witchcraft!

That's certainly something I never ever thought to attempt in Node and, judging by what I've seen, nobody else has really. Now you've got me trying to think of ways this could be a useful technique in anything I've built and I'm drawing a blank at the moment <_< .

To be honest, when I decided I wanted this feature and started exploring how to do it, my first approach was to write my own implementation of 'module' and 'require', overriding require() with a call to fs.readFile() and eval'ing what I got back. Then that tiny voice inside my head saying this is so dirty oh my god this is dirty please don't do this it's so frigging dirty got the better of me and I decided to figure out how Node tracked what's already been loaded. Lo and behold, it was in the docs the whole time. Not exactly well-documented, but there nonetheless.

The more I dug, though, it turns out they really strongly recommend against ever modifying the cache, because it can often result in some nasty circular logic. And they're not wrong; so to be safe, you have to design your app structure around ensuring that there's no way a dynamically reloaded module could ever have a dependency on something involved in loading that module, or loading THAT module, or loading... you get the picture. So after banging my head off the wall for a couple hours, I realized that the core issue is that, in Node.js, modules generally require() anything they need. What if they didn't have to? What if each module was passed its dependencies by the parent sometime after it was require()'d, rather than the module loading its own dependencies when it's potentially not safe?

So I tried it. All Toady mods are functions that accept the module manager class and some other dependencies as arguments, and running that function is what returns the actual mod. So you can require() a mod without it ever touching a core dependency, and then pass the mod its main dependencies (rather than the mod finding them itself) whenever they've all been initialized and you're ready to call that function. Now I can willy-nilly delete almost anything from the cache, reload it, and not have an issue. I just call a function called unload() on each module before I drop it out of the cache so that it can detach its event listeners. (I'm still working on a way to hook node's EventEmitter to let my mod manager forcibly drop any mod's listeners without trusting that the author of the mod will do it in unload(). Nothing elegant so far, but I'm determined)

So that was my really long way of saying: This is totally awesome and incredibly useful, **especially** to upgrade applications that hold open long persistent connections like socket.io does. But to pull it off safely, you have to design your entire application around this "dependency push" pattern. Chances are, any existing application won't be compatible with the concept without a rewrite. Damn.

#4
Daniel15

Daniel15

    dan.cx

  • Moderators
  • 3,761 posts
  • Joined: 17-April 10
  • LocationMountain View, CA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
Sounds really cool! Great work, I'll definitely have to try it out :)
Daniel15! :D
Posted Image

Repeat after me: jQuery is not JavaScript. It is not the answer to every JavaScript-related question. When you have to write some JavaScript, do not instantly react with "Oh, I'll do that with jQuery!"

Spoiler

#5
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
AHAHAHAHAHA HOW COOL IS THIS:

Posted Image

One can now, while running Toady, search for third-party mods that aren't on your local machine, download and install said mod from a remote repository, and load that mod into Toady, ALL FROM IRC WITHOUT RESTARTING :D :D :D :D

(And those first few lines are me developing the mod. The search didn't work because I didn't provide a search term. So I fixed that bug, saved it, live-reloaded the mod, and then the exact same command that didn't work before started working.)

#6
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
Toady now plays Acrophobia.

I spent way too much damn time on this xD

https://github.com/T...oady-acrophobia

#7
callumacrae

callumacrae

    JavaScript Ninja

  • Members
  • 3,467 posts
  • Joined: 20-January 11
  • LocationLondon
  • Expertise:HTML, CSS, Javascript, Node.js
tl;dr: Kyek has plenty of time to be on IRC, but he hates us too much to want to be in the same channel as us

Front-end developer and writer
Twitter | GitHub | phpBB Contributor and Website Team Member | macr.ae


#8
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
Who's not on IRC *now*?

#9
callumacrae

callumacrae

    JavaScript Ninja

  • Members
  • 3,467 posts
  • Joined: 20-January 11
  • LocationLondon
  • Expertise:HTML, CSS, Javascript, Node.js
> 01:56 AM

Front-end developer and writer
Twitter | GitHub | phpBB Contributor and Website Team Member | macr.ae


#10
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
No excuse!

#11
callumacrae

callumacrae

    JavaScript Ninja

  • Members
  • 3,467 posts
  • Joined: 20-January 11
  • LocationLondon
  • Expertise:HTML, CSS, Javascript, Node.js
I had an exam at 09:15!

Front-end developer and writer
Twitter | GitHub | phpBB Contributor and Website Team Member | macr.ae


#12
TheEmpty

TheEmpty

    Less annoying than LinkedIn's Emails

  • Members
  • 5,433 posts
  • Joined: 02-October 10
  • Expertise:HTML, CSS, PHP, Java, Javascript, Python, Ruby on Rails, Node.js, SQL, MongoDB
Do we still hang out in IRC? What's the link?
all-thin-banner.jpg

#13
callumacrae

callumacrae

    JavaScript Ninja

  • Members
  • 3,467 posts
  • Joined: 20-January 11
  • LocationLondon
  • Expertise:HTML, CSS, Javascript, Node.js
Freenode / #webdevrefinery

A few of the more annoying members of wdR were banned, so it isn't annoying as it used to be

Front-end developer and writer
Twitter | GitHub | phpBB Contributor and Website Team Member | macr.ae


#14
TheEmpty

TheEmpty

    Less annoying than LinkedIn's Emails

  • Members
  • 5,433 posts
  • Joined: 02-October 10
  • Expertise:HTML, CSS, PHP, Java, Javascript, Python, Ruby on Rails, Node.js, SQL, MongoDB
... Fike... Lol, yeah I stopped when we got to the point of three trolls or so.
all-thin-banner.jpg

#15
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
Toady now has documentation on how to write your own mods. Bam.

#16
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL
I G+'ed an essay of why I wrote Toady and why I chose IRC for my dev team, if anyone's interested: https://plus.google....sts/b3CxiUc9cTC

#17
Mo3

Mo3

    HTTP 420 Enhance Your Calm

  • Moderators
  • 2,015 posts
  • Joined: 21-July 10
  • LocationBavaria
  • Expertise:PHP, Java, Javascript, Python, Ruby on Rails, Node.js, SQL, MongoDB

I G+'ed an essay of why I wrote Toady and why I chose IRC for my dev team, if anyone's interested: https://plus.google....sts/b3CxiUc9cTC


Very, very amazing. I'm currently working with node.js a lot myself and your code captivates me to no end. So easy to understand, so nice to look at, so potent.

I think I'm gonna move our communications to IRC, too. We're currently using a overly complicated PaaS called ChatWork and I would love to use IRC anyway.

Out of curiosity, what exactly is it that Toady does for you?

Node.js | Ruby on Rails | Python | PHP | Scala
What is necessary to change a person is to change his awareness of himself.


#18
callumacrae

callumacrae

    JavaScript Ninja

  • Members
  • 3,467 posts
  • Joined: 20-January 11
  • LocationLondon
  • Expertise:HTML, CSS, Javascript, Node.js
Until your bot can unlock the office door, Hubot remains the best IRC bot.

Front-end developer and writer
Twitter | GitHub | phpBB Contributor and Website Team Member | macr.ae


#19
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL

Very, very amazing. I'm currently working with node.js a lot myself and your code captivates me to no end. So easy to understand, so nice to look at, so potent.

I think I'm gonna move our communications to IRC, too. We're currently using a overly complicated PaaS called ChatWork and I would love to use IRC anyway.

Out of curiosity, what exactly is it that Toady does for you?

Thanks, glad you liked it!

My initial commit on Toady was two weeks ago and I've only really introduced my team to it in the past week, so right now the most truthful answer to "what does it do for you" is "it plays acrophobia" ;-). But the need that sparked the bot was for a channel logger with a web-based interface for viewing/searching. The only thing that comes close right now (without hacking together a few different things on Eggdrop) is Pierc, and it's a little buggy and a lot under-conceptualized. So that's one of my top priorities. Other things that we're playing with or planning are:
  • DCC send an image to the bot to have it auto-upload to a hosting service or S3 and post a link to the channel
  • Listen for Github links said in the room, respond with description, stars, forks, issues, and latest commit date. Hugely relevant in our room, where we're constantly discussing open-source options.
  • Listen for references to Jira tickets, respond with ticket link, name, and assignee
  • Command to get the git:// and https:// cloning URLs for a github repo. These URLs follow a standard format that is really not difficult to remember, but yet 90% of the time we go to github it's to get one of those urls. Our brains suck.
  • Search a repo on github for a certain string. Return results with links to line numbers in files.
  • Query Splunk, return link to results (and maybe number of results? That might be infeasible)

And on my list for generic mods to put in Ribbit are:
  • NickServ mod to auto-identify, and maybe to register too
  • A mod that allows you to change the minimum permission needed to execute any command for any other mod, core included.
  • Some way to auto-update the bot, and only restart/reconnect if code changed that's not in a core mod. Possibly. I need to think about this one.


#20
Kyek

Kyek

    Founder of wdR

  • Administrators
  • 5,527 posts
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML, CSS, PHP, Java, Javascript, Node.js, SQL

Listen for Github links said in the room, respond with description, stars, forks, issues, and latest commit date. Hugely relevant in our room, where we're constantly discussing open-source options.


Done.
ribbit install github


Posted Image




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users