{"id":37020863,"url":"https://github.com/smoketurner/notification","last_synced_at":"2026-01-14T02:26:22.267Z","repository":{"id":34502649,"uuid":"38443555","full_name":"smoketurner/notification","owner":"smoketurner","description":"Notification Service","archived":true,"fork":false,"pushed_at":"2019-05-06T11:42:41.000Z","size":1020,"stargazers_count":44,"open_issues_count":0,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-07-05T07:04:49.356Z","etag":null,"topics":["dropwizard","java","notification","riak","yammer"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/smoketurner/notification/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smoketurner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-02T16:21:48.000Z","updated_at":"2023-04-27T02:16:56.000Z","dependencies_parsed_at":"2022-09-06T04:02:12.328Z","dependency_job_id":null,"html_url":"https://github.com/smoketurner/notification","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/smoketurner/notification","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoketurner%2Fnotification","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoketurner%2Fnotification/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoketurner%2Fnotification/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoketurner%2Fnotification/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smoketurner","download_url":"https://codeload.github.com/smoketurner/notification/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smoketurner%2Fnotification/sbom","scorecard":{"id":833729,"data":{"date":"2025-08-11","repo":{"name":"github.com/smoketurner/notification","commit":"1465b1bbbccb26034205b254d0154712628b7646"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.6,"checks":[{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/10 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: Dockerfile:17","Warn: containerImage not pinned by hash: Dockerfile:37: pin your Docker image by updating openjdk:11-jre-slim to openjdk:11-jre-slim@sha256:93af7df2308c5141a751c4830e6b6c5717db102b3b31f012ea29d842dc4f2b02","Info:   0 out of   2 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 21 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"60 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-h46c-h94j-95f3","Warn: Project is vulnerable to: GHSA-wf8f-6423-gfxg","Warn: Project is vulnerable to: GHSA-27xj-rqx5-2255","Warn: Project is vulnerable to: GHSA-288c-cq4h-88gq","Warn: Project is vulnerable to: GHSA-4w82-r329-3q67","Warn: Project is vulnerable to: GHSA-57j2-w4cx-62h2","Warn: Project is vulnerable to: GHSA-58pp-9c76-5625","Warn: Project is vulnerable to: GHSA-5949-rw7g-wx7w","Warn: Project is vulnerable to: GHSA-5p34-5m6p-p58g","Warn: Project is vulnerable to: GHSA-5r5r-6hpj-8gg9","Warn: Project is vulnerable to: GHSA-5ww9-j83m-q7qx","Warn: Project is vulnerable to: GHSA-6fpp-rgj9-8rwc","Warn: Project is vulnerable to: GHSA-758m-v56v-grj4","Warn: Project is vulnerable to: GHSA-85cw-hj65-qqv9","Warn: Project is vulnerable to: GHSA-89qr-369f-5m5x","Warn: Project is vulnerable to: GHSA-8c4j-34r4-xr8g","Warn: Project is vulnerable to: GHSA-8w26-6f25-cm9x","Warn: Project is vulnerable to: GHSA-95cm-88f5-f2c7","Warn: Project is vulnerable to: GHSA-9gph-22xh-8x98","Warn: Project is vulnerable to: GHSA-9m6f-7xcq-8vf8","Warn: Project is vulnerable to: GHSA-9vvp-fxw6-jcxr","Warn: Project is vulnerable to: GHSA-c265-37vj-cwcc","Warn: Project is vulnerable to: GHSA-c2q3-4qrh-fm48","Warn: Project is vulnerable to: GHSA-cf6r-3wgc-h863","Warn: Project is vulnerable to: GHSA-cmfg-87vq-g5g4","Warn: Project is vulnerable to: GHSA-cvm9-fjm9-3572","Warn: Project is vulnerable to: GHSA-f3j5-rmmp-3fc5","Warn: Project is vulnerable to: GHSA-f9xh-2qgp-cq57","Warn: Project is vulnerable to: GHSA-fmmc-742q-jg75","Warn: Project is vulnerable to: GHSA-fqwf-pjwf-7vqv","Warn: Project is vulnerable to: GHSA-gjmw-vf9h-g25v","Warn: Project is vulnerable to: GHSA-gwp4-hfv6-p7hw","Warn: Project is vulnerable to: GHSA-gww7-p5w4-wrfv","Warn: Project is vulnerable to: GHSA-h3cw-g4mq-c5x2","Warn: Project is vulnerable to: GHSA-h4rc-386g-6m85","Warn: Project is vulnerable to: GHSA-h822-r4r5-v8jg","Warn: Project is vulnerable to: GHSA-j823-4qch-3rgm","Warn: Project is vulnerable to: GHSA-jjjh-jjxp-wpff","Warn: Project is vulnerable to: GHSA-m6x4-97wx-4q27","Warn: Project is vulnerable to: GHSA-mc6h-4qgp-37qh","Warn: Project is vulnerable to: GHSA-mph4-vhrx-mv67","Warn: Project is vulnerable to: GHSA-mx7p-6679-8g3q","Warn: Project is vulnerable to: GHSA-p43x-xfjf-5jhr","Warn: Project is vulnerable to: GHSA-q93h-jc49-78gg","Warn: Project is vulnerable to: GHSA-qjw2-hr98-qgfh","Warn: Project is vulnerable to: GHSA-qmqc-x3r4-6v39","Warn: Project is vulnerable to: GHSA-r3gr-cxrf-hg25","Warn: Project is vulnerable to: GHSA-r695-7vr9-jgc2","Warn: Project is vulnerable to: GHSA-rf6r-2c4q-2vwg","Warn: Project is vulnerable to: GHSA-rgv9-q543-rqg4","Warn: Project is vulnerable to: GHSA-rpr3-cw39-3pxh","Warn: Project is vulnerable to: GHSA-v3xw-c963-f5hc","Warn: Project is vulnerable to: GHSA-v585-23hc-c647","Warn: Project is vulnerable to: GHSA-vfqx-33qm-g869","Warn: Project is vulnerable to: GHSA-wh8g-3j2c-rqj5","Warn: Project is vulnerable to: GHSA-5mg8-w23w-74h3","Warn: Project is vulnerable to: GHSA-7g45-4rm6-3mm3","Warn: Project is vulnerable to: GHSA-3mcp-9wr4-cjqf","Warn: Project is vulnerable to: GHSA-8jpx-m2wh-2v34","Warn: Project is vulnerable to: GHSA-v6w3-2prq-h95f"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T18:25:20.190Z","repository_id":34502649,"created_at":"2025-08-23T18:25:20.190Z","updated_at":"2025-08-23T18:25:20.190Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["dropwizard","java","notification","riak","yammer"],"created_at":"2026-01-14T02:26:21.607Z","updated_at":"2026-01-14T02:26:22.256Z","avatar_url":"https://github.com/smoketurner.png","language":"Java","funding_links":["https://www.patreon.com/bePatron?u=9567343"],"categories":[],"sub_categories":[],"readme":"Notification\n============\n[![Build Status](https://travis-ci.org/smoketurner/notification.svg?branch=master)](https://travis-ci.org/smoketurner/notification)\n[![Coverage Status](https://coveralls.io/repos/smoketurner/notification/badge.svg)](https://coveralls.io/r/smoketurner/notification)\n[![Maven Central](https://img.shields.io/maven-central/v/com.smoketurner.notification/notification-parent.svg?style=flat-square)](https://maven-badges.herokuapp.com/maven-central/com.smoketurner.notification/notification-parent/)\n[![GitHub license](https://img.shields.io/github/license/smoketurner/notification.svg?style=flat-square)](https://github.com/smoketurner/notification/tree/master)\n[![Become a Patron](https://img.shields.io/badge/Patron-Patreon-red.svg)](https://www.patreon.com/bePatron?u=9567343)\n\nNotification is an implementation of an HTTP-based notification web service, based on Yammer's [Streamie](http://basho.com/posts/business/riak-and-scala-at-yammer/) service. This project was developed using:\n\n- [Dropwizard](http://dropwizard.io)\n- [Riak KV](http://basho.com/products/riak-kv/)\n- [Protocol Buffers](https://developers.google.com/protocol-buffers/)\n\nDesign\n------\nSimilar to Yammer's implementation, the Notification service relies on K-Sortable Unique Identifers ([KSUID](https://segment.com/blog/a-brief-history-of-the-uuid/)) that are used to resolve conflicts within Riak. The IDs are also used to provide a sorting order for the notifications so the newest notifications always appear at the top of a user's notification list. Every unique username can store up to 1000 notifications before the older notifications are aged out of the system.\n\nNotifications are stored in the `notifications` bucket in Riak. The service also stores a cursor representing the most recent seen notification for that user. Cursors are stored in the `cursors` bucket in Riak. A cursor looks like:\n\n```\n{\"key\": \"test-notifications\", \"value\": \"0ujsszwN8NRY24YaXiTIE2VWDTS\"}\n```\n\nWhere the username is `test`, the cursor name is `notifications` and the value of the cursor is `0ujsszwN8NRY24YaXiTIE2VWDTS`.\n\nWhen a user retrieves their list of notifications, the service will update the value of their cursor to the most recent notification.\n\nRollups\n-------\nThe Notification service supports the concept of \"rollups\" using rules. Rules are created by using the API (see below).\n\n```\n# Roll-up Rules\nrules:\n\n  new-follower:\n    max-size: 9\n    max-duration: 12 hours\n  like:\n    max-duration: 3 hours\n    match-on: message_id\n```\n\nThis would mean, for the `new-follower` category, roll up to a maximum of 9 notifications as long as there are no more than 12 hours between the first and last notifications. For the `like` category, roll up notifications within a 3 hour time window but they must have a matching `message_id` property value in each notification. As with Yammer's implementation, notifications are first partitioned between the seen and unseen prior to rolling up the notifications. This prevents pulling forward a notification that has already been seen and showing it to the user in a grouping of unseen notifications.\n\nInstallation\n------------\nTo build this code locally, clone the repository then build the jar:\n```\ngit clone https://github.com/smoketurner/notification.git\ncd notification\n./mvnw package\njava -jar notification-application/target/notification-application-1.3.1-SNAPSHOT.jar server config.yml\n```\n\nThe Notification service should be listening on port `8080` (with the Dropwizard administrative interface available at /admin).\n\nProduction\n----------\nTo deploy the Notification service into production, it can safely sit behind any HTTP-based load balancer (nginx, haproxy, F5, etc.).\n\nTo connect to Riak, [configure the cluster behind a load-balancer](http://docs.basho.com/riak/kv/latest/configuring/load-balancing-proxy/) as generally recommended. In order to support the Notification service automatically retrying Riak requests to separate nodes in the cluster, it is recommended to list each Riak node individually in the configuration file.\n\n*NOTE*: The notification service provides no authentication or authorization of requests. It is recommended to use a separate service such as [Kong](http://www.getkong.org) or the [Amazon API Gateway](https://aws.amazon.com/api-gateway/) to authenticate and authorize users.\n\nUsage\n-----\nThe Notification service provides RESTful URLs when creating, retrieving and deleting notifications. All of the API paths are in the form of `/v1/notifications/\u003cusername\u003e`. In the following examples, we'll be using `test` as the username.\n\nAPI documentation is also available via [GraphiQL](https://github.com/graphql/graphiql) at `http://localhost:8080/graphql`.\n\n### Creating a notification\n\nTo create a notification, you can execute a `POST` request to the API endpoint specifying `category` and `message` fields (both are required).\n\n```\ncurl \\\n-X POST \\\n-H \"Content-Type: application/json\" \\\n-d '{\"category\": \"new-follower\", \"message\": \"You have a new follower\"}' \\\nhttp://localhost:8080/v1/notifications/test -i\n\nHTTP/1.1 201 Created\nDate: Sun, 26 Jul 2015 16:06:10 GMT\nLocation: http://localhost:8080/v1/notifications/test\nContent-Type: application/json;charset=UTF-8\nX-Request-Id: 9a3ec8d0-1e00-47de-bb78-609a499849c4\nContent-Length: 157\n\n{\n  \"id\":\"0ujsszwN8NRY24YaXiTIE2VWDTS\",\n  \"category\":\"new-follower\",\n  \"message\":\"You have a new follower\",\n  \"created_at\":\"2015-07-26T16:06:10.970Z\"\n}\n```\n\nThe service will generate a globally unique ID and return it in the response along with the `created_at` timestamp.\n\n### Retrieving notifications\n\n```\ncurl -X GET http://localhost:8080/v1/notifications/test -i\n\nHTTP/1.1 200 OK\nDate: Sun, 26 Jul 2015 16:12:11 GMT\nLast-Modified: Sun, 26 Jul 2015 16:06:10 GMT\nAccept-Ranges: id\nContent-Range: id 0ujsszwN8NRY24YaXiTIE2VWDTS..0ujsszwN8NRY24YaXiTIE2VWDTS\nContent-Type: application/json;charset=UTF-8\nX-Request-Id: ce32a162-483d-4c34-9524-02b7f667704f\nCache-Control: no-cache, no-store, no-transform, must-revalidate\nContent-Length: 190\n\n[\n  {\n    \"id\": \"0ujsszwN8NRY24YaXiTIE2VWDTS\",\n    \"category\": \"new-follower\",\n    \"message\": \"You have a new follower\",\n    \"created_at\": \"2015-07-26T16:06:10.970Z\",\n    \"unseen\": true,\n    \"properties\": {}\n  }\n]\n```\n\nThe service defaults to only returning the 20 most recent notifications at a time. To return more notifications, you can execute a request specifying the `Range` HTTP header:\n\n```\ncurl -X GET -H \"Range: id;max=100\" http://localhost:8080/v1/notifications/test -i\n```\n\nIf there are more notifications available, the service will include a `Next-Range` HTTP response header that you can specify in a `Range` header on a subsequent request. This will allow you to paginate through all of the results, up to a 1000 notifications.\n\n### Deleting individual notifications\n\nTo delete individual notifications, you can execute a `DELETE` request specifying the notification ID's to delete.\n\n```\ncurl -X DELETE \"http://localhost:8080/v1/notifications/test?ids=0ujsszwN8NRY24YaXiTIE2VWDTS,0ujsswThIGTUYm2K8FjOOfXtY1K\" -i\n\nHTTP/1.1 204 No Content\nDate: Sun, 26 Jul 2015 16:34:15 GMT\nX-Request-Id: d3b446ea-08b4-4e81-9c13-06c6c372ba46\n```\n\nThis endpoint will always return a `204` response code even if the notification ID's don't exist.\n\n### Deleting all notifications\n\nTo remove all of the notifications for a user, you can execute a `DELETE` request without specifying any individual notification IDs.\n\n```\ncurl -X DELETE http://localhost:8080/v1/notifications/test -i\n\nHTTP/1.1 204 No Content\nDate: Sun, 26 Jul 2015 16:34:15 GMT\nX-Request-Id: d3b446ea-08b4-4e81-9c13-06c6c372ba46\n```\n\nThis will remove all of the `test` user's notifications, their cursor and will always return a `204` response code.\n\n### Creating or updating a rollup rule\n\nTo create or update a rollup rule, you can execute a `PUT` request specifying the category of notifications this rule applies to.\n\n```\ncurl \\\n-X PUT \\\n-H \"Content-Type: application/json\" \\\n-d '{\"max_size\": 9, \"max_duration\": \"12 hours\"}' \\\nhttp://localhost:8080/v1/rules/new-follower -i\n\nHTTP/1.1 204 No Content\nDate: Sun, 26 Jul 2015 16:34:15 GMT\nX-Request-Id: d3b446ea-08b4-4e81-9c13-06c6c372ba46\n```\n\nWhen retrieving notifications, any notifications with the `new-follower` category will be rolled up to a maximum of 9 notifications as long as there are no more than 12 hours between the first and last notifications.\n\n### Deleting a rollup rule\n\n```\ncurl -X DELETE http://localhost:8080/v1/rules/new-follower -i\n\nHTTP/1.1 204 No Content\nDate: Sun, 26 Jul 2015 16:34:15 GMT\nX-Request-Id: d3b446ea-08b4-4e81-9c13-06c6c372ba46\n```\n\n### Retrieve rollup rules\n\n```\ncurl -X GET http://localhost:8080/v1/rules -i\n\nHTTP/1.1 200 OK\nDate: Sun, 26 Jul 2015 16:12:11 GMT\nContent-Type: application/json;charset=UTF-8\nX-Request-Id: ce32a162-483d-4c34-9524-02b7f667704f\nCache-Control: no-cache, no-store, no-transform, must-revalidate\nContent-Length: 190\n\n{\n  \"new-follower\": {\n    \"max_size\": 3,\n    \"max_duration\": \"12 hours\"\n  },\n  \"like\": {\n    \"max_duration\": \"3 hours\",\n    \"match_on\": \"message_id\"\n  }\n}\n```\n\n\nSupport\n-------\n\nPlease file bug reports and feature requests in [GitHub issues](https://github.com/smoketurner/notification/issues).\n\n\nLicense\n-------\n\nCopyright (c) 2018 Smoke Turner, LLC\n\nThis library is licensed under the Apache License, Version 2.0.\n\nSee http://www.apache.org/licenses/LICENSE-2.0.html or the [LICENSE](LICENSE) file in this repository for the full license text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmoketurner%2Fnotification","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmoketurner%2Fnotification","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmoketurner%2Fnotification/lists"}