예제 #1
0
def publish_network_messages(net):
    """ Push messages to network, ``net``. """
    from x84.bbs import DBProxy
    from x84.bbs.msgbase import format_origin_line, MSGDB

    log = logging.getLogger(__name__)

    log.debug(u'[{net[name]}] publishing new messages.'.format(net=net))

    queuedb = DBProxy('{0}queues'.format(net['name']), use_session=False)
    transdb = DBProxy('{0}trans'.format(net['name']), use_session=False)
    msgdb = DBProxy(MSGDB, use_session=False)

    # publish each message
    for msg_id in sorted(queuedb.keys(),
                         cmp=lambda x, y: cmp(int(x), int(y))):
        if msg_id not in msgdb:
            log.warn('[{net[name]}] No such message (msg_id={msg_id})'
                     .format(net=net, msg_id=msg_id))
            del queuedb[msg_id]
            continue

        msg = msgdb[msg_id]

        trans_parent = None
        if msg.parent is not None:
            matches = [key for key, data in transdb.items()
                       if int(data) == msg.parent]

            if len(matches) > 0:
                trans_parent = matches[0]
            else:
                log.warn('[{net[name]}] Parent ID {msg.parent} '
                         'not in translation-DB (msg_id={msg_id})'
                         .format(net=net, msg=msg, msg_id=msg_id))

        trans_id = push_rest(net=net, msg=msg, parent=trans_parent)
        if trans_id is False:
            log.error('[{net[name]}] Message not posted (msg_id={msg_id})'
                      .format(net=net, msg_id=msg_id))
            continue

        if trans_id in transdb.keys():
            log.error('[{net[name]}] trans_id={trans_id} conflicts with '
                      '(msg_id={msg_id})'
                      .format(net=net, trans_id=trans_id, msg_id=msg_id))
            with queuedb:
                del queuedb[msg_id]
            continue

        # transform, and possibly duplicate(?) message ..
        with transdb, msgdb, queuedb:
            transdb[trans_id] = msg_id
            msg.body = u''.join((msg.body, format_origin_line()))
            msgdb[msg_id] = msg
            del queuedb[msg_id]
        log.info('[{net[name]}] Published (msg_id={msg_id}) => {trans_id}'
                 .format(net=net, msg_id=msg_id, trans_id=trans_id))
예제 #2
0
파일: msgpoll.py 프로젝트: hick/x84
def publish_network_messages(net):
    " Push messages to network. "
    from x84.bbs import DBProxy
    from x84.bbs.msgbase import format_origin_line, MSGDB

    log = logging.getLogger(__name__)

    log.debug(u'[{net[name]}] publishing new messages.'.format(net=net))

    queuedb = DBProxy('{0}queues'.format(net['name']), use_session=False)
    transdb = DBProxy('{0}trans'.format(net['name']), use_session=False)
    msgdb = DBProxy(MSGDB, use_session=False)

    # publish each message
    for msg_id in sorted(queuedb.keys(),
                         cmp=lambda x, y: cmp(int(x), int(y))):
        if msg_id not in msgdb:
            log.warn('{net[name]} No such message (msg_id={msg_id})'
                     .format(net=net, msg_id=msg_id))
            del queuedb[msg_id]
            continue

        msg = msgdb[msg_id]

        trans_parent = None
        if msg.parent is not None:
            matches = [key for key, data in transdb.items()
                       if int(data) == msg.parent]

            if len(matches) > 0:
                trans_parent = matches[0]
            else:
                log.warn('{net[name]} Parent ID {msg.parent} '
                         'not in translation-DB (msg_id={msg_id})'
                         .format(net=net, msg=msg, msg_id=msg_id))

        trans_id = push_rest(net=net, msg=msg, parent=trans_parent)
        if trans_id is False:
            log.error('{net[name]} Message not posted (msg_id={msg_id})'
                      .format(net=net['name'], msg_id=msg_id))
            continue

        if trans_id in transdb.keys():
            log.error('{net[name]} trans_id={trans_id} conflicts with '
                      '(msg_id={msg_id})'
                      .format(net=net, trans_id=trans_id, msg_id=msg_id))
            with queuedb:
                del queuedb[msg_id]
            continue

        # transform, and possibly duplicate(?) message ..
        with transdb, msgdb, queuedb:
            transdb[trans_id] = msg_id
            msg.body = u''.join((msg.body, format_origin_line()))
            msgdb[msg_id] = msg
            del queuedb[msg_id]
        log.info('{net[name]} Published (msg_id={msg_id}) => {trans_id}'
                 .format(net=net, msg_id=msg_id, trans_id=trans_id))
