npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

stakeout

v0.6.0

Published

For watching a set of URLs and notifying someone when something has changed.

Downloads

8

Readme

Stakeout

For watching a set of URLs and notifying someone when something has changed.

Step 1. Install Stakeout

npm install -g stakeout

Step 2. Create a task

A task is a comparison function. It should be a module that exports a single function like so:


module.exports = function compare(oldValue,callback) {

  // Figure out what the new value is
  // Figure out whether there's a notification to send (has something changed?)
  // Call the callback
  callback(err,newValue,notificationMessage);

};

The function will be passed the previous value for the task, and a callback function. Once the task has figured out the new value and whether there's any notification text, it should call the callback.

A value can be anything that's JSON-serializable. A string, a number, an array, a hashmaptionary, etc.

Here's a crude example task that checks to see if there are any new links on a page:


var request = require("request"),
    cheerio = require("cheerio");

module.exports = function compare(oldValue,callback) {

  request("http://www.somewebsite.com",function(err,response,body){

    if (err) {
      return callback(err);
    }

    // On the first run, oldValue will be undefined
    // Make sure to catch that
    if (!oldValue) {
      oldValue = [];
    }

    var links = [],
        newLinks = [],
        notificationText;

    cheerio.load(body)("a").each(function(){

      var url = $(this).attr("href");

      links.push(url);

      if (oldValue.indexOf(url) === -1) {
        newLinks.push(url);
      }

    });

    if (newLinks.length) {
      notificationText = "New links found: " + newLinks.join(", ");
    }

    callback(null,links,notificationText);

  });

};

The first argument to the callback is an error message. If it's anything but falsey, the script will exit with an error. The second argument is the new value to save (which will become the old value during the next run). The third optional value is a notification message. If it's not falsey, it will be sent to every email/Slack address that's watching the task.

Step 3. Add the task to stakeout

stakeout add task-name -p /absolute/path/to/module

Step 4. Add some people to be notified

Watchers can be email addresses, Slack usernames or Slack channels. Preface Slack usernames with @. Channel names start with #, which is interpreted on the command line as the start of a comment. So either enclose the whole channel name in quotes or escape the # using \#:

stakeout watch task-name [email protected],@john,'#notifications',\#botnotes

Step 5. Create a cronjob for the task

To check every minute:

* * * * * stakeout run task-name

Commands

Run a task

stakeout run task-name

Run all the tasks

stakeout runall

Create a new task (path is required, description is optional):

stakeout add task-name -p /absolute/path/to/bot -d "Description of this task"

Delete a task:

stakeout remove task-name

List existing tasks:

stakeout list

Rename a task:

stakeout rename old-name new-name

Add email notifications for someone:

stakeout watch task-name [email protected]

Add Slack notifications for someone:

stakeout watch task-name @person

Remove notifications for someone:

stakeout unwatch task-name [person]

Set up options like API keys and email metadata:

stakeout config

Clean out stored data for a particular task:

stakeout clean task-name

Clean out all stored task data:

stakeout cleanall

Notes

Config for bots is stored as YAML in ~/.stakeout/config. You can edit it manually there.

To send email notifications, you need to set a few options, especially a Mailgun API key. To send Slack notifications, you need to set a few options, especially a Slack incoming webhook URL. You can add these all using stakeout config or edit them manually in ~/.stakeout/config:

MAILGUN_API_KEY: def456
EMAIL_FROM: 'Data News Team <[email protected]>'
EMAIL_SUBJECT_PREFIX: 'Data News Bot: '
SLACK_NAME: Data News Bot
SLACK_ICON: ':robot:'
SLACK_WEBHOOK_URL: 'https://hooks.slack.com/services/ABC123...'
tasks:
  task-name:
    ...

The most recent value returned by a given task will be saved in ~/.stakeout/task-name.json. Notifiations aren't sent the first time the bot runs because nothing has yet changed.

Why?

These sorts of "watch to see if a certain thing has happened/changed" bots can come in a lot of different flavors. It's hard to abstract out the actual checking. stakeout assumes that each bot will still need to be written by hand, but tries to abstract out the plumbing of keeping track of current values over time for comparison, and sending notifications. It's probably overkill.

To Do

  • Build in handler for "Have this URLs contents changed at all?"
  • Make this handle the scheduling instead of requiring separate cronjobs per task
  • Rewrite these docs more thoroughly
  • Include some example bots