Implemented DnD in the backend and in the presence code
authorEd Page <eopage@byu.net>
Sun, 29 Nov 2009 00:49:41 +0000 (18:49 -0600)
committerEd Page <eopage@byu.net>
Sun, 29 Nov 2009 00:49:41 +0000 (18:49 -0600)
Switching user alias to the account number

Removing irrelevant TODOs

clarified some TODOs

src/aliasing.py
src/channel/contact_list.py
src/channel/text.py
src/connection.py
src/gvoice/backend.py
src/simple_presence.py

index 9d76629..ed79708 100644 (file)
@@ -6,6 +6,12 @@ import gtk_toolbox
 import handle
 
 
+USER_ALIAS_ACCOUNT = "account"
+USER_ALIAS_CALLBACK = "callback"
+
+USER_ALIAS = USER_ALIAS_ACCOUNT
+
+
 _moduleLogger = logging.getLogger('aliasing')
 
 
@@ -100,6 +106,10 @@ class AliasingMixin(telepathy.server.ConnectionInterfaceAliasing):
        @gtk_toolbox.log_exception(_moduleLogger)
        def SetAliases(self, aliases):
                _moduleLogger.debug("Called SetAliases")
+               if USER_ALIAS == USER_ALIAS_ACCOUNT:
+                       raise telepathy.errors.PermissionDenied("No user customizable aliases")
+               elif USER_ALIAS != USER_ALIAS_CALLBACK:
+                       raise RuntimeError("Invalid alias type: %r" % USER_ALIAS)
 
                # first validate that no other handle types are included
                userHandleAndAlias = None
@@ -123,8 +133,13 @@ class AliasingMixin(telepathy.server.ConnectionInterfaceAliasing):
        def _get_alias(self, handleId):
                h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
                if isinstance(h, handle.ConnectionHandle):
-                       callbackNumber = self.session.backend.get_callback_number()
-                       userAlias = make_pretty(callbackNumber)
+                       if USER_ALIAS == USER_ALIAS_CALLBACK:
+                               aliasNumber = self.session.backend.get_callback_number()
+                       elif USER_ALIAS == USER_ALIAS_ACCOUNT:
+                               aliasNumber = self.session.backend.get_account_number()
+                       else:
+                               raise RuntimeError("Invalid alias type: %r" % USER_ALIAS)
+                       userAlias = make_pretty(aliasNumber)
                        return userAlias
                else:
                        contactId = h.contactID
index c753f0b..e2a8493 100644 (file)
@@ -43,12 +43,6 @@ class AllContactsListChannel(AbstractListChannel):
        @coroutines.expand_positional
        @gobject_utils.async
        def _on_contacts_refreshed(self, addressbook, added, removed, changed):
-               """
-               @todo This currently filters out people not yet added to the contact
-                       list.  Something needs to be done about those
-               @todo This currently does not handle people with multiple phone
-                       numbers, yay that'll be annoying to resolve
-               """
                self._process_refresh(addressbook, added, removed)
 
        def _process_refresh(self, addressbook, added, removed):
@@ -56,13 +50,11 @@ class AllContactsListChannel(AbstractListChannel):
                handlesAdded = [
                        handle.create_handle(connection, "contact", contactId, phoneNumber)
                        for contactId in added
-                       if contactId
                        for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
                ]
                handlesRemoved = [
                        handle.create_handle(connection, "contact", contactId, phoneNumber)
                        for contactId in removed
-                       if contactId
                        for (phoneType, phoneNumber) in addressbook.get_contact_details(contactId)
                ]
                message = ""
index d394b0f..83de6da 100644 (file)
@@ -10,7 +10,6 @@ import handle
 _moduleLogger = logging.getLogger("channel.text")
 
 
-# @todo Get receiving of texts to work
 class TextChannel(telepathy.server.ChannelTypeText):
        """
        Look into implementing ChannelInterfaceMessages for rich text formatting
@@ -38,7 +37,7 @@ class TextChannel(telepathy.server.ChannelTypeText):
 
        def _on_message_received(self, contactId, contactNumber, message):
                """
-               @todo Attatch this to receiving a message
+               @todo Attatch this to receiving a message signal
                """
                currentReceivedId = self._nextRecievedId
 
index 00c0e83..2724a45 100644 (file)
@@ -22,8 +22,7 @@ class TheOneRingConnection(
 ):
 
        # Overriding a base class variable
-       # @todo remove forward as one of the settings but instead use the alias
-       # with set sane defaults and saving it to an ini file
+       # Should the forwarding number be handled by the alias or by an option?
        _mandatory_parameters = {
                'username' : 's',
                'password' : 's',
@@ -191,9 +190,6 @@ class TheOneRingConnection(
                return handles
 
        def _create_contact_handle(self, requestedHandleName):
-               """
-               @todo Determine if nay of this is really needed
-               """
                requestedContactId, requestedContactNumber = handle.ContactHandle.from_handle_name(
                        requestedHandleName
                )
@@ -202,7 +198,7 @@ class TheOneRingConnection(
 
        def _on_invite_text(self, contactId):
                """