예제 #3
0
파일: ol.py 프로젝트: rostob/x84
def add_oneline(session, message):
    """ Add a oneliner to the local database. """
    udb = DBProxy('oneliner')
    with udb:
        key = max([int(key) for key in udb.keys()] or [0]) + 1
        udb[key] = {
            'oneliner': message,
            'alias': getsession().user.handle,
            'bbsname': get_ini('system', 'bbsname'),
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
        }
    maybe_expunge_records()

    # tell everybody a new oneliner was posted, including our
    # -- allows it to work something like a chatroom.
    session.send_event('global', ('oneliner', True))
예제 #4
0
파일: ol.py 프로젝트: tcummings19/3x84
def add_oneline(session, message):
    """ Add a oneliner to the local database. """
    udb = DBProxy('oneliner')
    with udb:
        key = max([int(key) for key in udb.keys()] or [0]) + 1
        udb[key] = {
            'oneliner': message,
            'alias': getsession().user.handle,
            'bbsname': get_ini('system', 'bbsname'),
            'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
        }
    maybe_expunge_records()

    # tell everybody a new oneliner was posted, including our
    # -- allows it to work something like a chatroom.
    session.send_event('global', ('oneliner', True))
예제 #5
0
파일: ol.py 프로젝트: hick/x84
def add_oneline(msg):
    """
    Add a oneliner to the local database.
    """
    import time
    from x84.bbs import getsession, DBProxy, ini
    session = getsession()
    udb = DBProxy('oneliner')
    udb.acquire()
    udb[max([int(key) for key in udb.keys()] or [0]) + 1] = {
        'oneliner': msg,
        'alias': getsession().handle,
        'bbsname': ini.CFG.get('system', 'bbsname'),
        'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
    }
    udb.release()
    session.buffer_event('oneliner_update', True)
    session.send_event('global', ('oneliner_update', True))
예제 #6
0
파일: ol.py 프로젝트: hick/x84
def add_oneline(msg):
    """
    Add a oneliner to the local database.
    """
    import time
    from x84.bbs import getsession, DBProxy, ini
    session = getsession()
    udb = DBProxy('oneliner')
    udb.acquire()
    udb[max([int(key) for key in udb.keys()] or [0]) + 1] = {
        'oneliner': msg,
        'alias': getsession().handle,
        'bbsname': ini.CFG.get('system', 'bbsname'),
        'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
    }
    udb.release()
    session.buffer_event('oneliner_update', True)
    session.send_event('global', ('oneliner_update', True))
예제 #7
0
파일: ol.py 프로젝트: hick/x84
def chk_thread(thread):
    """
    check if bbs-scene.org thread finished, if so, farm
    its data and send updates via event 'oneliner_update' if there
    are any.
    """
    from x84.bbs import getsession, DBProxy
    import logging
    log = logging.getLogger(__name__)
    session = getsession()
    if thread is not None and not thread.is_alive():
        udb = DBProxy('oneliner')
        udbkeys = udb.keys()
        nlc = 0
        for key, value in thread.content:
            if key not in udbkeys:
                udb[key] = value
                nlc += 1
        if nlc:
            log.debug('%d new entries', nlc)
            session.buffer_event('oneliner_update', True)
        else:
            log.debug('no new %s entries'.format(thread.ident))
        return True
예제 #8
0
파일: ol.py 프로젝트: hick/x84
def chk_thread(thread):
    """
    check if bbs-scene.org thread finished, if so, farm
    its data and send updates via event 'oneliner_update' if there
    are any.
    """
    from x84.bbs import getsession, DBProxy
    import logging
    log = logging.getLogger(__name__)
    session = getsession()
    if thread is not None and not thread.is_alive():
        udb = DBProxy('oneliner')
        udbkeys = udb.keys()
        nlc = 0
        for key, value in thread.content:
            if key not in udbkeys:
                udb[key] = value
                nlc += 1
        if nlc:
            log.debug('%d new entries', nlc)
            session.buffer_event('oneliner_update', True)
        else:
            log.debug('no new %s entries'.format(thread.ident))
        return True
