1
2
3
4
5
6
7
8
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
68 import copy
69 import sha
70 import time
71
72
73
74
75 import database
76
77
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'] })
88 smsobjectfactory=database.dataobjectfactory(SMSDataObject)
89
90
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
121 return copy.deepcopy(self._data, {})
123 self._data={}
124 self._data.update(d)
125
126 - def get_db_dict(self):
128 - def set_db_dict(self, 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
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)
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)
190
191
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
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, [])
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)
280
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
304 return copy.deepcopy(self._data, {})
306 self._data={}
307 self._data.update(d)
308
309 - def get_db_dict(self):
311 - def set_db_dict(self, 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())})
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
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
336 l=[x for x in self._data.get(self._data_key, []) \
337 if x.get('type', None)==self.builtin_type]
338
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