def set_subscription_tags(session, term): """ This function is called to assign a new set of subscription tags for a user. If escape is pressed, the existing value is used, or '*' is used if not previously set. This should be called for first-time users, and optionally at any later time to change a subscription. """ line_no = display_banner(art_file, encoding=art_encoding) # introduce the user to the concept ... description = ( u"{term.yellow}You can think of tags as a system of providing " u"context to any message stored on this system. A tag might signify " u"that it was received on a particular message network, or it might " u"provide the topic of conversation, such as " u"{term.bold_yellow}python{term.normal}{term.yellow} or " u"{term.bold_yellow}rock music{term.normal}{term.yellow}. " u"This is similar to flicker's tags, or twitter hashtags. " u"Use glob expressions as a comma-delimited list, for example, " u"the expression {term.bold_yellow}x84net{term.normal}{term.yellow}, " u"{term.bold_yellow}sysop{term.normal}{term.yellow}, " u"{term.bold_yellow}python*{term.normal}{term.yellow} " u"will subscribe to all tags of the x84net message network, " u"sysop messages, and any topics that begin with the phrase " u"{term.bold_yellow}python{term.normal}{term.yellow}. You can " u"subscribe to all topics using the expression, " u"{term.bold_yellow}*{term.normal}{term.yellow}.".format(term=term) ) echo(u"\r\n") line_no += 1 line_no += show_description(description, color=None) description = u" ".join( [u"tags available:"] + ["{tag}{term.yellow},{term.normal}".format(tag=tag, term=term) for tag in list_tags()] ) echo(u"\r\n\r\n") line_no += 2 # display our prompt prefix, input_prefix: input_prefix = u" {sep} {key:>18}: ".format(sep=term.bright_yellow(u"::"), key="subscription tags") echo(input_prefix) xloc = term.length(input_prefix) # and prompt an editor on that row editor = ScrollingEditor( xloc=xloc, yloc=line_no, width=(term.width - xloc - 2), colors={"highlight": term.black_on_yellow} ) value = editor.read() or u"" echo(term.normal + u"\r\n\r\n") return map(unicode.strip, value.split(","))
def get_inputbar(pager): """ Return ScrollingEditor for use as inputbar. """ from x84.bbs import getterminal, ScrollingEditor term = getterminal() width = pager.visible_width - 2 yloc = (pager.yloc + pager.height) - 2 xloc = pager.xloc + 2 ibar = ScrollingEditor(width, yloc, xloc) ibar.enable_scrolling = True ibar.max_length = 512 ibar.colors['highlight'] = term.cyan_reverse return ibar
def get_inputbar(pager): """ Return ScrollingEditor for use as inputbar. """ from x84.bbs import getterminal, ScrollingEditor term = getterminal() width = pager.visible_width - 2 yloc = (pager.yloc + pager.height) - 2 xloc = pager.xloc + 2 ibar = ScrollingEditor(width=width, yloc=yloc, xloc=xloc) ibar.enable_scrolling = True ibar.max_length = 512 ibar.colors['highlight'] = term.white_on_blue return ibar
def main(): """ x/84 script launch point """ term, session = getterminal(), getsession() session.activity = u'Chatting on IRC' # 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, set font echo(term.home) if SYNCTERM_FONT and term.kind.startswith('ansi'): echo(syncterm_setfont(SYNCTERM_FONT)) scrollback = collections.deque(maxlen=MAX_SCROLLBACK) client = establish_connection(term, session) if not client: return clean_up(term) # ignore "not in view" warning for AnsiWindow with warnings.catch_warnings(): warnings.simplefilter("ignore") editor = ScrollingEditor( width=term.width + 1, xloc=-1, yloc=term.height - 2, colors={'highlight': getattr(term, COLOR_INPUTBAR)}, max_length=MAX_INPUT ) # delete 'Connecting' message echo(u''.join([term.home, term.clear, editor.refresh()])) while True: client.reactor.process_once() event, data = session.read_events( ('irc-quit', 'irc', 'input', 'refresh'), timeout=0.1) if event == 'refresh': refresh_event(term, scrollback, editor) continue elif event == 'irc': irc_event(term, data, scrollback, editor) elif event == 'input': if not input_event(term, session, client, data, editor): break elif event == 'irc-quit': time.sleep(0.5) break client.connection.disconnect() clean_up(term)
def get_lneditor(lightbar): """ Returns editor positioned at location of current selection. """ term = getterminal() width = min(80, max(term.width, 40)) yloc = (lightbar.yloc + lightbar.ypadding + lightbar.position[0] - 1) xloc = max(0, (term.width / 2) - (width / 2)) lneditor = ScrollingEditor(width=width, yloc=yloc, xloc=xloc) lneditor.enable_scrolling = True lneditor.max_length = 65534 lneditor.glyphs['bot-horiz'] = u'' lneditor.glyphs['top-horiz'] = u'' lneditor.colors['highlight'] = term.red_reverse lneditor.colors['border'] = term.bold_red # converts u'xxxxxx\r\n' to 'xxxxxx', # or 'zzzz\nxxxxxx\n' to u'zzzz xxxxxx', lneditor.update(softwrap_join(wrap_rstrip(lightbar.selection[1]))) return lneditor
def main(): """ x/84 script launch point """ term, session = getterminal(), getsession() session.activity = u'Chatting on IRC' session.flush_event('irc') # 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)) echo(term.home + term.clear) # set font if SYNCTERM_FONT and term.kind.startswith('ansi'): echo(syncterm_setfont(SYNCTERM_FONT)) try: client, scrollback = establish_connection(term, session) except EOFError: # connection failed, return clean_up(term) # ignore "not in view" warning for AnsiWindow with warnings.catch_warnings(): warnings.simplefilter("ignore") editor = ScrollingEditor( width=term.width + 1, xloc=-1, yloc=term.height, colors={'highlight': getattr(term, COLOR_INPUTBAR)}, max_length=MAX_INPUT ) refresh_event(term, scrollback, editor) while True: client.reactor.process_once() event, data = session.read_events( ('irc-quit', 'irc', 'input', 'refresh'), timeout=0.1) if event == 'refresh': refresh_event(term, scrollback, editor) continue elif event == 'irc': irc_event(term, data, scrollback, editor) elif event == 'input': session.buffer_input(data, pushback=True) if not input_event(term, client, editor): break elif event == 'irc-quit': time.sleep(0.5) break client.connection.disconnect() clean_up(term)
def make_editor_series(winsize, editors): colors = {'highlight': u''} # prevent horizontal scrolling prior to final column margin_pct = 100 - (100 / (winsize.width - 3)) # scroll at final column scroll_pct = 100 / (winsize.width - 3) return [ ScrollingEditor( yloc=_yloc, xloc=winsize.xloc, width=winsize.width, colors=colors, margin_pct=margin_pct, scroll_pct=scroll_pct, content=(u'' if not editors or _idx >= len(editors) else editors[_idx].content), max_length=winsize.width ) for _idx, _yloc in enumerate(range( winsize.yloc, winsize.yloc + winsize.height + -2))]
def do_command(term, session, inp, fields, tgt_user, point): """ Perform action by given input. """ _color1, _color2, _color3 = [ getattr(term, _color) for _color in (color_lowlight, color_highlight, color_field_edit) ] # discover edit field by matching command key field_name = None for _fname, field in fields.items(): if field.key == inp.lower(): field_name = _fname break if field_name is None: # return False if no field matches this key return False # only 'sysop' may edit user groups if field_name == 'groups' and not session.user.is_sysop: return False # pylint: disable=W0631 # Using possibly undefined loop variable 'field' # TODO: we could probably stand to do a bit of a better job of detecting # screen resizes and providing ^L full-screen refresh during the remainder # of this procedure ... It would require quite the refactor, though. # special case; ssh public keys and groups use scrolling editor if field_name in ('pubkey', 'groups'): editor = ScrollingEditor( # issue #161; because of a 'border' (that we don't draw), # y must be offset by 1 and height by 2. yloc=field.edit_location.y - 1, xloc=field.edit_location.x - 1, width=field.width + 2, colors={'highlight': _color3}) # limit input to 1K editor.max_length = 1024 else: editor = LineEditor(field.width, colors={'highlight': _color3}) # find width for displaying description text and validation errors width = term.width - (point.x * 2) # show field description and cancellation description = (field.description or u'') + ' Press escape to cancel.' description_text = term.wrap(description, width=width) for y_offset, txt in enumerate(description_text): echo(term.move(point.y + y_offset, point.x)) echo(_color1(txt) + term.clear_eol) echo(term.clear_eos) # edit input field (occludes display field). echo(term.move(*field.edit_location)) inp = editor.read() if inp is None: # escape was pressed echo(term.move(*point)) echo(_color2('Canceled !') + term.clear_eos) time.sleep(1) return True else: # validate input if field.validate_fn is not None: errmsg, _ = field.validate_fn(tgt_user, inp) if errmsg: # failed validation, display validation error errmsg += ' Press any key.' for y_offset, txt in enumerate(term.wrap(errmsg, width=width)): echo(term.move(point.y + y_offset, point.x)) echo(_color2(txt) + term.clear_eol) echo(term.clear_eos) term.inkey() return True # well, it has validated, shall we apply it, then? if field_name in ( 'password', 'location', 'email', ): # except for anonymous, if tgt_user.handle != 'anonymous': setattr(tgt_user, field_name, inp) elif field_name in ( 'timeout', 'pubkey', ): if field_name == 'timeout': # coerce to integer, set, and if tgt_user is our current # user, then send new value for as engine event try: timeout_val = int(inp) except ValueError: return True if tgt_user.handle != 'anonymous': tgt_user[field_name] = timeout_val if tgt_user.handle == session.user.handle: session.send_event('set-timeout', timeout_val) elif field_name == 'pubkey': if tgt_user.handle != 'anonymous': tgt_user[field_name] = inp elif field_name in ('groups'): new_groups = set( filter(None, set(map(unicode.strip, inp.split(','))))) for old_grp in tgt_user.groups.copy(): if old_grp not in new_groups: tgt_user.group_del(old_grp) for new_grp in new_groups: if new_grp not in tgt_user.groups: tgt_user.group_add(new_grp) else: raise ValueError('unknown field name: {0}'.format(field_name)) if tgt_user.handle != 'anonymous': tgt_user.save() return True
def prompt_subscription(session, term, yloc, subscription, colors): """ This function is called to assign a new set of subscription tags for a user. If escape is pressed, the existing value is used, or '*' is used if not previously set. This should be called for first-time users, and optionally at any later time to change a subscription. """ if session.user.get('msg_subscription', None) is None: # force-display introductory description for first-time users. yloc += do_describe_message_system(term, colors) echo(u'\r\n\r\n') yloc += 2 # remind ourselves of all available tags yloc += do_describe_available_tags(term, colors) + 2 # for small screens, scroll and leave room for prompt & errors if yloc > term.height + 3: echo(u'\r\n' * 3) yloc = term.height - 3 # and prompt for setting of message tags xloc = max(0, (term.width // 2) - 40) input_prefix = u':: subscription tags:' echo(u''.join((term.move(yloc, xloc), input_prefix))) xloc += len(input_prefix) wide = min(40, (term.width - xloc - 2)) while True: editor = ScrollingEditor(xloc=xloc, yloc=yloc - 1, width=wide, colors={'highlight': colors['backlight']}, content=u', '.join(subscription), max_length=100) # Prompt for and evaluate the given input, splitting by comma, # removing any empty items, and defaulting to ['*'] on escape. inp = editor.read() or u'' subscription = filter(None, set(map(unicode.strip, inp.split(',')))) or set([u'*']) # Then, reduce to only validate tag patterns, tracking those # that do not match any known tags, and display a warning and # re-prompt if any are removed. removed, subscription = validate_tag_patterns(subscription) # clear existing warning, if any echo(u''.join((term.normal, u'\r\n\r\n', term.clear_eos))) if removed: # and display any unmatched tags as a warning, re-prompt txt = ''.join( (term.bold_red(u"The following patterns are not matched: "), u', '.join(removed))) show_description(term, txt, color=None) continue # otherwise everything is fine, # return new subscription set return subscription
def do_command(term, session, inp, fields, tgt_user, point): """ Perform action by given input. """ _color1, _color2, _color3 = [ getattr(term, _color) for _color in ( color_lowlight, color_highlight, color_field_edit)] # discover edit field by matching command key field_name = None for _fname, field in fields.items(): if field.key == inp.lower(): field_name = _fname break if field_name is None: # return False if no field matches this key return False # only 'sysop' may edit user groups if field_name == 'groups' and not session.user.is_sysop: return False # pylint: disable=W0631 # Using possibly undefined loop variable 'field' # TODO: we could probably stand to do a bit of a better job of detecting # screen resizes and providing ^L full-screen refresh during the remainder # of this procedure ... It would require quite the refactor, though. # special case; ssh public keys and groups use scrolling editor if field_name in ('pubkey', 'groups'): editor = ScrollingEditor( # issue #161; because of a 'border' (that we don't draw), # y must be offset by 1 and height by 2. yloc=field.edit_location.y - 1, xloc=field.edit_location.x - 1, width=field.width + 2, colors={'highlight': _color3}) # limit input to 1K editor.max_length = 1024 else: editor = LineEditor(field.width, colors={'highlight': _color3}) # find width for displaying description text and validation errors width = term.width - (point.x * 2) # show field description and cancellation description = (field.description or u'') + ' Press escape to cancel.' description_text = term.wrap(description, width=width) for y_offset, txt in enumerate(description_text): echo(term.move(point.y + y_offset, point.x)) echo(_color1(txt) + term.clear_eol) echo(term.clear_eos) # edit input field (occludes display field). echo(term.move(*field.edit_location)) inp = editor.read() if inp is None: # escape was pressed echo(term.move(*point)) echo(_color2('Canceled !') + term.clear_eos) time.sleep(1) return True else: # validate input if field.validate_fn is not None: errmsg, _ = field.validate_fn(tgt_user, inp) if errmsg: # failed validation, display validation error errmsg += ' Press any key.' for y_offset, txt in enumerate(term.wrap(errmsg, width=width)): echo(term.move(point.y + y_offset, point.x)) echo(_color2(txt) + term.clear_eol) echo(term.clear_eos) term.inkey() return True # well, it has validated, shall we apply it, then? if field_name in ('password', 'location', 'email',): # except for anonymous, if tgt_user.handle != 'anonymous': setattr(tgt_user, field_name, inp) elif field_name in ('timeout', 'pubkey',): if field_name == 'timeout': # coerce to integer, set, and if tgt_user is our current # user, then send new value for as engine event timeout_val = int(inp) if tgt_user.handle != 'anonymous': tgt_user[field_name] = timeout_val if tgt_user.handle == session.user.handle: session.send_event('set-timeout', timeout_val) elif field_name == 'pubkey': if tgt_user.handle != 'anonymous': tgt_user[field_name] = inp elif field_name in ('groups'): new_groups = set(filter(None, set(map(unicode.strip, inp.split(','))))) for old_grp in tgt_user.groups.copy(): if old_grp not in new_groups: tgt_user.group_del(old_grp) for new_grp in new_groups: if new_grp not in tgt_user.groups: tgt_user.group_add(new_grp) else: raise ValueError('unknown field name: {0}'.format(field_name)) if tgt_user.handle != 'anonymous': tgt_user.save() return True
def process_keystroke(inp, user): """ Process keystroke, ``inp``, for target ``user``. """ # pylint: disable=R0914,R0912,R0915,R0911,W0603 # Too many local variables # Too many branches # Too many statements # Too many return statements # Using the global statement # ^ lol, this is one of those things that should be # refactored into smaller subroutines =) from x84.bbs import getsession, getterminal, echo, getch, gosub from x84.bbs import LineEditor, ScrollingEditor from x84.default.nua import set_email, set_location from x84.bbs.ini import CFG def_timeout = CFG.getint('system', 'timeout') global EXIT session, term = getsession(), getterminal() is_self = bool(user.handle == session.user.handle) invalid = u'\r\niNVAlid.' assert is_self or 'sysop' in session.user.groups if is_self and inp in (u'c', u'C'): gosub('charset') elif is_self and inp in (u't', u'T'): echo(term.move(term.height - 1, 0)) echo(ABOUT_TERM + u'\r\n') echo(u'\r\ntERMiNAl tYPE: ') term = LineEditor(30, session.env.get('TERM')).read() echo(u"\r\n\r\nset TERM to '%s'? [yn]" % (term,)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): session.env['TERM'] = term break elif inp2 in (u'n', u'N'): break elif is_self and inp in (u'w', u'W'): echo(u'\r\ntERMiNAl Width: ') width = LineEditor(3, str(term.width)).read() try: width = int(width) except ValueError: echo(invalid) return True if width < 0 or width > 999: echo(invalid) return True echo(u"\r\n\r\nset COLUMNS=%d? [yn]" % (width,)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): term.columns = width break elif inp2 in (u'n', u'N'): break elif is_self and inp in (u'h', u'H'): echo(u'\r\ntERMiNAl hEiGht: ') height = LineEditor(3, str(term.height)).read() try: height = int(height) except ValueError: echo(invalid) return True if height < 0 or height > 999: echo(invalid) return True echo(u"\r\n\r\nset LINES=%d? [yn]" % (height,)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): term.rows = height break elif inp2 in (u'n', u'N'): break elif 'sysop' in session.user.groups and inp in (u'd', u'D',): echo(u"\r\n\r\ndElEtE %s ? [yn]" % (user.handle,)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): user.delete() break elif inp2 in (u'n', u'N'): break EXIT = True elif 'sysop' in session.user.groups and inp in (u's', u'S',): sysop = not 'sysop' in user.groups echo(u"\r\n\r\n%s SYSOP ACCESS? [yn]" % ( 'ENAblE' if sysop else 'diSAblE',)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): if sysop: user.groups.add('sysop') else: user.groups.remove('sysop') user.save() break elif inp2 in (u'n', u'N'): break elif inp in (u'p', u'P'): from x84.default.nua import set_password set_password(user) echo(u"\r\n\r\nSEt PASSWORd ? [yn]") while True: inp2 = getch() if inp2 in (u'y', u'Y'): user.save() break elif inp2 in (u'n', u'N'): break elif inp in (u'k', 'K',): change = True if user.get('pubkey', False): echo(u"\r\n\r\nSSh PUbliC kEY AlREAdY SEt, ChANGE ? [yn]") while True: inp2 = getch() if inp2 in (u'y', u'Y'): break elif inp2 in (u'n', u'N'): change = False break if change: echo(u"\r\n\r\njUSt PAStE iN YOUR PUbliC kEY, MAkE SURE itS " u"All iN ONE lINE!\r\n\r\n\r\n") editor = ScrollingEditor(width=term.width - 6, yloc=term.height - 3, xloc=3) echo(term.reverse_yellow) pubkey = editor.read() echo(term.normal) if pubkey is not None: if not pubkey.strip(): if user.get('pubkey', None): del user['pubkey'] echo(u'\r\n\r\nYOUR SECREtS ARE NEVER SAfE!\r\n') else: echo(u'\r\n\r\nWElCOME tO thE bROthERhOOd!\r\n') user['pubkey'] = pubkey user.save() getch(timeout=1.5) else: echo(u'\r\n\r\nCANCElEd!!\r\n') getch(timeout=0.5) elif inp in (u'.',): echo(term.move(0, 0) + term.normal + term.clear) echo(term.move(int(term.height * .8), 0)) for line in term.wrap(ABOUT_DOT_PLAN, term.width / 3): echo(line.center(term.width).rstrip() + u'\r\n') echo(u'\r\n\r\nPRESS ANY kEY ...') getch() if is_self: gosub('editor', '.plan') else: tmpkey = '%s-%s' % (user.handle, user.plan) draft = user.get('.plan', u'') session.user[tmpkey] = draft gosub('editor', tmpkey) if session.user.get(tmpkey, u'') != draft: echo(u"\r\n\r\nSEt .PlAN ? [yn]") while True: inp2 = getch() if inp2 in (u'y', u'Y'): user['.plan'] = session.user[tmpkey] break elif inp2 in (u'n', u'N'): break elif inp in (u'l', u'L'): echo(term.move(term.height - 1, 0)) set_location(user) echo(u"\r\n\r\nSEt lOCAtiON tO '%s'? [yn]" % (user.location,)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): user.save() break elif inp2 in (u'n', u'N'): break elif inp in (u'e', u'E'): echo(term.move(term.height - 1, 0)) set_email(user) echo(u"\r\n\r\nSEt EMAil tO '%s'? [yn]" % (user.email,)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): user.save() break elif inp2 in (u'n', u'N'): break elif inp in (u'i', u'I'): echo(u'\r\ntiMEOUt (0=NONE): ') timeout = LineEditor(6, str(user.get('timeout', def_timeout))).read() try: timeout = int(timeout) except ValueError: echo(invalid) return True if timeout < 0: echo(invalid) return True echo(u"\r\n\r\nSet tiMEOUt=%s? [yn]" % ( timeout if timeout else 'None',)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): user['timeout'] = timeout session.send_event('set-timeout', timeout) break elif inp2 in (u'n', u'N'): break elif inp in (u'm', u'M'): mesg = False if user.get('mesg', True) else True echo(u"\r\n\r\n%s iNStANt MESSAGiNG? [yn]" % ( 'ENAblE' if mesg else 'DiSAblE',)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): user['mesg'] = mesg break elif inp2 in (u'n', u'N'): break elif inp in (u'x', u'X'): expert = not user.get('expert', False) echo(u"\r\n\r\n%s EXPERt MOdE? [yn]" % ( 'ENAblE' if expert else 'DiSAblE',)) while True: inp2 = getch() if inp2 in (u'y', u'Y'): user['expert'] = expert break elif inp2 in (u'n', u'N'): break elif inp in (u'q', u'Q',): EXIT = True else: return False return True
def do_command(term, session, inp, fields, tgt_user, point): """ Perform action by given input. """ _color1, _color2, _color3 = [ getattr(term, _color) for _color in (color_lowlight, color_highlight, color_field_edit) ] # discover edit field by matching command key field_name = None for _fname, field in fields.items(): if field.key == inp.lower(): field_name = _fname break if field_name is None: # return False if no field matches this key return False # TODO: we could probably stand to do a bit of a better job of detecting # screen resizes and providing ^L full-screen refresh during the remainder # of this procedure ... It would require quite the refactor, though. # special case; ssh public keys require scrolling editor if field_name == "pubkey": editor = ScrollingEditor( # issue #161; because of a 'border' (that we don't draw), # y must be offset by 1 and height by 2. yloc=field.edit_location.y - 1, xloc=field.edit_location.x - 1, width=field.width + 2, colors={"highlight": _color3}, ) # limit input to 1K, scroll at final field character editor.max_length = 1024 else: editor = LineEditor(field.width, colors={"highlight": _color3}) # find width for displaying description text and validation errors width = term.width - (point.x * 2) # show field description and cancellation description = (field.description or u"") + " Press escape to cancel." description_text = term.wrap(description, width=width) for y_offset, txt in enumerate(description_text): echo(term.move(point.y + y_offset, point.x)) echo(_color1(txt) + term.clear_eol) echo(term.clear_eos) # edit input field (occludes display field). echo(term.move(*field.edit_location)) inp = editor.read() if inp is None: # escape was pressed echo(term.move(*point)) echo(_color2("Canceled !") + term.clear_eos) time.sleep(1) return True else: # validate input if field.validate_fn is not None: errmsg, _ = field.validate_fn(tgt_user, inp) if errmsg: # failed validation, display validation error errmsg += " Press any key." for y_offset, txt in enumerate(term.wrap(errmsg, width=width)): echo(term.move(point.y + y_offset, point.x)) echo(_color2(txt) + term.clear_eol) echo(term.clear_eos) term.inkey() return True # well, it has validated, shall we apply it, then? if field_name in ("password", "location", "email"): # except for anonymous, if tgt_user.handle != "anonymous": setattr(tgt_user, field_name, inp) elif field_name in ("timeout", "pubkey"): if field_name == "timeout": # coerce to integer, set, and if tgt_user is our current # user, then send new value for as engine event timeout_val = int(inp) if tgt_user.handle != "anonymous": tgt_user[field_name] = timeout_val if tgt_user.handle == session.user.handle: session.send_event("set-timeout", timeout_val) elif field_name == "pubkey": if tgt_user.handle != "anonymous": tgt_user[field_name] = inp else: raise ValueError("unknown field.name: {0}".format(field.name)) if tgt_user.handle != "anonymous": tgt_user.save() return True
def prompt_subscription(session, term, yloc, subscription, colors): """ This function is called to assign a new set of subscription tags for a user. If escape is pressed, the existing value is used, or '*' is used if not previously set. This should be called for first-time users, and optionally at any later time to change a subscription. """ if session.user.get('msg_subscription', None) is None: # force-display introductory description for first-time users. yloc += do_describe_message_system(term, colors) echo(u'\r\n\r\n') yloc += 2 # remind ourselves of all available tags yloc += do_describe_available_tags(term, colors) + 2 # for small screens, scroll and leave room for prompt & errors if yloc > term.height + 3: echo(u'\r\n' * 3) yloc = term.height - 3 # and prompt for setting of message tags xloc = max(0, (term.width // 2) - 40) input_prefix = u':: subscription tags:' echo(u''.join((term.move(yloc, xloc), input_prefix))) xloc += len(input_prefix) wide = min(40, (term.width - xloc - 2)) while True: editor = ScrollingEditor(xloc=xloc, yloc=yloc - 1, width=wide, colors={'highlight': colors['backlight']}, content=u', '.join(subscription), max_length=100) # Prompt for and evaluate the given input, splitting by comma, # removing any empty items, and defaulting to ['*'] on escape. inp = editor.read() or u'' subscription = filter(None, set(map(unicode.strip, inp.split(','))) ) or set([u'*']) # Then, reduce to only validate tag patterns, tracking those # that do not match any known tags, and display a warning and # re-prompt if any are removed. removed, subscription = validate_tag_patterns(subscription) # clear existing warning, if any echo(u''.join((term.normal, u'\r\n\r\n', term.clear_eos))) if removed: # and display any unmatched tags as a warning, re-prompt txt = ''.join(( term.bold_red(u"The following patterns are not matched: "), u', '.join(removed))) show_description(term, txt, color=None) continue # otherwise everything is fine, # return new subscription set return subscription