예제 #9
0
def main():
    """ Main procedure. """
    # pylint: disable=R0914,R0912
    #         Too many local variables
    #         Too many branches
    from x84.bbs import DBProxy, getsession, getterminal, echo
    from x84.bbs import ini, LineEditor, timeago, showart
    from x84.bbs import disconnect, getch
    import time
    import os
    session, term = getsession(), getterminal()
    session.activity = 'logging off'
    handle = session.user.handle or 'anonymous'
    max_user = ini.CFG.getint('nua', 'max_user')
    prompt_msg = u'[spnG]: ' if session.user.get('expert', False) else (
        u'%s:AY SOMEthiNG %s:REViOUS %s:EXt %s:Et thE f**k Off !\b' % (
            term.bold_blue_underline(u's'),
            term.bold_blue_underline(u'p'),
            term.bold_blue_underline(u'n'),
            term.red_underline(u'Escape/g'),))
    prompt_say = u''.join((term.bold_blue(handle),
                           term.bold_blue(u' SAYS WhAt'), term.bold(': '),))
    boards = (('1984.ws', 'x/84 dEfAUlt bOARd', 'Dingo',),
              ('htc.zapto.org', 'Haunting the Chapel', 'Mercyful fate',),
              ('bbs.pharcyde.org', 'Pharcyde BBS', 'Access Denied',),
              ('bloodisland.ph4.se', 'Blood Island/X', 'Xzippo',),
              ('blackflag.acid.org:2627', 'Piranha: Black Flag', 'Caphood',),
              ('oddnetwork.org', '79 columns', 'Haliphax'),
              ('bbs.beardy.se', 'The Swamp', 'Beardy'),
              ('maze.io', 'rANDOM nOIZE', 'Maze'),)
    board_fmt = u'%25s %-30s %-15s\r\n'
    goodbye_msg = u''.join((
        term.move(term.height, 0),
        u'\r\n' * 10,
        u'tRY ANOthER fiNE bOARd', term.bold(u':'), u'\r\n\r\n',
        board_fmt % (
            term.underline('host'.rjust(25)),
            term.underline('board'.ljust(30)),
            term.underline('sysop'.ljust(15)),),
        u'\r\n'.join([board_fmt % (
            term.bold(host.rjust(25)),
            term.reverse(board.center(30)),
            term.bold_underline(sysop),)
            for (host, board, sysop) in boards]),
        u'\r\n\r\n',
        term.bold(
            u'back to the mundane world...'),
        u'\r\n',))
    commit_msg = term.bold_blue(
        u'-- !  thANk YOU fOR YOUR CONtRibUtiON, bROthER  ! --')
    write_msg = term.red_reverse(
        u'bURNiNG tO ROM, PlEASE WAiT ...')
    db_firstrecord = ((time.time() - 1984,
                       u'B. b.', u'bEhAVE YOURSElVES ...'),)
    automsg_len = 40

    def refresh_prompt(msg):
        """ Refresh automsg prompt using string msg. """
        echo(u''.join((u'\r\n\r\n', term.clear_eol, msg)))

    def refresh_automsg(idx):
        """ Refresh automsg database, display automsg of idx, return idx. """
        session.flush_event('automsg')
        autodb = DBProxy('automsg')
        automsgs = sorted(autodb.values()) if len(autodb) else db_firstrecord
        dblen = len(automsgs)
        # bounds check
        if idx < 0:
            idx = dblen - 1
        elif idx > dblen - 1:
            idx = 0
        tm_ago, handle, msg = automsgs[idx]
        asc_ago = u'%s ago' % (timeago(time.time() - tm_ago))
        disp = u''.join(('\r\n\r\n',
                         term.bold(handle.rjust(max_user)),
                         term.bold_blue(u'/'),
                         term.bold_blue(u'%*d' % (len('%d' % (dblen,)), idx,)),
                         term.bold_blue(u':'),
                         term.bold_green(msg.ljust(automsg_len)),
                         term.bold(u'\\'),
                         term.bold_blue(asc_ago),))
        echo(u'\r\n'.join(term.wrap(disp)))
        return idx

    def refresh_all(idx=None):
        """
        refresh screen, database, and return database index
        """
        echo(u''.join((u'\r\n\r\n', term.clear_eol,)))
        for line in showart(
                os.path.join(os.path.dirname(__file__), 'art', 'logoff.ans'), 'cp437'):
            echo(line)
        idx = refresh_automsg(-1 if idx is None else idx)
        refresh_prompt(prompt_msg)
        return idx

    idx = refresh_all()
    while True:
        if session.poll_event('refresh'):
            idx = refresh_all()
        elif session.poll_event('automsg'):
            refresh_automsg(-1)
            echo(u'\a')  # bel
            refresh_prompt(prompt_msg)
        inp = getch(1)
        if inp in (u'g', u'G', term.KEY_EXIT, unichr(27), unichr(3),):
            # http://www.xfree86.org/4.5.0/ctlseqs.html
            # Restore xterm icon and window title from stack.
            echo(unichr(27) + u'[23;0t')
            echo(goodbye_msg)
            getch(1.5)
            disconnect('logoff.')
        elif inp in (u'n', u'N', term.KEY_DOWN, term.KEY_NPAGE,):
            idx = refresh_automsg(idx + 1)
            refresh_prompt(prompt_msg)
        elif inp in (u'p', u'P', term.KEY_UP, term.KEY_PPAGE,):
            idx = refresh_automsg(idx - 1)
            refresh_prompt(prompt_msg)
        elif inp in (u's', u'S'):
            # new prompt: say something !
            refresh_prompt(prompt_say)
            msg = LineEditor(width=automsg_len).read()
            if msg is not None and msg.strip():
                echo(u''.join((u'\r\n\r\n', write_msg,)))
                autodb = DBProxy('automsg')
                autodb.acquire()
                idx = max([int(ixx) for ixx in autodb.keys()] or [-1]) + 1
                autodb[idx] = (time.time(), handle, msg.strip())
                autodb.release()
                session.send_event('global', ('automsg', True,))
                refresh_automsg(idx)
                echo(u''.join((u'\r\n\r\n', commit_msg,)))
                getch(0.5)  # for effect, LoL
            # display prompt
            refresh_prompt(prompt_msg)
