home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 June / maximum-cd-2009-06.iso / DiscContents / digsby_setup.exe / lib / digsby / videochat.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-02-26  |  10.4 KB  |  268 lines

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