{"action":"created","comment":{"url":"https://api.github.com/repos/edx/edx-notifications/pulls/comments/24031708","id":24031708,"diff_hunk":"@@ -0,0 +1,121 @@\n+\"\"\"\n+All in-proc API endpoints for acting as a Notifications Consumer\n+NOTE that we can only query for notifications that are \"durable\", i.e.\n+persisted in our database\n+\"\"\"\n+\n+import pytz\n+from datetime import datetime\n+\n+from edx_notifications.stores.store import notification_store\n+\n+from edx_notifications.exceptions import (\n+    ItemIntegrityError\n+)\n+\n+\n+def get_notifications_count_for_user(user_id, filters=None):\n+    \"\"\"\n+    Returns the number of notifications this user has\n+\n+    ARGS:\n+        user_id: The id of the user to query\n+        filters: A dict containing the following optional keys\n+            - 'namespace': what namespace to search (defuault None)\n+            - 'read': Whether to return read notifications (default True)\n+            - 'unread': Whether to return unread notifications (default True)\n+            - 'type_name': what msg_types to count\n+\n+    NOTE: If the 'msg_id' filter is passed in, a ValueError will be raised as\n+    this is not a valid combination\n+    \"\"\"\n+\n+    # make sure user_id is an integer\n+    if not isinstance(user_id, int):\n+        raise TypeError(\"user_id must be an integer\")\n+\n+    return notification_store().get_num_notifications_for_user(\n+        user_id,\n+        filters=filters,\n+    )\n+\n+\n+def get_notifications_for_user(user_id, filters=None, options=None):\n+    \"\"\"\n+    Returns a list of NotificationUserMap for the passed in user. The list will be\n+    ordered by most recent first\n+\n+    ARGS:\n+        - user_id: The id of the user\n+        - filters: a dict containing\n+            - msg_id: a particular notification id to retrieve\n+                ( if this is used in conjuction with other filters, it may\n+                  result in an empty set being returned )\n+            - namespace: what namespace to search (defuault None)\n+            - read: Whether to return read notifications (default True)\n+            - unread: Whether to return unread notifications (default True)\n+            - type_name: which type to return\n+        - options: a dict containing some optional parameters\n+            - limit: max number to return (up to some system defined max)\n+            - offset: offset into the list, to implement paging\n+    \"\"\"\n+\n+    # make sure user_id is an integer\n+    if not isinstance(user_id, int):\n+        raise TypeError(\"user_id must be an integer\")\n+\n+    return notification_store().get_notifications_for_user(\n+        user_id,\n+        filters=filters,\n+        options=options\n+    )\n+\n+\n+def mark_notification_read(user_id, msg_id, read=True):\n+    \"\"\"\n+    Will mark a given NotificationUserMap as 'read' (or unread is 'unread' argument is passed in)\n+\n+    ARGS:\n+        - user_id: The user that wishes to mark the msg as read/unread\n+        - msg_id: The corresponding message that is being marked\n+        - read: (Optional) indicate whether message should be marked as read or unread\n+\n+    NOTE: If the corresponding user_id/msg_id cannot be found, then this will raise\n+    a ItemNotFoundError(). Also, if there is some database integrity error where the\n+    same user_id/msg_id mapping is found more than once, it will raise a\n+    ItemIntegrityError()\n+    \"\"\"\n+\n+    store = notification_store()\n+    notifications = store.get_notifications_for_user(\n+        user_id,\n+        filters={\n+            'msg_id': msg_id,\n+        },\n+        options={\n+            'select_related': False,  # we don't need the related objects to do this\n+        }\n+    )\n+\n+    if len(notifications) > 1:\n+        # There should be at most one match, else raise an exception\n+        # this really shouldn't happen because there is a database constraint,\n+        # at least with SQL backends. However, for future no-SQL backends\n+        # this is conceptually a possibility, so good to double check\n+        err_msg = (\n+            'There should be at most 1 NotificationUserMap items found for '\n+            'msg_id {msg_id} and user_id {user_id}. {cnt} were found!'\n+        ).format(msg_id=msg_id, user_id=user_id, cnt=len(notifications))\n+\n+        raise ItemIntegrityError(err_msg)\n+\n+    user_map = notifications[0]","path":"edx_notifications/api/consumer.py","position":null,"original_position":112,"commit_id":"acdc018a4cfd9b3fbbea1d8609e23a93bd7ca159","original_commit_id":"2916967233fefae30bfbcd0ea89c4efee8c21ae6","user":{"login":"cpennington","id":30236,"avatar_url":"https://avatars.githubusercontent.com/u/30236?v=3","gravatar_id":"","url":"https://api.github.com/users/cpennington","html_url":"https://github.com/cpennington","followers_url":"https://api.github.com/users/cpennington/followers","following_url":"https://api.github.com/users/cpennington/following{/other_user}","gists_url":"https://api.github.com/users/cpennington/gists{/gist_id}","starred_url":"https://api.github.com/users/cpennington/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpennington/subscriptions","organizations_url":"https://api.github.com/users/cpennington/orgs","repos_url":"https://api.github.com/users/cpennington/repos","events_url":"https://api.github.com/users/cpennington/events{/privacy}","received_events_url":"https://api.github.com/users/cpennington/received_events","type":"User","site_admin":false},"body":"From #3: `user_map` is a confusing name for the results of `get_notifications_for_user`. Is there a better name for that concept? Perhaps `UserNotificationMessage` (in contrast to `NotificationMessage` for the raw message)?","created_at":"2015-02-03T19:30:45Z","updated_at":"2015-02-03T19:30:45Z","html_url":"https://github.com/edx/edx-notifications/pull/12#discussion_r24031708","pull_request_url":"https://api.github.com/repos/edx/edx-notifications/pulls/12","_links":{"self":{"href":"https://api.github.com/repos/edx/edx-notifications/pulls/comments/24031708"},"html":{"href":"https://github.com/edx/edx-notifications/pull/12#discussion_r24031708"},"pull_request":{"href":"https://api.github.com/repos/edx/edx-notifications/pulls/12"}}},"pull_request":{"url":"https://api.github.com/repos/edx/edx-notifications/pulls/12","id":28491511,"html_url":"https://github.com/edx/edx-notifications/pull/12","diff_url":"https://github.com/edx/edx-notifications/pull/12.diff","patch_url":"https://github.com/edx/edx-notifications/pull/12.patch","issue_url":"https://api.github.com/repos/edx/edx-notifications/issues/12","number":12,"state":"open","locked":false,"title":"For ongoing reviews/comments","user":{"login":"chrisndodge","id":2362917,"avatar_url":"https://avatars.githubusercontent.com/u/2362917?v=3","gravatar_id":"","url":"https://api.github.com/users/chrisndodge","html_url":"https://github.com/chrisndodge","followers_url":"https://api.github.com/users/chrisndodge/followers","following_url":"https://api.github.com/users/chrisndodge/following{/other_user}","gists_url":"https://api.github.com/users/chrisndodge/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisndodge/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisndodge/subscriptions","organizations_url":"https://api.github.com/users/chrisndodge/orgs","repos_url":"https://api.github.com/users/chrisndodge/repos","events_url":"https://api.github.com/users/chrisndodge/events{/privacy}","received_events_url":"https://api.github.com/users/chrisndodge/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-02-02T18:37:25Z","updated_at":"2015-02-03T19:30:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1c8ca0931a5ceac6f134813a0a3705a02a454b46","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/edx/edx-notifications/pulls/12/commits","review_comments_url":"https://api.github.com/repos/edx/edx-notifications/pulls/12/comments","review_comment_url":"https://api.github.com/repos/edx/edx-notifications/pulls/comments/{number}","comments_url":"https://api.github.com/repos/edx/edx-notifications/issues/12/comments","statuses_url":"https://api.github.com/repos/edx/edx-notifications/statuses/acdc018a4cfd9b3fbbea1d8609e23a93bd7ca159","head":{"label":"edx:master","ref":"master","sha":"acdc018a4cfd9b3fbbea1d8609e23a93bd7ca159","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":29154572,"name":"edx-notifications","full_name":"edx/edx-notifications","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-notifications","description":"","fork":false,"url":"https://api.github.com/repos/edx/edx-notifications","forks_url":"https://api.github.com/repos/edx/edx-notifications/forks","keys_url":"https://api.github.com/repos/edx/edx-notifications/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-notifications/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-notifications/teams","hooks_url":"https://api.github.com/repos/edx/edx-notifications/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-notifications/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-notifications/events","assignees_url":"https://api.github.com/repos/edx/edx-notifications/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-notifications/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-notifications/tags","blobs_url":"https://api.github.com/repos/edx/edx-notifications/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-notifications/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-notifications/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-notifications/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-notifications/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-notifications/languages","stargazers_url":"https://api.github.com/repos/edx/edx-notifications/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-notifications/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-notifications/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-notifications/subscription","commits_url":"https://api.github.com/repos/edx/edx-notifications/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-notifications/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-notifications/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-notifications/issues/comments/{number}","contents_url":"https://api.github.com/repos/edx/edx-notifications/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-notifications/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-notifications/merges","archive_url":"https://api.github.com/repos/edx/edx-notifications/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-notifications/downloads","issues_url":"https://api.github.com/repos/edx/edx-notifications/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-notifications/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-notifications/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-notifications/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-notifications/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-notifications/releases{/id}","created_at":"2015-01-12T20:11:02Z","updated_at":"2015-02-03T19:27:35Z","pushed_at":"2015-02-03T19:27:35Z","git_url":"git://github.com/edx/edx-notifications.git","ssh_url":"git@github.com:edx/edx-notifications.git","clone_url":"https://github.com/edx/edx-notifications.git","svn_url":"https://github.com/edx/edx-notifications","homepage":null,"size":1036,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":4,"forks":1,"open_issues":4,"watchers":0,"default_branch":"master"}},"base":{"label":"edx:empty","ref":"empty","sha":"e624fc3ebe0bc444ac580f93c4c971b4bb878c95","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":29154572,"name":"edx-notifications","full_name":"edx/edx-notifications","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/edx-notifications","description":"","fork":false,"url":"https://api.github.com/repos/edx/edx-notifications","forks_url":"https://api.github.com/repos/edx/edx-notifications/forks","keys_url":"https://api.github.com/repos/edx/edx-notifications/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/edx-notifications/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/edx-notifications/teams","hooks_url":"https://api.github.com/repos/edx/edx-notifications/hooks","issue_events_url":"https://api.github.com/repos/edx/edx-notifications/issues/events{/number}","events_url":"https://api.github.com/repos/edx/edx-notifications/events","assignees_url":"https://api.github.com/repos/edx/edx-notifications/assignees{/user}","branches_url":"https://api.github.com/repos/edx/edx-notifications/branches{/branch}","tags_url":"https://api.github.com/repos/edx/edx-notifications/tags","blobs_url":"https://api.github.com/repos/edx/edx-notifications/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/edx-notifications/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/edx-notifications/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/edx-notifications/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/edx-notifications/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/edx-notifications/languages","stargazers_url":"https://api.github.com/repos/edx/edx-notifications/stargazers","contributors_url":"https://api.github.com/repos/edx/edx-notifications/contributors","subscribers_url":"https://api.github.com/repos/edx/edx-notifications/subscribers","subscription_url":"https://api.github.com/repos/edx/edx-notifications/subscription","commits_url":"https://api.github.com/repos/edx/edx-notifications/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/edx-notifications/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/edx-notifications/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/edx-notifications/issues/comments/{number}","contents_url":"https://api.github.com/repos/edx/edx-notifications/contents/{+path}","compare_url":"https://api.github.com/repos/edx/edx-notifications/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/edx-notifications/merges","archive_url":"https://api.github.com/repos/edx/edx-notifications/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/edx-notifications/downloads","issues_url":"https://api.github.com/repos/edx/edx-notifications/issues{/number}","pulls_url":"https://api.github.com/repos/edx/edx-notifications/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/edx-notifications/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/edx-notifications/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/edx-notifications/labels{/name}","releases_url":"https://api.github.com/repos/edx/edx-notifications/releases{/id}","created_at":"2015-01-12T20:11:02Z","updated_at":"2015-02-03T19:27:35Z","pushed_at":"2015-02-03T19:27:35Z","git_url":"git://github.com/edx/edx-notifications.git","ssh_url":"git@github.com:edx/edx-notifications.git","clone_url":"https://github.com/edx/edx-notifications.git","svn_url":"https://github.com/edx/edx-notifications","homepage":null,"size":1036,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":4,"forks":1,"open_issues":4,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/edx-notifications/pulls/12"},"html":{"href":"https://github.com/edx/edx-notifications/pull/12"},"issue":{"href":"https://api.github.com/repos/edx/edx-notifications/issues/12"},"comments":{"href":"https://api.github.com/repos/edx/edx-notifications/issues/12/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/edx-notifications/pulls/12/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/edx-notifications/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/edx/edx-notifications/pulls/12/commits"},"statuses":{"href":"https://api.github.com/repos/edx/edx-notifications/statuses/acdc018a4cfd9b3fbbea1d8609e23a93bd7ca159"}}}}