home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / common / Buddy.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  21.8 KB  |  707 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. from threading import RLock
  6. from util.callbacks import callsback
  7. from traceback import print_exc
  8. from util.threads import threaded
  9. from util.primitives.error_handling import traceguard
  10. from util.primitives.funcs import do, readonly
  11. from util.primitives.mapping import Storage
  12. from util.primitives.synchronization import lock
  13. from digsby_chatlogs.interfaces import IAliasProvider
  14. import traceback
  15. import os.path as os
  16. import wx
  17. import cPickle
  18. import stat
  19. from os.path import isfile, join as pathjoin, exists as pathexists
  20. from cStringIO import StringIO
  21. from util import Timer
  22. import stdpaths
  23. from path import path
  24. from util.observe import Observable, ObservableProperty as oproperty
  25. from common.actions import ObservableActionMeta, action
  26. from common import profile
  27. from PIL import Image
  28. from time import time
  29. from gui.toolbox import calllimit
  30. from logging import getLogger
  31. log = getLogger('Buddy')
  32. info = log.info
  33. from common.buddyicon import _rate_limited_icon_get
  34.  
  35. class FileTransferException(Exception):
  36.     pass
  37.  
  38. ICON_HASH_FILE = 'iconhashes.dat'
  39.  
  40. def load_hashes():
  41.     global hashes, cache_path, hashes
  42.     hashes = { }
  43.     wx.GetApp().PreShutdown.append(write_hashes)
  44.     cache_path = pathjoin(stdpaths.userlocaldata, 'cache')
  45.     if not pathexists(cache_path):
  46.         os.makedirs(cache_path)
  47.     elif pathexists(cache_path):
  48.         hash_filename = pathjoin(cache_path, ICON_HASH_FILE)
  49.     None if not pathexists(hash_filename) else None<EXCEPTION MATCH>Exception
  50.  
  51. hash_lock = RLock()
  52.  
  53. def buddy_icon_key(buddy):
  54.     return buddy.service
  55.  
  56.  
  57. def write_hashes():
  58.     if 'hashes' not in globals():
  59.         load_hashes()
  60.     
  61.     log.info('writing icon hashes')
  62.     hash_lock.__enter__()
  63.     
  64.     try:
  65.         
  66.         try:
  67.             f = _[1]
  68.             cPickle.dump(hashes, f)
  69.         finally:
  70.             pass
  71.  
  72.     except Exception:
  73.         hash_lock.__exit__
  74.         hash_lock.__exit__
  75.         hash_lock
  76.         log.critical('error writing icon hashes')
  77.         print_exc()
  78.     except:
  79.         hash_lock.__exit__
  80.     finally:
  81.         pass
  82.  
  83.  
  84. write_hashes = calllimit(5)(write_hashes)
  85.  
  86. def icon_path_for(buddy):
  87.     if 'cache_path' not in globals():
  88.         load_hashes()
  89.     
  90.     return pathjoin(cache_path, buddy_icon_key(buddy), '%s_ICON.dat' % buddy.name).decode('filesys')
  91.  
  92.  
  93. def get_disk_icon_hash(buddy):
  94.     if 'hashes' not in globals():
  95.         load_hashes()
  96.     
  97.     protoname = buddy_icon_key(buddy)
  98.     
  99.     try:
  100.         protohashes = hashes[protoname]
  101.     except KeyError:
  102.         return None
  103.  
  104.     return protohashes.get(buddy.name, None)
  105.  
  106.  
  107. def get_cached_icon(buddy):
  108.     if 'hashes' not in globals():
  109.         load_hashes()
  110.     
  111.     icon_path = icon_path_for(buddy)
  112.     if not isfile(icon_path):
  113.         return (None, None)
  114.     
  115.     try:
  116.         icon_file = open(icon_path, 'rb')
  117.         data = icon_file.read()
  118.     except Exception:
  119.         isfile(icon_path)
  120.         isfile(icon_path)
  121.         print_exc()
  122.         return (None, None)
  123.  
  124.     icon_file.close()
  125.     if buddy.name not in hashes.setdefault(buddy_icon_key(buddy), { }):
  126.         return (None, None)
  127.     hash = hashes[buddy_icon_key(buddy)][buddy.name]
  128.     if len(data) == 0:
  129.         return ('empty', hash)
  130.     
  131.     try:
  132.         img = Image.open(StringIO(data))
  133.     except Exception:
  134.         len(data) == 0
  135.         len(data) == 0
  136.         buddy.name not in hashes.setdefault(buddy_icon_key(buddy), { })
  137.         log.critical('%s was not an icon, removing it', icon_path)
  138.         
  139.         try:
  140.             os.remove(icon_path)
  141.         except Exception:
  142.             isfile(icon_path)
  143.             isfile(icon_path)
  144.             log.critical('could not remove nonimage icon %s', icon_path)
  145.         except:
  146.             isfile(icon_path)
  147.  
  148.         return (None, None)
  149.         isfile(icon_path)
  150.  
  151.     img.path = unicode(icon_path) + unicode(time())
  152.     return (img, hash)
  153.  
  154.  
  155. def save_cached_icon(buddy, imgdata, imghash):
  156.     full_path = icon_path_for(buddy)
  157.     (dir, file) = os.path.split(full_path)
  158.     if not pathexists(dir):
  159.         
  160.         try:
  161.             os.makedirs(dir)
  162.         except Exception:
  163.             traceback.print_exc()
  164.         except:
  165.             None<EXCEPTION MATCH>Exception
  166.         
  167.  
  168.     None<EXCEPTION MATCH>Exception
  169.     
  170.     try:
  171.         
  172.         try:
  173.             f = _[1]
  174.             f.write(imgdata)
  175.         finally:
  176.             pass
  177.  
  178.     except Exception:
  179.         traceback.print_exc()
  180.  
  181.     hash_lock.__enter__()
  182.     
  183.     try:
  184.         hashes.setdefault(buddy_icon_key(buddy), { })[buddy.name] = imghash
  185.     finally:
  186.         pass
  187.  
  188.  
  189.  
  190. def get_bname(b):
  191.     
  192.     try:
  193.         return b.name
  194.     except AttributeError:
  195.         return str(b)
  196.  
  197.  
  198. available_fix = {
  199.     'online': 'available',
  200.     'normal': 'available' }
  201.  
  202. def get_status_orb(contact):
  203.     st = contact.status.lower()
  204.     st = available_fix.get(st, st)
  205.     if st == 'unknown':
  206.         pass
  207.     elif contact.mobile:
  208.         st = 'mobile'
  209.     elif not contact.online:
  210.         st = 'offline'
  211.     elif st == 'idle' or contact.idle:
  212.         st = 'idle'
  213.     elif contact.away:
  214.         st = 'away'
  215.     
  216.     return st
  217.  
  218.  
  219. def get_log_size(buddy):
  220.     return get_log_size_tup(buddy.name, buddy.service)
  221.  
  222.  
  223. def get_log_size_tup(name, service):
  224.     return profile.logger.logsize_for_nameservice(name, service)
  225.  
  226.  
  227. class LogSizeDict(dict):
  228.     
  229.     def __init__(self):
  230.         dict.__init__(self)
  231.         self.needed = dict()
  232.         self.triggered = False
  233.  
  234.     
  235.     def __missing__(self, key, initialize = True):
  236.         if initialize:
  237.             self.needed[key] = []
  238.         
  239.         self.__setitem__(key, 0)
  240.         if not self.triggered:
  241.             self.triggered = True
  242.             self.trigger()
  243.         
  244.         return 0
  245.  
  246.     __missing__ = lock(__missing__)
  247.     
  248.     def trigger(self):
  249.         Timer(0.1, self.do_disk_access, success = self.update).start()
  250.  
  251.     
  252.     def do_disk_access(self):
  253.         self._lock.__enter__()
  254.         
  255.         try:
  256.             needed = self.needed
  257.             self.needed = dict()
  258.         finally:
  259.             pass
  260.  
  261.         retval = dict()
  262.         for key in needed:
  263.             retval[key] = get_log_size_tup(*key)
  264.         
  265.         log.info('getting %d log sizes: %r', len(needed), needed)
  266.         return (retval, needed)
  267.  
  268.     do_disk_access = threaded(do_disk_access)
  269.     
  270.     def update(self, d):
  271.         self._lock.__enter__()
  272.         
  273.         try:
  274.             (newvals, retrieved) = d
  275.             for key in newvals:
  276.                 self.needed.pop(key, None)
  277.             
  278.             if not self.needed:
  279.                 self.triggered = False
  280.             else:
  281.                 self.trigger()
  282.         finally:
  283.             pass
  284.  
  285.         
  286.         try:
  287.             retval = dict.update(self, newvals)
  288.         except Exception:
  289.             self._lock.__exit__
  290.             self._lock.__exit__
  291.             self._lock
  292.             raise 
  293.         except:
  294.             self._lock.__exit__
  295.         else:
  296.             for val in retrieved.values():
  297.                 for buddy in val:
  298.                     traceguard.__enter__()
  299.                     
  300.                     try:
  301.                         buddy.notify('log_size')
  302.                     finally:
  303.                         pass
  304.  
  305.                 
  306.             
  307.             return retval
  308.         return None
  309.  
  310.  
  311.     
  312.     def notify_get(self, key, buddy):
  313.         if key in self.needed:
  314.             self.needed[key].append(buddy)
  315.             return self[key]
  316.         if key not in self:
  317.             self.needed[key] = [
  318.                 buddy]
  319.             return self.__missing__(key, initialize = False)
  320.         return self[key]
  321.  
  322.     notify_get = lock(notify_get)
  323.     
  324.     def __getitem__(self, key):
  325.         return dict.__getitem__(self, key)
  326.  
  327.     __getitem__ = lock(__getitem__)
  328.     
  329.     def __setitem__(self, key, value):
  330.         return dict.__setitem__(self, key, value)
  331.  
  332.     __setitem__ = lock(__setitem__)
  333.  
  334.  
  335. class Buddy(Observable):
  336.     __metaclass__ = ObservableActionMeta
  337.     _icon_requests = 0
  338.     _get_image_min_once = False
  339.     
  340.     def __init__(self, name, protocol):
  341.         Observable.__init__(self)
  342.         self.add_observer(self.store_remote_alias, 'remote_alias')
  343.         self.name = name
  344.         self.protocol = protocol
  345.         self._notify_dirty = True
  346.         self.entering = self.leaving = False
  347.         (do,)((lambda .0: for s in .0:
  348. setattr(self, s, None))([
  349.             'icon_bitmap']))
  350.         self.icon_hash = self.get_icon_hash()
  351.         self._getting_image = False
  352.         self._cached_hash = None
  353.         self.icon_disabled = False
  354.         
  355.         try:
  356.             register = profile.account_manager.buddywatcher.register
  357.         except AttributeError:
  358.             log.debug('No buddy watcher to register with')
  359.             return None
  360.  
  361.         register(self)
  362.  
  363.     
  364.     def store_remote_alias(self, obj, attr, old, new):
  365.         if attr is None or attr == 'remote_alias':
  366.             IAliasProvider(profile()).set_alias(self.name, self.service, protocol = self.protocol.service, alias = self.alias)
  367.         
  368.  
  369.     
  370.     def raise_proto_impl_err(self, prop = ''):
  371.         raise NotImplementedError('%s has not implemented a required property %s' % (getattr(self, '__class__', str(self)), prop))
  372.  
  373.     
  374.     def __repr__(self):
  375.         return '<%s %s>' % (self.__class__.__name__, self.name)
  376.  
  377.     nice_name = readonly('name')
  378.     
  379.     def online(self):
  380.         self.raise_proto_impl_err('online')
  381.  
  382.     online = property(online)
  383.     
  384.     def mobile(self):
  385.         self.raise_proto_impl_err('mobile')
  386.  
  387.     mobile = property(mobile)
  388.     
  389.     def status_message(self):
  390.         self.raise_proto_impl_err('status_message')
  391.  
  392.     status_message = property(status_message)
  393.     
  394.     def stripped_msg(self):
  395.         if not self.status_message:
  396.             pass
  397.         return u''
  398.  
  399.     stripped_msg = property(stripped_msg)
  400.     
  401.     def idle(self):
  402.         self.raise_proto_impl_err('idle')
  403.  
  404.     idle = property(idle)
  405.     
  406.     def away(self):
  407.         self.raise_proto_impl_err('away')
  408.  
  409.     away = property(away)
  410.     
  411.     def blocked(self):
  412.         self.raise_proto_impl_err('blocked')
  413.  
  414.     blocked = property(blocked)
  415.     
  416.     def isbot(self):
  417.         caps = caps
  418.         import common
  419.         return caps.BOT in self.caps
  420.  
  421.     isbot = property(isbot)
  422.     bot = isbot
  423.     
  424.     def service(self):
  425.         return self.protocol.name
  426.  
  427.     service = property(service)
  428.     
  429.     def serviceicon(self):
  430.         skin = skin
  431.         import gui
  432.         return skin.get('serviceicons.%s' % self.service)
  433.  
  434.     serviceicon = property(serviceicon)
  435.     
  436.     def pending_auth(self):
  437.         return False
  438.  
  439.     pending_auth = property(pending_auth)
  440.     
  441.     def sms(self):
  442.         return False
  443.  
  444.     sms = property(sms)
  445.     
  446.     def get_caps(self):
  447.         caps = caps
  448.         import common
  449.         if self.sms:
  450.             return set([
  451.                 caps.SMS])
  452.         buddy_caps = set(self.protocol.caps)
  453.         if not self.online:
  454.             buddy_caps.discard(caps.FILES)
  455.             buddy_caps.discard(caps.VIDEO)
  456.         
  457.         return buddy_caps
  458.  
  459.     caps = property(get_caps)
  460.     
  461.     def imwin_mode(self, mode):
  462.         begin_conversation = begin_conversation
  463.         import gui.imwin
  464.         begin_conversation(self, mode = mode)
  465.  
  466.     
  467.     def chat(self):
  468.         self.imwin_mode('im')
  469.  
  470.     chat = action((lambda self: 'IM' in self.caps))(chat)
  471.     
  472.     def buddy_info(self):
  473.         self.imwin_mode('info')
  474.  
  475.     buddy_info = action((lambda self: 'INFO' in self.caps))(buddy_info)
  476.     
  477.     def send_email(self):
  478.         self.imwin_mode('email')
  479.  
  480.     send_email = action((lambda self: 'EMAIL' in self.caps))(send_email)
  481.     
  482.     def send_sms(self):
  483.         self.imwin_mode('sms')
  484.  
  485.     send_sms = action((lambda self: 'SMS' in self.caps))(send_sms)
  486.     
  487.     def idstr(self):
  488.         return '/'.join([
  489.             self.protocol.name,
  490.             self.protocol.username,
  491.             self.name])
  492.  
  493.     
  494.     def alias(self):
  495.         a = profile.get_contact_info(self, 'alias')
  496.         if a:
  497.             return a
  498.         a = getattr(self, 'local_alias', None)
  499.         if a:
  500.             return a
  501.         a = getattr(self, 'remote_alias', None)
  502.         if a:
  503.             return a
  504.         return self.name
  505.  
  506.     alias = property(alias)
  507.     
  508.     def local_alias(self):
  509.         return profile.blist.get_contact_info(self, 'alias')
  510.  
  511.     local_alias = property(local_alias)
  512.     
  513.     def block(self, set_blocked = True, callback = None):
  514.         self.raise_proto_impl_err('block')
  515.  
  516.     block = action((lambda self: if self.blocked:
  517. NoneTrue))(callsback(block))
  518.     
  519.     def equals_chat_buddy(self, chat_buddy):
  520.         return self == chat_buddy
  521.  
  522.     
  523.     def unblock(self, callback = None):
  524.         self.raise_proto_impl_err('unblock')
  525.  
  526.     unblock = action((lambda self: if self.blocked:
  527. True))(callsback(unblock))
  528.     
  529.     def send_file(self, filepath = None):
  530.         if filepath is None:
  531.             Hub = Hub
  532.             import hub
  533.             filepath = Hub.getInstance().get_file('Sending file to %s' % self.name)
  534.         
  535.         if filepath:
  536.             finfo = fileinfo(filepath)
  537.             if finfo.size:
  538.                 if self.online:
  539.                     xfer = self.protocol.send_file(self, finfo)
  540.                     profile.xfers.insert(0, xfer)
  541.                 
  542.             else:
  543.                 Hub = Hub
  544.                 import hub
  545.                 Hub.getInstance().on_error(FileTransferException('%s is an empty file' % finfo.name))
  546.         
  547.  
  548.     send_file = action((lambda self: if self.online:
  549. pass'FILES' in self.caps))(send_file)
  550.     
  551.     def send_folder(self, dirpath = None):
  552.         Hub = Hub
  553.         import hub
  554.         if dirpath is None:
  555.             dirpath = Hub.getInstance().get_dir('Choose a directory to send to %s.' % self.name)
  556.         
  557.         if dirpath:
  558.             finfo = fileinfo(dirpath)
  559.             if len(finfo.files) == 0:
  560.                 Hub.getInstance().on_error(ValueError('No files in that directory.'))
  561.             elif finfo.size == 0:
  562.                 Hub.getInstance().on_error(ValueError('There are zero bytes in that directory.'))
  563.             else:
  564.                 self.protocol.send_file(self, finfo)
  565.         
  566.  
  567.     
  568.     def remove(self, protocol_obj):
  569.         self.protocol.remove_buddy(protocol_obj)
  570.  
  571.     remove = action()(remove)
  572.     
  573.     def icon_path(self):
  574.         return path(icon_path_for(self))
  575.  
  576.     icon_path = property(icon_path)
  577.     
  578.     def num_online(self):
  579.         return int(self.online)
  580.  
  581.     num_online = property(num_online)
  582.     
  583.     def notify(self, attr = None, *a, **k):
  584.         self._notify_dirty = True
  585.         profile.blist.buddy_changed(self, attr)
  586.         return Observable.notify(self, attr, *a, **k)
  587.  
  588.     
  589.     def cache_path(self):
  590.         proto = self.protocol
  591.         return pathjoin(proto.name, self.name) + '.dat'
  592.  
  593.     cache_path = property(cache_path)
  594.     
  595.     def info_key(self):
  596.         return self.name + '_' + self.service
  597.  
  598.     info_key = property(info_key)
  599.     email_hint = property((lambda self: self.protocol.email_hint(self)))
  600.     
  601.     def history(self):
  602.         return profile.logger.history_for_safe(self.protocol, self)
  603.  
  604.     history = property(history)
  605.     
  606.     def icon(self):
  607.         if self.icon_disabled:
  608.             return None
  609.         nh = self.icon_hash
  610.         if self.icon_bitmap is not None and self.icon_bitmap is not -1:
  611.             if not (self._getting_image) and nh is not None and nh != self._cached_hash:
  612.                 self._getting_image = True
  613.                 _rate_limited_icon_get(self)
  614.             
  615.         elif (nh or self._get_image_min_once) and not (self._getting_image):
  616.             self._getting_image = True
  617.             _rate_limited_icon_get(self)
  618.         
  619.         if self.icon_bitmap is not None and self.icon_bitmap is not -1:
  620.             if isinstance(self.icon_bitmap, str) and self.icon_bitmap == 'empty':
  621.                 return None
  622.             return self.icon_bitmap
  623.         self.icon_bitmap is not -1
  624.         return None
  625.  
  626.     icon = property(icon)
  627.     
  628.     def cache_icon(self, icon_data, icon_hash):
  629.         self.icon_bitmap = None
  630.         self._cached_hash = None
  631.         self._getting_image = False
  632.         save_cached_icon(self, icon_data, icon_hash)
  633.         wx.CallAfter(write_hashes)
  634.         self.notify('icon')
  635.  
  636.     
  637.     def get_icon_hash(self):
  638.         return get_disk_icon_hash(self)
  639.  
  640.     
  641.     def log_size(self):
  642.         return profile.log_sizes.notify_get((self.name, self.service), self)
  643.  
  644.     log_size = property(log_size)
  645.     
  646.     def increase_log_size(self, num_bytes):
  647.         profile.log_sizes[(self.name, self.service)] += num_bytes
  648.         self.notify('log_size')
  649.  
  650.     
  651.     def __eq__(self, b):
  652.         s = object()
  653.         if getattr(b, 'name', s) == self.name:
  654.             pass
  655.         return getattr(b, 'protocol') is self.protocol
  656.  
  657.     
  658.     def __ne__(self, other):
  659.         return not self.__eq__(other)
  660.  
  661.     
  662.     def __hash__(self):
  663.         return hash(self.info_key)
  664.  
  665.     status_notifies = { }
  666.     
  667.     def _set_status(self, status):
  668.         status = {
  669.             'online': 'available' }.get(status, status)
  670.         self.setnotifyif('status', status)
  671.  
  672.     status_orb = oproperty((lambda self: get_status_orb(self)), observe = 'status')
  673.     
  674.     def sightly_status(self):
  675.         return self.status.title()
  676.  
  677.     sightly_status = property(sightly_status)
  678.     
  679.     def pretty_profile(self):
  680.         return u''
  681.  
  682.     pretty_profile = property(pretty_profile)
  683.     
  684.     def buddy_icon(self):
  685.         get_buddy_icon = get_buddy_icon
  686.         import gui.buddylist.renderers
  687.         return get_buddy_icon(self, 32, False)
  688.  
  689.     buddy_icon = property(buddy_icon)
  690.     
  691.     def view_past_chats(self, fromacct = None):
  692.         if fromacct is None:
  693.             fromacct = self.protocol
  694.         
  695.         buddypath = profile.logger.pathfor(fromacct, self)
  696.         PastBrowser = PastBrowser
  697.         import gui.pastbrowser
  698.         PastBrowser.MakeOrShowAndSelect(buddypath)
  699.  
  700.  
  701.  
  702. def fileinfo(filepath):
  703.     filestats = os.stat(filepath)
  704.     s = Storage(size = os.path.getsize(filepath), modtime = filestats[stat.ST_MTIME], ctime = filestats[stat.ST_CTIME], name = os.path.split(filepath)[1], path = path(filepath))
  705.     return s
  706.  
  707.