Пример #1
0
def prompt_tags(msg):
    """ Prompt for and return tags wished for message. """
    # pylint: disable=R0914,W0603
    #         Too many local variables
    #         Using the global statement
    from x84.bbs import DBProxy, echo, getterminal, getsession
    from x84.bbs import Ansi, LineEditor
    session, term = getsession(), getterminal()
    tagdb = DBProxy('tags')
    msg_onlymods = (u"\r\nONlY MEMbERS Of thE '%s' OR '%s' "
                    "GROUP MAY CREAtE NEW tAGS." % (
                        term.bold_yellow('sysop'),
                        term.bold_blue('moderator'),))
    msg_invalidtag = u"\r\n'%s' is not a valid tag."
    prompt_tags1 = u"ENtER %s, COMMA-dEliMitEd. " % (
        term.bold_red('TAG(s)'),)
    prompt_tags2 = u"OR '/list', %s:quit\r\n : " % (
        term.bold_yellow_underline('Escape'),)
    while True:
        # Accept user input for multiple 'tag's, or /list command
        echo(u'\r\n\r\n')
        echo(prompt_tags1)
        echo(prompt_tags2)
        width = term.width - 6
        sel_tags = u', '.join(msg.tags)
        inp_tags = LineEditor(width, sel_tags).read()
        if inp_tags is not None and 0 == len(inp_tags.strip()):
            # no tags must be (private ..)
            msg.tags = set()
            return True
        if inp_tags is None or inp_tags.strip().lower() == '/quit':
            return False
        elif inp_tags.strip().lower() == '/list':
            # list all available tags, and number of messages
            echo(u'\r\n\r\nTags: \r\n')
            all_tags = sorted(tagdb.items())
            if 0 == len(all_tags):
                echo(u'None !'.center(term.width / 2))
            else:
                echo(Ansi(u', '.join(([u'%s(%d)' % (_key, len(_value),)
                                       for (_key, _value) in all_tags]))
                          ).wrap(term.width - 2))
            continue
        echo(u'\r\n')

        # search input as valid tag(s)
        tags = set([inp.strip().lower() for inp in inp_tags.split(',')])
        err = False
        for tag in tags.copy():
            if not tag in tagdb and not (
                    'sysop' in session.user.groups or
                    'moderator' in session.user.groups):
                tags.remove(tag)
                echo(msg_invalidtag % (term.bold_red(tag),))
                err = True
        if err:
            echo(msg_onlymods)
            continue
        msg.tags = tags
        return True
Пример #2
0
def chk_thread(thread):
    """
    for asyncronous lightbar, return False if thread is still running,
    'dirty' if thread completed and new entries were found, 'None' if thread
    completed and no no entries were discovered.
    """
    from x84.bbs import getsession, DBProxy
    if thread is None or thread.is_alive():
        return False

    # check if bbs-scene.org thread finished, silly hack
    logger = logging.getLogger()
    session = getsession()
    udbkeys = DBProxy('bbslist').keys()
    nlc = 0
    for key, value in thread.content:
        if key not in udbkeys:
            DBProxy('bbslist')[key] = value
            DBProxy('bbslist', 'comments')[key] = list()
            DBProxy('bbslist', 'ratings')[key] = list()
            nlc += 1
        else:
            # update anyway (fe. port changed), we don't
            # detect this as an update.
            DBProxy('bbslist')[key] = value
    if nlc > 0:
        logger.info('%d new entries', nlc)
        session.send_event('global', ('bbslist_update', None))
        session.buffer_event('bbslist_update')
        return 'dirty'
    else:
        logger.info('no new bbs-scene.org entries')
    return None
Пример #3
0
def get_bbsinfo(key, active=True):
    """
    given a bbs key, fetch detailed information for use in pager
    """
    # pylint: disable=R0914
    #        Too many local variables.
    from x84.bbs import getterminal, DBProxy, timeago
    rstr = u''
    term = getterminal()
    highlight = term.bold_blue if active else term.blue
    lowlight = term.bold_black
    bbs = DBProxy('bbslist')[key]
    epoch = time.mktime(time.strptime(bbs['timestamp'], '%Y-%m-%d %H:%M:%S'))
    ratings = DBProxy('bbslist', 'ratings')[key]
    comments = DBProxy('bbslist', 'comments')[key]
    rstr += (lowlight('bbSNAME') + highlight(u': ') + bbs['bbsname'] +
             highlight('  +o ') + bbs['sysop'] + u'\r\n')
    rstr += (lowlight('AddRESS') + highlight(': ') + bbs['address'] +
             highlight(': ') + bbs['port'] + u'\r\n')
    rstr += (lowlight('lOCAtiON') + highlight(': ') + bbs['location'] + '\r\n')
    rstr += (lowlight('SOftWARE') + highlight(': ') + bbs['software'] + '\r\n')
    rstr += (lowlight('tiMEStAMP') + highlight(':') +
             lowlight(timeago(time.time() - epoch)) + ' ago\r\n')
    rstr += (
        lowlight('RAtiNG') + highlight(': ') + '%s (%2.2f of %d)\r\n' %
        (highlight(calc_rating(ratings)), 0 if 0 == len(ratings) else sum(
            [_rating
             for (_handle, _rating) in ratings]) / len(ratings), len(ratings)))
    rstr += u'\r\n' + bbs['notes']
    for handle, comment in comments:
        rstr += '\r\n\r\n' + lowlight(handle)
        rstr += highlight(': ')
        rstr += comment
    return rstr
Пример #4
0
def add_comment(key):
    """ Prompt user to add a comment about a bbs. """
    # pylint: disable=R0914
    #        Too many local variables.
    from x84.bbs import getsession, getterminal, echo, DBProxy, LineEditor
    from x84.bbs import getch
    session, term = getsession(), getterminal()
    prompt_comment = u'\r\n\r\nWhAt YOU GOt tO SAY? '
    prompt_chg = u'\r\n\r\nChANGE EXiStiNG ? [yn] '
    echo(term.move(term.height, 0))
    echo(prompt_comment)
    comment = LineEditor(max(10, term.width - len(prompt_comment) - 5)).read()
    if comment is None or 0 == len(comment.strip()):
        return
    new_entry = (session.handle, comment)
    comments = DBProxy('bbslist', 'comments')
    comments.acquire()
    existing = comments[key]
    if session.handle in (_nick for (_nick, _cmt) in comments[key]):
        # change existing comment,
        echo(prompt_chg)
        if getch() not in (u'y', u'Y'):
            comments.release()
            return
        # re-define list without existing entry, + new entry
        comments[key] = [(_enick, _ecmt) for (_enick, _ecmt) in existing
                         if session.handle != _enick] + [new_entry]
        comments.release()
        return
    # re-define as existing list + new entry
    comments[key] = existing + [new_entry]
    comments.release()