예제 #10
0
def poll_network_for_messages(net):
    " pull for new messages of network, storing locally. "
    from x84.bbs import Msg, DBProxy
    from x84.bbs.msgbase import to_localtime

    log = logging.getLogger(__name__)

    log.debug(u'[{net[name]}] polling for new messages.'.format(net=net))

    try:
        last_msg_id = get_last_msg_id(net['last_file'])
    except (OSError, IOError) as err:
        log.error('[{net[name]}] skipping network: {err}'.format(net=net,
                                                                 err=err))
        return

    msgs = pull_rest(net=net, last_msg_id=last_msg_id)

    if msgs is not False:
        log.info('{net[name]} Retrieved {num} messages'.format(net=net,
                                                               num=len(msgs)))
    else:
        log.debug('{net[name]} no messages.'.format(net=net))
        return

    transdb = DBProxy('{0}trans'.format(net['name']), use_session=False)
    transkeys = transdb.keys()
    msgs = sorted(msgs, cmp=lambda x, y: cmp(int(x['id']), int(y['id'])))

    # store messages locally, saving their translated IDs to the transdb
    for msg in msgs:
        store_msg = Msg()
        store_msg.recipient = msg['recipient']
        store_msg.author = msg['author']
        store_msg.subject = msg['subject']
        store_msg.body = msg['body']
        store_msg.tags = set(msg['tags'])
        store_msg.tags.add(u''.join((net['name'])))

        if msg['recipient'] is None and u'public' not in msg['tags']:
            log.warn("{net[name]} No recipient (msg_id={msg[id]}), "
                     "adding 'public' tag".format(net=net, msg=msg))
            store_msg.tags.add(u'public')

        if (msg['parent'] is not None and str(msg['parent']) not in transkeys):
            log.warn('{net[name]} No such parent message ({msg[parent]}, '
                     'msg_id={msg[id]}), removing reference.'.format(net=net,
                                                                     msg=msg))
        elif msg['parent'] is not None:
            store_msg.parent = int(transdb[msg['parent']])

        if msg['id'] in transkeys:
            log.warn('{net[name]} dupe (msg_id={msg[id]}) discarded.'.format(
                net=net, msg=msg))
        else:
            # do not save this message to network, we already received
            # it from the network, set send_net=False
            store_msg.save(send_net=False, ctime=to_localtime(msg['ctime']))
            with transdb:
                transdb[msg['id']] = store_msg.idx
            transkeys.append(msg['id'])
            log.info(
                '{net[name]} Processed (msg_id={msg[id]}) => {new_id}'.format(
                    net=net, msg=msg, new_id=store_msg.idx))

        if 'last' not in net.keys() or int(net['last']) < int(msg['id']):
            net['last'] = msg['id']

    if 'last' in net.keys():
        with open(net['last_file'], 'w') as last_fp:
            last_fp.write(str(net['last']))

    return
