Module sms
[hide private]
[frames] | no frames]

Source Code for Module sms

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2005 Joe Pham <djpham@netzero.net> 
  4  ### 
  5  ### This program is free software; you can redistribute it and/or modify 
  6  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  7  ### 
  8  ### $Id: sms.py 3126 2006-04-20 22:08:45Z djpham $ 
  9   
 10  """ 
 11  Code to handle SMS items. 
 12   
 13  The format for the SMS item is standardized.  It is an object with the following 
 14  attributes: 
 15   
 16  _from: string (email addr or phone #) 
 17  _to: string (email addr or phone #) Deprecated, should use add_recipient() 
 18  subject: string 
 19  text: string 
 20  datetime: string "YYYYMMDDThhmmss" or (y,m,d,h,m) 
 21  callback: string (optional callback phone #) 
 22  folder: string (where this item belongs: 'Inbox', 'Sent', 'Saved') 
 23  locked: True/False 
 24  msg_id: unique message id (hexstring sha encoded (datetime+text)) 
 25  priority: (normal/high) 
 26  read: (T/F) 
 27   
 28  available methods: 
 29   
 30  add_recipient(name, confirmed=None, confirmed_datetime=None) 
 31    - name: email addr or phone # of the recipient 
 32    - confirmed: True/False/None 
 33    - confirmed_datetime: "YYYYMMDDThhmmss" or (y,m,d,h,m) 
 34   
 35  confirm_recipient(name, confirmed_datetime) 
 36    - name: email addr or phone # of the recipient 
 37    - confirmed_datetime: "YYYYMMDDThhmmss" or (y,m,d,h,m) 
 38   
 39   
 40  The format for the Canned SMS Message item is standard.  It is an object with 
 41  the following attributes: 
 42   
 43  user_list: ['msg1', 'msg2', ...] list of user canned messages. 
 44  builtin_list: ['msg1', 'msg2', ...] list of built-in canned messages. 
 45             This attribute is Read-Only. 
 46   
 47   
 48  To implement SMS read for a phone module: 
 49   Add an entry into Profile._supportedsyncs: 
 50          ... 
 51          ('sms', 'read', None),     # sms reading 
 52   
 53   Implement the following method in your Phone class:  
 54      def getsms(self, result): 
 55          ... 
 56          return result 
 57   
 58  The result dict key for the SMS messages is 'sms', which is a dict of SMSEntry 
 59  objetcs. 
 60  The result dict key for the canned messages is 'canned_msg', which has the 
 61  following format: 
 62   
 63  result['canned_msg']=[{ 'text': 'Yes', 'type': 'builtin' }, 
 64                        { 'text': 'No', 'type': 'user' }, ... ] 
 65  """ 
 66   
 67  # standard modules 
 68  import copy 
 69  import sha 
 70  import time 
 71   
 72  # wx modules 
 73   
 74  # BitPim modules 
 75  import database 
 76   
 77  #------------------------------------------------------------------------------- 