Пример #5
0
 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
Пример #6
0
 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
Пример #7
0
def login(session, user):
    """
    登记登录用户---没有改操作后边会处理为匿名
    Assign ``user`` to ``session`` and return time of last call.

    performs various saves and lookups of call records
    """
    session.user = user

    # assign timeout preference
    timeout = session.user.get('timeout', None)
    if timeout is not None:
        session.send_event('set-timeout', timeout)

    # update call records
    user.calls += 1
    user.lastcall = time.time()

    # save user record
    if user.handle != u'anonymous':
        user.save()

    # update 'lastcalls' database
    lc_db = DBProxy('lastcalls')
    with lc_db:
        previous_call, _, _ = lc_db.get(user.handle, (
            0,
            0,
            0,
        ))
        lc_db[user.handle] = (user.lastcall, user.calls, user.location)

    return previous_call
Пример #8
0
def delete_message(msg):
    """ Experimental message delete! """
    # ! belongs as msg.delete() function !
    msg.recipient = u''
    msg.subject = u''
    msg.body = u''
    msg.children = set()
    msg.parent = None
    msg.tags = set()
    msg.save()
    with DBProxy('tags') as tag_db:
        for key, values in tag_db.items()[:]:
            if msg.idx in values:
                newvalue = values - set([msg.idx])
                if newvalue:
                    tag_db[key] = newvalue
                else:
                    # no more messages by this tag, delete it
                    del tag_db[key]
    with DBProxy('privmsg') as priv_db:
        for key, values in priv_db.items()[:]:
            if msg.idx in values:
                priv_db[key] = values - set([msg.idx])
    with DBProxy('msgbase') as msg_db:
        del msg_db['%d' % int(msg.idx)]
Пример #9
0
def view_leaf_msgnet(server_tag=None, board_id=None):
    if server_tag is None:
        server_tags = get_ini(section='msg', key='server_tags', split=True)
        if not server_tags:
            raise ValueError("no `server_tags' defined in ini file, "
                             "section [msg].")
        # RECURSION
        for _st in server_tags:
            view_leaf_msgnet(server_tag=_st, board_id=None)
        return

    if board_id is None:
        board_ids = DBProxy('{0}keys'.format(server_tag)).keys()
        for _bid in board_ids:
            # RECURSION
            view_leaf_msgnet(server_tag=server_tag, board_id=_bid)
        return

    with DBProxy('{0}keys'.format(server_tag)) as key_db:
        echo(u'\r\n[msgnet_{0}]'.format(server_tag))
        echo(u'\r\nurl_base = https://{addr}:{port}/'.format(
            addr=get_ini('web', 'addr'), port=get_ini('web', 'port')))
        echo(u'\r\nboard_id = {0}'.format(board_id))
        echo(u'\r\ntoken = {0}'.format(key_db[board_id]))
        echo(u'\r\npoll_interval = 300')
        echo(u'\r\n')
        echo(u'\r\n[msg]')
        echo(u'\r\nnetwork_tags = {0}'.format(server_tag))
    echo(u'\r\n')
    echo(u'-' * 40)