예제 #11
0
파일: msgpoll.py 프로젝트: hick/x84
def poll_network_for_messages(net):
    " pull for new messages of network, storing locally. "
    from x84.bbs import Msg, DBProxy
    from x84.bbs.msgbase import to_localtime

    log = logging.getLogger(__name__)

    log.debug(u'[{net[name]}] polling for new messages.'.format(net=net))

    try:
        last_msg_id = get_last_msg_id(net['last_file'])
    except (OSError, IOError) as err:
        log.error('[{net[name]}] skipping network: {err}'
                  .format(net=net, err=err))
        return

    msgs = pull_rest(net=net, last_msg_id=last_msg_id)

    if msgs is not False:
        log.info('{net[name]} Retrieved {num} messages'
                 .format(net=net, num=len(msgs)))
    else:
        log.debug('{net[name]} no messages.'.format(net=net))
        return

    transdb = DBProxy('{0}trans'.format(net['name']), use_session=False)
    transkeys = transdb.keys()
    msgs = sorted(msgs, cmp=lambda x, y: cmp(int(x['id']), int(y['id'])))

    # store messages locally, saving their translated IDs to the transdb
    for msg in msgs:
        store_msg = Msg()
        store_msg.recipient = msg['recipient']
        store_msg.author = msg['author']
        store_msg.subject = msg['subject']
        store_msg.body = msg['body']
        store_msg.tags = set(msg['tags'])
        store_msg.tags.add(u''.join((net['name'])))

        if msg['recipient'] is None and u'public' not in msg['tags']:
            log.warn("{net[name]} No recipient (msg_id={msg[id]}), "
                     "adding 'public' tag".format(net=net, msg=msg))
            store_msg.tags.add(u'public')

        if (msg['parent'] is not None and
                str(msg['parent']) not in transkeys):
            log.warn('{net[name]} No such parent message ({msg[parent]}, '
                     'msg_id={msg[id]}), removing reference.'
                     .format(net=net, msg=msg))
        elif msg['parent'] is not None:
            store_msg.parent = int(transdb[msg['parent']])

        if msg['id'] in transkeys:
            log.warn('{net[name]} dupe (msg_id={msg[id]}) discarded.'
                     .format(net=net, msg=msg))
        else:
            # do not save this message to network, we already received
            # it from the network, set send_net=False
            store_msg.save(send_net=False, ctime=to_localtime(msg['ctime']))
            with transdb:
                transdb[msg['id']] = store_msg.idx
            transkeys.append(msg['id'])
            log.info('{net[name]} Processed (msg_id={msg[id]}) => {new_id}'
                     .format(net=net, msg=msg, new_id=store_msg.idx))

        if 'last' not in net.keys() or int(net['last']) < int(msg['id']):
            net['last'] = msg['id']

    if 'last' in net.keys():
        with open(net['last_file'], 'w') as last_fp:
            last_fp.write(str(net['last']))

    return
