node-groupme
A GroupMe v3 API Module for NodeJS.
Available from NPM: npm install groupme
https://npmjs.org/package/groupme
For known issues, see ISSUES.md file.
This supports all 3 parts of the GroupMe API:
- The Stateless API
- The Push API, a Websocket-based message pushing service
- The Image Service API, for uploading images to messages
One use case of this library is building bots.
If you are using this library, feel free to shoot me an email with any questions! Niels Joubert njoubert@gmail.com
Getting Started
The GroupMe API is built upon the OAuth Implicit Autentication standard. This means that once you have an access token for your application, you never have to reauthenticate or mess with usernames and passwords. The access token is bound to your specific username.
For this server-side library, we assume you're writing an app using your own account (aka on the server side). If you're writing an app that sits on a client, you have to go through an extra step to get that user's access token from your application's access token.
Step 1: Obtain an Access Token.
First, you register an application with GroupMe here.
Once you've done this, you will have an access token string that you can now use to identify and authenticate yourself. You can copy this into your code directly:
const ACCESS_TOKEN = "13a14310effe0130ee234ea2b99c2231";
If you want to act on the behalf of other users, you have to send them to your redirect url, also supplied by GroupMe. Once the user authenticates, they are routed back to your application with an access token for this user.
An example of this is beyond the scope of our introduction, but you can peruse GroupMe's example or the official RFC for OAuth Implicit Grant.
Step 2: Get access to the stateless API
var API = require('groupme').Stateless
Step 3: Getting and posting data with the stateless API, using your Access Token
API.Users.me(ACCESS_TOKEN, function(err,ret) {
if (!err) {
console.log("Your user id is", ret.id, "and your name is", ret.name);
}
});
Using the Command Line Inteface to GroupMe
A simple CLI interface to the GroupMe API is one of the examples. This is useful to prototype and test, since all the commands print out the raw JSON returned from GroupMe. See it in /examples/CommandLineInterface. Simply run:
npm install .
node cli.js --help
This depends on the excellent commander.js for command line option parsing.
Examples
Examples live in the /example
directory.
Examples require that you pass it an Access Token as a command line argument
HelloWorld
This example simply requests your username and user id, and prints out the groups you belong to.
node HelloWorld.js <ACCESS_TOKEN>
HelloBot
This example uses the IncomingStream API to monitor for a message containing the words "@BOT", and replies to that with a canned message.
Step 1: Get info about your account, groups and bots
node HelloBot.js <ACCESS_TOKEN>
Step 2: Register a bot with GroupMe
node HelloBot.js <ACCESS_TOKEN> <USER_ID> <GROUP_ID> <BOT_NAME>
Step 3: Start the bot to listen for messages coming in, replying to the group it is registerd on
node HelloBot.js <ACCESS_TOKEN> <USER_ID> <BOT_ID>
PictureText
This example uploads an image to GroupMe's ImageService, which is then used to send a picture message.
It also demonstrates using EventEmitters to turn callback-based APIs into event-based APIs, a useful and alternative way to fight callback bloat.
You can use it to just upload an image:
node PictureText.js <ACCESS_TOKEN> <IMAGE_PATH>
Or you can use it to upload an image and post it as a message to a group:
node PictureText.js <ACCESS_TOKEN> <IMAGE_PATH> <GROUP_ID>
Command Line Interface.
This lets you query the stateless API from the command line.
node cli.js --help
Usage: cli.js [options] [command]
Commands:
Groups.index List the authenticated user's active groups.
Groups.former List they groups you have left but can rejoin.
Groups.show List a specific group.
Groups.create Create a new group.
Groups.update Update a group after creation.
Groups.destroy Disband a group. This action is only available to the group creator.
Members.add Add members to a group.
Members.results Get the membership results from an add call.
Messages.index Messages for a group. Return 20, can request before_id or after_id.
Messages.create Send a message to a group.
Likes.create Like a message.
Likes.destroy Unlike a liked message.
Bots.create Create a bot.
Bots.post Post a message as a bot
Bots.index List bots you have created
Bots.destroy Remove a bot that you have created
Users.me Get details about the authenticated user.
Options:
-h, --help output usage information
-V, --version output the version number
-a, --authtoken <token> Set the auth token to use
-g, --group_id <id> The group_id to use
-r, --results_id <id> The results_id to use
-m, --message_id <id> The message_id to use
-b, --bot_id <id> The message_id to use
-n, --name <string> The bot name to use
-t, --text <string> The text to use for a bot message. Be sure to quote it!
-o, --opts <JSON> supply a json object as options. Be sure to wrap it in double-quotes!
Example: Creating a bot
node cli.js -a <ACCESSTOKEN> Bots.create --name "My Bot" --group_id <GROUPID>
Example: Creating a group
node cli.js -a 02f19310adac0130ac394ea6b36c8247 Groups.create -o '{"name":"testing","description":"bookashala"}'
Promises
node Promises.js <ACCESS_TOKEN>
This prints out your group info, and shows how an error is handles.
Shows how to use the fantastic Q promise library to wrap all the callback-based Stateless API functions and create a promise-based library.
All the functions in the stateless API is patched to have a .Q function hanging off it. We can use these functions to generate promises:
API.Users.me.Q(ACCESS_TOKEN)
.then(function(da) {
return API.Groups.index.Q(ACCESS_TOKEN);
}).then(function(da) {
console.log(da);
});
Development
I welcome pull requests, emails, bug reports and the like.
That being said, this is not my full-time job. If you are using this as part of yours and want to take over as lead developer we can have that discussion.
Testing
Tests live in the /test
directory. To run them, simply type: node test.js ACCESS_TOKEN
.
Currently there is a set integration test of the entire Stateless API.
API Documentation
The code itself is fairly terse and well-commented, and is the best place to go for the full API, but here we stub out all the functionality for quick reference.
Stateless
Include it as follows: var api = require('groupme').Stateless;
Callbacks follow the node.js standard: function callback(error, data) {};
. If no error occurs, the error
parameter is null
.
Opts
are always optional, except for api.Messages.create
, and consists of a JSON object.
Promises vs Callbacks:
The default interface uses callbacks, but you can also use the Promise interface to every function, by calling promise = func.Q()
. The parameters are exactly the same, except the last callback
parameter from the original function is gone in the Promise-based version. See the Promise example and read the Q documentation.
Groups
Groups.index(access_token, callback)
List the authenticated user's active groups.Groups.former(access_token, callback)
List they groups you have left but can rejoin.Groups.show(access_token, group_id, callback)
Load a specific group.Groups.create(access_token, opts, callback)
Create a new group.- Opts consists of
{name:,description:,mage_url:,share:}
- Opts consists of
Groups.update(access_token, group_id, opts, callback)
Update a group after creation.- Opts consists of
{name:,description:,mage_url:,share:}
- Opts consists of
Groups.destroy(access_token, group_id, callback)
Disband a group. This action is only available to the group creator.
Members
Members.add(access_token, group_id, opts, callback)
Add members to a group.- Opts consists of
{members: [{nickname:, user_id:, phone_number:, email: }, ...]}
- Opts consists of
Members.results(access_token, group_id, results_id, callback)
Get the membership results from an add call.
Messages
Messages.index(access_token, group_id, opts, callback)
Get messages for a group- Opts consists of
{before_id:}
or{after_id:}
- Opts consists of
Messages.create(access_token, group_id, opts, callback)
- Opts here are required, and consists of
{message:{source_guid:, text:, attachments: [{type:"image", url:}, {type:"location", name:, lat, lng}, {type:"split", token:}, {type:"emoji", placeholder:, charmap:}]}}
- Opts here are required, and consists of
Likes
Likes.create(access_token, group_id, message_id, callback)
Like a message.Likes.destroy(access_token, group_id, message_id, callback)
Unlike a liked message.
Bots
Bots.create(access_token, name, group_id, opts, callback)
Create a bot. Associated with a specific name and group.- Opts consists of
{avatar_url:, callback_url:}
- Opts consists of
Bots.post(access_token, bot_id, text, opts, callback)
Post a message as a bot.- Opts cosists of
{picture_url:}
- Opts cosists of
Bots.index(access_token, callback)
List bots you have createdBots.destroy(access_token, bot_id, callback)
Remove a bot that you have created
Users
Users.me(access_token, callback)
Get details about the authenticated user
IncomingStream
The IncomingStream is based around a PubSub message passing approach. It extends EventEmitter, and all the asynchronous push messages coming in from the server causes events to be fired.
Initialization & Function Calls
IncomingStream(access_token, userid, groupids)
- Constructs an IncomingStream for the given token and user_id. The optional groupids parameter is an array of group ids to receive in-progress notifications from.IncomingStream.connect()
- Starts the websocket connection process, handshakes with GroupMeIncomingStream.disconnect()
- Ends the websocket connection. Canconnect()
after this again.
Include the IncomingStream as follows:
var IncomingStream = require('groupme').IncomingStream;
You can construct an IncomingStream for a given access token and user id, which will receive all messages sent to that user, regardless of group:
var iStream = new IncomingStream(ACCESS_TOKEN, USER_ID);
If you want to receive typing-in-progress notifications for specific groups, you can supply an array of group ids:
var iStream = new IncomingStream(ACCESS_TOKEN, USER_ID, [GROUP_ID1, ...]);
Events
Register for events using iStream.on(EVENT, CALLBACK);
connected
When the connection succeeds and is listening for messages.pending
When a connection is in progressdisconnected
When a connection is dropped.message
Received a message from GroupMe, passing(data)
, JSON from servererror
when a failure occurs, passing(message, payload)
status
For logging purposes, passing(message, payload)
ImageService
If you want to post images as part of messages or set your avatar, you need a URL to an image that's living on GroupMe's ImageService. This part of the API allows you to upload a raw png to GroupMe, and get a GroupMe ImageService URL back. This URL can then be used in subsequent messages and to set your avatar.
This uses the node-mime library to determine the content-type of the file.
Include it:
var ImageService = require('groupme').ImageService;
Upload an image based on a path on your server:
ImageService.post(
IMAGE_PATH,
function(err,ret) {
if (err) {
console.log(err)
} else {
console.log(ret);
}
});
API
post(path, callback)
Callback receives a JSON object with thepicture_url
of your upload.
ISSUES
For known issues, see ISSUES.md file.
LICENSE
See LICENSE file