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