-               @todo Make this work
+               @todo Get externally initiated conversations working
                """
                h = self._create_contact_handle(contactId)
 
index 9bada99..4a66181 100755 (executable)
@@ -136,6 +136,10 @@ class GVoiceBackend(object):
                self._accountNumRe = re.compile(r"""<b class="ms\d">(.{14})</b></div>""")
                self._callbackRe = re.compile(r"""\s+(.*?):\s*(.*?)<br\s*/>\s*$""", re.M)
 
+               self._isDndURL = "https://www.google.com/voice/m/donotdisturb"
+               self._isDndRe = re.compile(r"""<input.*?id="doNotDisturb".*?checked="(.*?)"\s*/>""")
+               self._setDndURL = "https://www.google.com/voice/m/savednd"
+
                self._gvDialingStrRe = re.compile("This may take a few seconds", re.M)
                self._clicktocallURL = "https://www.google.com/voice/m/sendcall"
                self._sendSmsURL = "https://www.google.com/voice/m/sendsms"
@@ -248,6 +252,32 @@ class GVoiceBackend(object):
                self._browser.cookies.clear()
                self._browser.cookies.save()
 
+       def is_dnd(self):
+               try:
+                       isDndPage = self._browser.download(self._isDndURL)
+               except urllib2.URLError, e:
+                       _moduleLogger.exception("Translating error: %s" % str(e))
+                       raise NetworkError("%s is not accesible" % self._isDndURL)
+
+               dndGroup = self._isDndRe.search(isDndPage)
+               if dndGroup is None:
+                       return False
+               dndStatus = dndGroup.group(1)
+               isDnd = True if dndStatus.strip().lower() == "true" else False
+               return isDnd
+
+       def set_dnd(self, doNotDisturb):
+               dndPostData = urllib.urlencode({
+                       "doNotDisturb": 1 if doNotDisturb else 0,
+                       "_rnr_se": self._token,
+               })
+
+               try:
+                       dndPage = self._browser.download(self._setDndURL, dndPostData)
+               except urllib2.URLError, e:
+                       _moduleLogger.exception("Translating error: %s" % str(e))
+                       raise NetworkError("%s is not accesible" % self._setDndURL)
+
        def dial(self, number):
                """
                This is the main function responsible for initating the callback
@@ -668,6 +698,11 @@ def test_backend(username, password):
        if not backend.is_authed():
                print "Login?: ", backend.login(username, password)
        print "Authenticated: ", backend.is_authed()
+       print "Is Dnd: ", backend.is_dnd()
+       #print "Setting Dnd", backend.set_dnd(True)
+       #print "Is Dnd: ", backend.is_dnd()
+       #print "Setting Dnd", backend.set_dnd(False)
+       #print "Is Dnd: ", backend.is_dnd()
 
        #print "Token: ", backend._token
        #print "Account: ", backend.get_account_number()
@@ -711,6 +746,7 @@ def grab_debug_info(username, password):
                ("forward", backend._forwardURL),
                ("token", backend._tokenURL),
                ("login", backend._loginURL),
+               ("isdnd", backend._isDndURL),
                ("contacts", backend._contactsURL),
 
                ("voicemail", backend._voicemailURL),
@@ -775,5 +811,5 @@ def grab_debug_info(username, password):
 if __name__ == "__main__":
        import sys
        logging.basicConfig(level=logging.DEBUG)
-       #test_backend(sys.argv[1], sys.argv[2])
-       grab_debug_info(sys.argv[1], sys.argv[2])
+       test_backend(sys.argv[1], sys.argv[2])
+       #grab_debug_info(sys.argv[1], sys.argv[2])
index 6e6e324..8a615b4 100644 (file)
@@ -3,6 +3,7 @@ import logging
 import telepathy
 
 import gtk_toolbox
+import handle
 
 
 _moduleLogger = logging.getLogger("simple_presence")
@@ -44,19 +45,22 @@ class SimplePresenceMixin(telepathy.server.ConnectionInterfaceSimplePresence):
        @gtk_toolbox.log_exception(_moduleLogger)
        def GetPresences(self, contacts):
                """
-               @todo Copy Aliasing's approach to knowing if self and get whether busy or not
-
                @return {ContactHandle: (Status, Presence Type, Message)}
                """
                presences = {}
                for handleId in contacts:
-                       handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
-
-                       presence = TheOneRingPresence.BUSY
-                       personalMessage = u""
-                       presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
-
-                       presences[handle] = (presenceType, presence, personalMessage)
+                       h = self.handle(telepathy.HANDLE_TYPE_CONTACT, handleId)
+                       if isinstance(h, handle.ConnectionHandle):
+                               isDnd = self.session.backend.is_dnd()
+                               presence = TheOneRingPresence.BUSY if isDnd else TheOneRingPresence.ONLINE
+                               personalMessage = u""
+                               presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
+                       else:
+                               presence = TheOneRingPresence.ONLINE
+                               personalMessage = u""
+                               presenceType = TheOneRingPresence.TO_PRESENCE_TYPE[presence]
+
+                       presences[h] = (presenceType, presence, personalMessage)
                return presences
 
        @gtk_toolbox.log_exception(_moduleLogger)
@@ -66,13 +70,9 @@ class SimplePresenceMixin(telepathy.server.ConnectionInterfaceSimplePresence):
 
 
                if status == TheOneRingPresence.ONLINE:
-                       # @todo Implement dnd
-                       #self.gvoice_backend.mark_dnd(True)
-                       pass
+                       self.gvoice_backend.set_dnd(False)
                elif status == TheOneRingPresence.BUSY:
-                       # @todo Implement dnd
-                       #self.gvoice_backend.mark_dnd(False)
-                       raise telepathy.errors.NotAvailable("DnD support not yet added to TheOneRing")
+                       self.gvoice_backend.set_dnd(True)
                else:
                        raise telepathy.errors.InvalidArgument("Unsupported status: %r" % status)
                _moduleLogger.info("Setting Presence to '%s'" % status)