def yes_no(lightbar, msg, prompt_msg='are you sure? ', attr=None): """ Prompt user for yes/no, returns True for yes, False for no. """ term = getterminal() keyset = { 'yes': (u'y', u'Y'), 'no': (u'n', u'N'), } echo(u''.join(( lightbar.border(), lightbar.pos(lightbar.yloc + lightbar.height - 1, lightbar.xpadding), msg, u' ', prompt_msg,))) sel = Selector(yloc=lightbar.yloc + lightbar.height - 1, xloc=term.width - 25, width=18, left='Yes', right=' No ') sel.colors['selected'] = term.reverse_red if attr is None else attr sel.keyset['left'].extend(keyset['yes']) sel.keyset['right'].extend(keyset['no']) echo(sel.refresh()) term = getterminal() while True: inp = term.inkey() echo(sel.process_keystroke(inp)) if((sel.selected and sel.selection == sel.left) or inp in keyset['yes']): # selected 'yes', return True elif((sel.selected or sel.quit) or inp in keyset['no']): # selected 'no' return False
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 saysomething(dumb=True): """ Prompt user to post oneliner, also prompt user to post to bbs-scene.org if configured, returning background Thread. """ import time from x84.bbs import getsession, getterminal, echo, LineEditor, ini session, term = getsession(), getterminal() prompt_say = u'SAY WhAt ?! ' # heard_msg = u'YOUR MESSAGE hAS bEEN VOiCEd.' yloc = term.height - 3 xloc = max(0, ((term.width / 2) - (MAX_INPUT / 2))) if dumb: echo(u'\r\n\r\n' + term.bold_blue(prompt_say)) else: echo(term.move(yloc, xloc) or u'\r\n\r\n') echo(term.bold_blue(prompt_say)) ole = LineEditor(MAX_INPUT) ole.highlight = term.green_reverse oneliner = ole.read() if oneliner is None or 0 == len(oneliner.strip()): if not dumb: # clear input line, echo(term.normal + term.move(yloc, 0) + term.clear_eol) return None session.user['lastliner'] = time.time() # post local-onlyw hen bbs-scene.org is not configured if not ini.CFG.has_section('bbs-scene'): add_oneline(oneliner.strip()) return None return post_bbs_scene(oneliner, dumb)
def redraw(pager, selector): """ Redraw pager and selector """ from x84.bbs import getsession, getterminal, echo session, term = getsession(), getterminal() session.flush_event('oneliner_update') pager.colors['border'] = term.white pager.glyphs['top-horiz'] = u'' pager.glyphs['top-right'] = u'' pager.glyphs['top-left'] = u'' pager.glyphs['bot-horiz'] = u'' pager.glyphs['bot-right'] = u'' pager.glyphs['bot-left'] = u'' pager.glyphs['left-vert'] = u'' pager.glyphs['right-vert'] = u'' prompt_ole = u'write an oneliner?' pager.update(u'\n\n\nFetching ...') echo(u''.join(( pager.refresh(), pager.border(), term.move(selector.yloc - 2, selector.xloc), term.bold_red(prompt_ole.center(selector.width).rstrip()), term.clear_eol, selector.refresh(), ))) pager.update(u'\n'.join(get_oltxt())) pager.move_end() echo(pager.refresh())
def chk_save_location(location): """ Prompt user to save location for quick re-use """ from x84.bbs import getterminal, getsession, echo session, term = getsession(), getterminal() stored_location = session.user.get('location', dict()).items() if (sorted(location.items()) == sorted(stored_location)): # location already saved return False if session.user.handle == 'anonymous': # anonymous cannot save preferences return False # prompt to store (unsaved/changed) location echo(u'\r\n\r\n') echo(term.yellow(u'Save Location')) echo(term.bold_yellow(u' (')) echo(term.bold_black(u'private')) echo(term.bold_yellow(u') ')) echo(term.yellow(u'? ')) echo(term.bold_yellow(u'[')) echo(term.underline_yellow(u'yn')) echo(term.bold_yellow(u']')) echo(u': ') while True: inp = term.inkey() if inp.code == term.KEY_EXIT or inp.lower() in (u'n', 'q'): break elif inp.code == term.KEY_ENTER or inp.lower() in (u'y', u' '): session.user['location'] = location break
def prompt_network(msg, network_tags): """ Prompt for network message """ from x84.bbs import getterminal, echo, Lightbar, Selector from x84.bbs.ini import CFG term = getterminal() inp = Selector(yloc=term.height - 1, xloc=term.width - 22, width=20, left=u'YES', right=u'NO') blurb = u'iS thiS A NEtWORk MESSAGE?' echo(u'\r\n\r\n') echo(term.move(inp.yloc, inp.xloc - len(blurb))) echo(term.bold_yellow(blurb)) selection = inp.read() echo(term.move(inp.yloc, 0) + term.clear_eol) if selection == u'NO': return False lb = Lightbar(20, 20, term.height / 2 - 10, term.width / 2 - 10) lb.update([(tag, tag,) for tag in network_tags]) echo(u''.join(( term.clear , term.move(term.height / 2 - 11, term.width / 2 - 9) , term.bold_white(u'ChOOSE YOUR NEtWORk') ))) network = lb.read() if network is not None: msg.tags = (u'public', network,) return True return False
def prompt_ok(): """ Prompt user to continue, True if they select yes. """ from x84.bbs import getsession, getterminal, echo, getch, Selector session, term = getsession(), getterminal() prompt_confirm = u'EVERYthiNG lOOk Ok ?' prompt_continue = u'YES (CONtiNUE)' prompt_chg = u'NO! (ChANGE)' def prompt_ok_dumb(): """ Dummy terminal prompt for confirm/cancel. """ echo('\r\n\r\n%s\r\n' % (prompt_confirm,)) echo('1 - %s\r\n' % (prompt_continue,)) echo('2 - %s\r\n\r\n' % (prompt_chg,)) echo('select (1, 2) --> ') while True: inp = getch() if inp == u'1': return True elif inp == u'2': return False if session.env.get('TERM') == 'unknown': return prompt_ok_dumb() sel = Selector(yloc=term.height - 1, xloc=5, width=term.width - 10, left=prompt_continue, right=prompt_chg) echo(term.normal) echo(term.move(term.height - 2, 0) + term.clear_eol) echo(prompt_confirm.center(term.width - 1) + '\r\n') echo(term.clear_eol + sel.refresh()) while True: echo(sel.process_keystroke(getch())) if sel.selected: return True if sel.selection == prompt_continue else False
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()
def get_ui(position=None): """ Returns user interface (lightbar, pager). Optional argument position is tuple position of prior lightbar instance. """ from x84.bbs import getterminal, Lightbar, Pager term = getterminal() assert term.height > 10 and term.width >= 40 # +-+ +----+ # |lb |pager # +-+ +----+ height = term.height - 7 lb_width = int(term.width * .3) pg_width = term.width - (lb_width) lb_xloc = (term.width / 2) - (term.width / 2) pg_xloc = lb_xloc + lb_width lightbar = Lightbar(height, lb_width, (term.height - height - 1), lb_xloc) pager = Pager(height, pg_width, (term.height - height - 1), pg_xloc) pager.ypadding = 2 pager.xpadding = 2 lightbar.update(get_bbslist(max_len=lightbar.visible_width)) ## pressing Return is same as 't'elnet lightbar.keyset['enter'].extend((u't', u'T')) ## re-select previous selection if position is not None: lightbar.position = position return (pager, lightbar)
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 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()
def display_msg(msg): """ Display full message """ from x84.bbs import getterminal, getsession, echo, decode_pipe session, term = getsession(), getterminal() body = msg.body.splitlines() style = getstyle() receipt = (msg.recipient if msg.recipient is not None else u'<(None)=All users>') echo(u' AUthOR: ' + style['highlight'](msg.author) + u'\r\n\r\n') echo(u' RECiPiENt: ') echo(style['lowlight'](receipt)) echo(u'\r\n\r\n') echo(u' SUBjECt: ') echo(style['lowlight'](msg.subject)) echo(u'\r\n\r\n') echo(u' tAGS: ') echo(style['lowlight'](u', '.join(msg.tags))) echo(u'\r\n\r\n') echo(term.underline(u' bOdY: '.ljust(term.width - 1)) + u'\r\n') echo(decode_pipe(u'\r\n'.join(body)) + term.normal) echo(u'\r\n' + term.underline(u''.ljust(term.width - 1))) echo(u'\r\n\r\n') session.activity = 'Constructing a %s message' % ( u'public' if u'public' in msg.tags else u'private',) return
def test_xmodem(filepath, protocol='xmodem1k'): import os from x84.bbs import echo, send_modem, recv_modem, getterminal term = getterminal() echo(u"\r\n\r\n") # test bbs sending to client stream = open(filepath, 'rb') echo(u"Sending {0} using protocol {1}. \r\n" u"Start your receiving program now. \r\n" u"Press ^X twice to cancel: " .format(filepath, protocol)) status = send_modem(stream, protocol) if not status: echo(u"\r\nThat didn't go so well.. " u"status={0}; sorry!\r\n".format(status)) term.inkey() return # test client sending to bbs echo(u"Now its your turn cowboy -- send me anything\r\n" u"using the {0} protocol. really, I don't care.\r\n" .format(protocol)) stream = open(os.devnull, 'wb') if not recv_modem(stream, protocol): echo(u"That didn't go so well.. sorry!\r\n") term.inkey() return echo(u"fine shooting, soldier!\r\n") term.inkey()
def redraw_lightbar(lightbar, active=True): """ Display bbs listing in lightbar. """ from x84.bbs import getterminal term = getterminal() lightbar.colors['border'] = term.bold_green if active else term.bold_black output = lightbar.border() if active: lightbar.colors['selected'] = term.green_reverse else: lightbar.colors['selected'] = term.blue_reverse # output += lightbar.footer(u''.join(( # u'- ', # fancy_green('up', '.'), # fancy_green('down', '.'), # fancy_green('right', u''), # u' -'))) # output += lightbar.footer(u''.join(( # u'- ', # fancy_blue('up', '.'), # fancy_blue('down', '.'), # fancy_green('left', u''), # u' -'))) output += lightbar.title(u'- ' + fancy_green('a', 'add') + ' -') output += lightbar.refresh() return output
def main(): session, term = getsession(), getterminal() session.activity = "Tripping out on colors!" term.color_distance_algorithm = 'rgb-weighted' with term.hidden_cursor(), term.fullscreen(): pause, dirty = False, True t = time.time() while True: if dirty or not pause: if not pause: t = time.time() with elapsed_timer() as elapsed: outp = term.home + screen_plasma(term, rgb_at_xy, t) outp += status(term, elapsed()) echo(outp) #assert False, repr(outp) dirty = False if pause: show_paused(term) inp = term.inkey(timeout=0.01 if not pause else None) if inp.lower() == 'q': break if inp == '?': assert False, "don't panic" if inp == '\x0c': dirty = True if inp in ('[', ']'): term.color_distance_algorithm = next_algo( term.color_distance_algorithm, inp == '[') show_please_wait(term) dirty = True if inp == ' ': pause = not pause
def display_banner(filepattern, vertical_padding=0, **kwargs): """ Start new screen and show artwork, centered. :param str filepattern: file to display :param int vertical_padding: number of blank lines to prefix art :return: number of lines displayed :rtype: int Remaining parameters are inherited from :func:`showart`, such as ``center`` and ``encoding``. By default, ``center`` is True. """ # This is unfortunate, we should use 'term' as first argument term = getterminal() kwargs['center'] = kwargs.get('center', True) # move to bottom of screen, reset attribute echo(term.move(term.height, 0) + term.normal) # create a new, empty screen echo(u'\r\n' * (term.height + 1)) # move to home, insert vertical padding echo(term.home + (u'\r\n' * vertical_padding)) art_generator = showart(filepattern, **kwargs) line_no = 0 for txt in art_generator: line_no += 1 echo(txt) # return line number return line_no + vertical_padding
def banner(): """ Display banner/art ... nothing for now """ from x84.bbs import echo, getterminal term = getterminal() echo(u'\r\n\r\n') echo(term.bold_black(u'art needed ../'.center(term.width).rstrip())) echo(u'\r\n\r\n')
def main(anonymous=False, new=False): """ Script entry point. This is the default login matrix for the bbs system. It takes no arguments or keyword arguments, because it assumes the user should now be authenticated, such as occurs for example on telnet. """ term = getterminal() display_banner(term) if anonymous: # user rlogin'd in as anonymous@ goto(top_script, 'anonymous') elif new: # user rlogin'd in as new@ goto(new_script) # do_login will goto/gosub various scripts, if it returns, then # either the user entered 'bye', or had too many failed attempts. do_login(term) log.debug('Disconnecting.') # it is necessary to provide sufficient time to send any pending # output across the transport before disconnecting. term.inkey(1.5)
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 prompt(): """ Return string suitable for displaying prompt and available commands. """ from x84.bbs import getsession, getterminal session, term = getsession(), getterminal() decorate = lambda key, desc: u"".join( (u"(", term.magenta_underline(key), u")", term.cyan(desc.split()[0]), u" ", u" ".join(desc.split()[1:]), u" ") ) return term.wrap( u"".join( ( u" " * 2, term.green_reverse(":keys"), u" ", decorate("c", "hAt USR"), decorate("s", "ENd MSG"), ( u"".join( (decorate("d", "iSCONNECt SiD"), decorate("e", "diT USR"), decorate("v", "iEW SiD AttRS"), u" ") ) if "sysop" in session.user.groups else u"" ), decorate("Escape/q", "Uit"), decorate("Spacebar", "REfRESh"), ) ), int(term.width * 0.8), subsequent_indent=u" " * 8, )
def chk_save_location(location): """ Prompt user to save location for quick re-use """ from x84.bbs import getterminal, getsession, echo, getch session, term = getsession(), getterminal() stored_location = session.user.get('location', dict()).items() if (sorted(location.items()) == sorted(stored_location)): # location already saved return if session.user.handle == 'anonymous': # anonymous cannot save preferences return # prompt to store (unsaved/changed) location echo(u'\r\n\r\n') echo(term.yellow(u'Save Location')) echo(term.bold_yellow(u' (')) echo(term.bold_black(u'private')) echo(term.bold_yellow(u') ')) echo(term.yellow(u'? ')) echo(term.bold_yellow(u'[')) echo(term.underline_yellow(u'yn')) echo(term.bold_yellow(u']')) echo(u': ') while True: inp = getch() if inp is None or inp in (u'n', u'N', u'q', u'Q', term.KEY_EXIT): break if inp in (u'y', u'Y', u' ', term.KEY_ENTER): session.user['location'] = location break
def get_pager(pager=None): """ Return Pager for use as chat window. """ from x84.bbs import getterminal, Pager term = getterminal() height = (term.height - 4) width = int(term.width * .9) yloc = term.height - height - 1 xloc = int(term.width / 2) - (width / 2) new_pager = Pager(height, width, yloc, xloc) if pager is not None: content = pager.content # little hack to keep empty lines from re-importing for row in range(len(content)): ucs = content[row] if ucs.startswith(u'\x1b(B'): ucs = ucs[len(u'\x1b(B'):] if ucs.endswith(u'\x1b[m'): ucs = ucs[len(u'\x1b[m'):] content[row] = ucs new_pager.update('\r\n'.join(content)) new_pager.enable_scrolling = True new_pager.colors['border'] = term.cyan new_pager.glyphs['right-vert'] = u'|' new_pager.glyphs['left-vert'] = u'|' new_pager.glyphs['bot-horiz'] = u'' return new_pager
def prompt_body(msg): """ Prompt for 'body' of message, executing 'editor' script. """ from x84.bbs import echo, Selector, getterminal, getsession, gosub term = getterminal() session = getsession() inp = Selector(yloc=term.height - 1, xloc=term.width - 22, width=20, left=u'CONtiNUE', right=u'CANCEl') # check for previously existing draft if 0 != len(session.user.get('draft', u'')): # XXX display age of message inp = Selector(yloc=term.height - 1, xloc=term.width - 22, width=20, left=u'REStORE', right=u'ERASE') blurb = u'CONtiNUE PREViOUSlY SAVEd dRAft ?' echo(u'\r\n\r\n') echo(term.move(inp.yloc, inp.xloc - len(blurb))) echo(term.bold_yellow(blurb)) selection = inp.read() echo(term.move(inp.yloc, 0) + term.clear_eol) if selection == u'REStORE': msg.body = session.user['draft'] echo(u'\r\n\r\n') session.user['draft'] = msg.body if gosub('editor', 'draft'): echo(u'\r\n\r\n' + term.normal) msg.body = session.user.get('draft', u'') del session.user['draft'] return 0 != len(msg.body.strip()) return False
def main(anonymous=False, new=False, username=''): """ Main procedure. """ from x84.bbs import ( getsession, getterminal, find_user, get_user, User, ) session, term = getsession(), getterminal() session.activity = 'sftp' if anonymous: user = User(u'anonymous') else: assert not new, ("new@ user not supported by SFTP.") # ProperCase user-specified handle handle = find_user(username) assert handle is not None, handle # fetch user record user = get_user(handle) # assign session user, just as top.py function login() session.user = user while True: inp = term.inkey() # should block indefinately log = logging.getLogger(__name__) log.warn('Got inkey: {0!r}'.format(inp))
def prompt(): """ Return string suitable for displaying prompt and available commands. """ from x84.bbs import getsession, getterminal, Ansi session, term = getsession(), getterminal() decorate = lambda key, desc: u''.join(( u'(', term.green_underline(key,), u')', term.reverse_green(desc.split()[0]), u' ', u' '.join(desc.split()[1:]), u' ',)) return Ansi(u''.join(( u' ' * 2, term.green_reverse(':keys'), u' ', decorate('c', 'hAt USR'), decorate('s', 'ENd MSG'), (u''.join(( decorate('p', 'lAYbACk REC'), decorate('w', 'AtCh liVE'), decorate('d', 'iSCONNECt SiD'), decorate('e', 'diT USR'), decorate('v', 'iEW SiD AttRS'), u' ',)) if 'sysop' in session.user.groups else u''), decorate('Escape/q', 'Uit'), decorate('Spacebar', 'REfRESh'), ))).wrap(int(term.width * .7), indent=u' ' * 8)
def display_banner(filepattern, vertical_padding=0, **kwargs): """ Start new screen and show artwork, centered. :param str filepattern: file to display :param int vertical_padding: number of blank lines to prefix art :return: number of lines displayed :rtype: int Remaining parameters are inherited from :func:`showart`, such as ``center`` and ``encoding``. By default, ``center`` is True. """ # This is unfortunate, we should use 'term' as first argument term = getterminal() kwargs['center'] = kwargs.get('center', True) # move to bottom of screen, reset attribute echo(term.move(term.height, 0) + term.normal) # create a new, empty screen echo(u'\r\n' * (term.height + 1)) # move to home, insert vertical padding echo(term.home + (u'\r\n' * vertical_padding)) art_generator = showart(filepattern, **kwargs) line_no = 0 for line_no, txt in enumerate(art_generator): echo(txt) # return line number return line_no + vertical_padding
def redraw(pager, selector): """ Redraw pager and selector """ from x84.bbs import getsession, getterminal, echo session, term = getsession(), getterminal() session.flush_event('oneliner_update') pager.colors['border'] = term.white pager.glyphs['top-horiz'] = u'' pager.glyphs['top-right'] = u'' pager.glyphs['top-left'] = u'' pager.glyphs['bot-horiz'] = u'' pager.glyphs['bot-right'] = u'' pager.glyphs['bot-left'] = u'' pager.glyphs['left-vert'] = u'' pager.glyphs['right-vert'] = u'' prompt_ole = u'write an oneliner?' pager.update(u'\n\n\nFetching ...') echo(u''.join(( pager.refresh(), pager.border(), term.move(selector.yloc - 2, selector.xloc), term.bold_red(prompt_ole.center(selector.width).rstrip()), term.clear_eol, selector.refresh(),))) pager.update(u'\n'.join(get_oltxt())) pager.move_end() echo(pager.refresh())
def describe(sessions): """ Returns unicode string suitable for describing the activity of session id's of array ``sessions``. """ from x84.bbs import getsession, getterminal, ini slen = lambda sessions: len(u'%d' % (len(sessions), )) session, term = getsession(), getterminal() max_user = ini.CFG.getint('nua', 'max_user') text = u'\r\n'.join(([ u''.join(( term.move_x(max(0, (term.width / 2) - 40)), term.green, u'%*d' % (5 + slen(sessions), node), u' ' * 7, term.normal, u'%4is' % (attrs.get('idle', 0), ), u' ', u' ' * 8, (term.bold_red(u'%-*s' % ( max_user, (u'** diSCONNECtEd' if 'delete' in attrs else attrs.get( 'handle', u'** CONNECtiNG')), )) if attrs.get('handle', u'') != session.user.handle else term.red(u'%-*s' % (max_user, session.user.handle))), term.green(u' '), term.yellow((attrs.get('activity', u'')) if attrs.get('sid') != session.sid else term.yellow(session.activity)), )) for node, (_, attrs) in get_nodes(sessions) ])) return text + '\r\n'
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()
def prompt(): """ Return string suitable for displaying prompt and available commands. """ from x84.bbs import getsession, getterminal session, term = getsession(), getterminal() decorate = lambda key, desc: u''.join(( u'(', term.magenta_underline(key, ), u')', term.cyan(desc.split()[0]), u' ', u' '.join(desc.split()[1:]), u' ', )) return term.wrap(u''.join(( u' ' * 2, term.green_reverse(':keys'), u' ', decorate('c', 'hAt USR'), decorate('s', 'ENd MSG'), (u''.join(( decorate('d', 'iSCONNECt SiD'), decorate('e', 'diT USR'), decorate('v', 'iEW SiD AttRS'), u' ', )) if 'sysop' in session.user.groups else u''), decorate('Escape/q', 'Uit'), decorate('Spacebar', 'REfRESh'), )), int(term.width * .8), subsequent_indent=u' ' * 8)
def displayfile(filename): term = getterminal() echo(term.clear + term.move(0, 0) + term.normal) text = {} counter = 0 offset = 0 keypressed = '' # the string array named text will be zerobased for line in showart(filename): text[counter] = line counter = counter + 1 while True: echo(term.move(0, 0) + term.normal) # -2 om man vill spara en rad i botten for i in range(0, term.height - 1): if len(text) > i + offset: echo(term.clear_eol + u'\r' + text[i + offset]) keypressed = getch() echo(term.hide_cursor) if keypressed == 'q' or keypressed == 'Q' or keypressed == term.KEY_ESCAPE or keypressed == term.KEY_ENTER: break if keypressed == term.KEY_HOME: offset = 0 if keypressed == term.KEY_END: # if the textline has fewer lines than the screen.. if len(text) < term.height: offset = 0 else: offset = len(text) - term.height + 1 if keypressed == term.KEY_DOWN: # offset < len(text) + term.height: if len(text) > offset + term.height - 1: offset = offset + 1 if keypressed == term.KEY_UP: if offset > 0: offset = offset - 1 if keypressed == term.KEY_LEFT or keypressed == term.KEY_PGUP: if offset > term.height: offset = offset - term.height + 2 else: offset = 0 if keypressed == term.KEY_RIGHT or keypressed == term.KEY_PGDOWN: if (offset + term.height * 2) - 1 < len(text): offset = offset + term.height - 2 else: # if the textline has fewer lines than the screen.. if len(text) < term.height: offset = 0 else: offset = len(text) - term.height + 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 set_password(user): """ Prompt for user.password, minimum length. """ # pylint: disable=R0914 # Too many local variables from x84.bbs import getterminal, echo, ini, LineEditor term = getterminal() hidden_ch = u'x' prompt_password = u'password: '******' again: ' msg_empty = u'ENtER A PASSWORd!' msg_tooshort = u'TOO ShORt, MUSt bE At lEASt %s.' msg_unmatched = u'VERifY MUSt MAtCH!' width = ini.CFG.getint('nua', 'max_pass') min_pass = ini.CFG.getint('nua', 'min_pass') while True: echo(u'\r\n\r\n' + term.clear_eol + term.normal + prompt_password) led = LineEditor(width) led.hidden = hidden_ch password = led.read() if password == u'' or password is None: warning(msg_empty) elif len(password) < min_pass: warning(msg_tooshort % min_pass) else: echo(u'\r\n\r\n' + term.clear_eol + term.normal + prompt_verify) led = LineEditor(width) led.hidden = hidden_ch verify = led.read() if password != verify: warning(msg_unmatched) continue user.password = password return
def main(handle=u''): """ Main procedure. """ # pylint: disable=R0914 # Too many local variables from x84.bbs import getsession, getterminal, echo, ini, User, goto from x84.bbs import showcp437 session, term = getsession(), getterminal() import os session.activity = u'Applying for an account' artfile = os.path.join(os.path.dirname(__file__), 'art', 'nua.asc') msg_header = u'NEW USER APPliCAtiON' # pylint: disable=E1103 # Instance of '_Chainmap' has no 'split' member # (but some types could not be inferred) newcmds = ini.CFG.get('matrix', 'newcmds').split() topscript = ini.CFG.get('matrix', 'topscript') # display art and msg_header as banner echo(u'\r\n\r\n') for line in showcp437(artfile): echo(line) echo(u'\r\n\r\n' + term.reverse + msg_header.center(term.width)) # create new user record for manipulation user = User(handle if handle.lower() not in newcmds else u'') while True: set_handle(user) set_location(user) set_email(user) set_password(user) set_sacookies(user) if prompt_ok(): user.save() goto(topscript, user.handle)
def banner(): term = getterminal() banner = '' artfile = os.path.join(os.path.dirname(__file__), 'art', 'bulletins.ans') for line in showart(artfile, 'topaz'): banner = banner + line return banner
def get_centigrade(): """ Blocking prompt for setting C/F preference. """ from x84.bbs import getterminal, getsession, echo term = getterminal() session = getsession() if bool(session.user.handle == 'anonymous'): # anonymous cannot set a preference. return echo(u''.join(( u'\r\n\r\n', term.yellow(u'Celcius'), term.bold_yellow(u'('), term.bold_yellow_reverse(u'C'), term.bold_yellow(u')'), u' or ', term.yellow(u'Fahrenheit'), term.bold_yellow(u'('), term.bold_yellow_reverse(u'F'), term.bold_yellow(u')'), u'? '))) while True: inp = term.inkey() if inp in (u'c', u'C'): session.user['centigrade'] = True session.user.save() break elif inp in (u'f', u'F'): session.user['centigrade'] = False session.user.save() break elif inp in (u'q', u'Q', term.KEY_EXIT): break
def display_banner(filepattern, encoding=None, vertical_padding=0): """ Start new screen and show artwork, centered. :param filepattern: file to display :type filepattern: str :param encoding: encoding of art file(s). :type encoding: str or None :param vertical_padding: number of blank lines to prefix art :type vertical_padding: int :returns: number of lines displayed :rtype: int """ term = getterminal() # move to bottom of screen, reset attribute echo(term.pos(term.height) + term.normal) # create a new, empty screen echo(u'\r\n' * (term.height + 1)) # move to home, insert vertical padding echo(term.home + (u'\r\n' * vertical_padding)) # show art art_generator = showart(filepattern, encoding=encoding, auto_mode=False, center=True) line_no = 0 for line_no, txt in enumerate(art_generator): echo(txt) # return line number return line_no + vertical_padding
def get_centigrade(): """ Blocking prompt for setting C/F preference """ from x84.bbs import getterminal, getsession, echo, getch term = getterminal() session = getsession() echo(u'\r\n\r\n') echo(term.yellow(u'CElCiUS')) echo(term.bold_yellow(u'(')) echo(term.bold_yellow_reverse(u'C')) echo(term.bold_yellow(u')')) echo(u' or ') echo(term.yellow(u'fAhRENhEit')) echo(term.bold_yellow(u'(')) echo(term.bold_yellow_reverse(u'F')) echo(term.bold_yellow(u')')) echo('? ') while True: inp = getch() if inp in (u'c', u'C'): session.user['centigrade'] = True session.user.save() break elif inp in (u'f', u'F'): session.user['centigrade'] = False session.user.save() break elif inp in (u'q', u'Q', term.KEY_EXIT): break
def get_centigrade(): """ Blocking prompt for setting C/F preference. """ from x84.bbs import getterminal, getsession, echo term = getterminal() session = getsession() if bool(session.user.handle == 'anonymous'): # anonymous cannot set a preference. return echo(u''.join( (u'\r\n\r\n', term.yellow(u'Celcius'), term.bold_yellow(u'('), term.bold_yellow_reverse(u'C'), term.bold_yellow(u')'), u' or ', term.yellow(u'Fahrenheit'), term.bold_yellow(u'('), term.bold_yellow_reverse(u'F'), term.bold_yellow(u')'), u'? '))) while True: inp = term.inkey() if inp in (u'c', u'C'): session.user['centigrade'] = True session.user.save() break elif inp in (u'f', u'F'): session.user['centigrade'] = False session.user.save() break elif inp in (u'q', u'Q', term.KEY_EXIT): break
def chk_save_location(location): """ Prompt user to save location for quick re-use """ from x84.bbs import getterminal, getsession, echo, getch session, term = getsession(), getterminal() stored_location = session.user.get('location', dict()).items() if (sorted(location.items()) == sorted(stored_location)): return # prompt to store (unsaved/changed) location echo(u'\r\n\r\n') echo(term.yellow(u'SAVE lOCAtION')) echo(term.bold_yellow(' (')) echo(term.bold_black(u'PRiVAtE')) echo(term.bold_yellow(') ')) echo(term.yellow('? ')) echo(term.bold_yellow(u'[')) echo(term.underline_yellow(u'yn')) echo(term.bold_yellow(u']')) echo(u': ') while True: inp = getch() if inp is None or inp in (u'n', u'N', u'q', u'Q', term.KEY_EXIT): break if inp in (u'y', u'Y', u' ', term.KEY_ENTER): session.user['location'] = location break
def disp_msg(msg): """ Display unicode string ``msg`` in yellow. """ from x84.bbs import getterminal, echo term = getterminal() msg = term.bold_yellow(msg) dotdot = term.yellow_reverse_bold(u'...') echo(u'\r\n\r\n{msg} {dotdot}'.format(msg=msg, dotdot=dotdot))
def set_lbcontent(lightbar, ucs): """ Sets content of Lightbar instance, ``lightbar`` for given Unicode string, ``ucs``. """ # a custom 'soft newline' versus 'hard newline' is implemented, # '\n' == 'soft', '\r\n' == 'hard' term = getterminal() content = dict() lno = 0 lines = ucs.split(HARDWRAP) for idx, ucs_line in enumerate(lines): if idx == len(lines) - 1 and 0 == len(ucs_line): continue ucs_joined = WHITESPACE.join(ucs_line.split(SOFTWRAP)) ucs_wrapped = term.wrap(text=ucs_joined, width=lightbar.visible_width) for inner_lno, inner_line in enumerate(ucs_wrapped): softwrap = SOFTWRAP if inner_lno != len(ucs_wrapped) - 1 else u'' content[lno] = u''.join((inner_line, softwrap)) lno += 1 if 0 == len(ucs_wrapped): content[lno] = HARDWRAP lno += 1 else: content[lno - 1] += HARDWRAP if 0 == len(content): content[0] = HARDWRAP lightbar.update(sorted(content.items()))