PyXR

c:\projects\bitpim\src \ sms.py



0001 ### BITPIM
0002 ###
0003 ### Copyright (C) 2005 Joe Pham <djpham@netzero.net>
0004 ###
0005 ### This program is free software; you can redistribute it and/or modify
0006 ### it under the terms of the BitPim license as detailed in the LICENSE file.
0007 ###
0008 ### $Id: sms.py 3126 2006-04-20 22:08:45Z djpham $
0009 
0010 """
0011 Code to handle SMS items.
0012 
0013 The format for the SMS item is standardized.  It is an object with the following
0014 attributes:
0015 
0016 _from: string (email addr or phone #)
0017 _to: string (email addr or phone #) Deprecated, should use add_recipient()
0018 subject: string
0019 text: string
0020 datetime: string "YYYYMMDDThhmmss" or (y,m,d,h,m)
0021 callback: string (optional callback phone #)
0022 folder: string (where this item belongs: 'Inbox', 'Sent', 'Saved')
0023 locked: True/False
0024 msg_id: unique message id (hexstring sha encoded (datetime+text))
0025 priority: (normal/high)
0026 read: (T/F)
0027 
0028 available methods:
0029 
0030 add_recipient(name, confirmed=None, confirmed_datetime=None)
0031   - name: email addr or phone # of the recipient
0032   - confirmed: True/False/None
0033   - confirmed_datetime: "YYYYMMDDThhmmss" or (y,m,d,h,m)
0034 
0035 confirm_recipient(name, confirmed_datetime)
0036   - name: email addr or phone # of the recipient
0037   - confirmed_datetime: "YYYYMMDDThhmmss" or (y,m,d,h,m)
0038 
0039 
0040 The format for the Canned SMS Message item is standard.  It is an object with
0041 the following attributes:
0042 
0043 user_list: ['msg1', 'msg2', ...] list of user canned messages.
0044 builtin_list: ['msg1', 'msg2', ...] list of built-in canned messages.
0045            This attribute is Read-Only.
0046 
0047 
0048 To implement SMS read for a phone module:
0049  Add an entry into Profile._supportedsyncs:
0050         ...
0051         ('sms', 'read', None),     # sms reading
0052 
0053  Implement the following method in your Phone class: 
0054     def getsms(self, result):
0055         ...
0056         return result
0057 
0058 The result dict key for the SMS messages is 'sms', which is a dict of SMSEntry
0059 objetcs.
0060 The result dict key for the canned messages is 'canned_msg', which has the
0061 following format:
0062 
0063 result['canned_msg']=[{ 'text': 'Yes', 'type': 'builtin' },
0064                       { 'text': 'No', 'type': 'user' }, ... ]
0065 """
0066 
0067 # standard modules
0068 import copy
0069 import sha
0070 import time
0071 
0072 # wx modules
0073 
0074 # BitPim modules
0075 import database
0076 
0077 #-------------------------------------------------------------------------------
0078 class SMSDataObject(database.basedataobject):
0079     _knownproperties=['_from', '_to', 'subject', 'text', 'datetime',
0080                       'callback', 'folder', 'msg_id', 'read', 'priority' ]
0081     _knownlistproperties=database.basedataobject._knownlistproperties.copy()
0082     _knownlistproperties.update( { 'flags': ['locked', 'read'],
0083                                    'receivers': ['name', 'confirmed_datetime'] })
0084     def __init__(self, data=None):
0085         if data is None or not isinstance(data, SMSEntry):
0086             return;
0087         self.update(data.get_db_dict())
0088 smsobjectfactory=database.dataobjectfactory(SMSDataObject)
0089 
0090 #-------------------------------------------------------------------------------
0091 class CannedMsgDataObject(database.basedataobject):
0092     _knownproperties=[]
0093     _knownlistproperties=database.basedataobject._knownlistproperties.copy()
0094     _knownlistproperties.update( { 'canned_msg': ['text', 'type'] })
0095     def __init__(self, data=None):
0096         if data is None or not isinstance(data, CannedMsgEntry):
0097             return;
0098         self.update(data.get_db_dict())
0099 cannedmsgobjectfactory=database.dataobjectfactory(CannedMsgDataObject)
0100 
0101 #-------------------------------------------------------------------------------
0102 class SMSEntry(object):
0103     Folder_Inbox='Inbox'
0104     Folder_Sent='Sent'
0105     Folder_Saved='Saved'
0106     Valid_Folders=(Folder_Inbox, Folder_Sent, Folder_Saved)
0107     _id_index=0
0108     _max_id_index=999
0109     Priority_Normal=1
0110     Priority_High=2
0111     _priority_name={
0112         Priority_Normal: 'Normal',
0113         Priority_High: 'High' }
0114     _unknown_datetime='YYYY-MM-DD hh:mm:ss'
0115 
0116     def __init__(self):
0117         self._data={ 'serials': [] }
0118         self._create_id()
0119 
0120     def get(self):
0121         return copy.deepcopy(self._data, {})
0122     def set(self, d):
0123         self._data={}
0124         self._data.update(d)
0125 
0126     def get_db_dict(self):
0127         return self.get()
0128     def set_db_dict(self, d):
0129         self.set(d)
0130 
0131     def _create_id(self):
0132         "Create a BitPim serial for this entry"
0133         self._data.setdefault("serials", []).append(\
0134             {"sourcetype": "bitpim",
0135              "id": '%.3f%03d'%(time.time(), SMSEntry._id_index) })
0136         if SMSEntry._id_index<SMSEntry._max_id_index:
0137             SMSEntry._id_index+=1
0138         else:
0139             SMSEntry._id_index=0
0140     def _get_id(self):
0141         s=self._data.get('serials', [])
0142         for n in s:
0143             if n.get('sourcetype', None)=='bitpim':
0144                 return n.get('id', None)
0145         return None
0146     id=property(fget=_get_id)
0147 
0148     def _set_or_del(self, key, v, v_list=[]):
0149         if v is None or v in v_list:
0150             if self._data.has_key(key):
0151                 del self._data[key]
0152         else:
0153             self._data[key]=v
0154 
0155     def _get_from(self):
0156         return self._data.get('_from', '')
0157     def _set_from(self, v):
0158         self._set_or_del('_from', v, [''])
0159     _from=property(fget=_get_from, fset=_set_from)
0160     def _get_to(self):
0161         l=self._data.get('receivers', [])
0162         if l:
0163             return ','.join([x['name'] for x in l])
0164         return self._data.get('_to', '')
0165     def _set_to(self, v):
0166         self._set_or_del('_to', v, [''])
0167     _to=property(fget=_get_to, fset=_set_to)
0168     def _get_subject(self):
0169         return self._data.get('subject', '<None>')
0170     def _set_subject(self, v):
0171         self._set_or_del('subject', v, [''])
0172     subject=property(fget=_get_subject, fset=_set_subject)
0173     def _get_text(self):
0174         return self._data.get('text', '')
0175     def _set_text(self, v):
0176         self._set_or_del('text', v, [''])
0177         self._check_and_create_msg_id()
0178     text=property(fget=_get_text, fset=_set_text)
0179     def _get_datetime(self):
0180         return self._data.get('datetime', '')
0181     def _set_datetime(self, v):
0182         if isinstance(v, (list, tuple)) and len(v)==5:
0183             v='%04d%02d%02dT%02d%02d00'%v
0184         elif not isinstance(v, (str, unicode)):
0185             raise TypeError('must be YYYYMMDDThhmmss or (y,m,d,h,m)')
0186         self._set_or_del('datetime', v, [''])
0187         self._check_and_create_msg_id()
0188     datetime=property(fget=_get_datetime, fset=_set_datetime)
0189     def get_date_time_str(self):
0190         # return a string representing this date/time in the format of
0191         # YYYY-MM-DD hh:mm:ss
0192         s=self.datetime
0193         if not len(s):
0194             s=self._unknown_datetime
0195         else:
0196             s=s[:4]+'-'+s[4:6]+'-'+s[6:8]+' '+s[9:11]+':'+s[11:13]+':'+s[13:]
0197         return s
0198     def _check_and_create_msg_id(self):
0199         if not len(self.msg_id) and len(self.text) and len(self.datetime):
0200             self._data['msg_id']=sha.new(self.datetime+self.text).hexdigest()
0201     def _get_callback(self):
0202         return self._data.get('callback', '')
0203     def _set_callback(self, v):
0204         self._set_or_del('callback', v, [''])
0205     callback=property(fget=_get_callback, fset=_set_callback)
0206     def _get_folder(self):
0207         return self._data.get('folder', '')
0208     def _set_folder(self, v):
0209         if v not in self.Valid_Folders:
0210             raise ValueError
0211         self._set_or_del('folder', v, [''])
0212     folder=property(fget=_get_folder, fset=_set_folder)
0213 
0214     def _get_flag_value(self, flag_key, default=None):
0215         f=self._data.get('flags', [])
0216         for n in f:
0217             if n.has_key(flag_key):
0218                 return n[flag_key]
0219         return default
0220     def _set_flag_value(self, flag_key, v):
0221         f=self._data.get('flags', [])
0222         for i, n in enumerate(f):
0223             if n.has_key(flag_key):
0224                 if v is None or not v:
0225                     del f[i]
0226                     if not len(self._data['flags']):
0227                         del self._data['flags']
0228                 else:
0229                     n[flag_key]=v
0230                 return
0231         if v is not None and v:
0232             self._data.setdefault('flags', []).append({flag_key: v})
0233 
0234     def _get_locked(self):
0235         return self._get_flag_value('locked', False)
0236     def _set_locked(self, v):
0237         self._set_flag_value('locked', v)
0238     locked=property(fget=_get_locked, fset=_set_locked)
0239     def _get_read(self):
0240         return self._get_flag_value('read', False)
0241     def _set_read(self, v):
0242         self._set_flag_value('read', v)
0243     read=property(fget=_get_read, fset=_set_read)
0244 
0245     def _get_msg_id(self):
0246         return self._data.get('msg_id', '')
0247     msg_id=property(fget=_get_msg_id)
0248 
0249     def _get_priority(self):
0250         return self._data.get('priority', SMSEntry.Priority_Normal)
0251     def _set_priority(self, v):
0252         if v not in (SMSEntry.Priority_Normal, SMSEntry.Priority_High):
0253             raise ValueError('must be SMSEntry.Priority_Normal or SMSEntry.Priority_High')
0254         self._set_or_del('priority', v, [])
0255     def _get_priority_str(self):
0256         return self._priority_name[self.priority]
0257     priority=property(fget=_get_priority, fset=_set_priority)
0258     priority_str=property(fget=_get_priority_str)
0259 
0260     def add_recipient(self, name, confirmed=None, confirmed_datetime=None):
0261         if isinstance(confirmed_datetime, (list, tuple)):
0262             if len(confirmed_datetime)!=5:
0263                 raise ValueError('must be (y,m,d,h,m)')
0264             confirmed_datetime='%04d%02d%02dT%02d%02d00'%confirmed_datetime
0265         r={'name': name }
0266         if confirmed_datetime:
0267             r['confirmed_datetime']=confirmed_datetime
0268         self._data.setdefault('receivers', []).append(r)
0269     def confirm_recipient(self, name, confirmed_datetime):
0270         if isinstance(confirmed_datetime, (list, tuple)):
0271             if len(confirmed_datetime)!=5:
0272                 raise ValueError('must be (y,m,d,h,m)')
0273             confirmed_datetime='%04d%02d%02dT%02d%02d00'%confirmed_datetime
0274         for e in self._data.get('receivers', []):
0275             if e['name']==name:
0276                 e['confirmed_datetime']=confirmed_datetime
0277                 return
0278         raise Exception('Receiver %s not found'%name)
0279     def _get_delivery_status(self):
0280         # return a list of delivery status, one of each recipient
0281         res=[]
0282         l=self._data.get('receivers', [])
0283         for e in l:
0284             s=e.get('confirmed_datetime', None)
0285             if s:
0286                 res.append('%s confirmed on %s-%s-%s %s:%s'%
0287                            (e['name'], s[:4], s[4:6], s[6:8],
0288                             s[9:11], s[11:13]))
0289             else:
0290                 res.append('%s not confirmed'%e['name'])
0291         return res
0292     delivery_status=property(fget=_get_delivery_status)
0293 
0294 #-------------------------------------------------------------------------------
0295 class CannedMsgEntry(object):
0296     _data_key='canned_msg'
0297     builtin_type='builtin'
0298     user_type='user'
0299     def __init__(self):
0300         self._data={ 'serials': [] }
0301         self._create_id()
0302 
0303     def get(self):
0304         return copy.deepcopy(self._data, {})
0305     def set(self, d):
0306         self._data={}
0307         self._data.update(d)
0308 
0309     def get_db_dict(self):
0310         return self.get()
0311     def set_db_dict(self, d):
0312         self.set(d)
0313 
0314     def _create_id(self):
0315         "Create a BitPim serial for this entry"
0316         self._data.setdefault("serials", []).append(\
0317             {"sourcetype": "bitpim", "id": str(time.time())})
0318     def _get_id(self):
0319         s=self._data.get('serials', [])
0320         for n in s:
0321             if n.get('sourcetype', None)=='bitpim':
0322                 return n.get('id', None)
0323         return None
0324     id=property(fget=_get_id)
0325 
0326     def _get_builtin_list(self):
0327         return [x['text'] for x in self._data.get(self._data_key, []) \
0328                 if x.get('type', None)==self.builtin_type]
0329     builtin_list=property(fget=_get_builtin_list)
0330 
0331     def _get_user_list(self):
0332         return [x['text'] for x in self._data.get(self._data_key, []) \
0333                 if x.get('type', None)==self.user_type]
0334     def _set_user_list(self, v):
0335         # first get all the builtin ones
0336         l=[x for x in self._data.get(self._data_key, []) \
0337            if x.get('type', None)==self.builtin_type]
0338         # then add the user ones
0339         l+=[ { 'text': x, 'type': self.user_type } for x in v]
0340         self._data[self._data_key]=l
0341     msg_list=user_list=property(fget=_get_user_list, fset=_set_user_list)
0342 
0343 #-------------------------------------------------------------------------------
0344 

Generated by PyXR 0.9.4