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
def redrawlightbar(filer, lighty,lightx,lightbar,start,antalrader): # if the variable lightbar is negative the lightbar will be invisible import time from x84.bbs import timeago term = getterminal() echo(term.move(lighty,lightx)) for i in range (0, term.height - 2): echo(term.move(lighty+i,lightx)+u' '*(term.width - lightx)) # erases 60 char. dont want to use clreol. So filenames/directories can be 45 char. i2 = 0 for i in range (start,start+antalrader): origtime = filer[i][6].strip() secsago = timeago(time.time() - (3600 * 6)- time.mktime(time.strptime(origtime,"%I:%M %p %b %d, %Y"))) # if secsago[-1] == 's': secsago = secsago[:-3] secsago = u''.join([ u' ' * (5-len(secsago)), secsago ]) rightbar = filer[i][5].rjust(19)+u' '+ str(secsago) leftbar = filer[i][1][:term.width - len(rightbar) - 5] if i2 == lightbar: echo(term.move(lighty+i-start-1,lightx)+term.blue_reverse+leftbar[:10]+term.normal) else: echo(term.move(lighty+i-start-1,lightx)+term.white+leftbar[:10]+term.normal) echo(term.move(lighty+i-start-1,term.width - len(rightbar) - 2)+rightbar+term.normal) i2 = i2 + 1
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 list_users, get_user, ini, timeago, getterminal import time term = getterminal() udb = dict() for handle in list_users(): user = get_user(handle) udb[(user.lastcall, handle)] = (user.calls, user.location) 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(udb.items()))): is_sysop = 'sysop' in get_user(handle).groups rstr += (term.bold_red(u'@') if is_sysop else u'' ) + (handle.ljust(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())
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_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 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):]
def main(): session, term = getsession(), getterminal() session.activity = 'Viewing Userlist' colors = { 'highlight': term.red, 'lowlight': term.green, } line_no = display_banner(filepattern=art_file, encoding=art_encoding) # get and format userlist userlist = (u'{sp}{handle} {location} {lastcall}'.format( sp=u' ' * 4, handle=ur.handle.ljust(username_max_length), location=colors['lowlight'](ur.location.ljust(location_max_length)), lastcall=timeago(ur.timeago)) for ur in iter_userlist()) echo(u'\r\n') # display users, using a command-prompt pager. prompt_pager(content=userlist, line_no=line_no + 1, colors={ 'highlight': term.red, 'lowlight': term.green, }, width=80, breaker=None)
def main(): session, term = getsession(), getterminal() session.activity = 'Viewing Userlist' colors = {'highlight': term.red, 'lowlight': term.green, } line_no = display_banner(filepattern=art_file, encoding=art_encoding) # get and format userlist userlist = ( u'{sp}{handle} {location} {lastcall}' .format(sp=u' ' * 4, handle=ur.handle.ljust(username_max_length), location=colors['lowlight']( ur.location.ljust(location_max_length)), lastcall=timeago(ur.timeago)) for ur in iter_userlist()) echo(u'\r\n') # display users, using a command-prompt pager. prompt_pager(content=userlist, line_no=line_no + 1, colors={'highlight': term.red, 'lowlight': term.green, }, width=80, breaker=None)
def main(last=10): """ Script entry point. :param last: Number of last callers to display :type last: int """ session, term = getsession(), getterminal() session.activity = u'Viewing last callers' colors = [term.green, term.bright_blue, term.bold, term.cyan, term.bold_black] # set syncterm font, if any if syncterm_font and term._kind.startswith('ansi'): echo(syncterm_setfont(syncterm_font)) # display banner line_no = display_banner(filepattern=art_file, encoding=art_encoding) # get last callers last_callers = get_lastcallers(last=last) echo(u'\r\n\r\n') # format callers, header: callers_txt = [ '{handle} {location} {num_calls} {timeago}' .format( handle=term.bold_underline( term.ljust('handle', username_max_length + 1)), location=term.underline( term.ljust('location', location_max_length)), num_calls=term.bold_underline( term.ljust('# calls', numcalls_max_length)), timeago=term.underline('time ago')) ] # content: callers_txt.extend([ u'{handle} {location} {num_calls} {timeago}' .format(handle=lc.handle.ljust(username_max_length + 1), location=term.ljust(colors[idx % len(colors)]( lc.location or '-' * location_max_length), location_max_length), num_calls='{0}'.format( lc.num_calls).rjust(numcalls_max_length), timeago=colors[idx % len(colors)]( timeago(lc.timeago)) ) for idx, lc in enumerate(last_callers) ]) # display file contents, decoded, using a command-prompt pager. prompt_pager(content=callers_txt, line_no=line_no + 2, colors={'highlight': term.bright_green, 'lowlight': term.cyan, }, width=max(term.length(txt) for txt in callers_txt), breaker=None)
def main(last=10): """ Script entry point. :param int last: Number of last callers to display """ session, term = getsession(), getterminal() session.activity = u'Viewing last callers' colors = [term.green, term.bright_blue, term.bold, term.cyan, term.bold_black] # set syncterm font, if any if syncterm_font and term.kind.startswith('ansi'): echo(syncterm_setfont(syncterm_font)) # display banner line_no = display_banner(filepattern=art_file, encoding=art_encoding) # get last callers last_callers = get_lastcallers(last=last) echo(u'\r\n\r\n') # format callers, header: callers_txt = [ '{handle} {location} {num_calls} {timeago}' .format( handle=term.bold_underline( term.ljust('handle', username_max_length + 1)), location=term.underline( term.ljust('location', location_max_length)), num_calls=term.bold_underline( term.ljust('# calls', numcalls_max_length)), timeago=term.underline('time ago')) ] # content: callers_txt.extend([ u'{handle} {location} {num_calls} {timeago}' .format(handle=lc.handle.ljust(username_max_length + 1), location=term.ljust(colors[idx % len(colors)]( lc.location or '-' * location_max_length), location_max_length), num_calls='{0}'.format( lc.num_calls).rjust(numcalls_max_length), timeago=colors[idx % len(colors)]( timeago(lc.timeago)) ) for idx, lc in enumerate(last_callers) ]) # display file contents, decoded, using a command-prompt pager. prompt_pager(content=callers_txt, line_no=line_no + 2, colors={'highlight': term.bright_green, 'lowlight': term.cyan, }, width=max(term.length(txt) for txt in callers_txt), breaker=None)
def main(): session, term = getsession(), getterminal() session.activity = 'Viewing Userlist' colors = { 'highlight': term.red, 'lowlight': term.green, } line_no = display_banner(filepattern=art_file, encoding=art_encoding) def make_header(fmt): return fmt.format( handle=term.bold('handle'.ljust(username_max_length)), location=term.bold('location'.ljust(location_max_length)), lastcall=term.bold('time ago').ljust(8)) userlist_fmt = u'| {handle} | {location} | {lastcall} |' header = make_header(userlist_fmt) header_length = term.length(header) # for smaller screens, remove 'location' field. if header_length > term.width: userlist_fmt = u'| {handle} | {lastcall} |' header = make_header(userlist_fmt) header_length = term.length(header) userlist = [header] + ['-' * header_length] echo(u'Fetching ... ') for _ur in iter_userlist(): location_txt = u'' if 'location' in userlist_fmt: location_txt = colors['lowlight']( _ur.location.ljust(location_max_length)) timeago_txt = timeago(_ur.timeago).ljust(8) handle_txt = _ur.handle.ljust(username_max_length) userlist.append( userlist_fmt.format(handle=handle_txt, location=location_txt, lastcall=timeago_txt)) echo(term.move_x(0) + term.clear_eol + u'Processing ...' + term.move_x(0)) # display users, using a command-prompt pager. prompt_pager(content=userlist, line_no=line_no + 1, colors={ 'highlight': term.red, 'lowlight': term.green, }, width=80, breaker=None)
def show_whois(attrs): """ return terminal sequence for /whois result. """ from x84.bbs import getsession, getterminal, timeago session, term = getsession(), getterminal() return u''.join(( time.strftime('%H:%M'), u' ', term.blue('-'), u'!', term.blue('-'), u' ', term.bold(attrs['handle']), u' ', (u''.join((term.bold_black('['), term.cyan(attrs['sid']), term.bold_black(']'), u' ',)) if 'sysop' in session.user.groups else u''), u'\n', time.strftime('%H:%M'), u' ', term.blue('-'), u'!', term.blue('-'), u' ', u'CONNECtED ', term.bold_cyan(timeago(time.time() - attrs['connect_time'])), ' AGO.', u'\n', time.strftime('%H:%M'), u' ', term.blue('-'), u'!', term.blue('-'), u' ', term.bold(u'idlE: '), term.bold_cyan(timeago(time.time() - attrs['idle'])), u'\n', ))
def main(): session, term = getsession(), getterminal() session.activity = 'Viewing Userlist' colors = {'highlight': term.red, 'lowlight': term.green, } line_no = display_banner(filepattern=art_file, encoding=art_encoding) def make_header(fmt): return fmt.format( handle=term.bold('handle'.ljust(username_max_length)), location=term.bold('location'.ljust(location_max_length)), lastcall=term.bold('time ago').ljust(8)) userlist_fmt = u'| {handle} | {location} | {lastcall} |' header = make_header(userlist_fmt) header_length = term.length(header) # for smaller screens, remove 'location' field. if header_length > term.width: userlist_fmt = u'| {handle} | {lastcall} |' header = make_header(userlist_fmt) header_length = term.length(header) userlist = [header] + ['-' * header_length] for _ur in iter_userlist(): location_txt = u'' if 'location' in userlist_fmt: location_txt = colors['lowlight']( _ur.location.ljust(location_max_length)) timeago_txt = timeago(_ur.timeago).ljust(8) handle_txt = _ur.handle.ljust(username_max_length) userlist.append(userlist_fmt.format( handle=handle_txt, location=location_txt, lastcall=timeago_txt)) echo(u'\r\n') # display users, using a command-prompt pager. prompt_pager(content=userlist, line_no=line_no + 1, colors={'highlight': term.red, 'lowlight': term.green, }, width=80, breaker=None)
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
def get_header(msgs_idx): """ Return list of tuples, (idx, unicodestring), suitable for Lightbar. """ import datetime msg_list = list() thread_indent = lambda depth: (term.red( (indent_start + (indent * depth) + indent_end)) if depth else u'') def head(msg, depth=0, maxdepth=reply_depth): """ This recursive routine finds the 'head' message of any relationship, up to maxdepth. """ if (depth <= maxdepth and hasattr(msg, 'parent') and msg.parent is not None): return head(get_msg(msg.parent), depth + 1, maxdepth) return msg.idx, depth for idx in msgs_idx: msg = get_msg(idx) author, subj = msg.author, msg.subject tm_ago = (datetime.datetime.now() - msg.stime).total_seconds() # pylint: disable=W0631 # Using possibly undefined loop variable 'idx' attr = lambda arg: (term.bold_green(arg) if (not idx in ALREADY_READ and msg.recipient == session.user.handle) else term.red(arg) if not idx in ALREADY_READ else term.yellow(arg )) status = [ u'U' if not idx in ALREADY_READ else u' ', u'D' if idx in DELETED else u' ', ] row_txt = u'%s %s %s %s %s%s ' % ( u''.join(status), attr(str(idx).rjust(len_idx)), attr(author.ljust(len_author)), (timeago(tm_ago)).rjust(len_ago), attr(u'ago'), term.bold_black(':'), ) msg_list.append((head(msg), idx, row_txt, subj)) msg_list.sort(reverse=True) return [(idx, row_txt + thread_indent(depth) + subj) for (_threadid, depth), idx, row_txt, subj in msg_list]
def get_header(msgs_idx): """ Return list of tuples, (idx, unicodestring), suitable for Lightbar. """ import datetime msg_list = list() thread_indent = lambda depth: (term.red( (indent_start + (indent * depth) + indent_end)) if depth else u'') def head(msg, depth=0, maxdepth=reply_depth): """ This recursive routine finds the 'head' message of any relationship, up to maxdepth. """ if (depth <= maxdepth and hasattr(msg, 'parent') and msg.parent is not None): return head(get_msg(msg.parent), depth + 1, maxdepth) return msg.idx, depth for idx in msgs_idx: msg = get_msg(idx) author, subj = msg.author, msg.subject tm_ago = (datetime.datetime.now() - msg.stime).total_seconds() # pylint: disable=W0631 # Using possibly undefined loop variable 'idx' attr = lambda arg: ( term.bold_green(arg) if ( not idx in ALREADY_READ and msg.recipient == session.user.handle) else term.red(arg) if not idx in ALREADY_READ else term.yellow(arg)) status = [u'U' if not idx in ALREADY_READ else u' ', u'D' if idx in DELETED else u' ', ] row_txt = u'%s %s %s %s %s%s ' % ( u''.join(status), attr(str(idx).rjust(len_idx)), attr(author.ljust(len_author)), (timeago(tm_ago)).rjust(len_ago), attr(u'ago'), term.bold_black(':'),) msg_list.append((head(msg), idx, row_txt, subj)) msg_list.sort() return [(idx, row_txt + thread_indent(depth) + subj) for (_threadid, depth), idx, row_txt, subj in msg_list]
def display_message(session, term, msg_index, colors): """ Format message of index ``idx``. """ color_handle = lambda handle: (colors["highlight"](handle) if handle == session.user.handle else handle) msg = get_msg(msg_index) txt_sent = msg.stime.replace(tzinfo=dateutil.tz.tzlocal()).astimezone(dateutil.tz.tzutc()).strftime(TIME_FMT) txt_sentago = colors["highlight"](timeago((datetime.datetime.now() - msg.stime).total_seconds()).strip()) txt_to = color_handle(msg.recipient) txt_private = colors["highlight"](" (private)") if not "public" in msg.tags else u"" txt_from = color_handle(msg.author) txt_tags = u", ".join((quote(tag, colors) for tag in msg.tags)) txt_subject = colors["highlight"](msg.subject) txt_body = decode_pipe(msg.body) txt_breaker = ("-" if session.encoding == "ansi" else u"\u2500") * min(80, term.width) msg_txt = ( u"\r\n{txt_breaker}\r\n" u" from: {txt_from}\r\n" u" to: {txt_to}{txt_private}\r\n" u" sent: {txt_sent} ({txt_sentago} ago)\r\n" u" tags: {txt_tags}\r\n" u"subject: {txt_subject}\r\n" u"\r\n" u"{txt_body}\r\n".format( txt_breaker=txt_breaker, txt_from=txt_from, txt_to=txt_to, txt_sent=txt_sent, txt_sentago=txt_sentago, txt_tags=txt_tags, txt_subject=txt_subject, txt_body=txt_body, txt_private=txt_private, ) ) do_mark_as_read(session, [msg_index]) prompt_pager( content=msg_txt.splitlines(), line_no=0, width=min(80, term.width), colors=colors, breaker=u"- ", end_prompt=False, break_long_words=True, )
def display_message(session, term, msg_index, colors): """ Format message of index ``idx``. """ color_handle = lambda handle: (colors['highlight'](handle) if handle == session.user.handle else handle) msg = get_msg(msg_index) txt_sent = msg.stime.replace(tzinfo=dateutil.tz.tzlocal()).astimezone( dateutil.tz.tzutc()).strftime(TIME_FMT) txt_sentago = colors['highlight'](timeago( (datetime.datetime.now() - msg.stime).total_seconds()).strip()) txt_to = color_handle(msg.recipient) txt_private = (colors['highlight'](' (private)') if not 'public' in msg.tags else u'') txt_from = color_handle(msg.author) txt_tags = u', '.join((quote(tag, colors) for tag in msg.tags)) txt_subject = colors['highlight'](msg.subject) txt_body = decode_pipe(msg.body) txt_breaker = ('-' if session.encoding == 'ansi' else u'\u2500') * min( 80, term.width) msg_txt = (u'\r\n{txt_breaker}\r\n' u' from: {txt_from}\r\n' u' to: {txt_to}{txt_private}\r\n' u' sent: {txt_sent} ({txt_sentago} ago)\r\n' u' tags: {txt_tags}\r\n' u'subject: {txt_subject}\r\n' u'\r\n' u'{txt_body}\r\n'.format(txt_breaker=txt_breaker, txt_from=txt_from, txt_to=txt_to, txt_sent=txt_sent, txt_sentago=txt_sentago, txt_tags=txt_tags, txt_subject=txt_subject, txt_body=txt_body, txt_private=txt_private)) do_mark_as_read(session, [msg_index]) prompt_pager(content=msg_txt.splitlines(), line_no=0, width=min(80, term.width), colors=colors, breaker=u'- ', end_prompt=False, break_long_words=True)
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())
def get_timeago(now, given_datestr): """ Return '3m' or some such as 'ago' time for given datestr. """ return timeago(now - time.mktime( time.strptime(given_datestr, '%Y-%m-%d %H:%M:%S')) ).strip()
def get_timeago(now, given_datestr): """ Return '3m' or some such as 'ago' time for given datestr. """ return timeago(now - time.mktime( time.strptime(given_datestr, '%Y-%m-%d %H:%M:%S'))).strip()
def get_display_fields(user, point): """ Return OrderedDict of display fields. """ # reference the description text fields from nua.py # for their same purpose here. descriptions = { key: field.description for (key, field) in nua.get_validation_fields(user).items() } fields = collections.OrderedDict() _indent = point.x + 4 + nua.username_max_length # user: <name> last called 10m ago # from ssh-127.0.0.1:65534 # 1 calls, 1 posts fields['user'] = field(value=user.handle, field_fmt=u'{rb}{value}{lb}', display_location=Point(y=point.y, x=point.x), edit_location=Point(y=point.y, x=point.x + 1), key=None, width=nua.username_max_length, validate_fn=None, description=descriptions.get('handle')) fields['ago'] = field( value=timeago(time.time() - user.lastcall), field_fmt=u'last called {value} ago', display_location=Point(y=point.y, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields['last_from'] = field( value=user.get('last_from', 'None'), field_fmt=u'from {value}', display_location=Point(y=point.y + 1, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields['calls'] = field( value=str(user.calls), field_fmt=u'{value} calls', display_location=Point(y=point.y + 2, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields['posts'] = field( value=str(user.get('msgs_sent', 0)), field_fmt=u'{value} posts', display_location=Point(y=point.y + 2, x=_indent + len('1999 calls') + 1), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) # go ahead, show them the password salt; it gets trimmed, and its gibberish, # maybe it gives them confidence that we don't know their actual password. _password = u'' if user.handle != 'anonymous': _password = u''.join(user.password) fields['password'] = field( value=_password, field_fmt=u'{lb}{key}{rb}assword{colon} {value}', display_location=Point(y=point.y + 5, x=point.x), edit_location=Point(y=point.y + 5, x=point.x + 12), key=u'p', width=nua.password_max_length, validate_fn=nua.validate_password, description=None, ) fields['location'] = field( value=user.location, field_fmt=u'{lb}{key}{rb}rigin{colon} {value}', display_location=Point(y=point.y + 7, x=point.x), edit_location=Point(y=point.y + 7, x=point.x + 12), key=u'o', width=nua.location_max_length, validate_fn=None, description=descriptions.get('location'), ) fields['email'] = field( value=user.email, field_fmt=u'{lb}{key}{rb}mail{colon} {value}', display_location=Point(y=point.y + 9, x=point.x), edit_location=Point(y=point.y + 9, x=point.x + 12), key=u'e', width=nua.email_max_length, validate_fn=None, description=descriptions.get('email'), ) fields['timeout'] = field( value=str(user.get('timeout', 'no')), field_fmt=u'{lb}{key}{rb}dle off{colon} {value}', display_location=Point(y=point.y + 11, x=point.x), edit_location=Point(y=point.y + 11, x=point.x + 12), key=u'i', width=5, # XXX validate_fn=None, description=(u"When set, Your session will be disconnected after this " u"period of time has elapsed (in seconds). 0 disables."), ) fields['pubkey'] = field( value=user.get('pubkey') or 'no', field_fmt=u'{lb}{key}{rb}sh-key{colon} {value}', display_location=Point(y=point.y + 11, x=point.x + 19), edit_location=Point(y=point.y + 11, x=point.x + 31), key=u's', width=20, # XXX validate_fn=None, description=(u"Place your OpenSSH-compatible ssh public key into your " u"clipboard, using command `pbcopy < ~/.ssh/id_rsa.pub` " "on OSX or `xclip -i < ~/.ssh/id_rsa.pub` in X11. Then, " "simply paste it here. "), ) fields['groups'] = field( value=','.join(user.groups), field_fmt=u'{lb}{key}{rb}roups{colon} {value}', display_location=Point(y=point.y + 13, x=point.x), edit_location=Point(y=point.y + 13, x=point.x + 12), key=u'g', width=30, validate_fn=None, description=(u"Groups this user is a member of, separated by comma. " u"Notably, group 'sysop' has system-wide access, and " u"group 'moderator' is able to moderate messages. "), ) return fields
def get_display_fields(user, point): """ Return OrderedDict of display fields. """ # reference the description text fields from nua.py # for their same purpose here. descriptions = {key: field.description for (key, field) in nua.get_validation_fields(user).items()} fields = collections.OrderedDict() _indent = point.x + 4 + nua.username_max_length # user: <name> last called 10m ago # from ssh-127.0.0.1:65534 # 1 calls, 1 posts fields["user"] = field( value=user.handle, field_fmt=u"{rb}{value}{lb}", display_location=Point(y=point.y, x=point.x), edit_location=Point(y=point.y, x=point.x + 1), key=None, width=nua.username_max_length, validate_fn=None, description=descriptions.get("handle"), ) fields["ago"] = field( value=timeago(time.time() - user.lastcall), field_fmt=u"last called {value} ago", display_location=Point(y=point.y, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields["last_from"] = field( value=user.get("last_from", "None"), field_fmt=u"from {value}", display_location=Point(y=point.y + 1, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields["calls"] = field( value=str(user.calls), field_fmt=u"{value} calls", display_location=Point(y=point.y + 2, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields["posts"] = field( value=str(user.get("msgs_sent", 0)), field_fmt=u"{value} posts", display_location=Point(y=point.y + 2, x=_indent + len("1999 calls") + 1), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) # go ahead, show them the password salt; it gets trimmed, and its gibberish, # maybe it gives them confidence that we don't know their actual password. _password = u"" if user.handle != "anonymous": _password = u"".join(user.password) fields["password"] = field( value=_password, field_fmt=u"{lb}{key}{rb}assword{colon} {value}", display_location=Point(y=point.y + 5, x=point.x), edit_location=Point(y=point.y + 5, x=point.x + 12), key=u"p", width=nua.password_max_length, validate_fn=nua.validate_password, description=None, ) fields["location"] = field( value=user.location, field_fmt=u"{lb}{key}{rb}rigin{colon} {value}", display_location=Point(y=point.y + 7, x=point.x), edit_location=Point(y=point.y + 7, x=point.x + 12), key=u"o", width=nua.location_max_length, validate_fn=None, description=descriptions.get("location"), ) fields["email"] = field( value=user.email, field_fmt=u"{lb}{key}{rb}mail{colon} {value}", display_location=Point(y=point.y + 9, x=point.x), edit_location=Point(y=point.y + 9, x=point.x + 12), key=u"e", width=nua.email_max_length, validate_fn=None, description=descriptions.get("email"), ) fields["timeout"] = field( value=str(user.get("timeout", "no")), field_fmt=u"{lb}{key}{rb}dle off{colon} {value}", display_location=Point(y=point.y + 11, x=point.x), edit_location=Point(y=point.y + 11, x=point.x + 12), key=u"i", width=5, # XXX validate_fn=None, description=( u"When set, Your session will be disconnected after this " u"period of time has elapsed (in seconds). 0 disables." ), ) fields["pubkey"] = field( value=user.get("pubkey") or "no", field_fmt=u"{lb}{key}{rb}sh-key{colon} {value}", display_location=Point(y=point.y + 11, x=point.x + 19), edit_location=Point(y=point.y + 11, x=point.x + 31), key=u"s", width=20, # XXX validate_fn=None, description=( u"Place your OpenSSH-compatible ssh public key into your " u"clipboard, using command `pbcopy < ~/.ssh/id_rsa.pub` " "on OSX or `xclip -i < ~/.ssh/id_rsa.pub` in X11. Then, " "simply paste it here. " ), ) return fields
def get_display_fields(user, point): """ Return OrderedDict of display fields. """ # reference the description text fields from nua.py # for their same purpose here. descriptions = { key: field.description for (key, field) in nua.get_validation_fields(user).items()} fields = collections.OrderedDict() _indent = point.x + 4 + nua.username_max_length # user: <name> last called 10m ago # from ssh-127.0.0.1:65534 # 1 calls, 1 posts fields['user'] = field( value=user.handle, field_fmt=u'{rb}{value}{lb}', display_location=Point(y=point.y, x=point.x), edit_location=Point(y=point.y, x=point.x + 1), key=None, width=nua.username_max_length, validate_fn=None, description=descriptions.get('handle') ) fields['ago'] = field( value=timeago(time.time() - user.lastcall), field_fmt=u'last called {value} ago', display_location=Point(y=point.y, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields['last_from'] = field( value=user.get('last_from', 'None'), field_fmt=u'from {value}', display_location=Point(y=point.y + 1, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields['calls'] = field( value=str(user.calls), field_fmt=u'{value} calls', display_location=Point(y=point.y + 2, x=_indent), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) fields['posts'] = field( value=str(user.get('msgs_sent', 0)), field_fmt=u'{value} posts', display_location=Point(y=point.y + 2, x=_indent + len('1999 calls') + 1), edit_location=Point(None, None), key=None, width=None, validate_fn=None, description=None, ) # go ahead, show them the password salt; it gets trimmed, and its gibberish, # maybe it gives them confidence that we don't know their actual password. _password = u'' if user.handle != 'anonymous': _password = u''.join(user.password) fields['password'] = field( value=_password, field_fmt=u'{lb}{key}{rb}assword{colon} {value}', display_location=Point(y=point.y + 5, x=point.x), edit_location=Point(y=point.y + 5, x=point.x + 12), key=u'p', width=nua.password_max_length, validate_fn=nua.validate_password, description=None, ) fields['location'] = field( value=user.location, field_fmt=u'{lb}{key}{rb}rigin{colon} {value}', display_location=Point(y=point.y + 7, x=point.x), edit_location=Point(y=point.y + 7, x=point.x + 12), key=u'o', width=nua.location_max_length, validate_fn=None, description=descriptions.get('location'), ) fields['email'] = field( value=user.email, field_fmt=u'{lb}{key}{rb}mail{colon} {value}', display_location=Point(y=point.y + 9, x=point.x), edit_location=Point(y=point.y + 9, x=point.x + 12), key=u'e', width=nua.email_max_length, validate_fn=None, description=descriptions.get('email'), ) fields['timeout'] = field( value=str(user.get('timeout', 'no')), field_fmt=u'{lb}{key}{rb}dle off{colon} {value}', display_location=Point(y=point.y + 11, x=point.x), edit_location=Point(y=point.y + 11, x=point.x + 12), key=u'i', width=5, # XXX validate_fn=None, description=(u"When set, Your session will be disconnected after this " u"period of time has elapsed (in seconds). 0 disables."), ) fields['pubkey'] = field( value=user.get('pubkey') or 'no', field_fmt=u'{lb}{key}{rb}sh-key{colon} {value}', display_location=Point(y=point.y + 11, x=point.x + 19), edit_location=Point(y=point.y + 11, x=point.x + 31), key=u's', width=20, # XXX validate_fn=None, description=(u"Place your OpenSSH-compatible ssh public key into your " u"clipboard, using command `pbcopy < ~/.ssh/id_rsa.pub` " "on OSX or `xclip -i < ~/.ssh/id_rsa.pub` in X11. Then, " "simply paste it here. "), ) fields['groups'] = field( value=','.join(user.groups), field_fmt=u'{lb}{key}{rb}roups{colon} {value}', display_location=Point(y=point.y + 13, x=point.x), edit_location=Point(y=point.y + 13, x=point.x + 12), key=u'g', width=30, validate_fn=None, description=(u"Groups this user is a member of, separated by comma. " u"Notably, group 'sysop' has system-wide access, and " u"group 'moderator' is able to moderate messages. "), ) return fields