def initDaemon(self): log('main', self.app) self.daemonThread = SignalDaemonThread(self) self.daemonThread.start() self.messageThread = SignalMessageThread(self, self.message_queue) self.messageThread.start()
def sendHandler(self, event): cur = self.wCommand.currentSend log('sendHandler', cur.value, cur.timestamp) self.parentApp.message_queue.put({ 'state': self.parentApp.state, 'currentSend': cur })
def _handleEnter(self, inp): now = int(time.time() * 1000) val = self.entry_widget.value log('handleEnter', inp, val, now) self.entry_widget.value = '' self.entry_widget.clear() self.currentSend = CurrentSend(now, val) self.parent.parentApp.handleSelfEnvelope(now, self._getSelfName(), val) self.parent.parentApp.queue_event(npyscreen.Event("SEND")) self.parent.parentApp.queue_event(npyscreen.Event("RELOAD"))
def sendLinkLine(self, line): if not self.setup.token: token = line.strip() log('GOT TOKEN:', token) self.setup.token = token else: log('AFTER:', line) if not self.setup.response: self.setup.response = line else: self.setup.response += '\n' + line
def sync_read_matches(self, env): ret = False for msg in self.readMessages: if env and env.dataMessage.is_message(): log('dm: ts=', env.dataMessage.timestamp, 'source=', env.source) log('msg: ts=', msg.get('timestamp'), 'sender=', msg.get('sender')) ret = ret or ((env.source == msg.get('sender')) and self._compare_ts(env.dataMessage.timestamp, msg.get('timestamp'))) return ret
def create(self): log('appForm creating') self.m1 = self.add_menu(name="Main Menu", shortcut="^X") self.m1.addItemsFromList([ ("Switch", self.whenSwitch, None, None, ("blah", )), ("Exit", self.whenExit, "e"), ]) self.add_event_hander("RELOAD", self.reloadHandler) self.add_event_hander("SEND", self.sendHandler) super(AppForm, self).create() log('appForm created')
def afterEditing(self): log(self.tree.value) selected, is_group = self.getFromId(self.tree.value) log(selected) if not selected: npyscreen.notify_confirm('Invalid entry', title='Select User/Group') return self.parentApp.app.wMain.clearValues() self.parentApp.app.wMain.update() self.parentApp.updateState(selected, is_group) self.parentApp.setNextForm('APP')
def handleEnvelope(self, env): self.envelopes.append(env) if env.timestamp and (time.time() - env.epoch_ts) >= 60: log('ignoring envelope due to time difference of', str((time.time() - env.epoch_ts))) return if env.dataMessage.is_message(): if self.state.shouldDisplayEnvelope(env): self.addEnvelope(env) elif self.state.shouldNotifyEnvelope(env): log('notifying line') gen_line = env.gen_line() txt = '{}:\n\n{}'.format(gen_line[0], gen_line[2]) if env.group: txt = 'Group: {}\n'.format(json.dumps(env.group)) + txt npyscreen.notify_wait(txt, title='New Message from {}'.format( gen_line[1])) else: log('not displaying or notifying dataMessage') if env.syncMessage.is_read_message(): log('is read message', env.syncMessage) for e in self.envelopes[:-1]: if env.syncMessage.sync_read_matches(e): log('mark_read', e) self.markAsEnvelope(e, '(read)') if env.callMessage.is_offer(): self.app.wMain.addValues([ ('*', 'You are receiving an inbound call from {}'.format( env.source)) ]) npyscreen.notify_wait('You are receiving an inbound call', title='Call from {}'.format(env.source)) if env.callMessage.is_busy(): self.app.wMain.addValues([ ('*', 'The caller {} is busy'.format(env.source)) ]) npyscreen.notify_wait('The caller is busy', title='Call from {}'.format(env.source)) if env.callMessage.is_hangup(): self.app.wMain.addValues([ ('*', 'The caller {} hung up'.format(env.source)) ]) npyscreen.notify_wait('The caller hung up', title='Call from {}'.format(env.source))
def __init__(self, state): phoneDir = '{}/data'.format(state.configDir) noConfig = False try: f = open('{}/{}'.format(phoneDir, state.phone), 'r') except FileNotFoundError as e: log('ERR: config load', e) noConfig = True if noConfig: setup = scurses.tui.setup.SetupApp(state) setup.run() exit(0) self.data = json.loads(f.read()) noContacts = (not self.data['contactStore'] and (not self.data['groupStore'] or not self.data['groupStore']['groups'])) if noContacts: log('noContacts!') f.close()
def create(self): log('selectForm create') super(SelectForm, self).create() self.tree = self.add(SelectFormTree) td = npyscreen.TreeData(content='Select one:', selectable=False, ignore_root=False) cobj = td.new_child(content='Contacts:', selectable=False) contacts = self.parentApp.configData.contacts for c in contacts: cobj.new_child(content='{} ({})'.format(c['name'], c['number'])) gobj = td.new_child(content='Groups:', selectable=True) groups = self.parentApp.configData.groups for g in groups: gobj.new_child( content='{} ({})'.format(g['name'], ', '.join(g['members']))) self.tree.values = td log('selectForm done')
def run(self): log('daemon thread') state = self.app.state script = ['signal-cli', '-u', state.phone, 'daemon', '--json'] #script = ['python3', 'sp.py'] try: popen = scurses.utils.processes.execute_popen(script) self.app.daemonPopen = popen log('daemon popen') for line in scurses.utils.processes.execute(popen): out_file_lock.acquire() out_file.write(line) out_file.flush() out_file_lock.release() log('line:', line) self.app.handleDaemonLine(line) self.app.queue_event(npyscreen.Event("RELOAD")) except subprocess.CalledProcessError as e: if not self.app.isShuttingDown: log('EXCEPTION in daemon', e) log('daemon exit')
def onStart(self): log('contacts: ', len(self.configData.contacts)) self.addForm('MAIN', SelectForm, name='Select User/Group') self.addForm('APP', AppForm, name='Application') log('start forms', self._Forms) self.app = self.getForm('APP') log('app is defined')
def run(self): log('link daemon thread') state = self.app.state script = ['signal-cli', 'link', '-n{} on {}'.format('signal-curses', socket.gethostname())] try: popen = scurses.utils.processes.execute_popen(script) self.app.daemonPopen = popen log('link daemon popen') for line in scurses.utils.processes.execute(popen): #log('queue event') """out_file_lock.acquire() out_file.write(line) out_file.flush() out_file_lock.release()""" log('link line:', line) if len(line) > 0: self.app.sendLinkLine(line) except subprocess.CalledProcessError as e: if not self.app.isShuttingDown: log('EXCEPTION in daemon', e) log('daemon exit')
def onInMainLoop(self): log('mloop forms', self._Forms)
def markAs(self, value, suffix): for i in range(len(self._real_values)): if self._mark_value_eq(self._real_values[i], value): log('markAs success:', value) self._real_values[i] = self._mark_value_as(value, suffix)
def sigterm_handler(self, sig, frame): log('SIGTERM') self.handleExit() exit(0)
def handleDaemonLine(self, line): self.raw_lines.append(line) log('handleDaemonLine', line) data = json.loads(line) env = Envelope.load(data, self, Envelope.NETWORK) self.handleEnvelope(env)
def _mark_value_as(self, value, txt): log('mark: ', value, 'as: ', txt) return (value[0], value[1], value[2], txt)
def send_message(self, state, currentSend): message = currentSend.value script = [] if state.is_user: log('send_message user', state.toNumber, message) self.signal.sendMessage(message, [], [str(state.toNumber)]) elif state.is_group: log('send_message group', state.groupId, message) b64 = base64.b64encode(state.groupId.encode()) log('group id:', state.groupId, ' b64:', b64) self.signal.sendGroupMessage(message, [], b64) else: log('ERR: send_message inconsistent state') return env = self.app.generateSelfEnvelope(currentSend.timestamp, self.app.state.phone, message) log('send_message env:', env) self.app.markAsEnvelope(env, '(sent)') log('send_message done')
def markAsEnvelope(self, env, suffix): log('markAsEnvelope:', env, suffix) gen_line = env.gen_line() self.app.wMain.markAs(gen_line, suffix) self.app.wMain.update()
def run(self): log('message thread') if self.app.state.bus == 'system': self.bus = pydbus.SystemBus() else: self.bus = pydbus.SessionBus() log('waiting for ({}) dbus...'.format(self.app.state.bus)) self.signal = exception_waitloop(self.get_message_bus, GLib.Error, 60) if not self.signal: log('dbus err') npyscreen.notify_wait( 'Unable to get signal {} bus. Messaging functionality will not function.' .format(self.app.state.bus), title='Error in SignalDaemonThread') exit(1) log('got dbus') # self.signal.onMessageReceived while True: item = self.queue.get() log('queue item', item) if 'exit' in item: break self.do_action(**item) self.queue.task_done() log('message thread exit')
def sigint_handler(self, sig, frame): log('SIGINT') self.handleExit() exit(0)
def updateState(self, selected, is_group): self.state.load(selected, is_group) log('new state:', self.state) self.app.updateState()
def should_notify(self, toNumber, phone): # fromNumber != phone log('should_notify', toNumber, phone, self.source, self.dataMessage.should_display()) return (self.source != toNumber) and ( self.source != phone) and self.dataMessage.should_notify()
def handleMessageLine(self, line): self.messageLines.append(line) log('handleMessageLine', line)