Пример #10
0
def process_outbound():
    # Scan for New Messages ready for sending out
    """
    :rtype : none
    """
    from x84.bbs import DBProxy

    print 'process_outbound()'

    # Status is a list of all Message Keys
    status = set(int(key) for key in DBProxy(FIDO_DB).keys())
    print status

    # Scan message Status.
    with DBProxy(FIDO_DB) as fido_db:
        for key, values in fido_db.items():
            # print key, values.check_status
            # print key, values.check_kludge
            for k, v in values.check_kludge.items():
                # Grabs Key values of all Kludges
                print k, v

    # Work out kludge lines now.
    # Example modern msg id.
    '''
Пример #11
0
def process_keystroke(inp, key=None):
    """ Process general keystroke and call routines.  """
    from x84.bbs import getsession, DBProxy, gosub, echo
    session = getsession()
    if inp is None:
        return False
    elif type(inp) is int:
        return False
    elif inp in (u't', u'T') and key is not None:
        bbs = DBProxy('bbslist')[key]
        gosub(
            'telnet',
            bbs['address'],
            bbs['port'],
        )
    elif inp in (u'a', u'A'):
        add_bbs()
    elif inp in (u'c', u'C') and key is not None:
        add_comment(key)
    elif inp in (u'r', u'R') and key is not None:
        rate_bbs(key)
    elif inp in (u'i', u'I') and key is not None:
        echo(get_bbsinfo(key) + '\r\n')
    elif inp in (u'v', u'V') and key is not None:
        view_ansi(key)
    elif inp in (u'd', u'D') and key is not None and ('sysop'
                                                      in session.user.groups):
        del DBProxy('bbslist')[key]
    else:
        return False  # unhandled
    return True
Пример #12
0
Файл: top.py Проект: ztaylor/x84
def login(session, user):
    """
    Assign ``user`` to ``session`` and return time of last call.

    performs various saves and lookups of call records
    """
    session.user = user

    # assign timeout preference
    timeout = session.user.get('timeout', None)
    if timeout is not None:
        session.send_event('set-timeout', timeout)

    # update call records
    user.calls += 1
    user.lastcall = time.time()

    # save user record
    if user.handle != u'anonymous':
        user.save()

    # update 'lastcalls' database
    lc_db = DBProxy('lastcalls')
    with lc_db:
        previous_call, _, _ = lc_db.get(user.handle, (0, 0, 0,))
        lc_db[user.handle] = (user.lastcall, user.calls, user.location)

    return previous_call
Пример #13
0
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))
Пример #14
0
def serve_messages_for(board_id, request_data, db_source):
    " Reply-to api client request to receive new messages. "
    from x84.bbs import DBProxy, msgbase
    from x84.bbs.msgbase import to_utctime
    log = logging.getLogger(__name__)
    #log.error(msg)
    db_tags = DBProxy(msgbase.TAGDB, use_session=False)
    db_messages = DBProxy(msgbase.MSGDB, use_session=False)

    def message_owned_by(msg_id, board_id):
        return (msg_id in db_source and db_source[msg_id] == board_id)

    def msgs_after(idx=None):
        for msg_id in db_tags.get(request_data['network'], []):
            if idx is None:
                yield db_messages[idx]
            elif (int(msg_id) > int(idx)
                  and not message_owned_by(msg_id, board_id)):
                yield db_messages[msg_id]

    last_seen = request_data.get('last', None)
    pending_messages = msgs_after(last_seen)
    return_messages = list()
    num_sent = 0
    for num_sent, msg in enumerate(pending_messages, start=1):
        return_messages.append({
            u'id':
            msg.idx,
            u'author':
            msg.author,
            u'recipient':
            msg.recipient,
            u'parent':
            msg.parent,
            u'subject':
            msg.subject,
            u'tags':
            list(msg.tags ^ set([request_data['network']])),
            u'ctime':
            to_utctime(msg.ctime),
            u'body':
            msg.body
        })
        if num_sent >= BATCH_MSGS:
            log.warn('[{request_data[network]}] Batch limit reached for '
                     'board {board_id}; halting'.format(
                         request_data=request_data, board_id=board_id))
            break

    if num_sent > 0:
        log.info('[{request_data[network]}] {num_sent} messages '
                 'served to {board_id}'.format(request_data=request_data,
                                               num_sent=num_sent,
                                               board_id=board_id))

    return {u'response': True, u'messages': return_messages}
Пример #15
0
def add_comment(key):
    """ Prompt user to add a comment about a bbs. """
    # pylint: disable=R0914
    #        Too many local variables.
    from x84.bbs import getsession, getterminal, echo, DBProxy, LineEditor
    from x84.bbs import getch
    session, term = getsession(), getterminal()
    prompt_comment = u'\r\n\r\nWhAt YOU GOt tO SAY? '
    prompt_chg = u'\r\n\r\nChANGE EXiStiNG ? [yn] '
    echo(term.move(term.height, 0))
    echo(prompt_comment)
    comment = LineEditor(max(10, term.width - len(prompt_comment) - 5)).read()
    if comment is None or 0 == len(comment.strip()):
        return
    new_entry = (session.handle, comment)
    comments = DBProxy('bbslist', 'comments')
    comments.acquire()
    existing = comments[key]
    if session.handle in (_nick for (_nick, _cmt) in comments[key]):
        # change existing comment,
        echo(prompt_chg)
        if getch() not in (u'y', u'Y'):
            comments.release()
            return
        # re-define list without existing entry, + new entry
        comments[key] = [(_enick, _ecmt) for (_enick, _ecmt) in existing
                         if session.handle != _enick] + [new_entry]
        comments.release()
        return
    # re-define as existing list + new entry
    comments[key] = existing + [new_entry]
    comments.release()
Пример #16
0
Файл: debug.py Проект: hick/x84
def x84net_requeue():
    # a message failed to queue for delivery, but hellbeard
    # really wanted to see em, so re-queue.
    from x84.bbs import DBProxy, echo
    from pprint import pformat
    queuedb = DBProxy('x84netqueues')
    with queuedb:
        queuedb['264'] = 1
    echo('-')
    echo(pformat(queuedb.items()))
    echo('-')
Пример #17
0
def x84net_requeue():
    # a message failed to queue for delivery, but hellbeard
    # really wanted to see em, so re-queue.
    from x84.bbs import DBProxy, echo
    from pprint import pformat
    queuedb = DBProxy('x84netqueues')
    with queuedb:
        queuedb['264'] = 1
    echo('-')
    echo(pformat(queuedb.items()))
    echo('-')
Пример #18
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))
Пример #19
0
def add_leaf_msgnet():
    import cryptography.fernet
    server_tags = get_ini(section='msg', key='server_tags', split=True)
    if not server_tags:
        raise ValueError(MSG_NO_SERVER_TAGS)

    if len(server_tags) == 1:
        server_tag = server_tags[0]
    else:
        while True:
            echo('chose a server tag: ')
            idx = 0
            for idx, tag in server_tags:
                echo(u'\r\n{0}. {1}'.format(idx, tag))
            echo(u'\r\n: ')
            inp = LineEditor(width=len(str(idx)).read())
            if inp is None:
                return
            try:
                server_tag = server_tags[int(inp)]
                break
            except ValueError:
                pass

    with DBProxy('{0}keys'.format(server_tag)) as key_db:
        board_id = max(map(int, key_db.keys()) or [-1]) + 1
        client_key = cryptography.fernet.Fernet.generate_key()
        key_db[board_id] = client_key
    echo(u'\r\n')
    echo(u'-' * 40)
    view_leaf_msgnet(server_tag, board_id)
Пример #20
0
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))
Пример #21
0
def maybe_expunge_records():
    """ Check ceiling of database keys; trim-to MAX_HISTORY. """
    udb = DBProxy('oneliner')
    expunged = 0
    with udb:
        if len(udb) > MAX_HISTORY + 10:
            contents = DBProxy('oneliner').copy()
            _sorted = sorted(
                ((value, key) for (key, value) in contents.items()),
                key=lambda _valkey: keysort_by_datetime(_valkey[0]))
            for expunged, (_,
                           key) in enumerate(_sorted[len(udb) - MAX_HISTORY:]):
                del udb[key]
    if expunged:
        log = logging.getLogger(__name__)
        log.info('expunged %d records from database', expunged)
Пример #22
0
Файл: ol.py Проект: hick/x84
def get_oltxt():
    """ Return unicode terminal string of oneliners. """
    import time
    from x84.bbs import getterminal, DBProxy, timeago, decode_pipe
    term = getterminal()
    colors = (term.bright_white, term.cyan, term.white)
    hist = [(int(k), v) for (k, v) in DBProxy('oneliner').items()]
    hist.sort(_sort_oneliner)
    output = list()
    for idx, onel in hist[BUF_HISTORY * -1:]:
        color = colors[int(idx) % len(colors)]
        atime = timeago(time.time() - time.mktime(
            time.strptime(onel['timestamp'], '%Y-%m-%d %H:%M:%S'))).strip()
        if onel.get('fake', False):
            alias = term.bold_red(u'x') + color(onel['alias'])
        else:
            alias = color(onel['alias'])
        output.append(u''.join((
            term.bold_white('('),
            color(atime),
            term.bold_black(u' ago'),
            term.bold_black(u' '),
            alias,
            term.bold_black(u'/'),
            onel['bbsname'],
            term.bold_white(u')'),
            color(u': '),
            decode_pipe(onel['oneliner']),
        )))
    return output[(BUF_HISTORY * -1):]
Пример #23
0
def view_ansi(key):
    """ fetch and view a bbs ansi. They're not often very good ...
    """
    from x84.bbs import getterminal, echo, DBProxy, ini, getch, from_cp437
    term = getterminal()
    ansiurl = DBProxy('bbslist')[key]['ansi']
    logger = logging.getLogger()
    echo(u'\r\n\r\n')
    if ansiurl is not None and 0 != len(ansiurl) and ansiurl != 'NONE':
        usernm = ini.CFG.get('bbs-scene', 'user')
        passwd = ini.CFG.get('bbs-scene', 'pass')
        req = requests.get(ansiurl, auth=(usernm, passwd))
        if req.status_code != 200:
            echo(u'\r\n\r\nrequest failed,\r\n')
            echo(u'%r' % (req.content, ))
            echo(u'\r\n\r\n(code : %s).\r\n' % (req.status_code, ))
            echo(u'\r\nPress any key ..')
            logger.warn('ansiurl request failed: %s' % (ansiurl, ))
            getch()
            return
        ansi_txt = from_cp437(sauce.SAUCE(data=req.content).__str__())
        echo(ansi_txt)
    else:
        echo('no ansi available (%s)' % (ansiurl, ))
    # move to bottom of screen and getch
    echo(u''.join((term.move(term.height,
                             0), term.normal, u'\r\n\r\nPRESS ANY kEY ...'), ))
    getch()
Пример #24
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))
Пример #25
0
def generate_database():  # generates a database file with a generic question.
    db = DBProxy(databasename)

    index = []
    index.append(0)
    indexcounter = 0

    questions = []
    questions.append('Which is your prefered BBS software?')

    alternatives = {}
    alternatives[(0, 0)] = 'X/84'
    alternatives[(0, 1)] = 'Daydream'
    alternatives[(0, 2)] = 'Mystic'
    alternatives[(0, 3)] = 'Synchronet'

    results = {}
    results[(0, 0)] = 0
    results[(0, 1)] = 0
    results[(0, 2)] = 0
    results[(0, 3)] = 0

    amount_of_alternatives = []
    # this is the only list/dict that is not zerobased..
    amount_of_alternatives.append(4)

    db['indexcounter'] = indexcounter
    db['index'] = index
    db['amount_of_alternatives'] = amount_of_alternatives
    db['alternatives'] = alternatives
    db['results'] = results
    db['questions'] = questions
Пример #26
0
def register_score(handle, score):
    from x84.bbs import DBProxy
    db = DBProxy('tetris')
    if not handle in db:
        db[handle] = score
    elif score[0] > db[handle][0]:
        db[handle] = score
Пример #27
0
Файл: ol.py Проект: rostob/x84
def maybe_expunge_records():
    """ Check ceiling of database keys; trim-to MAX_HISTORY. """
    udb = DBProxy('oneliner')
    expunged = 0
    with udb:
        if len(udb) > MAX_HISTORY + 10:
            contents = DBProxy('oneliner').copy()
            _sorted = sorted(
                ((value, key) for (key, value) in contents.items()),
                key=lambda _valkey: keysort_by_datetime(_valkey[0]))
            for expunged, (_, key) in enumerate(
                    _sorted[len(udb) - MAX_HISTORY:]):
                del udb[key]
    if expunged:
        log = logging.getLogger(__name__)
        log.info('expunged %d records from database', expunged)
Пример #28
0
 def __init__(self):
     # It's not safe to receive data from a database from
     # within a thread ... something we should address ..
     # so we do it in __init__, bug #154
     self.existing_content = DBProxy('oneliner').copy()
     self.new_content = None
     self.log = logging.getLogger(__name__)
     super(FetchUpdatesShrooMs, self).__init__()
Пример #29
0
def get_lastcallers(last):
    timenow = time.time()
    return sorted([call_record(timeago=timenow - time_called,
                               num_calls=num_calls,
                               location=location,
                               handle=handle.decode('utf8'))
                   for handle, (time_called, num_calls, location)
                   in DBProxy('lastcalls').items()])[:last]
Пример #30
0
def tygerofdantye_fix():
    """ This user was too long! """
    from x84.bbs import DBProxy
    user = DBProxy('userbase')['tygerofdanyte']
    user.delete()
    user.handle = u'tygerdanyte'
    user.save()
Пример #31
0
def add_question():
    term = getterminal()
    db = DBProxy(databasename)
    questions = []
    amount_of_alternatives = []
    index = {}
    alternatives = {}
    results = {}
    index = db['index']
    questions = db['questions']
    alternatives = db['alternatives']
    results = db['results']
    amount_of_alternatives = db['amount_of_alternatives']
    amount_of_questions = len(questions)

    echo(term.clear + term.white + u'\r\nQuestion: ')
    le = LineEditor(65)
    new_question = le.read()
    if new_question == '' or new_question == None:
        return

    echo(
        term.bold_black(u'\r\n\r\nLeave a blank line when you are finished..'))
    new_amount = 0
    while True:
        echo(term.normal + term.white + u'\r\nchoice ' + term.red +
             str(new_amount) + term.white + u': ')
        le = LineEditor(48)
        alternatives[(amount_of_questions, new_amount)] = le.read()
        if alternatives[(amount_of_questions,
                         new_amount)] == '' or alternatives[(
                             amount_of_questions, new_amount)] == None:
            break
        else:
            results[(amount_of_questions, new_amount)] = 0
            new_amount = new_amount + 1

    if new_amount > 0:
        echo(term.white(u'\r\n\r\nSave this voting question?'))
        answer = ynprompt()
        if answer == 1:
            questions.append(new_question)
            amount_of_alternatives.append(new_amount)

            indexcounter = db['indexcounter']
            indexcounter = indexcounter + 1
            index.append(str(indexcounter))

            db['indexcounter'] = indexcounter
            db['index'] = index
            db['questions'] = questions
            db['amount_of_alternatives'] = amount_of_alternatives
            db['results'] = results
            db['amount_of_questions'] = amount_of_questions
            db['alternatives'] = alternatives

            waitprompt(term)
Пример #32
0
def migrate_105lc():
    from x84.bbs import echo, DBProxy, list_users, get_user
    # migrating lastcallers database for 1.0.5 upgrade
    lc = DBProxy('lastcalls')
    for handle in list_users():
        user = get_user(handle)
        lc[(handle)] = (user.lastcall, user.calls, user.location)
        echo('\r\n' + user.handle + '.')
    echo('\r\n\r\nlast callers db rebuilt!')
Пример #33
0
def list_results(questionnumber):
    term = getterminal()
    db = DBProxy(databasename)
    alternatives = {}
    questions = []
    results = []
    amount_of_alternatives = db['amount_of_alternatives']
    alternatives = db['alternatives']
    questions = db['questions']
    results = db['results']

    echo(term.clear())

    text = (term.white + questions[questionnumber] + u'\r\n' + term.blue +
            u'-' * len(questions[questionnumber]) + u'\r\n\r\n')

    # only display full statistics if the screen width is above 79 columns.
    if term.width > 79:
        text = text + (term.magenta + u'(alternatives)' + term.move_x(49) +
                       u'(votes)' + term.move_x(57) + u'(percentage)\r\n')
        totalvotes = 0.00
        for i in range(0, amount_of_alternatives[questionnumber]):
            totalvotes = totalvotes + results[(questionnumber, i)]
        for i in range(0, amount_of_alternatives[questionnumber]):
            if results[(questionnumber, i)] > 0:
                percentage = (results[(questionnumber, i)] / totalvotes) * 100
            else:
                percentage = 0
            staple = int(round(percentage / 5))
            text = text + u''.join(
                term.move_x(0) + term.white(alternatives[
                    (questionnumber, i)]) + term.move_x(49) +
                term.cyan(str(results[(questionnumber, i)])) + u'  ' +
                term.cyan + str(int(percentage)) + term.cyan(u'%') +
                term.move_x(57) + term.cyan(u'[') + term.green('#' * staple) +
                term.move_x(78) + term.cyan(']'))
            if i != amount_of_alternatives[questionnumber]:
                text = text + u'\r\n'
    else:
        for i in range(0, amount_of_alternatives[questionnumber]):
            text = text + (term.white(str(alternatives[(questionnumber, i)])) +
                           term.cyan(u' votes: ') + term.magenta(
                               str(results[(questionnumber, i)])) + u'\r\n')

    text = text.splitlines()
    prompt_pager(content=text,
                 line_no=0,
                 colors={
                     'highlight': term.cyan,
                     'lowlight': term.green,
                 },
                 width=term.width,
                 breaker=None,
                 end_prompt=False)
    echo(term.move_x(0) + term.bold_black(u'* = already voted\r\n'))
    waitprompt(term)
Пример #34
0
def generate_recent_oneliners(term, n_liners, offset):
    """ return string of all oneliners, its vert. hieght and adj. offset. """
    # generate a color palette
    palette = [getattr(term, _color) for _color in color_palette]

    # for relative 'time ago'
    now = time.time()

    # fetch all liners in database, sorted ascending by time
    oneliners = sorted(DBProxy('oneliner').values(), key=keysort_by_datetime)

    # decide the start/end by given offset, to allow paging, bounds check to
    # ensure that it does not scroll out of range
    offset = min(offset, len(oneliners))
    start, end = len(oneliners) - (n_liners + offset), len(oneliners) - offset
    if start < 0:
        offset += start
        start, end = 0, end - start
    if offset < 0:
        start, end = start + offset, end + offset
        offset = 0

    # build up one large text field; refresh is smoother when
    # all text is received as a single packet
    final_text_field = u''
    count = 0
    for count, oneliner in enumerate(oneliners[start:end]):
        _color = palette[count % len(palette)]
        ago = get_timeago(now, oneliner.get('timestamp'))
        alias = oneliner.get('alias', 'anonymous')
        bbsname = ('' if not shroo_ms_enabled else oneliner.get(
            'bbsname', 'untergrund'))
        content = (oneliner.get('oneliner', u''))
        max_msglen = MAX_MSGLEN
        if len(alias) > username_max_length:
            max_msglen -= (len(alias) - username_max_length)
        for _ in range(10):
            left_part = u'{0}: {1} '.format(
                alias.rjust(username_max_length),
                term.ljust(decode_pipe(content[:max_msglen]), max_msglen))
            right_part = '{0} {1}'.format(_color(bbsname.rjust(4)), ago)
            txt_field = left_part + right_part
            if term.length(txt_field) < term.width:
                break
            elif term.length(left_part) < term.width:
                txt_field = left_part
                break
            max_msglen -= 2
        final_text_field = u''.join(
            (final_text_field, term.move_x(max(0, (term.width / 2) - 45)),
             txt_field, term.clear_eol, u'\r\n'))

    # return text, vertical height, and adjusted offset
    return final_text_field, count, offset
Пример #35
0
    def save(self):
        # persist message index record to database
        from x84.bbs import DBProxy
        new = self.idx is None

        with DBProxy(FIDO_DB, use_session=False) as db_index:
            # Not Used, Messages are saved first, with Fido
            # Data save with matching index.
            if new:
                self.idx = max(map(int, db_index.keys()) or [-1]) + 1
            db_index['%d' % (self.idx,)] = self
Пример #36
0
    def GET(self, num=10):
        """ Return last x oneliners """

        num = int(num)
        oneliners = DBProxy('oneliner', use_session=False).items()
        oneliners = [(int(k), v)
                     for (k,
                          v) in DBProxy('oneliner', use_session=False).items()]
        last = oneliners[-num:]

        # output JSON instead?
        if 'json' in web.input(_method='get'):
            return json.dumps(last)

        board = CFG.get('system', 'bbsname', 'x/84')
        page_title = 'Last {num} Oneliners on {board}'.format(num=num,
                                                              board=board)
        oneliners_html = ''

        for line in last:
            val = line[1]
            oneliners_html += '<li><b>{alias}:</b> {oneliner}</li>'.format(
                alias=val['alias'], oneliner=val['oneliner'])

        web.header('Content-Type', 'text/html; charset=utf-8', unique=True)
        output = """
            <!DOCTYPE html>
            <html lang="en-US">
            <head>
                <meta charset="utf-8" />
                <title>{page_title}</title>
            </head>
            <body>
                <h1>{page_title}</h1>
                <ul>
                    {oneliners_html}
                </ul>
            </body>
            </html>
            """.format(page_title=page_title, oneliners_html=oneliners_html)
        return output
Пример #37
0
def more(cont=False):
    """
    Returns True if user 'q'uit; otherwise False
    when prompting is complete (moar/next/whatever)
    """
    from x84.bbs import echo, getch, getterminal, LineEditor, DBProxy
    prompt_key = u'\r\n\r\nENtER BBS iD: '
    msg_badkey = u'\r\n\r\nbbS id iNVAliD!'
    term = getterminal()
    prompt = u', '.join(
        fancy_blue(char, blurb) for char, blurb in ((
            'i',
            'NfO',
        ), (
            'a',
            'dd',
        ), (
            'c',
            'OMMENt',
        ), (
            'r',
            'AtE',
        ), (
            't',
            'ElNEt',
        ), ('v', 'ANSi'), (
            'q',
            'Uit',
        )))
    if cont:
        prompt += u', ' + fancy_blue(' ', 'more')
    prompt += u': '
    while True:
        echo(u'\r\n')
        echo(u'\r\n'.join(
            term.wrap(text=prompt, width=(term.width - (term.width / 3)))))
        inp = getch()
        if inp in (u'q', 'Q'):
            return True
        elif inp is not None and type(inp) is not int:
            if cont and inp == u' ':
                echo(u'\r\n\r\n')
                return False
            if inp.lower() in u'acrtviACRTVI':
                # these keystrokes require a bbs key argument,
                # prompt the user for one
                echo(prompt_key)
                key = LineEditor(5).read()
                if (key is None or 0 == len(key.strip())
                        or not key in DBProxy('bbslist')):
                    echo(msg_badkey)
                    continue
                process_keystroke(inp, key)
Пример #38
0
def main():
    """ File browser launch point. """
    import subprocess
    import functools
    session, term = getsession(), getterminal()
    session.activity = u'Browsing files'
    db_desc = DBProxy(DIZ_DB)

    # set syncterm font, if any
    if SYNCTERM_FONT and term.kind.startswith('ansi'):
        echo(syncterm_setfont(SYNCTERM_FONT))

    # assign extractors to file types
    browser.diz_extractors['.zip'] = diz_from_zip

    # detect LHA and DMS support
    output, _ = subprocess.Popen(('which', 'lha'),
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE).communicate()
    if output:
        browser.diz_extractors['.lha'] = functools.partial(
            diz_from_lha, output.rstrip())
    output, _ = subprocess.Popen(('which', 'xdms'),
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE).communicate()
    if output:
        browser.diz_extractors['.dms'] = functools.partial(
            diz_from_dms, output.rstrip())

    # load flagged files
    browser.flagged_files = session.user.get('flaggedfiles', set())

    # remove missing files/dirs from flagged files, just in case
    if len(browser.flagged_files):
        for filepath in list(browser.flagged_files)[:]:
            if not os.path.exists(filepath):
                browser.flagged_files.remove(filepath)
        session.user['flaggedfiles'] = browser.flagged_files

    # fire it up!
    lightbar = Lightbar(height=term.height,
                        width=min(10, int(term.width * 0.25)),
                        xloc=0,
                        yloc=0,
                        colors={
                            'border': getattr(term, COLOR_BORDER),
                            'highlight': getattr(term, COLOR_HIGHLIGHT)
                        })
    draw_interface(term, lightbar)
    with term.hidden_cursor():
        browse_dir(session, db_desc, term, lightbar, ROOT)
    echo(term.move(term.height, term.width))
    echo(u'\r\n\r\n' + term.normal)
Пример #39
0
def tygerofdantye_fix():
    """ This user was too long! """
    from x84.bbs import DBProxy
    user = DBProxy('userbase')['tygerofdanyte']
    user.delete()
    user.handle = u'tygerdanyte'
    user.save()
Пример #40
0
def lc_retrieve():
    """
    Returns tuple of ([nicknames,] u'text'), where 'text' describes in Ansi
    color the last callers to the system, and 'nicknames' is simply a list
    of last callers (for lightbar selection key).
    """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import get_user, ini, timeago, getterminal
    from x84.bbs import DBProxy
    import time
    term = getterminal()
    udb = DBProxy('lastcalls')
    # re-order by time called; unfortunate ..; note that sqlite
    # encodes unicode as utf-8; but doesn't decode it on retrieval,
    # of dict keys; possible upstream patching opportunity here,
    sortdb = {}
    for ((handle), (tm_lc, _nc, origin)) in (udb.items()):
        while tm_lc in sortdb:
            tm_lc += 0.1
        sortdb[tm_lc] = [handle.decode('utf-8'), _nc, origin]

    padd_handle = (ini.CFG.getint('nua', 'max_user') + 2)
    padd_origin = (ini.CFG.getint('nua', 'max_location') + 2)
    rstr = u''
    nicks = []
    for tm_lc, (handle, _nc, origin) in (reversed(sorted(sortdb.items()))):
        try:
            is_sysop = 'sysop' in get_user(handle).groups
        except KeyError:
            # anonymous/deleted accts,
            is_sysop = False
        rstr += (term.bold_red(u'@') if is_sysop else u''
                 ) + (term.ljust(handle,
                     (padd_handle - (2 if is_sysop else 1))))
        rstr += term.red(origin.ljust(padd_origin))
        rstr += timeago(time.time() - tm_lc)
        rstr += u'\n'
        nicks.append(handle)
    return (nicks, rstr.rstrip())
Пример #41
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
Пример #42
0
def rate_bbs(key):
    """ Prompt user to rate a bbs. """
    # pylint: disable=R0914
    #        Too many local variables
    from x84.bbs import getsession, getterminal, echo, LineEditor, DBProxy
    from x84.bbs import getch
    session, term = getsession(), getterminal()
    prompt_rating = u'\r\n\r\nRAtE 0.0 - 4.0: '
    prompt_chg = u'\r\n\r\nChANGE EXiStiNG ? [yn] '
    msg_invalid = u'\r\n\r\niNVAlid ENtRY.\r\n'
    echo(term.move(term.height, 0) + '\r\n')
    echo(prompt_rating)
    s_rating = LineEditor(3).read()
    if s_rating is None or 0 == len(s_rating.strip()):
        return
    try:
        f_rating = float(s_rating)
    except ValueError:
        echo(msg_invalid)
        return
    if f_rating < 0 or f_rating > 4:
        echo(msg_invalid)
        return
    entry = (session.handle, f_rating)
    ratings = DBProxy('bbslist', 'ratings')
    ratings.acquire()
    if session.handle in (_handle for (_handle, _rating) in ratings[key]):
        echo(prompt_chg)
        if getch() not in (u'y', u'Y'):
            ratings.release()
            return
        # re-define list without existing entry, + new entry
        ratings[key] = [(__handle, __rating)
                        for (__handle, __rating) in ratings[key]
                        if session.handle != __handle] + [entry]
        ratings.release()
        return
    # re-define as existing list + new entry
    ratings[key] = ratings[key] + [entry]
    ratings.release()
Пример #43
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))
Пример #44
0
Файл: ol.py Проект: rostob/x84
def do_merge_shroo_ms(new_content):
    """ Add oneliners from shroo-ms to local database. """
    udb = DBProxy('oneliner')
    with udb:
        udb.update(new_content)
    maybe_expunge_records()
Пример #45
0
def prompt_tags(msg):
    """ Prompt for and return tags wished for message. """
    # pylint: disable=R0914,W0603
    #         Too many local variables
    #         Using the global statement
    from x84.bbs import DBProxy, echo, getterminal, getsession
    from x84.bbs import LineEditor, ini
    session, term = getsession(), getterminal()
    tagdb = DBProxy('tags')
    # version 1.0.9 introduced new ini option; set defaults for
    # those missing it from 1.0.8 upgrades.
    import ConfigParser
    try:
        moderated_tags = ini.CFG.getboolean('msg', 'moderated_tags')
    except ConfigParser.NoOptionError:
        moderated_tags = False
    try:
        moderated_groups = set(ini.CFG.get('msg', 'tag_moderator_groups'
                                           ).split())
    except ConfigParser.NoOptionError:
        moderated_groups = ('sysop', 'moderator',)
    msg_onlymods = (u"\r\nONlY MEMbERS Of GROUPS %s MAY CREAtE NEW tAGS." % (
        ", ".join(["'%s'".format(term.bold_yellow(grp)
                                 for grp in moderated_groups)])))
    msg_invalidtag = u"\r\n'%s' is not a valid tag."
    prompt_tags1 = u"ENtER %s, COMMA-dEliMitEd. " % (term.bold_red('TAG(s)'),)
    prompt_tags2 = u"OR '/list', %s:quit\r\n : " % (
        term.bold_yellow_underline('Escape'),)
    while True:
        # Accept user input for multiple 'tag's, or /list command
        echo(u'\r\n\r\n')
        echo(prompt_tags1)
        echo(prompt_tags2)
        width = term.width - 6
        sel_tags = u', '.join(msg.tags)
        inp_tags = LineEditor(width, sel_tags).read()
        if inp_tags is not None and 0 == len(inp_tags.strip()):
            # no tags must be (private ..)
            msg.tags = set()
            return True
        if inp_tags is None or inp_tags.strip().lower() == '/quit':
            return False
        elif inp_tags.strip().lower() == '/list':
            # list all available tags, and number of messages
            echo(u'\r\n\r\nTags: \r\n')
            all_tags = sorted(tagdb.items())
            if 0 == len(all_tags):
                echo(u'None !'.center(term.width / 2))
            else:
                echo(u', '.join((term.wrap([u'%s(%d)' % (_key, len(_value),)
                                       for (_key, _value) in all_tags]))
                          ), term.width - 2)
            continue
        echo(u'\r\n')

        # search input as valid tag(s)
        tags = set([inp.strip().lower() for inp in inp_tags.split(',')])

        # if the tag is new, and the user's group is not in
        # tag_moderator_groups, then dissallow such tag if
        # 'moderated_tags = yes' in ini cfg
        if moderated_tags:
            err = False
            for tag in tags.copy():
                if not tag in tagdb and not (
                        session.users.groups & moderated_groups):
                    tags.remove(tag)
                    echo(msg_invalidtag % (term.bold_red(tag),))
                    err = True
            if err:
                echo(msg_onlymods)
                continue
        msg.tags = tags
        return True
Пример #46
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
Пример #47
0
Файл: feeds.py Проект: hick/x84
def main(autoscan_tags=None):
    """ Main procedure. """
    # pylint: disable=W0603,R0912
    #         Using the global statement
    #         Too many branches
    from x84.bbs import getsession, getterminal, echo, getch
    from x84.bbs import list_msgs
    session, term = getsession(), getterminal()
    session.activity = 'autoscan msgs'

    ### 尝试
    session.log.info("Hick3")
    ### 获取所有 tag
    tagdb = DBProxy('tags')
    all_tags = sorted(tagdb.items())
    session.log.info(all_tags)
    ### 尝试直接调出显示的 message ,第二个参数应该是标识为未读的
    msg = new = [1, 2, 3, 4,5 ,6, 7, 8,9]
    read_messages(msg, new)
    return

    ### 首先是显示提示输入的 tag 的标签
    echo(banner())
    global ALREADY_READ, SEARCH_TAGS, DELETED
    if autoscan_tags is not None:
        SEARCH_TAGS = autoscan_tags
        echo(u''.join((
            term.bold_black('[ '),
            term.yellow('AUtOSCAN'),
            term.bold_black(' ]'), u'\r\n')))
    ### 默认就往这里了, 提示输入 tag
    else:
        # 默认 tag 为 public
        SEARCH_TAGS = set(['hick3'])
        # also throw in user groups, maybe the top 3 .. ?
        SEARCH_TAGS.update(session.user.groups)
        SEARCH_TAGS = prompt_tags(SEARCH_TAGS)
        # user escape
        if SEARCH_TAGS is None:
            return

    echo(u'\r\n\r\n%s%s ' % (
        term.bold_yellow('SCANNiNG'),
        term.bold_black(':'),))
    echo(u','.join([term.red(tag) for tag in SEARCH_TAGS]
                   if 0 != len(SEARCH_TAGS) else ['<All>', ]))

    ### 直到有选择 tags , 保存到 session.user 中
    if (SEARCH_TAGS != session.user.get('autoscan', None)):
        echo(u'\r\n\r\nSave tag list as autoscan on login [yn] ?\b\b')
        while True:
            inp = getch()
            if inp in (u'q', 'Q', unichr(27), u'n', u'N'):
                break
            elif inp in (u'y', u'Y'):
                session.user['autoscan'] = SEARCH_TAGS
                break

    # retrieve all matching messages,:  list_msgs 根据 tags 获得所有记录,看情形这个信息量大了有问题哈
    all_msgs = list_msgs(SEARCH_TAGS)
    echo(u'\r\n\r\n%s messages.' % (term.yellow_reverse(str(len(all_msgs),))))
    if 0 == len(all_msgs):
        getch(0.5)
        return

    # filter messages public/private/group-tag/new
    ### 分 tag 和是否未读,删除等统计
    ALREADY_READ = session.user.get('readmsgs', set())
    DELETED = session.user.get('trash', set())
    msgs, new = msg_filter(all_msgs)
    if 0 == len(msgs) and 0 == len(new):
        getch(0.5)
        return

    # prompt read 'a'll, 'n'ew, or 'q'uit
    echo(u'\r\n  REAd [%s]ll %d%s message%s [qa%s] ?\b\b' % (
        term.yellow_underline(u'a'),
        len(msgs), (
        u' or %d [%s]EW ' % (
        len(new), term.yellow_underline(u'n'),)
            if new else u''),
        u's' if 1 != len(msgs) else u'',
        u'n' if new else u'',))
    while True:
        inp = getch()
        if inp in (u'q', 'Q', unichr(27)):
            return
        elif inp in (u'n', u'N') and len(new):
            # read only new messages
            msgs = new
            break
        elif inp in (u'a', u'A'):
            break

    # 根君上面的用户选择,读取消息, 某次记录 log  msgs 和 new 都是帖子 id 的 set 
    # read target messages
    # session.log.info(msgs)
    # session.log.info(new)
    read_messages(msgs, new)
Пример #48
0
def prompt_tags(tags):
    """ Prompt for and return valid tags from TAGDB. """
    # pylint: disable=R0914,W0603
    #         Too many local variables
    #         Using the global statement
    from x84.bbs import DBProxy, echo, getterminal, getsession
    from x84.bbs import Ansi, LineEditor, getch
    session, term = getsession(), getterminal()
    tagdb = DBProxy('tags')
    global FILTER_PRIVATE
    while True:
        # Accept user input for a 'search tag', or /list command
        #
        echo(u"\r\n\r\nENtER SEARCh %s, COMMA-dEliMitEd. " % (
            term.red('TAG(s)'),))
        echo(u"OR '/list', %s%s\r\n : " % (
            (term.yellow_underline('^x') + u':autoscan '
                if session.user.get('autoscan', False) else u''),
            term.yellow_underline('^a') + u':ll msgs ' +
            term.yellow_underline('Esc') + u':quit',))
        width = term.width - 6
        sel_tags = u', '.join(tags)
        while len(Ansi(sel_tags)) >= (width - 8):
            tags = tags[:-1]
            sel_tags = u', '.join(tags)
        lne = LineEditor(width, sel_tags)
        echo(lne.refresh())
        while not lne.carriage_returned:
            inp = getch()
            if inp in (unichr(27), term.KEY_EXIT):
                return None
            if inp in (unichr(24),): # ^A:all
                return set()
            if inp in (unichr(1),): # ^X:autoscan
                return session.user.get('autoscan', set())
            else:
                echo(lne.process_keystroke(inp))
        if lne.carriage_returned:
            inp_tags = lne.content
        if (inp_tags is None or 0 == len(inp_tags)
                or inp_tags.strip().lower() == '/quit'):
            return set()
        elif inp_tags.strip().lower() == '/list':
            # list all available tags, and number of messages
            echo(term.normal)
            echo(u'\r\n\r\nTags: \r\n')
            all_tags = sorted(tagdb.items())
            if 0 == len(all_tags):
                echo(u'None !'.center(term.width / 2))
            else:
                echo(Ansi(u', '.join(([u'%s(%s)' % (
                    term.red(tag),
                    term.yellow(str(len(msgs))),)
                        for (tag, msgs) in all_tags]))).wrap(term.width - 2))
            continue
        elif (inp_tags.strip().lower() == '/nofilter'
                and 'sysop' in session.user.groups):
            # disable filtering private messages
            FILTER_PRIVATE = False
            continue

        echo(u'\r\n')
        # search input as valid tag(s)
        tags = set([_tag.strip().lower() for _tag in inp_tags.split(',')])
        for tag in tags.copy():
            if not tag in tagdb:
                tags.remove(tag)
                echo(u"\r\nNO MESSAGES With tAG '%s' fOUNd." % (
                    term.red(tag),))
        return tags
Пример #49
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, 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)