Page MenuHome

activities.py
No OneTemporary

activities.py

import logging
from flask import request, current_app
from pillar.api.utils import gravatar
from pillar.auth import current_user
log = logging.getLogger(__name__)
def notification_parse(notification):
activities_collection = current_app.data.driver.db['activities']
activities_subscriptions_collection = \
current_app.data.driver.db['activities-subscriptions']
users_collection = current_app.data.driver.db['users']
nodes_collection = current_app.data.driver.db['nodes']
activity = activities_collection.find_one({'_id': notification['activity']})
if activity is None or activity['object_type'] != 'node':
return
node = nodes_collection.find_one({'_id': activity['object']})
if not node:
# This can happen when a notification is generated and then the
# node is deleted.
return
# Initial support only for node_type comments
if node['node_type'] != 'comment':
return
node['parent'] = nodes_collection.find_one({'_id': node['parent']})
object_type = 'comment'
object_name = ''
object_id = activity['object']
if node['parent']['user'] == current_user.user_id:
owner = "your {0}".format(node['parent']['node_type'])
else:
parent_comment_user = users_collection.find_one(
{'_id': node['parent']['user']})
if parent_comment_user['_id'] == node['user']:
user_name = 'their'
else:
user_name = "{0}'s".format(parent_comment_user['username'])
owner = "{0} {1}".format(user_name, node['parent']['node_type'])
context_object_type = node['parent']['node_type']
context_object_name = owner
context_object_id = activity['context_object']
if activity['verb'] == 'replied':
action = 'replied to'
elif activity['verb'] == 'commented':
action = 'left a comment on'
else:
action = activity['verb']
lookup = {
'user': current_user.user_id,
'context_object_type': 'node',
'context_object': context_object_id,
}
subscription = activities_subscriptions_collection.find_one(lookup)
if subscription and subscription['notifications']['web'] == True:
is_subscribed = True
else:
is_subscribed = False
# Parse user_actor
actor = users_collection.find_one({'_id': activity['actor_user']})
if actor:
parsed_actor = {
'username': actor['username'],
'avatar': gravatar(actor['email'])}
else:
parsed_actor = None
updates = dict(
_id=notification['_id'],
actor=parsed_actor,
action=action,
object_type=object_type,
object_name=object_name,
object_id=str(object_id),
context_object_type=context_object_type,
context_object_name=context_object_name,
context_object_id=str(context_object_id),
date=activity['_created'],
is_read=('is_read' in notification and notification['is_read']),
is_subscribed=is_subscribed,
subscription=subscription['_id']
)
notification.update(updates)
def notification_get_subscriptions(context_object_type, context_object_id, actor_user_id):
subscriptions_collection = current_app.data.driver.db['activities-subscriptions']
lookup = {
'user': {"$ne": actor_user_id},
'context_object_type': context_object_type,
'context_object': context_object_id,
'is_subscribed': True,
}
return subscriptions_collection.find(lookup)
def activity_subscribe(user_id, context_object_type, context_object_id):
"""Subscribe a user to changes for a specific context. We create a subscription
if none is found.
:param user_id: id of the user we are going to subscribe
:param context_object_type: hardcoded index, check the notifications/model.py
:param context_object_id: object id, to be traced with context_object_type_id
"""
subscriptions_collection = current_app.data.driver.db['activities-subscriptions']
lookup = {
'user': user_id,
'context_object_type': context_object_type,
'context_object': context_object_id
}
subscription = subscriptions_collection.find_one(lookup)
# If no subscription exists, we create one
if not subscription:
current_app.post_internal('activities-subscriptions', lookup)
def activity_object_add(actor_user_id, verb, object_type, object_id,
context_object_type, context_object_id):
"""Add a notification object and creates a notification for each user that
- is not the original author of the post
- is actively subscribed to the object
This works using the following pattern:
ACTOR -> VERB -> OBJECT -> CONTEXT
:param actor_user_id: id of the user who is changing the object
:param verb: the action on the object ('commented', 'replied')
:param object_type: hardcoded name
:param object_id: object id, to be traced with object_type_id
"""
subscriptions = notification_get_subscriptions(
context_object_type, context_object_id, actor_user_id)
if subscriptions.count() == 0:
return
info, status = register_activity(actor_user_id, verb, object_type, object_id,
context_object_type, context_object_id)
if status != 201:
# If creation failed for any reason, do not create a any notifcation
return
for subscription in subscriptions:
notification = dict(
user=subscription['user'],
activity=info['_id'])
current_app.post_internal('notifications', notification)
def register_activity(actor_user_id, verb, object_type, object_id,
context_object_type, context_object_id,
project_id=None,
node_type=None):
"""Registers an activity.
This works using the following pattern:
ACTOR -> VERB -> OBJECT -> CONTEXT
:param actor_user_id: id of the user who is changing the object
:param verb: the action on the object ('commented', 'replied')
:param object_type: hardcoded name, see database schema
:param object_id: object id, to be traced with object_type
:param context_object_type: the type of the context object, like 'project' or 'node',
see database schema
:param context_object_id:
:param project_id: optional project ID to make the activity easily queryable
per project.
:param node_type: optional, node type of the node receiving the activity.
:returns: tuple (info, status_code), where a successful operation should have
status_code=201. If it is not 201, a warning is logged.
"""
activity = {
'actor_user': actor_user_id,
'verb': verb,
'object_type': object_type,
'object': object_id,
'context_object_type': context_object_type,
'context_object': context_object_id}
if project_id:
activity['project'] = project_id
if node_type:
activity['node_type'] = node_type
info, _, _, status_code = current_app.post_internal('activities', activity)
if status_code != 201:
log.error('register_activity: code %i creating activity %s: %s',
status_code, activity, info)
else:
log.info('register_activity: user %s "%s" on %s %s, context %s %s',
actor_user_id, verb, object_type, object_id,
context_object_type, context_object_id)
return info, status_code
def before_returning_item_notifications(response):
if request.args.get('parse'):
notification_parse(response)
def before_returning_resource_notifications(response):
for item in response['_items']:
if request.args.get('parse'):
notification_parse(item)
def setup_app(app):
app.on_fetched_item_notifications += before_returning_item_notifications
app.on_fetched_resource_notifications += before_returning_resource_notifications

File Metadata

Mime Type
text/x-python
Expires
Mon, Nov 30, 3:30 PM (2 d)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
f0/f5/f10b7e95b30cf6177707365914c6

Event Timeline