示例#1
0
 def update():
     '''
     process xhr request for update to posts or messages
     '''
     name, hashed = args.get('name', None), args.get('hash', None)
     update_status = status  # default from outer variable
     if name in ('messages', 'posts'):
         # pylint: disable=eval-used
         # check outer variables
         # must be done before eval or it will fail
         logging.debug('messages: ...%s', messages[-128:])
         logging.debug('messages_hash: %s', messages_hash)
         logging.debug('posts: %s...', posts[:128])
         logging.debug('posts_hash: %s', posts_hash)
         if hashed and hashed != eval(name + '_hash'):
             update_page = eval(name).encode()
         elif hashed:
             logging.debug('%s unchanged', args['name'])
             update_page = b''
             update_status = '304 Not Modified'
         else:
             logging.error('no hash passed to /update/')
             update_page = b''
             update_status = '406 Not Acceptable'
     else:
         update_page = (
             '<div>no updates for %s</div>' % args['name']
         ).encode()
         update_status = '404 Not Found'
     return update_status, update_page
示例#2
0
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')
示例#3
0
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')
示例#4
0
def post(post_type, *args, returned='hashed', **kwargs):
    '''
    make a new post from the command line or from another subroutine
    '''
    if len(args) == 1 and JSON.match(args[0]):
        try:
            kwargs.update(json.loads(args[0]))
        except json.decoder.JSONDecodeError:
            logging.error('Post not valid JSON format: %s' % args[0])
    else:
        logging.debug('args %s not valid JSON, using as key-value pairs', args)
        for arg in args:
            logging.debug('parsing %s', arg)
            kwargs.update(dict((arg.split('=', 1), )))
    # override post_type if specified
    if post_type:
        kwargs.update({'type': post_type})
    try:
        newpost = BasePost(None, **kwargs)
        jsonified = newpost.to_json()
        post_type = newpost.type
        hashed = kbhash(jsonified)
        cached = cache('.'.join((hashed, post_type)), jsonified)
        jsonified = newpost.to_json(for_hashing=True)
        hashed = kbhash(jsonified)
        hashcached = cache('.'.join((hashed, post_type)), jsonified)
        unadorned = os.path.splitext(hashcached)[0]
        try:
            os.symlink(cached, unadorned)
        except FileExistsError:
            existing = os.readlink(unadorned)
            if existing != cached:
                logging.warning('updating post %s to %s', unadorned, cached)
                os.unlink(unadorned)
                os.symlink(cached, unadorned)
            else:
                logging.debug('%s already symlinked to %s', unadorned, cached)
        return hashed if returned == 'hashed' else newpost
    except AttributeError:
        logging.exception('Post failed: attribute error')
        return None
    except TypeError:
        logging.exception('Post failed with kwargs: %s', kwargs)
        return None
示例#5
0
def init():
    '''
    initialize application
    '''
    logging.debug('beginning kybyz initialization')
    os.makedirs(CACHE, 0o700, exist_ok=True)
    CACHED.update(registration()._asdict())
    if not CACHED['gpgkey']:
        username = os.getenv('KB_USERNAME', None)
        email = os.getenv('KB_EMAIL', None)
        if username and email:
            register(username, email)
            CACHED.update(registration()._asdict())
        else:
            logging.error('need to set envvars KB_USERNAME and KB_EMAIL')
    CACHED['uptime'] = 0
    CACHED['javascript'] = 'ERROR:javascript disabled or incompatible'
    logging.debug('CACHED: %s', CACHED)
    kybyz = threading.Thread(target=background, name='kybyz')
    kybyz.daemon = True
    kybyz.start()
示例#6
0
def cache(path, data):
    '''
    store data in cache for later retrieval
    '''
    fullpath = os.path.realpath(os.path.join(KYBYZ_HOME, path))
    if not fullpath.startswith(os.path.realpath(KYBYZ_HOME) + os.sep):
        raise ValueError('Attempt to write %s outside of app bounds' %
                         fullpath)
    os.makedirs(os.path.dirname(fullpath), exist_ok=True)
    binary = 'b' if isinstance(data, bytes) else ''
    try:
        with open(fullpath, 'x' + binary) as outfile:
            outfile.write(data)
    except FileExistsError:
        existing = read(fullpath)
        if data != existing:
            logging.error('Failed to update %s from %r to %r', fullpath,
                          existing, data)
        else:
            logging.debug('% already cached', fullpath)
    return fullpath