{"id":43916822,"url":"https://github.com/zooniverse/sugar","last_synced_at":"2026-02-06T21:34:48.057Z","repository":{"id":21530720,"uuid":"24849998","full_name":"zooniverse/sugar","owner":"zooniverse","description":"Event system","archived":false,"fork":false,"pushed_at":"2025-09-25T01:54:57.000Z","size":745,"stargazers_count":1,"open_issues_count":15,"forks_count":1,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-09-25T03:44:13.865Z","etag":null,"topics":["utility"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zooniverse.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-10-06T14:47:27.000Z","updated_at":"2024-12-05T15:39:48.000Z","dependencies_parsed_at":"2023-10-02T12:57:23.800Z","dependency_job_id":"a1a4ee75-51ce-46a2-ace5-848710d6f64e","html_url":"https://github.com/zooniverse/sugar","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/zooniverse/sugar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zooniverse%2Fsugar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zooniverse%2Fsugar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zooniverse%2Fsugar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zooniverse%2Fsugar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zooniverse","download_url":"https://codeload.github.com/zooniverse/sugar/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zooniverse%2Fsugar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29177554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T20:14:21.878Z","status":"ssl_error","status_checked_at":"2026-02-06T20:14:21.443Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["utility"],"created_at":"2026-02-06T21:34:47.465Z","updated_at":"2026-02-06T21:34:48.049Z","avatar_url":"https://github.com/zooniverse.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![pullreminders](https://pullreminders.com/badge.svg)](https://pullreminders.com?ref=badge)\r\n\r\n# What is Sugar?\r\nSugar is a server side event notification system to deliver event data payloads to subscribed clients.\r\nBy default it will attempt to connect the client to the server using websockets and will fall back to long polling.\r\n\r\nSee https://github.com/zooniverse/Sugar-Client for the client implementation details.\r\n\r\n## How it works\r\nThe server is a wrapper around Redis pub/sub (https://redis.io/topics/pubsub) and real time events (https://github.com/primus/primus#engineio) connections all via a HTTP API.\r\n\r\nThe HTTP end points are:\r\n1. `get '/presence'`\r\n   + list the subscribed user counts for all channels\r\n0. `get '/active_users?channel=zooniverse'`\r\n   + list the subscribed users for a specific channel\r\n0. `post '/notify'`\r\n   + send a 'notification' message to a specific private user channel\r\n0. `post '/announce'`\r\n   + broadcast an 'announcement' message to a specific section channel, e.g. (project-1 || zooniverse)\r\n0. `post '/experiment'`\r\n   + send a 'experiment' message to a specific private user channel\r\n\r\nAll requests to the post end points must include a formatted message body for the matching event type as described below.\r\n\r\nThe 3 types of messages the system accepts are:\r\n1. Notifications\r\n    ``` JSON\r\n    {\"notifications\": [{\"user_id\": \"1\", \"message\": \"Hiya\", \"url\": \"test\", \"delivered\": \"false\"}]}\r\n    ```\r\n0. Announcements\r\n   ``` JSON\r\n   {\"announcements\": [{\"message\": \"announcment message\", \"url\": \"test\", \"section\": \"zooniverse\", \"delivered\": \"false\"}]}\r\n   ```\r\n0. Experiments\r\n   ``` JSON\r\n   {\"experiments\": [{\"user_id\": \"1\", \"message\": \"would you like to participate?\", \"url\": \"test\", \"delivered\": \"false\"}]}\r\n   ```\r\n\r\n## Manual testing of notifications\r\nConstruct per user notification payloads in JSON and use something like cURL to POST the payload to the notifications server.\r\nE.g.\r\n``` bash\r\ncurl -vv \\\r\n     -X \"POST\" \"https://notifications-staging.zooniverse.org/notify\" \\\r\n     -H 'Content-Type: application/json' \\\r\n     -u 'username:password' \\\r\n     -d $'{\r\n  \"notifications\": [{\r\n    \"message\": \"A message from curl to user 1\",\r\n    \"user_id\": \"1\",\r\n    \"url\": \"http://test.net\",\r\n    \"delivered\": false\r\n  }]\r\n}'\r\n```\r\n\r\nThe `examples` directory has some example scripts. Replace `USER` and `PASSWORD` with the username and password for the staging service:\r\n\r\n\u003cdl\u003e\r\n   \u003cdt\u003e\u003ccode\u003esugar-announce.sh\u003c/code\u003e\u003c/dt\u003e\r\n  \u003cdd\u003eSend an announcement to a Zooniverse project.\u003c/dd\u003e\r\n  \u003cdt\u003e\u003ccode\u003esugar-messages.sh\u003c/code\u003e\u003c/dt\u003e\r\n  \u003cdd\u003eSend a message to a user ID\u003c/dd\u003e\r\n  \u003cdt\u003e\u003ccode\u003esugar-notify.sh\u003c/code\u003e\u003c/dt\u003e\r\n  \u003cdd\u003eSend a notification to a user ID\u003c/dd\u003e\r\n  \u003cdt\u003e\u003ccode\u003esugar-subjects.sh\u003c/code\u003e\u003c/dt\u003e\r\n  \u003cdd\u003eInject specific subjects into the classification queue for a user ID (PFE only.)\u003c/dd\u003e\r\n\u003c/dl\u003e\r\n\r\n## Debugging\r\nVisit https://notifications-staging.zooniverse.org/ for debug user \u0026 testing section announcements and user notifications.\r\n\r\n## Development via docker \u0026 docker-compose\r\nTo Run a local version of the sugar system\r\n  + `docker-compose build`\r\n  + `docker-compose up`\r\n\r\nRun run the tests (you may need to rebuild the docker image if the src changes)\r\n  + `docker-compose run -T --rm sugar npm test`\r\n\r\nGet a bash container via docker to run tests, etc\r\n`docker-compose run --service-ports --rm sugar bash`\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzooniverse%2Fsugar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzooniverse%2Fsugar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzooniverse%2Fsugar/lists"}