def do_select_encoding(term, session): editor_colors = {'highlight': term.black_on_green} dirty = True while True: if session.poll_event('refresh') or dirty: # attempt to coerce encoding of terminal to match session. coerce_terminal_encoding(term, session.encoding) # display artwork and prompt vertical_padding = 2 if term.height >= 24 else 0 display_banner(filepattern=art_file, encoding=art_encoding, vertical_padding=vertical_padding) display_prompt(term) dirty = False inp = LineEditor(1, colors=editor_colors).read() if inp is None or inp.lower() == 'd': break elif len(inp): # bad input -- reposition cursor for next LineEditor() echo(u'\b') if inp.lower() == u'u' and session.encoding != 'utf8': # switch to utf8, session.encoding = 'utf8' dirty = True elif inp.lower() == 'c' and session.encoding != 'cp437': # or cp437 session.encoding = 'cp437' dirty = True
def disp_forecast(forecast): """ Display weather forecast. """ from x84.bbs import getterminal, echo, Ansi, getch term = getterminal() lno = 1 echo(u'\r\n') for key in sorted(forecast.keys()): fcast = forecast[key] rstr = u''.join(( term.bold_yellow_underline(fcast['DayCode']), u', ', u'/'.join(fcast['ObsDate'].split('/', 3)[0:2]), term.bold_underline(u':'), u' ', u'%s. ' % ( term.bold( fcast.get('TXT_Long', fcast.get('TXT_Short', u''))),), u'hiGH Of %sF, lOW Of %sF. ' % ( term.bold(fcast.get('High_Temperature')), term.bold(fcast.get('Low_Temperature')),),)) if 0.0 != float(fcast.get('Snow_Amount', '0.0')): rstr += u'SNOW AMOUNt %s iN., ' % ( term.yellow(fcast.get('Snow_Amount')),) if 0.0 != float(fcast.get('Rain_Amount', '0.0')): rstr += u'RAiN AMOUNt %s iN., ' % ( term.yellow(fcast.get('Snow_Amount')),) if 0.0 != float(fcast.get('Precip_Amount', '0.0')): rstr += u'PRECiPiTAtiON %s iN., ' % ( term.yellow(fcast.get('Precip_Amount')),) if 0 != int(fcast.get('TStorm_Prob', '0')): rstr += u'thUNdERStORM PRObAbilitY: %s, ' % ( term.yellow(fcast.get('TStorm_Prob')),) if 0 != len(fcast.get('WindDirection', u'')): rstr += u'WiNdS %s ' % ( term.yellow(fcast.get('WindDirection')),) if 0 != len(fcast.get('WindSpeed', u'')): rstr += u'At %sMPh, ' % ( term.yellow(fcast.get('WindSpeed')),) if 0 != len(fcast.get('WindGust', u'')): rstr += u'GUStS Of %sMPh. ' % ( term.yellow(fcast.get('WindGust')),) if 0 != len(fcast.get('Real_Feel_High', u'')): rstr += u'PROdUCiNG ' if 0 != len(fcast.get('Real_Feel_High', u'')): rstr += u'A WiNdCHill HiGh Of %sF, lOW %sF. ' % ( term.yellow( fcast.get('Real_Feel_High')), term.yellow( fcast.get('Real_Feel_Low', u'?')),) echo(u'\r\n') lno += 1 lines = Ansi(rstr).wrap(min(60, int(term.width * .8))).splitlines() for line in lines: lno += 1 echo(line + u'\r\n') if 0 == lno % (term.height - 1): echo(term.yellow_reverse('--MORE--')) if getch() is None: return False echo(u'\r\n')
def do_fetch(postal): """ Given postal code, fetch and return xml root node of weather results. """ from x84.bbs import echo, getch, getterminal import StringIO term = getterminal() disp_msg('fEtChiNG') resp = requests.get(u'http://apple.accuweather.com' + u'/adcbin/apple/Apple_Weather_Data.asp', params=(('zipcode', postal),)) if resp is None: disp_notfound() return None if resp.status_code != 200: # todo: logger.error echo(u'\r\n') echo(term.bold_red(u'StAtUS COdE: %s' % (resp.status_code,))) echo(u'\r\n\r\n') echo(repr(resp.content)) echo(u'\r\n\r\n' + 'PRESS ANY kEY') getch() return None xml_stream = StringIO.StringIO(resp.content) tree = ET.parse(xml_stream) return tree.getroot()
def main(handle=None): """ Main procedure. """ # pylint: disable=R0914,R0912,R0915 # Too many local variables # Too many branches # Too many statements session, term = getsession(), getterminal() session.activity = 'top' # attempt to coerce encoding of terminal to match session. coerce_terminal_encoding(term, session.encoding) # fetch user record user = get_user_record(handle) # register call login(session, user) # display art and prompt for quick login quick = do_intro_art(term, session) echo(term.move_down() * 3) # only display news if the account has not # yet read the news since last update. gosub('news', quick=True) if not quick: # display last 10 callers, if any gosub('lc') # one-liners gosub('ol') goto('main')
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)
def try_pass(user): """ Prompt for password and authenticate, returns True if succesfull. """ # pylint: disable=R0914 # Too many local variables from x84.bbs import getsession, getterminal, ini, LineEditor, echo session, term = getsession(), getterminal() prompt_pass = u'\r\n\r\n pass: '******'\r\n\r\n ' + term.yellow_reverse(u"Encrypting ..") badpass_msg = (u'\r\n\r\n' + term.red_reverse + u"'%s' login failed." + term.normal) max_pass = int(ini.CFG.get('nua', 'max_pass')) # prompt for password, disable input tap during, mask input with 'x', # and authenticate against user record, performing a script change to # topscript if sucessful. # pylint: disable=W0212 # Access to a protected member _tap_input of a client class echo(prompt_pass) chk = session._tap_input # <-- save session._tap_input = False lne = LineEditor(max_pass) lne.hidden = u'x' password = lne.read() session._tap_input = chk # restore --> if password is not None and 0 != len(password): echo(status_auth) if user.auth(password): return True denied(badpass_msg % (user.handle,)) return False
def get_article(term, articles): """ Prompt for an article number, return matching article. """ moveto_lastline = term.move(term.height, 0) width = term.width if term.kind.startswith('ansi'): # bah syncterm moveto_lastline = term.move(term.height - 1, 0) width -= 1 echo(u''.join(( moveto_lastline + getattr(term, COLOR_MAIN), term.center('', width), moveto_lastline, ))) echo(u':: enter article #: ') article_idx = LineEditor( width=len(str(ARTICLE_LIMIT)), colors={'highlight': getattr(term, COLOR_MAIN)} ).read() if article_idx is None: # pressed escape return None try: return articles[int(article_idx) - 1] except (ValueError, IndexError): # not an integer, or out of range return None
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 send_passkey(user): """ Send passkey token to user by e-mail. """ session = getsession() passkey = base64.encodestring(os.urandom(50))[:password_max_length] email_msg = MIMEText( msg_mailbody.format(bbsname=system_bbsname, session=session, user=user, passkey=passkey)) email_msg['From'] = msg_mailfrom email_msg['To'] = user.email email_msg['Subject'] = msg_mailsubj.format(bbsname=system_bbsname) try: smtp = smtplib.SMTP(mail_smtphost) smtp.sendmail(msg_mailfrom, [user.email], email_msg.as_string()) smtp.quit() except Exception as err: log.exception(err) echo(u'{0}'.format(err)) return False log.info(u'Password reset token delivered ' u'to address {0!r} for user {1!r}.'.format( user.email, user.handle)) return passkey
def drawfieldbig(): lastcolor = '' for y in range(0, field_height): gotoxy(field_width, 2 + y) for x in range(field_width): lastcolor = plotblock(field[y][x], lastcolor) echo(term.normal)
def dummy_pager(news_txt): """ Given news_txt as unicode string, display using a dummy pager. """ from x84.bbs import getterminal, echo, getch term = getterminal() prompt_msg = u'\r\n[%s]ontinue, [%s]top, [%s]on-stop ?\b\b' % ( term.bold_blue('c'), term.bold_blue('s'), term.bold_blue('n'), ) nonstop = False echo(redraw(None)) for row in range(len(news_txt)): echo(news_txt[row].rstrip() + '\r\n') if not nonstop and row > 0 and 0 == (row % (term.height - 3)): echo(prompt_msg) inp = getch() if inp in (u's', u'S', u'q', u'Q', term.KEY_EXIT): return if inp in ('n', u'N'): nonstop = True echo(u'\r\n') echo('\r\npress any key .. ') getch() return
def try_pass(user): """ Prompt for password and authenticate, returns True if succesfull. """ # pylint: disable=R0914 # Too many local variables from x84.bbs import getsession, getterminal, ini, LineEditor, echo session, term = getsession(), getterminal() prompt_pass = u'pass: '******'\r\n\r\n ' + term.yellow_reverse(u"Encrypting ..") badpass_msg = (u'\r\n\r\n' + term.red_reverse + u"'%s' login failed." + term.normal) max_pass = int(ini.CFG.get('nua', 'max_pass')) # prompt for password, disable input tap during, mask input with 'x', # and authenticate against user record, performing a script change to # topscript if sucessful. # pylint: disable=W0212 # Access to a protected member _tap_input of a client class echo(term.move(term.height, max_pass + 10) + prompt_pass) chk = session._tap_input # <-- save session._tap_input = False lne = LineEditor(max_pass) lne.hidden = u'x' password = lne.read() session._tap_input = chk # restore --> if password is not None and 0 != len(password): echo(status_auth) if user.auth(password): return True denied(badpass_msg % (user.handle, )) return False
def send_passkey(user): """ Send passkey token to user by e-mail. """ session = getsession() passkey = base64.encodestring(os.urandom(50))[:password_max_length] email_msg = MIMEText(msg_mailbody.format(bbsname=system_bbsname, session=session, user=user, passkey=passkey)) email_msg['From'] = msg_mailfrom email_msg['To'] = user.email email_msg['Subject'] = msg_mailsubj.format(bbsname=system_bbsname) try: smtp = smtplib.SMTP(mail_smtphost) smtp.sendmail(msg_mailfrom, [user.email], email_msg.as_string()) smtp.quit() except Exception as err: log.exception(err) echo('{0}'.format(err)) return False log.info(u'Password reset token delivered ' u'to address {0!r} for user {1!r}.' .format(user.email, user.handle)) return passkey
def describe_ssh_availability(term, session): from x84.bbs.ini import CFG if session.kind == 'ssh': # what a good citizen! return if not (CFG.has_section('ssh') and not CFG.has_option('ssh', 'enabled') or CFG.getboolean('ssh', 'enabled')): # ssh not enabled return about_key = (u"You may even use an ssh key, which you can configure from " u"your user profile, " if not session.user.get('pubkey') else u'') big_msg = term.bold_blue("Big Brother is Watching You") description = ( " {term.red}You are using {session.kind}, but ssh is available " "on port {ssh_port} of this server. If you want a secure connection " "with shorter latency, we recommend instead to use ssh! {about_key}" "Remember: {big_msg}!" .format(term=term, session=session, ssh_port=ssh_port, about_key=about_key, big_msg=big_msg) ) echo(u'\r\n\r\n') for txt in term.wrap(description, width=min(80, term.width)): echo(term.move_x(max(0, (term.width // 2) - 40))) echo(term.red(txt.rstrip() + '\r\n')) echo(u'\r\n\r\n') echo(term.center(term.bold_black('Press any key to continue: ')).rstrip()) term.inkey()
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 do_send_message(session, term, msg, colors): xpos = max(0, (term.width // 2) - (80 // 2)) msg.save() do_mark_as_read(session, [msg.idx]) echo(u''.join( (u'\r\n', term.move_x(xpos), colors['highlight']('message sent!')))) term.inkey(1)
def pak(): """ Press any key prompt. """ from x84.bbs import echo, getch msg_pak = u'PRESS ANY kEY' echo(u'\r\n%s ... ' % (msg_pak,)) getch() return
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 clear_diz(term): """ Clear file_id.diz area. """ echo(term.move(1, browser.diz_location)) # +2 for info line (filename, size) and empty line below it for i in range(browser.last_diz_len + 2): echo(u''.join(( term.move(i, browser.diz_location), term.clear_eol)))
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 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 disp_msg(msg): """ Display unicode string ``msg`` in yellow. """ from x84.bbs import getterminal, echo term = getterminal() echo(u''.join((u'\r\n\r\n', term.bold_yellow('%s ' % (msg,),), term.yellow_reverse_bold(u'...'),)))
def main(): """ main entry point. """ from x84.bbs import getterminal, getsession, echo session, term = getsession(), getterminal() session.activity = 'looking for a place to drink at' # 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)) while True: disp_search_help() search = get_city() if search is None or 0 == len(search): return item = do_get_random_item(search) display_suggestion(item) while True: # allow re-displaying weather between C/F, even at EOT prompt inp = term.inkey() if inp.lower() == cf_key: get_centigrade() break elif inp.code == term.KEY_ENTER: return
def disp_weather(weather): """ Display today's weather. """ from x84.bbs import getterminal, echo, Ansi term = getterminal() rstr = u''.join((u'At ', term.bold(u'%s%s' % (weather.get('City'), u', %s' % (weather['State'],) if ('State' in weather and 0 != len(weather['State'])) else u'',)), term.underline(u':'), u' ', u'%s. ' % ( term.bold_yellow(weather.get('WeatherText')),), u'tEMPERAtURE Of %sF, ' % ( term.bold(weather.get('Temperature')),), u'RElAtiVE hUMiditY %s. ' % ( term.yellow(weather.get('Humidity')),), u'WiNdS %s At %s MPh' % ( term.yellow(weather.get('WindDirection')), term.yellow(weather.get('WindSpeed'))), u', PROdUCiNG A WiNdCHill Of %sF. ' % ( term.yellow(weather.get('RealFeel')),) if (weather.get('RealFeel', weather.get('Temperature')) != weather.get('Temperature')) else u'. ', u'ThE PRESSURE WAS %s iNChES ANd %s.' % ( term.yellow(weather.get('Pressure')), term.yellow(weather.get('Pressure-state')), ),)) echo(u'\r\n\r\n') echo(Ansi(rstr).wrap(min(60, int(term.width * .8))))
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
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 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 refresh(): """ Refresh screen and return top-left (x, y) location. """ # set syncterm font to cp437 if term.kind.startswith('ansi'): echo(syncterm_setfont('cp437')) echo(u'\r\n\r\n') if term.width < width: echo(u''.join(( term.move(term.height, 0), u'\r\n\r\n', term.bold_red + 'screen too thin! (%s/%s)' % ( term.width, width,), u'\r\n\r\n', u'press any key...',))) getch() return (None, None) if term.height < height: echo(u''.join(( term.move(term.height, 0), u'\r\n\r\n', term.bold_red + 'screen too short! (%s/%s)' % ( term.height, height), u'\r\n\r\n', u'press any key...',))) getch() return (None, None) xloc = (term.width / 2) - (width / 2) yloc = (term.height / 2) - (height / 2) echo(u''.join(( term.normal, (u'\r\n' + term.clear_eol) * term.height, u''.join([term.move(yloc + abs_y, xloc) + line for abs_y, line in enumerate(otxt)]),))) return xloc, yloc
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
def prompt_input(term, key, sep_ok=u'::', width=None, colors=None): """ Prompt for and return input, up to given width and colorscheme. """ colors = colors or {'highlight': term.yellow} sep_ok = colors['highlight'](sep_ok) echo(u'{sep} {key:<8}: '.format(sep=sep_ok, key=key)) return LineEditor(colors=colors, width=width).read() or u''
def draw_star(star, xloc, yloc): """ draw star a (x, y) location """ char = char_at_pos(int(yloc), int(xloc), txt_y, txt_x) if char != ' ': melting[(int(yloc), int(xloc))] = len(melt_colors) if show_star: echo(term.move(int(yloc), int(xloc)) + melt_colors[-1] + star)
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 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 show_description(term, description, color='white', width=80, **kwargs): """ Display text as given ``color``, left-adjusted ``width``. :param str description: description text, may contain terminal attributes, in which case ``color`` should be set to None. :param str color: terminal color attribute name, may be None. :param int width: left-adjusted width, if this is greater than the current terminal's width, the terminal's width is used instead. :param kwargs: all remaining keyword arguments are passed to the built-in :class:`textwrap.TextWrapper`. :rtype: int :returns: number if lines written """ wide = min(width, term.width) xpos = max(0, (term.width // 2) - (wide // 2)) lines = [] for line in unicode(description).splitlines(): if line.strip(): lines.extend(term.wrap(line, wide, **kwargs)) else: lines.append(u'') # output as a single string, reducing latency outp = u''.join( [getattr(term, color) if color else u''] + [u''.join(( term.move_x(xpos) if xpos else u'', txt.rstrip(), term.clear_eol, u'\r\n')) for txt in lines]) echo(outp) return len(outp.splitlines())
def describe_file(term, diz, directory, filename, isdir=None): """ Describe a file in the diz area """ if isdir or filename == u'..{0}'.format(os.path.sep): # describe directory description = u'{txt_Directory}: {filename}'.format( txt_Directory=term.bold(u'Directory'), filename=filename.decode('utf8')) else: # describe file _size = filesize(os.path.join(directory, filename)) _filename = (filename[len(ROOT):].decode('utf8') if directory == os.path.join(ROOT, FLAGGED_DIRNAME) else filename.decode('utf8')) description = (u'{txt_Filename}: {filename} {txt_Size}: {size}' .format(txt_Filename=term.bold(u'Filename'), filename=_filename, txt_Size=term.bold(u'Size'), size=_size)) echo(u''.join((term.move(1, browser.diz_location), description, term.move(3, browser.diz_location)))) wrapped_diz = [] for line in diz[:browser.max_diz_height]: wrapped_diz += term.wrap(line, browser.max_diz_width) output = u'' for line in wrapped_diz: browser.last_diz_len += 1 output = u''.join( (output, term.move_x(browser.diz_location), line, u'\r\n')) echo(output)
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 recv_input(term, editors, edit_idx, inp): nextline = False editor = editors[edit_idx] # position cursor echo(editor.fixate()) if inp.is_sequence: echo(editor.process_keystroke(inp.code)) else: echo(editor.process_keystroke(inp)) # return pressed or at margin (bell) nextline = (editor.carriage_returned or editor.bell) if nextline: edit_idx = (0 if edit_idx == len(editors) - 1 else edit_idx + 1) editor = editors[edit_idx] editor.update(u'') echo(editor.refresh()) echo(editor.fixate()) return editors, edit_idx
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 delete_user(term, tgt_user, point): """ Delete given user. You may delete yourself. """ _color1, _color2 = [ getattr(term, _color) for _color in (color_lowlight, color_highlight) ] lb, rb, colon = _color1('['), _color1(']'), _color1(':') echo(term.move(*point)) echo(u'Delete {handle} {lb}yN{rb}{colon}{clear_eos} ?\b\b'.format( handle=_color2(tgt_user.handle), rb=rb, lb=lb, colon=colon, clear_eos=term.clear_eos)) inp = term.inkey() echo(inp + term.move(point.y + 2, point.x)) if inp == u'y': if tgt_user.handle != 'anonymous': tgt_user.delete() echo(_color2('Deleted !')) time.sleep(1) return True echo(_color2('Canceled !')) time.sleep(1) return False
def waitprompt(term): """ Display simple "press enter to continue prompt". """ echo(u''.join( (term.normal, '\r\n', term.move_x(max(0, (term.width // 2) - 40)), term.magenta('('), term.green('..'), 'press any key to continue', term.green('..'), term.magenta(')')))) term.inkey() return