{"id":20672771,"url":"https://github.com/flyclops/gocm","last_synced_at":"2025-04-19T19:11:28.298Z","repository":{"id":14879531,"uuid":"17603091","full_name":"Flyclops/GoCM","owner":"Flyclops","description":"Super-simple async GCM notification send service written in Go","archived":false,"fork":false,"pushed_at":"2014-07-17T17:06:16.000Z","size":412,"stargazers_count":45,"open_issues_count":0,"forks_count":7,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-06-19T00:22:06.482Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://tech.flyclops.com/gocm-super-simple-asynchronous-gcm-listener-in-go-403","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Flyclops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-03-10T18:13:44.000Z","updated_at":"2022-02-11T17:40:34.000Z","dependencies_parsed_at":"2022-08-03T04:06:26.613Z","dependency_job_id":null,"html_url":"https://github.com/Flyclops/GoCM","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flyclops%2FGoCM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flyclops%2FGoCM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flyclops%2FGoCM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flyclops%2FGoCM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Flyclops","download_url":"https://codeload.github.com/Flyclops/GoCM/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224970162,"owners_count":17400294,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-11-16T20:38:45.789Z","updated_at":"2024-11-16T20:38:46.444Z","avatar_url":"https://github.com/Flyclops.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"GoCM\n====\n\nSuper-simple asynchronous Google Cloud Messaging (GCM) notification send service written in Go\n\n[![Build Status](https://travis-ci.org/Flyclops/GoCM.png?branch=master)](https://travis-ci.org/Flyclops/GoCM)\n\n\nMotivation\n-----------\nThe world already has [pyapns](https://github.com/samuraisam/pyapns) for asynchronous sending of Apple Push Notifications. We needed similar async functionality for Google Cloud Messages that we use for push notifications on Android.\n\nSince we're (slowly) moving most of our backend codebase to [Go](http://golang.org), any new code is written in Go.\n\n[pyapns](https://github.com/samuraisam/pyapns) is so nice because [Apple Push Notification Services](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html) require a long-open socket through which all messages are sent. This minimizes the number of handshakes that need to take place, and gives the app an open pipe through which to dump messages.\n\nGCM, however, is a RESTful service (as of the writing of this README, the \"send\" URL is https://android.googleapis.com/gcm/send), that requires one HTTP connection per message sent. It does support multicasting to up to 1000 devices at once, but the message must be identical to all devices.\n\nIn our testing, from API servers running on AWS EC2 c1.medium cloud servers, sending a single APNS push notification takes \u003c 10ms on an open socket, while sending a single GCM notification can take between 150-250ms. Since we send hundreds of notifications per second, this became unacceptable.\n\nThe service\n------------\n\nIn order to not reinvent the wheel, we started with [Alex Lockwood's](https://github.com/alexjlockwood) open source GCM package for Go, called simply [gcm](https://github.com/alexjlockwood/gcm). Surrounding that, we instantiate a standard web server that takes an ```-apikey``` argument (and also configurable ```-ipaddress``` and ```-port``` arguments if the defaults are not desired) and listens for incoming POST requests. \n\nThe POST request should include two key-value pairs, ```tokens``` (an array of GCM device tokens) and ```payload``` (the JSON packet to send to GCM).\n\nThe server returns immediately, while pushing the main bulk of the work on to a new goroutine.\n\nFunctions: \n\n- Send GCM messages (retries any message twice (TODO, make configurable?))\n- Keep a run report for the process\n- Report [canonical IDs from GCM](http://developer.android.com/google/gcm/adv.html#canonical)\n- Report [NotRegistered tokens](http://developer.android.com/google/gcm/http.html#error_codes)\n\nExample\n--------\n\nStart the server\n\n```bash\n./GoCM --apikey \u003cGCM_API_KEY\u003e\n```\n\nSend a message...\n\n...via ```curl```:\n```bash\ncurl -d \"tokens=\u003cGCM_DEVICE_TOKEN\u003e\u0026tokens=\u003cGCM_DEVICE_TOKEN2\u003e\u0026payload={\\\"title\\\": \\\"This is the title\\\", \\\"subtitle\\\": \\\"This is the subtitle\\\", \\\"tickerText\\\": \\\"This is the ticker text\\\", \\\"datestamp\\\": \\\"2014-03-07T18:01:04.702100\\\"}\" localhost:5601/gcm/send\n```\n\n...via `python`\n```python\nimport requests\n\nGCM_SEND_ENDPOINT = 'http://localhost:5601/gcm/send'\n\ntoken = \"\u003cGCM_DEVICE_TOKEN\u003e\"\nmessage = {\n    'title': 'This is the title',\n    'subtitle': 'This is the subtitle',\n    'tickerText': 'This is the ticker text',\n    'datestamp': '2014-03-07T18:01:04.702100'\n}\ndata = {\n    'tokens': [token],\n    'payload': json.dumps(message)\n}\n\nresponse = requests.post(GCM_SEND_ENDPOINT, data=data)\n```\n\nGet back a run report of attempts, failures, and required changes:\n```bash\ncurl localhost:5601/gcm/report\n```\nResult like: ```{\"attempts\":0,\"failures\":0,\"pending\":0,\"canonicals\":0,\"notregistered\":0}```\n(\"attempts,\" \"failures,\" \"notregistered\", and \"canonicals\" is a running total for the running process, while \"pending\" is the number of messages waiting to finish transmitting successfully. Great for watching via Graphite graphs or the like.)\n\nGet back a list of push tokens that require updating (call if ```canonicals``` in above results \u003e 0):\n```bash\ncurl localhost:5601/gcm/report/canonical\n```\nResults like: ```{\"canonical_replacements\":null}```\n\nOr: ```{\"canonical_replacements\": [{\"original\": \"\u003ctoken\u003e\", \"canonical\": \"\u003cnew_token\u003e\"}]}```\n\n_Read more on Canonical IDs in GCM via the [offical documentation](http://developer.android.com/google/gcm/adv.html#canonical)_\n\nGet back a list of push tokens that should be purged from your database (app was uninstalled, etc.)\n```bash\ncurl localhost:5601/gcm/report/notregistered\n```\nResults like ```{\"tokens\": [\"token1\", \"token2\", ...]}```\n\n\n\nTODO\n-----------\n\n- Perhaps make runnable on a UNIX socket\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyclops%2Fgocm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflyclops%2Fgocm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyclops%2Fgocm/lists"}