home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2012 January / maximum-cd-2012-01.iso / DiscContents / digsby_setup.exe / lib / digsby / videochat.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-10-05  |  10.7 KB  |  264 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. import string
  6. import re
  7. from operator import attrgetter
  8. from digsby.web import DigsbyHttp, DigsbyHttpError
  9. import simplejson as json
  10. from contacts.buddyinfo import BuddyInfo
  11. from common import profile, netcall
  12. from util import threaded, traceguard
  13. from util.primitives.funcs import Delegate
  14. from logging import getLogger
  15. log = getLogger('videochat')
  16. INVITE_URL = 'http://v.digsby.com/?id=%(video_token)s&t=%(widget_id)s&v=%(tb_version)s'
  17. TOKBOX_VERSION = '2'
  18. VALID_TOKEN_CHARACTERS = string.ascii_letters + string.digits
  19. VIDEO_CHAT_TITLE = _('Audio/Video Call with %s')
  20.  
  21. def gui_call_later(cb, *a, **k):
  22.     import wx
  23.     wx.CallAfter(cb, *a, **k)
  24.  
  25.  
  26. class VideoChat(object):
  27.     
  28.     def __init__(self, buddy):
  29.         self.buddy_info = BuddyInfo(buddy)
  30.         self.http = VideoChatHttp(profile.username, profile.password)
  31.         self._widget_jid = None
  32.         self._stopped = False
  33.         self.on_stop = Delegate()
  34.         self.handle_buddy_state(buddy)
  35.         my_alias = buddy.protocol.self_buddy.name
  36.         friend_alias = buddy.name
  37.         create = threaded(self.http.create_video)
  38.         create(my_alias, friend_alias, success = self.on_token, error = self.error_token)
  39.  
  40.     
  41.     def handle_buddy_state(self, buddy):
  42.         proto = buddy.protocol
  43.         
  44.         def on_protocol_state(proto, attr, old, new):
  45.             if not proto.connected:
  46.                 self.stop()
  47.             
  48.  
  49.         proto.add_observer(on_protocol_state, 'state', obj = self)
  50.         (self, self.on_stop) += (lambda : proto.remove_observer(on_protocol_state, 'state'))
  51.  
  52.     
  53.     def __repr__(self):
  54.         return '<VideoChat with %s>' % self.buddy_info
  55.  
  56.     
  57.     def on_token(self):
  58.         token = self.http.video_token
  59.         log.info('received video token: %s', token)
  60.         profile.connection.add_video_chat(token, self)
  61.         gui_call_later(self.on_url, self.http.invite_url(), self.http.widget_id)
  62.  
  63.     
  64.     def on_url(self, invite_url, widget_id):
  65.         buddy = self.buddy_info.buddy()
  66.         if buddy is not None:
  67.             message = _('Join me in an audio/video call: %s') % invite_url
  68.             
  69.             def send_and_echo_invite():
  70.                 convo = buddy.protocol.convo_for(buddy)
  71.                 convo.send_plaintext_message(message)
  72.                 convo.system_message(_('You have invited %s to an audio/video chat.') % buddy.name)
  73.  
  74.             netcall(send_and_echo_invite)
  75.         
  76.         title = VIDEO_CHAT_TITLE % self.buddy_info.buddy_name
  77.         VideoChatWindow = VideoChatWindow
  78.         import gui.video.webvideo
  79.         frame = self.video_frame = VideoChatWindow(title, widget_id, on_close = self.stop)
  80.         gui_call_later(frame.Show)
  81.  
  82.     
  83.     def error_token(self):
  84.         log.warning('error receiving token')
  85.         self.system_message(_('Audio/Video chat is currently unavailable.'))
  86.  
  87.     
  88.     def send_im(self, message):
  89.         convo = self.widget_convo
  90.         if convo is not None:
  91.             (None, netcall)((lambda : convo.send_plaintext_message(message)))
  92.         
  93.  
  94.     
  95.     def widget_convo(self):
  96.         if self.widget_jid is None:
  97.             self.widget_jid = self.find_widget_jid()
  98.             if self.widget_jid is None:
  99.                 return log.warning('no widget jid, cannot forward message to widget')
  100.         
  101.         conn = profile.connection
  102.         if not conn:
  103.             return log.warning('no Digsby connection, cannot forward message to widget')
  104.         return conn.convo_for(self.widget_jid)
  105.  
  106.     widget_convo = property(widget_convo)
  107.     
  108.     def set_widget_jid(self, jid):
  109.         if jid != self._widget_jid:
  110.             self._widget_jid = jid
  111.             if profile.connection:
  112.                 profile.connection.get_buddy(jid).add_observer(self.buddy_status_change, 'status')
  113.             
  114.         
  115.  
  116.     widget_jid = property(attrgetter('_widget_jid'), set_widget_jid)
  117.     
  118.     def find_widget_jid(self):
  119.         conn = profile.connection
  120.         if conn is None:
  121.             return log.warning('cannot find widget jid: no digsby connection')
  122.         resource = 'video.' + self.http.video_token
  123.         for buddict in conn.buddy_dictionaries():
  124.             for name, buddy in buddict.iteritems():
  125.                 if buddy.jid.domain == u'guest.digsby.org':
  126.                     for jid, res in buddy.resources.iteritems():
  127.                         if jid.resource == resource:
  128.                             return jid
  129.                     
  130.                 jid.resource == resource
  131.             
  132.         
  133.  
  134.     
  135.     def buddy_status_change(self, buddy, attr, old, new):
  136.         if buddy.online:
  137.             return None
  138.         log.info('buddy %r went offline...stopping', buddy)
  139.         buddy.remove_observer(self.buddy_status_change, 'status')
  140.         if not self._stopped:
  141.             self.system_message(_('Audio/Video call ended by other party.'))
  142.         
  143.         self.stop()
  144.  
  145.     
  146.     def system_message(self, message, **opts):
  147.         traceguard.__enter__()
  148.         
  149.         try:
  150.             im_buddy = self.buddy_info.buddy()
  151.             if im_buddy is not None:
  152.                 convo = im_buddy.protocol.convo_for(im_buddy)
  153.                 convo.system_message(message, **opts)
  154.         finally:
  155.             pass
  156.  
  157.  
  158.     
  159.     def stop(self):
  160.         
  161.         self.stop = lambda *a: pass
  162.         self._stopped = True
  163.         log.info('stopping video chat %r', self)
  164.         if self.video_frame:
  165.             gui_call_later(self.video_frame.Destroy)
  166.         
  167.         convo = self.widget_convo
  168.         if convo is not None:
  169.             netcall(self.widget_convo.buddy.appear_offline_to)
  170.         
  171.         token = self.http.video_token
  172.         if token is not None:
  173.             conn = profile.connection
  174.             if conn is not None:
  175.                 conn.remove_video_chat(token)
  176.             
  177.         
  178.         threaded(self.http.close_video)()
  179.         self.on_stop()
  180.  
  181.  
  182.  
  183. class VideoChatException(Exception):
  184.     pass
  185.  
  186.  
  187. class VideoChatHttp(DigsbyHttp):
  188.     
  189.     def __init__(self, username, password):
  190.         DigsbyHttp.__init__(self, username, password)
  191.  
  192.     
  193.     def create_video(self, nick, guest, video_token = None, widget_id = None):
  194.         vtokens = self.GET(obj = 'widget', act = 'video', tbv = TOKBOX_VERSION, nick = nick.encode('utf-8'), guest = guest.encode('utf-8'))
  195.         tokens = json.loads(vtokens)
  196.         
  197.         def invalid():
  198.             raise DigsbyHttpError('invalid video token returned: %r' % tokens)
  199.  
  200.         
  201.         def validate(t):
  202.             if isinstance(t, basestring):
  203.                 pass
  204.             return set(t).issubset(VALID_TOKEN_CHARACTERS)
  205.  
  206.         if not isinstance(tokens, dict):
  207.             invalid()
  208.         
  209.         self.video_token = tokens.get('token')
  210.         self.widget_id = tokens.get('widget')
  211.         if not validate(self.video_token) or not validate(self.widget_id):
  212.             invalid()
  213.         
  214.  
  215.     
  216.     def invite_url(self):
  217.         if self.video_token is None:
  218.             raise VideoChatException('no AV page has been created')
  219.         self.video_token is None
  220.         return INVITE_URL % dict(video_token = self.video_token, widget_id = self.widget_id, tb_version = TOKBOX_VERSION)
  221.  
  222.     
  223.     def close_video(self):
  224.         log.info('%r.close_video()', self)
  225.         self.GET(obj = 'widget', act = 'killvideo')
  226.  
  227.  
  228. video_invite_re = re.compile('http://v\\.digsby\\.com/\\?id=(\\w+)&(?:amp;)?t=(\\w+)&(?:amp;)?v=2')
  229.  
  230. def _on_message(messageobj, type, **opts):
  231.     if type != 'incoming':
  232.         return None
  233.     msg = getattr(messageobj, 'message', None)
  234.     if not isinstance(msg, basestring):
  235.         return None
  236.     match = video_invite_re.search(msg)
  237.     if match is None:
  238.         return None
  239.     (id, wid) = match.groups()
  240.     buddy_name = messageobj.buddy.name
  241.     new_url = '<a href="digsby://avcall/%s/%s">Join Now</a>' % (buddy_name, wid)
  242.     first_part = msg[:match.start()]
  243.     last_part = msg[match.end():]
  244.     messageobj.message = ''.join((first_part, new_url, last_part))
  245.  
  246.  
  247. def show_video_chat_window(buddy_name, widget_id):
  248.     VideoChatWindow = VideoChatWindow
  249.     import gui.video.webvideo
  250.     (None, None, gui_call_later)((lambda : VideoChatWindow(VIDEO_CHAT_TITLE % buddy_name, widget_id).Show()))
  251.  
  252.  
  253. def register_message_hook():
  254.     import hooks
  255.     hooks.register('digsby.im.msg.pre', _on_message)
  256.     urlhandler = urlhandler
  257.     import common
  258.     urlhandler.register('avcall/([\\w@\\.]+)/(\\w+)', show_video_chat_window)
  259.  
  260.  
  261. def unregister_message_hook():
  262.     raise NotImplementedError('Hook does not have unregister yet')
  263.  
  264.