def _import_one_sms(data, current_number=None, dry_run=False): # define who's the actor and who's the receiver other_number = unicode(data['Number']) if data['State'] == 'Sent': sent_by, sent_to = current_number, other_number else: sent_by, sent_to = other_number, current_number fields = dict( sent_by = sent_by, sent_to = sent_to, date_time = data['DateTime'], #is_confirmed = True, # it is sent, yup summary = data['Text'] or u'[text missing]', # u'' is invalid, None not accepted ) search_fields = dict(fields) search_fields.pop('summary') # workaround: we don't know which number was "current" when the message was # last imported, so we look for any "our" number. my_numbers = _get_my_numbers() k = 'sent_by' if data['State']=='Sent' else 'sent_to' search_fields.pop(k) search_fields.update({'{0}__in'.format(k): my_numbers.values()}) db = app.get_feature('document_storage').default_db if not GammuSMS.objects(db).where(**search_fields).count(): #print 'NOT FOUND:', search_fields print u'SAVING {0} {1} → {2} {3}{4}'.format( fields['date_time'], sent_by, sent_to, fields['summary'][:20], u'…' if 20 < len(fields['summary']) else '') if dry_run: return '(stub: dry run)' else: return GammuSMS(**fields).save(db)
def import_sms(args): """Imports SMS from mobile phone. :param current_phone: Expects "current phone" so that incoming and outgoing messages can be correctly populated with both sender and receiver numbers (the phone only stores the "other" number) and you have to manually specify yours). Can be omitted if there's only one "my number" in the settings. Note that you should specify the label (e.g. "personal", "work" or "primary") instead of the number itself. The labels are defined in the "my_numbers" setting for the bundle:: extensions: orgtool.ext.mobile.MobileETL: my_numbers: home: +1234567890 work: +0987654321 :param full_archive: If True, attempts to import all messages in the phone. Despite this implies checking for duplicates, the process takes longer and issues with dates and phone numbers may arise. By default this option is off and only "new" messages are imported. Message is considered "new" if its date is greater than the last known message's date. Time is ignored in this check. :param dry_run: If True, newly imported messages are not saved. Use this for testing. Default is False. """ if args.dry_run: yield 'Dry run, no data will be changed.' db = app.get_feature('document_storage').default_db my_numbers = _get_my_numbers() current_number = None if args.current_phone: assert args.current_phone in my_numbers, ( 'unknown number label "{0}"'.format(args.current_phone)) current_number = my_numbers[args.current_phone] else: if len(my_numbers) != 1: raise CommandError('Which phone (SIM card) is that? Choices: ' '{0}'.format(', '.join(my_numbers))) the_only_label = my_numbers.keys()[0] current_number = my_numbers[the_only_label] assert current_number # find latest known message date if args.full_archive: last_imported_date = None yield 'Importing all messages from the phone...' else: msgs = GammuSMS.objects(db).order_by('date_time', reverse=True) last_imported_date = msgs[0].date_time.date() if msgs.count() else None yield 'Importing messages since {0}...'.format(last_imported_date) sm = _get_state_machine() seen_cnt = saved_cnt = 0 for data in _iterate_results(sm.GetNextSMS, Folder=0): if last_imported_date and not args.full_archive: # skip message without full check if a later message had been # already imported if data['DateTime'].date() < last_imported_date: continue saved = _import_one_sms(data, current_number, dry_run=args.dry_run) if saved: saved_cnt += 1 seen_cnt += 1 yield 'Imported {saved_cnt} of {seen_cnt}.'.format(**locals()) if args.dry_run: yield '(Dry run, nothing really changed.)'