def register(username=None, email=None, gpgkey=None): ''' register kybyz account ''' if gpgkey is None: gpgkey = verify_key(email) current = registration() # see what we already have, if anything if username is None or email is None: logging.error('Usage: %s %s USERNAME EMAIL_ADDRESS', COMMAND, ARGS[0]) raise ValueError('Must specify desired username and email address') if any(current): if (username, email, gpgkey) != current: raise ValueError('Previously registered as %s %s %s' % current) logging.warning('Already registered as %s %s %s', *current) else: os.makedirs(os.path.join(CACHE, gpgkey)) os.symlink(os.path.join(CACHE, gpgkey), os.path.join(CACHE, email)) os.symlink(os.path.join(CACHE, email), os.path.join(CACHE, username)) os.symlink(os.path.join(CACHE, username), KYBYZ_HOME) logging.info('Now registered as %s %s %s', username, email, gpgkey) if CACHED.get('ircbot', None): CACHED['ircbot'].nick(username) CACHED['ircbot'].leave() # rejoin to freshen CACHED['irc_id'] CACHED['ircbot'].join() else: logging.info('registering outside of running application')
def process(args): ''' process a kybyz command ''' if args and args[0] in COMMANDS: print(eval(args[0])(*args[1:])) # pylint: disable=eval-used elif args: logging.error('must specify one of: %s', COMMANDS) else: logging.info('no command received to process')
def background(): ''' load and maintain cache communicate with other kybyz servers ''' delay = int(os.getenv('KB_DELAY') or 600) # seconds CACHED['ircbot'] = IRCBot(nickname=CACHED.get('username', None)) while True: logging.info('kybyz active %s seconds', CACHED['uptime'], **TO_PAGE) time.sleep(delay) # releases the GIL for `serve` CACHED['uptime'] += delay logging.debug('CACHED: %s, threads: %s', CACHED, threading.enumerate())
def commandloop(): ''' simple repl (read-evaluate-process-loop) for command-line testing ''' time.sleep(10) # give page a chance to load before starting repl args = [] logging.info('Ready to accept commands; `quit` to terminate input loop') while args[0:1] != ['quit']: try: print(process(args)) args = shlex.split(input('kbz> ')) except EXPECTED_ERRORS: logging.exception('command failed, please try again') args[:] = [] except EOFError: break logging.warning('input loop terminated')
def uwsgi_init(): ''' initialize uwsgi application ''' # pylint: disable=import-error, bad-option-value, import-outside-toplevel logging.debug('beginning kybyz uwsgi initialization') import uwsgi if os.getenv('ANDROID_ROOT') is None: import webbrowser else: webbrowser = type( '', (), {'open': lambda url: subprocess.call(['am', 'start', url])} ) port = host = None try: port = fromfd(uwsgi.sockets[0], AF_INET, SOCK_STREAM).getsockname()[1] host = 'localhost:%s' % port except AttributeError: logging.exception('cannot determine port') init() if not sys.stdin.isatty(): logging.info('running as background process, will not launch browser') else: if host is not None and not os.getenv('WSL'): logging.debug('opening browser window to %s', host) webbrowser.open('http://%s' % host) else: logging.exception('cannot open browser to %s', host) logging.info("if you're running under WSL (Windows Subsystem for" " Linux), just open Windows browser to %s", host) repl = threading.Thread(target=commandloop, name='repl') repl.daemon = True repl.start() logging.debug('uwsgi initialization complete')
def monitor(self): ''' wait for input. send a PONG for every PING intended to run in a daemon thread set ircbot.terminate to True in order to shut it down ''' logging.debug('ircbot monitoring incoming traffic') tries = 0 while tries < 10: try: received = self.stream.readline().rstrip() tries = 0 except ConnectionResetError: tries += 1 self.connect(self.server, self.port, self.nickname, self.realname) continue logging.info('received: %r, length: %d', received, len(received)) end_message = len(received) < 510 # make sure all words[n] references are accounted for words = received.split() + ['', '', ''] nickname, matched = check_username(words[0]) if words[0] == 'PING': pong = received.replace('I', 'O', 1).rstrip() + CRLF logging.info('sending: %r', pong) self.client.send(pong.encode()) elif words[1] == 'JOIN' and matched: CACHED['irc_id'] = words[0] logging.info("CACHED['irc_id'] = %s", CACHED['irc_id']) elif words[1] == 'PRIVMSG': sender = nickname privacy = 'public' if words[2] == CHANNEL else 'private' logging.info('%s message received from %s:', privacy, sender) # chop preceding ':' from ':this is a private message' CACHED[sender] += ' '.join(words[3:])[1:].rstrip() # try decoding what we have so far logging.debug('attempting to decode %s', CACHED[sender]) text, trustlevel = decrypt(CACHED[sender].encode()) logging.debug('text: %s, trustlevel: %s', text, trustlevel) if text or end_message: text = text or CACHED[sender][:256].encode() logging.info( '%s %s message from %s: %s', trustlevel, privacy, sender, text.decode().replace('<', '<').replace('>', '>'), **TO_PAGE) if JSON.match(CACHED[sender]): POSTS_QUEUE.append(CACHED[sender]) logging.debug('appended %r to POSTS_QUEUE', CACHED[sender]) else: logging.debug('Not JSON: %s', CACHED[sender]) CACHED[sender] = '' elif len(CACHED[sender]) > MAXSIZE: logging.info( 'clearing overflow CACHED[%s]: %r..., length %d', sender, CACHED[sender][:256], len(CACHED[sender])) CACHED[sender] = '' else: logging.debug('CACHED[%s] now %r', sender, CACHED[sender]) clearcache() logging.warning('ircbot terminated from launching thread')