Skip to main content

GroupMe Push Client

A client for the GroupMe push service (Faye). It opens a websocket to GroupMe and calls your functions when messages, DMs and likes arrive.

Installation

pip install groupme-push, or clone the repo and run pip install .

Quick start

from groupme_push import PushClient

def on_message(message):
    print(message["text"])

client = PushClient(access_token="useraccesstoken", on_message=on_message)
client.start()
client.join()  # block until the client stops

Get an access token from dev.groupme.com.

Listening to one group

GroupMe pushes every group's messages down your personal channel, so subscribe_to_group() does not narrow the stream — it adds a group's own channel (typing notifications and the like) on top. To hear about only certain groups, pass group_ids:

client = PushClient(
    access_token="useraccesstoken",
    on_message=on_message,
    group_ids=["12345678"],  # everything else is dropped
)
client.start()

DMs and other events that have no group id are never filtered out; leave on_dm unset if you do not want them.

To find your group ids:

for group_id, name in PushClient(access_token="useraccesstoken").list_groups():
    print(group_id, name)

Options

Argument Description
access_token GroupMe access token for the user you want to listen as.
on_message Called with the message subject for every group message.
on_dm Called for direct messages.
on_like Called when another user likes a message.
on_favorite Called when your user likes a message.
on_other Called with the raw data blob for anything else, such as poll results.
on_connect Called with no arguments each time the socket becomes ready, including after a reconnect.
on_error Called with the exception when the websocket errors.
disregard_self Skip events sent by the authenticated user. Default False.
reconnect Seconds to wait before reconnecting after a dropped connection. Default 5. None disables reconnection, which means any drop is permanent.
ping_interval / ping_timeout Websocket keepalive. Defaults 30 / 10. See below.
stall_timeout Seconds of silence after which the client checks that the stream is still alive. Default 180. None disables the check.
probe_timeout How long that check waits for an answer. Default 10.
subscribe_timeout Seconds to wait for a connection's subscriptions to be accepted before rebuilding the session. Default 15. None disables the check.
group_ids Only dispatch events from these groups. Default: no filtering.
subscribe_to_user_channel Subscribe to /user/<id> on connect. This is where GroupMe delivers messages, so leave it on unless you know otherwise. Default True.
threaded_callbacks Run each callback in its own thread. Set False to run them inline, which keeps events in order but blocks the socket while they run. Default True.
request_timeout Timeout in seconds for the HTTP calls start() makes. Default 5.

Staying connected

A GroupMe push connection does not stay up on its own. An idle one is closed by the server, and the Faye session behind it gets reaped, after which the socket can still look perfectly healthy while never delivering anything again. That is the "it ran fine all day and then just stopped receiving" failure.

The client handles this out of the box:

  • Websocket pings (ping_interval) keep the connection warm and, more importantly, make a dead connection raise instead of hanging. Without them the reader blocks on a socket that will never produce another byte, which is what a sleeping laptop or a NAT timeout leaves behind.
  • Automatic reconnection is on by default (reconnect=5). Subscriptions are replayed on the new connection.
  • A liveness check (stall_timeout). GroupMe sends nothing at all down an idle connection, so silence proves nothing on its own. After a quiet stretch the client asks a question instead of guessing: it re-subscribes to a channel it already holds, which is the one request GroupMe reliably answers. An answer means the stream is fine, an error means the session was reaped and it rebuilds, and no answer at all means the socket is gone and it reconnects.
  • A subscription check (subscribe_timeout). Being connected is not the same as being subscribed. If nothing confirms a connection's subscriptions, the session is rebuilt rather than left silently listening to nothing.
  • A fresh session on reconnect. Reusing a Faye session across a dropped socket is unreliable — the server can keep delivering to the connection that just died — so a reconnect takes a new one. Rebuilding is retried with backoff, because a network that is down when the client notices is usually still down a second later.

If you would rather do your own supervision, set reconnect=None, stall_timeout=None and subscribe_timeout=None.

Methods

  • start(wait=False, timeout=10) — authenticate, handshake and open the socket. With wait=True it blocks until the socket is open and raises ConnectionTimeout if it never does.
  • stop(timeout=5) — close the socket and stop reconnecting.
  • join(timeout=None) — block the calling thread until the client stops.
  • wait_until_connected(timeout=10) / is_connected — connection state.
  • subscribe_to_group(group_id, timeout=10) — subscribe to a group's own channel. Safe to call right after start(): it waits for the socket, and the subscription is replayed automatically after a reconnect.
  • unsubscribe_from_group(group_id) — the reverse.
  • list_groups(per_page=100) — [(group_id, name), ...] for the user's groups, over REST. Handy for finding the ids to pass to group_ids.

PushClient is also a context manager:

with PushClient(access_token="useraccesstoken", on_message=on_message) as client:
    client.join()

Registering handlers with decorators

client = PushClient(access_token="useraccesstoken")

@client.receive_message
def on_message(message):
    print(message["text"])

There is one of these per callback: receive_message, receive_dm, receive_like, receive_favorite, receive_other, receive_connect, receive_error.

Errors

start() raises instead of logging and carrying on with a dead client:

  • AuthenticationError — GroupMe rejected the access token.
  • HandshakeError — Faye did not return a client id.
  • ConnectionTimeout — start(wait=True) timed out.

All of them subclass GroupMePushError.

Examples

See examples/: basic.py, single_group.py, decorators.py.

Development

pip install -e ".[dev]"
pytest

The tests run against a scripted fake websocket, so no token or network access is needed.

Releases are additionally smoke tested against the live GroupMe service: the client creates a throwaway group, posts to it, and asserts on delivery, ordering, filtering, disregard_self and reconnect recovery.

Issues

If you encounter any bugs or have feature requests, please open an issue on GitHub.

Metadata

Release files for groupme-push 0.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for groupme-push 0.0.6
File Size Uploaded
groupme_push-0.0.6.tar.gz 37.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for groupme-push 0.0.6
File Interpreter ABI Platform
groupme_push-0.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 64.4 kB

Release files / groupme_push-0.0.6.tar.gz

Download URL groupme_push-0.0.6.tar.gz
Size 37.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8e6d7f753173a371c7a0a95b1d47f54531afdef8b98efa18312cef7679553c75
BLAKE2b-256 checksum
How to use checksums
573cf4d52cd4f49877da6d9512fe7fac24889ccc903445beac0812cd22df1669
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release files / groupme_push-0.0.6-py3-none-any.whl

Download URL groupme_push-0.0.6-py3-none-any.whl
Size 26.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e79f275b3b096b03697f0e827268fb1379be8ea34a5b1672ec9d8ee4b4601c74
BLAKE2b-256 checksum
How to use checksums
3cceabeff123774d1a93f4a082ff630d583353eda068fa21f28c380536070172
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release history Release notifications | RSS feed

This release

0.0.6 This release

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page