Commits

Konstantine Rybnikov committed 3520565

message posting should now work

  • Participants
  • Parent commits 9061126

Comments (0)

Files changed (8)

     - @username+ (ok)
 
 #. @username to show his friends (ok)
-#. Message posting to tell about it to subscribers
+#. Notification
+#. Jabber auto-auth
 #. Write tests.
 #. Lor-talks-bot
 #. Make routes.py better (simpler then a bunch of functions)
 #. Bot named @top
 #. CMD NICK
 #. CMD DISCOVER that finds users you may want to be your friend
+#. Tags

openju/bl/message.py

-#!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-from openju.model import *
+import datetime
+from openju.model import Q, Message
 
 def post_message(user, body):
+    def notify_subscribers(user, message):
+        from openju.bl.notify import notify_message_posted
+        
+        for subscriber in user.friend_of():
+            notify_message_posted(subscriber, message.id)
+    
     message = (
         Message(
             user=user,
             body=body))
     message.save()
+    
+    notify_subscribers(user, message)
     return message
 
-def get_last_messages(skip=None, limit=10, q=lambda x: x):
-    return Message.objects(q(Q(reply_to__exists=False)))[skip:limit]
-
-def get_message(message_id):
-    return Message.objects.get(id=message_id)
-
-def get_replies(message_id):
-    return Message.objects(reply_to=message_id)
-
 def post_reply(message, user, body):
     """ Returns newly created message """
     reply = Message(
     reply.save()
     return reply
 
+def get_last_messages(skip=None, limit=10, q=lambda x: x):
+    return Message.objects(q(Q(reply_to__exists=False)))[skip:limit]
+
+def get_message(message_id):
+    return Message.objects.get(id=message_id)
+
+def get_replies(message_id):
+    return Message.objects(reply_to=message_id)
+
 def num_today_messages(q=lambda x: x):
     """ ``q`` is decorator for query """
     today = datetime.datetime.combine(datetime.date.today(),
     return len(Message.objects(q(Q(dt__gt = today))))
 
 def num_overall_messages(q=lambda x: x):
-    return len(Message.objects(q(Q(user=self))))
+    return len(Message.objects(q(Q())))

openju/bl/notify.py

+# -*- coding: utf-8 -*-
+
+from openju.model import Notification
+
+def get_user_notifications(user):
+    return Notification.objects(user=user)
+
+def notify_message_posted(user, message_id):
+    """ Used for notifying each friend about posted message """
+    notification = (
+        Notification(
+            action = 'message_posted',
+            user = user,
+            meta = dict(
+                message_id = message_id)))
+    notification.save()

openju/bl/user.py

 from mongoengine.queryset import OperationError
 
 from openju import _
-from openju.model import *
+from openju.model import User
 
 from openju import current_app as app
 

openju/controllers/notify.py

+# -*- coding: utf-8 -*-
+
+from openju.views import render_message
+
+def message_posted(user, meta):
+    from openju.bl.message import get_message
+    message_id = meta['message_id']
+    message = get_message(message_id)
+    return render_message(message)

openju/message_bus.py

 from mongoengine.queryset import DoesNotExist
 
 # from openju.util import none_or_int
-from openju import g, _
+from openju import g
+from openju current_app as app
 from openju.validators import UserAlertError
 from openju.routes import *
-from openju.model import User
 
 def error_handler(f):
     def new_f(conn, *args, **kw):
         domain=xmpp_user.getDomain())
     
     if text is not None: # don't know why, but sometimes it's None. TODO: debug it
-        def call_list(*f_list):
-            for f in f_list:
-                res = f(text)
-                if isinstance(res, unicode):
-                    conn.send(xmpp.Message(xmpp_user, res))
-                if res is not None:
-                    return
+        def auth_user():
+            from openju.model import User
+            try:
+                return User.objects.get(jid=user_jid)
+            except DoesNotExist:
+                return  None
         
-        # should be only place to put some g.-stuff
+        def dispatch(xmpp_user):
+            def call_list(*f_list):
+                for f in f_list:
+                    res = f(text)
+                    if isinstance(res, unicode):
+                        conn.send(xmpp.Message(xmpp_user, res))
+                    if res is not None:
+                        return
+            
+            call_list(
+                cmd_register,
+                cmd_last_messages,
+                cmd_last_messages_from_friends,
+                cmd_read_message,
+                cmd_read_message_with_replies,
+                cmd_post_reply,
+                cmd_user_info,
+                cmd_user_messages,
+                cmd_subscribe,
+                cmd_post_message,
+                )
+        
+        def notify_logic(xmpp_user):
+            def filter_empty(l):
+                return (x for x in l if x is not None)
+            
+            def process_notifications(notification):
+                from openju.controllers import notify
+                action = getattr(notify_routes, notification.action, default=None)
+                if action is not None:
+                    res = action(notification.user, notification.meta)
+                    if res is not None:
+                        yield res
+                else:
+                    app.logger.exception(
+                        Exception(u'Notification action %s not found' % action))
+            
+            notify_text = (
+                u"\n\n"
+                .join(
+                    filter_empty(
+                        process_notifications(
+                            g.auth_user.get_notifications()))))
+            if notify_text:
+                conn.send(xmpp.Message(xmpp_user, ))
+        
+        # should be only place to put some g-stuff
         g.xmpp_user = xmpp_user
         g.text = text
         g.user_jid = user_jid
-        try:
-            g.auth_user = User.objects.get(jid=user_jid)
-        except DoesNotExist:
-            g.auth_user = None
         
-        call_list(
-            cmd_register,
-            cmd_last_messages,
-            cmd_last_messages_from_friends,
-            cmd_read_message,
-            cmd_read_message_with_replies,
-            cmd_post_reply,
-            cmd_user_info,
-            cmd_user_messages,
-            cmd_subscribe,
-            cmd_post_message,
-            )
+        g.auth_user = auth_user()
+        dispatch(xmpp_user)
+        notify_logic(xmpp_user)
 import datetime
 from mongoengine import \
     Document, ReferenceField, StringField, DateTimeField, ListField, \
-    Q
+    DictField, Q
 
 class User(Document):
-    jid = StringField(max_length=200, required=True, unique=True)
+    jid = StringField(max_length=200, required=True)
     nick = StringField(max_length=200, required=True, unique=True)
     friends = ListField(ReferenceField('self'))
-
+    
+    meta = {
+        'indexes': ['nick', 'friends']
+        }
+    
     def friends_ids(self):
         return (x.id for x in self.friends)
-    
+
     def num_overall_messages(self):
-        return len(Message.objects(user=self))
-    
+        from openju.bl.message import num_overall_messages
+        return num_overall_messages(q=lambda q: q & Q(user=self))
+
     def num_today_messages(self):
         from openju.bl.message import num_today_messages
         return num_today_messages(lambda q: q & Q(user=self))
         from openju.bl.message import get_last_messages
         return get_last_messages(q=lambda q: q & Q(user = self))
 
+    def friend_of(self):
+        return User.objects(friends=self)
+    
+    def get_notifications(self):
+        from openju.bl.notify import get_user_notifications
+        return get_user_notifications(self)
+
 class Message(Document):
     user = ReferenceField(User, required=True)
     body = StringField(required=True)
     reply_to = ReferenceField('self')
     
     meta = {
-        'ordering': ['-dt']
+        'ordering': ['-dt'],
+        'indexes': ['user', 'dt', 'reply_to'],
     }
     
     def get_replies(self):
 
     def is_reply(self):
         return bool(self.reply_to)
+
+class Notification(Document):
+    user = ReferenceField(User, required=True)
+    action = StringField(required=True)
+    meta = DictField()
     return (
         u"""%(user)s:\n"""
         u"""%(body)s\n"""
-        u"""%(m_id)s posted at %(dt)s""") % dict(
+        u"""%(m_id)s posted %(dt)s""") % dict(
         user = render_user_nick(message.user),
         body = message.body,
         m_id = render_message_id(message),
         u"""%(user)s replied to %(user_reply)s (%(user_reply_msgid)s):\n"""
         u"""%(quote)s\n"""
         u"""%(body)s\n"""
-        u"""%(m_id)s posted at %(dt)s""") % dict(
+        u"""%(m_id)s posted %(dt)s""") % dict(
         user = render_user_nick(message.user),
         user_reply = render_user_nick(message.reply_to.user),
         user_reply_msgid = render_message_id(message.reply_to),