예제 #12
0
파일: logoff.py 프로젝트: jonny290/yos-x84
def main():
    """ Main procedure. """
    # pylint: disable=R0914,R0912
    #         Too many local variables
    #         Too many branches
    from x84.bbs import DBProxy, getsession, getterminal, echo
    from x84.bbs import ini, LineEditor, timeago, Ansi, showcp437
    from x84.bbs import disconnect, getch
    import time
    import os
    session, term = getsession(), getterminal()
    session.activity = 'logging off'
    handle = session.handle if (
        session.handle is not None
    ) else 'anonymous'
    max_user = ini.CFG.getint('nua', 'max_user')
    prompt_msg = u'[spnG]: ' if session.user.get('expert', False) else (
        u'%s:AY SOMEthiNG %s:REViOUS %s:EXt %s:Et thE f**k Off !\b' % (
        term.bold_blue_underline(u's'), term.blue_underline(u'p'),
        term.blue_underline(u'n'), term.red_underline(u'Escape/g'),))
    prompt_say = u''.join((term.bold_blue(handle),
                           term.blue(u' SAYS WhAt'), term.bold(': '),))
    boards = (('1984.ws', 'x/84 dEfAUlt bOARd', 'dingo',),
              ('htc.zapto.org', 'Haunting the Chapel', 'Mercyful',),
              ('pharcyde.ath.cx', 'Pharcyde BBS', 'Access Denied',),
              ('bloodisland.ph4.se', 'Blood Island', 'xzip',),
              ('ssl.archaicbinary.net', 'Archaic Binary', 'Wayne Smith',),
              ('bbs.godta.com', 'godta', 'sk-5',)
              ,)
    board_fmt = u'%25s %-30s %-15s\r\n'
    goodbye_msg = u''.join((
        term.move(term.height, 0),
        u'\r\n' * 10,
        u'tRY ANOthER fiNE bOARd', term.bold(u':'), u'\r\n\r\n',
        board_fmt % (
            term.underline('host'.rjust(25)),
            term.underline('board'.ljust(30)),
            term.underline('sysop'.ljust(15)),),
        u'\r\n'.join([board_fmt % (
            term.bold(host.rjust(25)),
            term.reverse(board.center(30)),
            term.bold_underline(sysop),)
            for (host, board, sysop) in boards]),
        u'\r\n\r\n',
        term.bold(
            u'back to the mundane world...'),
        u'\r\n',))
    commit_msg = term.bold_blue(
        u'-- !  thANk YOU fOR YOUR CONtRibUtiON, bROthER  ! --')
    write_msg = term.red_reverse(
        u'bURNiNG tO ROM, PlEASE WAiT ...')
    db_firstrecord = ((time.time() - 1984,
                       u'B. b.', u'bEhAVE YOURSElVES ...'),)
    automsg_len = 40
    artfile = os.path.join(os.path.dirname(__file__), 'art', '1984.asc')

    def refresh_prompt(msg):
        """ Refresh automsg prompt using string msg. """
        echo(u''.join((u'\r\n\r\n', term.clear_eol, msg)))

    def refresh_automsg(idx):
        """ Refresh automsg database, display automsg of idx, return idx. """
        session.flush_event('automsg')
        autodb = DBProxy('automsg')
        automsgs = sorted(autodb.values()) if len(autodb) else db_firstrecord
        dblen = len(automsgs)
        # bounds check
        if idx < 0:
            idx = dblen - 1
        elif idx > dblen - 1:
            idx = 0
        tm_ago, handle, msg = automsgs[idx]
        asc_ago = u'%s ago' % (timeago(time.time() - tm_ago))
        disp = (u''.join(('\r\n\r\n',
                          term.bold(handle.rjust(max_user)),
                          term.bold_blue(u'/'),
                          term.blue(u'%*d' % (len('%d' % (dblen,)), idx,)),
                          term.bold_blue(u':'),
                          term.blue_reverse(msg.ljust(automsg_len)),
                          term.bold(u'\\'),
                          term.blue(asc_ago),)))
        echo(u''.join((
            u'\r\n\r\n',
            Ansi(disp).wrap(term.width),
        )))
        return idx

    def refresh_all(idx=None):
        """
        refresh screen, database, and return database index
        """
        echo(u''.join((u'\r\n\r\n', term.clear_eol,)))
        for line in showcp437(artfile):
            echo(line)
        idx = refresh_automsg(-1 if idx is None else idx)
        refresh_prompt(prompt_msg)
        return idx

    idx = refresh_all()
    while True:
        if session.poll_event('refresh'):
            idx = refresh_all()
        elif session.poll_event('automsg'):
            refresh_automsg(-1)
            echo(u'\a')  # bel
            refresh_prompt(prompt_msg)
        inp = getch(1)
        if inp in (u'g', u'G', term.KEY_EXIT, unichr(27), unichr(3),):
            # http://www.xfree86.org/4.5.0/ctlseqs.html
            # Restore xterm icon and window title from stack.
            echo(unichr(27) + u'[23;0t')
            echo(goodbye_msg)
            getch(1.5)
            disconnect('logoff.')
        elif inp in (u'n', u'N', term.KEY_DOWN, term.KEY_NPAGE,):
            idx = refresh_automsg(idx + 1)
            refresh_prompt(prompt_msg)
        elif inp in (u'p', u'P', term.KEY_UP, term.KEY_PPAGE,):
            idx = refresh_automsg(idx - 1)
            refresh_prompt(prompt_msg)
        elif inp in (u's', u'S'):
            # new prompt: say something !
            refresh_prompt(prompt_say)
            msg = LineEditor(width=automsg_len).read()
            if msg is not None and msg.strip():
                echo(u''.join((u'\r\n\r\n', write_msg,)))
                autodb = DBProxy('automsg')
                autodb.acquire()
                idx = max([int(ixx) for ixx in autodb.keys()] or [-1]) + 1
                autodb[idx] = (time.time(), handle, msg.strip())
                autodb.release()
                session.send_event('global', ('automsg', True,))
                refresh_automsg(idx)
                echo(u''.join((u'\r\n\r\n', commit_msg,)))
                getch(0.5)  # for effect, LoL
            # display prompt
            refresh_prompt(prompt_msg)