78 -class SMSDataObject(database.basedataobject):
79 _knownproperties=['_from', '_to', 'subject', 'text', 'datetime', 80 'callback', 'folder', 'msg_id', 'read', 'priority' ] 81 _knownlistproperties=database.basedataobject._knownlistproperties.copy() 82 _knownlistproperties.update( { 'flags': ['locked', 'read'], 83 'receivers': ['name', 'confirmed_datetime'] })
84 - def __init__(self, data=None):
85 if data is None or not isinstance(data, SMSEntry): 86 return; 87 self.update(data.get_db_dict())
88 smsobjectfactory=database.dataobjectfactory(SMSDataObject) 89 90 #-------------------------------------------------------------------------------
91 -class CannedMsgDataObject(database.basedataobject):
92 _knownproperties=[] 93 _knownlistproperties=database.basedataobject._knownlistproperties.copy() 94 _knownlistproperties.update( { 'canned_msg': ['text', 'type'] })
95 - def __init__(self, data=None):
96 if data is None or not isinstance(data, CannedMsgEntry): 97 return; 98 self.update(data.get_db_dict())
99 cannedmsgobjectfactory=database.dataobjectfactory(CannedMsgDataObject) 100 101 #-------------------------------------------------------------------------------
102 -class SMSEntry(object):
103 Folder_Inbox='Inbox' 104 Folder_Sent='Sent' 105 Folder_Saved='Saved' 106 Valid_Folders=(Folder_Inbox, Folder_Sent, Folder_Saved) 107 _id_index=0 108 _max_id_index=999 109 Priority_Normal=1 110 Priority_High=2 111 _priority_name={ 112 Priority_Normal: 'Normal', 113 Priority_High: 'High' } 114 _unknown_datetime='YYYY-MM-DD hh:mm:ss' 115
116 - def __init__(self):
117 self._data={ 'serials': [] } 118 self._create_id()
119
120 - def get(self):
121 return copy.deepcopy(self._data, {})
122 - def set(self, d):
123 self._data={} 124 self._data.update(d)
125
126 - def get_db_dict(self):
127 return self.get()
128 - def set_db_dict(self, d):
129 self.set(d)
130
131 - def _create_id(self):
132 "Create a BitPim serial for this entry" 133 self._data.setdefault("serials", []).append(\ 134 {"sourcetype": "bitpim", 135 "id": '%.3f%03d'%(time.time(), SMSEntry._id_index) }) 136 if SMSEntry._id_index<SMSEntry._max_id_index: 137 SMSEntry._id_index+=1 138 else: 139 SMSEntry._id_index=0
140 - def _get_id(self):
141 s=self._data.get('serials', []) 142 for n in s: 143 if n.get('sourcetype', None)=='bitpim': 144 return n.get('id', None) 145 return None
146 id=property(fget=_get_id) 147
148 - def _set_or_del(self, key, v, v_list=[]):
149 if v is None or v in v_list: 150 if self._data.has_key(key): 151 del self._data[key] 152 else: 153 self._data[key]=v
154
155 - def _get_from(self):
156 return self._data.get('_from', '')
157 - def _set_from(self, v):
158 self._set_or_del('_from', v, [''])
159 _from=property(fget=_get_from, fset=_set_from)
160 - def _get_to(self):
161 l=self._data.get('receivers', []) 162 if l: 163 return ','.join([x['name'] for x in l]) 164 return self._data.get('_to', '')
165 - def _set_to(self, v):
166 self._set_or_del('_to', v, [''])
167 _to=property(fget=_get_to, fset=_set_to)
168 - def _get_subject(self):
169 return self._data.get('subject', '<None>')
170 - def _set_subject(self, v):
171 self._set_or_del('subject', v, [''])
172 subject=property(fget=_get_subject, fset=_set_subject)
173 - def _get_text(self):
174 return self._data.get('text', '')
175 - def _set_text(self, v):
176 self._set_or_del('text', v, ['']) 177 self._check_and_create_msg_id()
178 text=property(fget=_get_text, fset=_set_text)
179 - def _get_datetime(self):
180 return self._data.get('datetime', '')
181 - def _set_datetime(self, v):
182 if isinstance(v, (list, tuple)) and len(v)==5: 183 v='%04d%02d%02dT%02d%02d00'%v 184 elif not isinstance(v, (str, unicode)): 185 raise TypeError('must be YYYYMMDDThhmmss or (y,m,d,h,m)') 186 self._set_or_del('datetime', v, ['']) 187 self._check_and_create_msg_id()
188 datetime=property(fget=_get_datetime, fset=_set_datetime)
189 - def get_date_time_str(self):
190 # return a string representing this date/time in the format of 191 # YYYY-MM-DD hh:mm:ss 192 s=self.datetime 193 if not len(s): 194 s=self._unknown_datetime 195 else: 196 s=s[:4]+'-'+s[4:6]+'-'+s[6:8]+' '+s[9:11]+':'+s[11:13]+':'+s[13:] 197 return s
198 - def _check_and_create_msg_id(self):
199 if not len(self.msg_id) and len(self.text) and len(self.datetime): 200 self._data['msg_id']=sha.new(self.datetime+self.text).hexdigest()
201 - def _get_callback(self):
202 return self._data.get('callback', '')
203 - def _set_callback(self, v):
204 self._set_or_del('callback', v, [''])
205 callback=property(fget=_get_callback, fset=_set_callback)
206 - def _get_folder(self):
207 return self._data.get('folder', '')
208 - def _set_folder(self, v):
209 if v not in self.Valid_Folders: 210 raise ValueError 211 self._set_or_del('folder', v, [''])
212 folder=property(fget=_get_folder, fset=_set_folder) 213
214 - def _get_flag_value(self, flag_key, default=None):
215 f=self._data.get('flags', []) 216 for n in f: 217 if n.has_key(flag_key): 218 return n[flag_key] 219 return default
220 - def _set_flag_value(self, flag_key, v):
221 f=self._data.get('flags', []) 222 for i, n in enumerate(f): 223 if n.has_key(flag_key): 224 if v is None or not v: 225 del f[i] 226 if not len(self._data['flags']): 227 del self._data['flags'] 228 else: 229 n[flag_key]=v 230 return 231 if v is not None and v: 232 self._data.setdefault('flags', []).append({flag_key: v})
233
234 - def _get_locked(self):
235 return self._get_flag_value('locked', False)
236 - def _set_locked(self, v):
237 self._set_flag_value('locked', v)
238 locked=property(fget=_get_locked, fset=_set_locked)
239 - def _get_read(self):
240 return self._get_flag_value('read', False)
241 - def _set_read(self, v):
242 self._set_flag_value('read', v)
243 read=property(fget=_get_read, fset=_set_read) 244
245 - def _get_msg_id(self):
246 return self._data.get('msg_id', '')
247 msg_id=property(fget=_get_msg_id) 248
249 - def _get_priority(self):
250 return self._data.get('priority', SMSEntry.Priority_Normal)
251 - def _set_priority(self, v):
252 if v not in (SMSEntry.Priority_Normal, SMSEntry.Priority_High): 253 raise ValueError('must be SMSEntry.Priority_Normal or SMSEntry.Priority_High') 254 self._set_or_del('priority', v, [])
255 - def _get_priority_str(self):
256 return self._priority_name[self.priority]
257 priority=property(fget=_get_priority, fset=_set_priority) 258 priority_str=property(fget=_get_priority_str) 259
260 - def add_recipient(self, name, confirmed=None, confirmed_datetime=None):
261 if isinstance(confirmed_datetime, (list, tuple)): 262 if len(confirmed_datetime)!=5: 263 raise ValueError('must be (y,m,d,h,m)') 264 confirmed_datetime='%04d%02d%02dT%02d%02d00'%confirmed_datetime 265 r={'name': name } 266 if confirmed_datetime: 267 r['confirmed_datetime']=confirmed_datetime 268 self._data.setdefault('receivers', []).append(r)
269 - def confirm_recipient(self, name, confirmed_datetime):
270 if isinstance(confirmed_datetime, (list, tuple)): 271 if len(confirmed_datetime)!=5: 272 raise ValueError('must be (y,m,d,h,m)') 273 confirmed_datetime='%04d%02d%02dT%02d%02d00'%confirmed_datetime 274 for e in self._data.get('receivers', []): 275 if e['name']==name: 276 e['confirmed_datetime']=confirmed_datetime 277 return 278 raise Exception('Receiver %s not found'%name)
279 - def _get_delivery_status(self):
280 # return a list of delivery status, one of each recipient 281 res=[] 282 l=self._data.get('receivers', []) 283 for e in l: 284 s=e.get('confirmed_datetime', None) 285 if s: 286 res.append('%s confirmed on %s-%s-%s %s:%s'% 287 (e['name'], s[:4], s[4:6], s[6:8], 288 s[9:11], s[11:13])) 289 else: 290 res.append('%s not confirmed'%e['name']) 291 return res
292 delivery_status=property(fget=_get_delivery_status)
293 294 #-------------------------------------------------------------------------------
295 -class CannedMsgEntry(object):
296 _data_key='canned_msg' 297 builtin_type='builtin' 298 user_type='user'
299 - def __init__(self):
300 self._data={ 'serials': [] } 301 self._create_id()
302
303 - def get(self):
304 return copy.deepcopy(self._data, {})
305 - def set(self, d):
306 self._data={} 307 self._data.update(d)
308
309 - def get_db_dict(self):
310 return self.get()
311 - def set_db_dict(self, d):
312 self.set(d)
313
314 - def _create_id(self):
315 "Create a BitPim serial for this entry" 316 self._data.setdefault("serials", []).append(\ 317 {"sourcetype": "bitpim", "id": str(time.time())})
318 - def _get_id(self):
319 s=self._data.get('serials', []) 320 for n in s: 321 if n.get('sourcetype', None)=='bitpim': 322 return n.get('id', None) 323 return None
324 id=property(fget=_get_id) 325
326 - def _get_builtin_list(self):
327 return [x['text'] for x in self._data.get(self._data_key, []) \ 328 if x.get('type', None)==self.builtin_type]
329 builtin_list=property(fget=_get_builtin_list) 330
331 - def _get_user_list(self):
332 return [x['text'] for x in self._data.get(self._data_key, []) \ 333 if x.get('type', None)==self.user_type]
334 - def _set_user_list(self, v):
335 # first get all the builtin ones 336 l=[x for x in self._data.get(self._data_key, []) \ 337 if x.get('type', None)==self.builtin_type] 338 # then add the user ones 339 l+=[ { 'text': x, 'type': self.user_type } for x in v] 340 self._data[self._data_key]=l
341 msg_list=user_list=property(fget=_get_user_list, fset=_set_user_list)
342 343 #------------------------------------------------------------------------------- 344