def func(self): """returns the list of online characters""" count_accounts = (SESSIONS.account_count()) self.caller.msg("[%s] Through the fog you see:" % self.key) session_list = SESSIONS.get_sessions() table = evtable.EvTable(border='none') table.add_row('Character', 'On for', 'Idle', 'Location') for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time puppet = session.get_puppet() location = puppet.location.key if puppet and puppet.location else 'Nothingness' table.add_row(puppet.key if puppet else 'None', utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), location) table.reformat_column(0, width=25, align='l') table.reformat_column(1, width=12, align='l') table.reformat_column(2, width=7, align='l') table.reformat_column(3, width=25, align='l') is_one = count_accounts == 1 string = '%s' % 'A' if is_one else str(count_accounts) string += ' single ' if is_one else ' unique ' plural = ' is' if is_one else 's are' string += 'account%s logged in.' % plural self.caller.msg(table) self.caller.msg(string)
def func(self): """ Get all connected players by polling session. """ player = self.player session_list = SESSIONS.get_sessions() session_list = sorted(session_list, key=lambda o: o.player.key) if self.cmdstring == "doing": show_session_data = False else: show_session_data = player.check_permstring( "Immortals") or player.check_permstring("Wizards") nplayers = (SESSIONS.player_count()) if show_session_data: # privileged info table = prettytable.PrettyTable([ "{wPlayer Name", "{wOn for", "{wIdle", "{wPuppeting", "{wRoom", "{wCmds", "{wProtocol", "{wHost" ]) for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time player = session.get_player() puppet = session.get_puppet() location = puppet.location.key if puppet else "None" table.add_row([ utils.crop(player.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), utils.crop(puppet.key if puppet else "None", width=25), utils.crop(location, width=25), session.cmd_total, session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address ]) else: # unprivileged table = prettytable.PrettyTable( ["{wPlayer name", "{wOn for", "{wIdle"]) for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time player = session.get_player() table.add_row([ utils.crop(player.key, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1) ]) isone = nplayers == 1 string = "{wPlayers:{n\n%s\n%s unique account%s logged in." % ( table, "One" if isone else nplayers, "" if isone else "s") self.msg(string)
def func(self): """hook function""" account = self.account bye = '|RDisconnecting|n' exit_msg = 'Hope to see you again, soon! A survey is available at https://goo.gl/forms/yCyLpF6JsAhhUgGz2 for your thoughts' reason = self.args.strip() if self.args else 'Quitting' if reason: bye += " ( |w%s|n ) " % reason if 'all' in self.switches: for session in account.sessions.all(): session_online_time = utils.time_format(time.time() - session.conn_time, 1) msg = bye + ' all sessions after ' + session_online_time + ' online. ' account.msg(msg, session=session) account.msg(exit_msg, session=session) account.disconnect_session_from_account(session, reason=reason) else: session_count = len(account.sessions.all()) online = utils.time_format(time.time() - self.session.conn_time, 1) if session_count == 2: msg = bye others = [x for x in self.account.sessions.get() if x is not self.session] account.msg(msg + 'after ' + online + ' online.', session=self.session) account.msg(msg + 'your other session. |gThis session remains connected.|n', session=others) elif session_count > 2: msg = bye + "%i sessions are still connected." account.msg(msg % (session_count - 1)) else: # If quitting the last available session, give connect time. msg = bye + 'after ' + online + ' online. ' account.msg(msg, session=self.session) account.msg(exit_msg, session=self.session) account.disconnect_session_from_account(self.session, reason=reason)
def func(self): """Show server time data in a table.""" table1 = EvTable("|wServer time", "", align="l", width=78) table1.add_row("Current uptime", utils.time_format(gametime.uptime(), 3)) table1.add_row("Total runtime", utils.time_format(gametime.runtime(), 2)) table1.add_row( "First start", datetime.datetime.fromtimestamp(gametime.server_epoch())) table1.add_row("Current time", datetime.datetime.now()) table1.reformat_column(0, width=30) table2 = EvTable("|wIn-Game time", "|wReal time x %g" % gametime.TIMEFACTOR, align="l", width=77, border_top=0) epochtxt = "Epoch (%s)" % ("from settings" if settings.TIME_GAME_EPOCH else "server start") table2.add_row(epochtxt, datetime.datetime.fromtimestamp(gametime.game_epoch())) table2.add_row("Total time passed:", utils.time_format(gametime.gametime(), 2)) table2.add_row( "Current time ", datetime.datetime.fromtimestamp(gametime.gametime(absolute=True))) table2.reformat_column(0, width=30) self.caller.msg(unicode(table1) + "\n" + unicode(table2))
def func(self): """returns the list of online characters""" count_accounts = (SESSIONS.account_count()) self.caller.msg('[%s] Through the fog you see:' % self.key) session_list = SESSIONS.get_sessions() table = evtable.EvTable(border='none') table.add_row('Character', 'On for', 'Idle', 'Location') for session in session_list: puppet = session.get_puppet() if not session.logged_in or not puppet: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time location = puppet.location.key if puppet and puppet.location else 'Nothingness' table.add_row(puppet.key if puppet else 'None', utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), location) table.reformat_column(0, width=25, align='l') table.reformat_column(1, width=12, align='l') table.reformat_column(2, width=7, align='l') table.reformat_column(3, width=25, align='l') is_one = count_accounts == 1 string = '%s' % 'A' if is_one else str(count_accounts) string += ' single ' if is_one else ' unique ' plural = ' is' if is_one else 's are' string += 'account%s logged in.' % plural self.caller.msg(table) self.caller.msg(string)
def func(self): """Show server time data in a table.""" lat, lon, ele = 33.43, -112.07, 24 here = self.character.location if here: x = float(here.tags.get(category="coordx", default=0)) y = float(here.tags.get(category="coordy", default=0)) # z = here.tags.get(category="coordz") if x and y: lat, lon = float(y/10000), float(x/10000) print('Using location coordinates: {}, {}'.format(lat, lon)) place = astral.LocationInfo(timezone='UTC', latitude=lat, longitude=lon) obsr = astral.Observer(latitude=lat, longitude=lon, elevation=ele) def time_dif(at, when): diff = abs(at - when) return 'now' if diff.total_seconds() < 60 else (utils.time_format(diff.total_seconds(), 2) + (' ago' if at > when else '')) def moon_phase(days): """ Summarize the visible portion, given days into cycle Args: days (int or float): days into current cycle Returns: phase (str): summary of view of visible portion """ phases = ('new', 'waxing crescent', 'First quarter', 'waxing gibbous', 'full', 'waning gibbous', 'last quarter', 'waning crescent') percent = float((float(days) + 0.5) / 29.53) phase = int((percent - int(percent)) * len(phases)) return phases[phase] try: sun = astral.sun.sun(date=datetime.date.today(), observer=obsr) except Exception as e: return else: past = here.tags.get('past', category='realm') moon = astral.moon.phase(date=datetime.date.today()) now = timezone.now() moment = ['dawn', 'sunrise', 'noon', 'sunset', 'dusk'] events = zip([each.capitalize() + ':' for each in moment], [time_dif(now, sun[each]) for each in moment]) table1 = EvTable("|wServer", '|wtime', align='l', width=75) table1.add_row('Current uptime', utils.time_format(gametime.uptime(), 3)) table1.add_row('First start', time_dif(datetime.datetime.now(), datetime.datetime.fromtimestamp(gametime.server_epoch()))) if here.tags.get('past', category='realm'): table1.add_row('Moon phase', moon_phase(moon)) table1.reformat_column(0, width=20) up = self.cmdstring == 'uptime' # User asking for uptime mode self.msg(('Current uptime: ' + utils.time_format(gametime.uptime(), 3)) if up else str(table1)) if past: # Astral events are to be displayed while in past realm table2 = EvTable("|wEvent", "|wTime until", align="l", width=75) for entry in events: table2.add_row(entry[0], entry[1]) table2.reformat_column(0, width=20) self.msg(str(table2) if self.cmdstring == 'events' else ('\n' + str(table2)))
def func(self): "Show server time data in a table." table = prettytable.PrettyTable(["{wserver time statistic","{wtime"]) table.align = 'l' table.add_row(["Current server uptime", utils.time_format(gametime.uptime(), 3)]) table.add_row(["Total server running time", utils.time_format(gametime.runtime(), 2)]) table.add_row(["Total in-game time (realtime x %g)" % (gametime.TIMEFACTOR), utils.time_format(gametime.gametime(), 2)]) table.add_row(["Server time stamp", datetime.datetime.now()]) self.caller.msg(str(table))
def func(self): """ Get all connected players by polling session. """ player = self.player session_list = SESSIONS.get_sessions() session_list = sorted(session_list, key=lambda o: o.player.key) if self.cmdstring == "doing": show_session_data = False else: show_session_data = player.check_permstring("Immortals") or player.check_permstring("Wizards") nplayers = (SESSIONS.player_count()) if show_session_data: # privileged info table = prettytable.PrettyTable(["{wИмя игрока", "{wВ игре", "{wIdle", "{wУправляет", "{wКомната", "{wCmds", "{wПротокол", "{wХост"]) for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time player = session.get_player() puppet = session.get_puppet() location = puppet.location.key if puppet and puppet.location else "None" table.add_row([utils.crop(player.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), utils.crop(puppet.key if puppet else "None", width=25), utils.crop(location, width=25), session.cmd_total, session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address]) else: # unprivileged table = prettytable.PrettyTable(["{wИмя игрока", "{wВ игре", "{wIdle"]) for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time player = session.get_player() table.add_row([utils.crop(player.key, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1)]) isone = nplayers == 1 string = "{wИгроков:{n\n%s\n%s уникальных аккаунтов%s залогинено." % (table, "Один" if isone else nplayers, "" if isone else "") self.msg(string)
def func(self): """ Get all connected players by polling session. """ player = self.player session_list = SESSIONS.get_sessions() session_list = sorted(session_list, key=lambda o: o.player.key) if self.cmdstring == "doing": show_session_data = False else: show_session_data = player.check_permstring("Immortals") or player.check_permstring("Wizards") nplayers = (SESSIONS.player_count()) if show_session_data: # privileged info table = prettytable.PrettyTable(["{wPlayer Name", "{wOn for", "{wIdle", "{wPuppeting", "{wRoom", "{wCmds", "{wProtocol", "{wHost"]) for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time player = session.get_player() puppet = session.get_puppet() location = puppet.location.key if puppet else "None" table.add_row([utils.crop(player.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), utils.crop(puppet.key if puppet else "None", width=25), utils.crop(location, width=25), session.cmd_total, session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address]) else: # unprivileged table = prettytable.PrettyTable(["{wPlayer name", "{wOn for", "{wIdle"]) for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time player = session.get_player() table.add_row([utils.crop(player.key, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1)]) isone = nplayers == 1 string = "{wPlayers:{n\n%s\n%s unique account%s logged in." % (table, "One" if isone else nplayers, "" if isone else "s") self.msg(string)
def func(self): """ Get all connected accounts by polling session. """ account = self.account session_list = SESSIONS.get_sessions() session_list = sorted(session_list, key=lambda o: o.account.key) if self.cmdstring == "doing": show_session_data = False else: show_session_data = account.check_permstring("Developer") or account.check_permstring("Admins") naccounts = (SESSIONS.account_count()) if show_session_data: # privileged info table = evtable.EvTable("|wAccount Name", "|wOn for", "|wIdle", "|wPuppeting", "|wRoom", "|wCmds", "|wProtocol", "|wHost") for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time account = session.get_account() puppet = session.get_puppet() location = puppet.location.key if puppet and puppet.location else "None" table.add_row(utils.crop(account.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), utils.crop(puppet.key if puppet else "None", width=25), utils.crop(location, width=25), session.cmd_total, session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address) else: # unprivileged table = evtable.EvTable("|wAccount name", "|wOn for", "|wIdle") for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time account = session.get_account() table.add_row(utils.crop(account.key, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1)) is_one = naccounts == 1 self.msg("|wAccounts:|n\n%s\n%s unique account%s logged in." % (table, "One" if is_one else naccounts, "" if is_one else "s"))
def func(self): """ Get all connected accounts by polling session. """ account = self.account session_list = SESSIONS.get_sessions() session_list = sorted(session_list, key=lambda o: o.account.key) if self.cmdstring == "doing": show_session_data = False else: show_session_data = account.check_permstring( "Developer") or account.check_permstring("Admins") naccounts = SESSIONS.account_count() if show_session_data: # privileged info table = self.styled_table("|wAccount Name", "|wOn for", "|wIdle", "|wPuppeting", "|wRoom", "|wCmds", "|wProtocol", "|wHost") for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time account = session.get_account() puppet = session.get_puppet() location = puppet.location.key if puppet and puppet.location else "None" table.add_row( utils.crop(account.get_display_name(account), width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), utils.crop( puppet.get_display_name(account) if puppet else "None", width=25), utils.crop(location, width=25), session.cmd_total, session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address) else: # unprivileged table = self.styled_table("|wAccount name", "|wOn for", "|wIdle") for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time account = session.get_account() table.add_row( utils.crop(account.get_display_name(account), width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1)) is_one = naccounts == 1 self.msg( "|wAccounts:|n\n%s\n%s unique account%s logged in." % (table, "One" if is_one else naccounts, "" if is_one else "s"))
def func(self): session_list = SESSIONS.get_sessions() table = evtable.EvTable(" |w|uName:|n", "|w|uIdle:|n", "|w|uConn:|n", "|w|uClearance:|n", table=None, border=None, width=78) for session in session_list: player = session.get_account() idle = time.time() - session.cmd_last_visible conn = time.time() - session.conn_time clearance = session.get_puppet().db.clearance flag = None if player.locks.check_lockstring(player, "dummy:perm(Admin)"): flag = "|y!|n" elif player.locks.check_lockstring(player, "dummy:perm(Builder)"): flag = "|g&|n" elif player.locks.check_lockstring(player, "dummy:perm(Helper)"): flag = "|r$|n" else: flag = " " table.add_row( flag + utils.crop(player.name), utils.time_format(idle, 0), utils.time_format(conn, 0), "|{}{}|n".format(clearance_color(CLEARANCE.get(clearance)), CLEARANCE.get(clearance))) table.reformat_column(0, width=24) table.reformat_column(1, width=12) table.reformat_column(2, width=12) table.reformat_column(3, width=30) self.caller.msg("|w_|n" * 78) title = ansi.ANSIString("|[002|w|u{}|n".format(settings.SERVERNAME)) self.caller.msg(title.center(78, '^').replace('^', "|[002|w_|n")) self.caller.msg(table) self.caller.msg("|w_|n" * 78) self.caller.msg("Total Connected: %s" % SESSIONS.account_count()) whotable = evtable.EvTable("", "", "", header=False, border=None) whotable.reformat_column(0, width=26) whotable.reformat_column(1, width=26) whotable.reformat_column(2, width=26) whotable.add_row("|y!|n - Administrators", "|g&|n - Storytellers", "|r$|n - Player Helpers") self.caller.msg(whotable) self.caller.msg("|w_|n" * 78 + "\n")
def func(self): """Show server time data in a table.""" table1 = EvTable("|wServer time", "", align="l", width=78) table1.add_row("Current uptime", utils.time_format(gametime.uptime(), 3)) table1.add_row("Total runtime", utils.time_format(gametime.runtime(), 2)) table1.add_row("First start", datetime.datetime.fromtimestamp(gametime.server_epoch())) table1.add_row("Current time", datetime.datetime.now()) table1.reformat_column(0, width=30) table2 = EvTable("|wIn-Game time", "|wReal time x %g" % gametime.TIMEFACTOR, align="l", width=77, border_top=0) epochtxt = "Epoch (%s)" % ("from settings" if settings.TIME_GAME_EPOCH else "server start") table2.add_row(epochtxt, datetime.datetime.fromtimestamp(gametime.game_epoch())) table2.add_row("Total time passed:", utils.time_format(gametime.gametime(), 2)) table2.add_row("Current time ", datetime.datetime.fromtimestamp(gametime.gametime(absolute=True))) table2.reformat_column(0, width=30) self.caller.msg(unicode(table1) + "\n" + unicode(table2))
def func(self): """Main function for this command.""" filename = self.args.strip() if "." not in filename: filename += ".log" path = os.path.join("server/logs", filename) now = datetime.datetime.now() if not os.path.exists(path) or not os.path.isfile(path): self.msg("The {} log file doesn't exist.".format(filename)) else: lines = tail_log_file(filename, 0, 20) render = [] for line in lines: line = line.decode("utf-8") if line.count(" ") >= 2: date, time, message = line.split(" ", 2) try: entry = datetime.datetime.strptime(date + " " + time, "%Y-%m-%d %H:%M:%S,%f") except ValueError: continue else: seconds = round((now - entry).total_seconds()) format = time_format(seconds, 1) render.append("{:>4}: {}".format(format, message)) if render: self.msg("\n".join(render)) else: self.msg("|rNo message could be found in this log file.|n")
def board_timeout_posts(self, lhs, rhs): boardname, postnums = lhs.split('/', 1) boardname.strip() postnums.strip() try: board_group = self.board_group board = board_group.find_board(find_name=boardname, checker=self.character) posts = board.parse_postnums(player=self.player, check=postnums) except ValueError as err: self.error(unicode(err)) return if not board.timeout: self.error("'%s' has disabled timeouts." % board) return admin = board.perm_check(self.caller, 'admin') new_timeout = duration_from_string(rhs) if new_timeout.total_seconds() == 0 and not admin: self.error("Only board admins may sticky a post.") return if new_timeout > board.timeout and not admin: self.error("Only admin may set post timeouts above the board timeout.") return for post in posts: if not post.can_edit(self.player): self.error("Cannot Edit post '%s: %s' - Permission denied." % (post.order, post.subject)) else: post.timeout = new_timeout post.save(update_fields=['timeout']) self.sys_msg("Timeout set for post '%s: %s' - now %s" % (post.order, post.subject, time_format(new_timeout, style=1)))
def display_buckets(self): message = list() message.append(self.styled_header('Job Buckets')) col_color = self.account.options.column_names_color message.append( f"|{col_color}Name Description Pen App Dny Cnc Over Due Anon|n" ) message.append(self.styled_separator()) for bucket in evennia.GLOBAL_SCRIPTS.jobs.visible_buckets( self.account): bkey = bucket.key[:8].ljust(8) description = bucket.description if not description: description = "" pending = str( bucket.jobs.filter(status=0).count()).rjust(3).ljust(4) approved = str( bucket.jobs.filter(status=1).count()).rjust(3).ljust(4) denied = str( bucket.jobs.filter(status=2).count()).rjust(3).ljust(4) canceled = str( bucket.jobs.filter(status=3).count()).rjust(3).ljust(4) anon = 'No' now = datetime.datetime.utcnow() overdue = str( bucket.jobs.filter(status=0, due_date__lt=now).count()).rjust(3).ljust(4) due = time_format(bucket.due.total_seconds(), style=1).rjust(3) message.append( f"{bkey} {description[:34].ljust(34)} {pending} {approved} {denied} {canceled} {overdue} {due} {anon}" ) message.append(self.styled_footer()) self.msg('\n'.join(str(l) for l in message))
def func(self): "Show server time data in a table." table = prettytable.PrettyTable(["{wserver time statistic", "{wtime"]) table.align = 'l' table.add_row( ["Current server uptime", utils.time_format(gametime.uptime(), 3)]) table.add_row([ "Total server running time", utils.time_format(gametime.runtime(), 2) ]) table.add_row([ "Total in-game time (realtime x %g)" % (gametime.TIMEFACTOR), utils.time_format(gametime.gametime(), 2) ]) table.add_row(["Server time stamp", datetime.datetime.now()]) self.caller.msg(str(table))
def last_modified_ago(self): """Return the X {unit}{s} ago.""" revision = self.last_revision if revision: seconds = (now() - revision.created_on).total_seconds() ago = time_format(seconds, 4) return "{} ago".format(ago) return "never"
def func(self): """hook function""" account = self.account bye = '|RDisconnecting|n' quit_msg = settings.QUIT_MESSAGE cmd = self.cmdstring opt = self.switches char = self.character here = None if char is None else char.location sess = self.session if 'qhome' in cmd or 'home' in opt and char and here: # Go home before quitting. char.execute_cmd('home') reason = self.args.strip() + '(Quitting)' if reason: bye += " ( |w%s|n ) " % reason boot = ('bootme' in cmd) or 'boot' in opt if 'all' in opt or boot: for session in account.sessions.all(): if boot: if session is sess: continue # Exclude booting current session else: # and boot the rest. session.msg(quit_msg + reason + '/BOOT', session=session) account.disconnect_session_from_account( session, reason + '/BOOT') else: # Disconnect them all! session.msg(bye + reason + '/ALL|/' + quit_msg, session=session) account.disconnect_session_from_account( session, reason + '/ALL') if boot: self.msg( bye + 'all other sessions. |gThis session remains connected.|n') else: session_count = len(account.sessions.all()) online = utils.time_format(time.time() - sess.conn_time, 1) if session_count == 2: msg = bye others = [ x for x in self.account.sessions.get() if x is not sess ] self.msg(msg + 'after ' + online + ' online.') self.msg( msg + 'your other session. |gThis session remains connected.|n', session=others) elif session_count > 2: msg = bye + "%i sessions are still connected." self.msg(msg % (session_count - 1)) else: # If quitting the last available session, give connect time. msg = bye + 'after ' + online + ' online. ' self.msg(msg) self.msg(quit_msg) account.disconnect_session_from_account(sess, reason)
def display_line(self, account, admin, mode=None): start = f"{self.unread_star(account, admin)}{self.status_letter()}" num = str(self.id).rjust(4).ljust(5) owner_link = self.owner owner = str(self.owner) if owner_link else '' owner = owner[:15].ljust(16) title = self.title[:29].ljust(30) claimed = self.handler_names()[:12].ljust(13) now = utcnow().timestamp() last_updated = self.public_update.timestamp() if admin: last_updated = max(self.admin_update.timestamp(), last_updated) due = self.due_date.timestamp() - now if due <= 0: due = ANSIString("|rOVER|n") else: due = time_format(due, 1) due = due.rjust(6).ljust(7) last = time_format(now - last_updated, 1).rjust(4) return f"{start} {num}{owner}{title}{claimed}{due}{last}"
def func(self): """hook function""" account = self.account bye = '|RDisconnecting|n' exit_msg = 'Hope to see you again, soon! A survey is available at https://goo.gl/forms/yCyLpF6JsAhhUgGz2 for your thoughts' reason = self.args.strip() if self.args else 'Quitting' if reason: bye += " ( |w%s|n ) " % reason if 'all' in self.switches: for session in account.sessions.all(): session_online_time = utils.time_format( time.time() - session.conn_time, 1) msg = bye + ' all sessions after ' + session_online_time + ' online. ' account.msg(msg, session=session) account.msg(exit_msg, session=session) account.disconnect_session_from_account(session, reason=reason) else: session_count = len(account.sessions.all()) online = utils.time_format(time.time() - self.session.conn_time, 1) if session_count == 2: msg = bye others = [ x for x in self.account.sessions.get() if x is not self.session ] account.msg(msg + 'after ' + online + ' online.', session=self.session) account.msg( msg + 'your other session. |gThis session remains connected.|n', session=others) elif session_count > 2: msg = bye + "%i sessions are still connected." account.msg(msg % (session_count - 1)) else: # If quitting the last available session, give connect time. msg = bye + 'after ' + online + ' online. ' account.msg(msg, session=self.session) account.msg(exit_msg, session=self.session) account.disconnect_session_from_account(self.session, reason=reason)
def ago(self): """Return the time since the notification was created.""" if self.timestamp is None: return "now" gtime = gametime.gametime(absolute=True) seconds = gtime - self.timestamp if seconds < 5: return "a few seconds ago" ago = time_format(seconds, 4) return "{} ago".format(ago)
def sent_ago(self): """Return the human-readable time since sent (X units ago).""" global _GAMETIME if not _GAMETIME: from evennia.utils import gametime as _GAMETIME gtime = datetime.datetime.fromtimestamp( _GAMETIME.gametime(absolute=True)) gtime = make_aware(gtime) seconds = (gtime - self.date_sent).total_seconds() ago = time_format(seconds, 4) return "{} ago".format(ago)
def board_timeout_board_set(self, lhs, rhs): try: board_group = self.board_group board = board_group.find_board(find_name=lhs, group=self.group, checker=self.character) except ValueError as err: self.error(unicode(err)) return if not board.perm_check(self.player, 'admin'): self.error("Permission denied.") return new_timeout = duration_from_string(rhs) timeout_string = time_format(new_timeout.total_seconds(), style=1) if new_timeout else '0 - Permanent' board.timeout = new_timeout board.save(update_fields=['timeout']) self.sys_msg("'%s' timeout set to: %s" % (board, timeout_string))
def board_timeout_list(self, lhs, rhs): try: board_group = self.board_group except ValueError as err: self.error(unicode(err)) return message = list() message.append(self.board_header()) bbtable = self.player.render.make_table(["ID", "RWA", "Name", "Timeout"], width=[4, 4, 23, 47]) for board in board_group.visible_boards(checker=self.player): bbtable.add_row(mxp(board.order, "+bbread %s" % board.order), board.display_permissions(self.character), mxp(board, "+bbread %s" % board.order), time_format(board.timeout.total_seconds()) if board.timeout else '0 - Permanent') message.append(bbtable) message.append(self.player.render.footer()) self.msg_lines(message)
def list_tasks(self): """List the active tasks.""" obj = self.obj callback_name = self.callback_name handler = self.handler tasks = [(k, v[0], v[1], v[2]) for k, v in handler.db.tasks.items()] if obj: tasks = [task for task in tasks if task[2] is obj] if callback_name: tasks = [task for task in tasks if task[3] == callback_name] tasks.sort() table = EvTable("ID", "Object", "Callback", "In", width=78) table.reformat_column(0, align="r") now = datetime.now() for task_id, future, obj, callback_name in tasks: key = obj.get_display_name(self.caller) delta = time_format((future - now).total_seconds(), 1) table.add_row(task_id, key, callback_name, delta) self.msg(unicode(table))
def execute_cmd(self, session=None, txt=None, **kwargs): """ Take incoming data and send it to connected channel. This is triggered by the bot_data_in Inputfunc. Args: session (Session, optional): Session responsible for this command. Note that this is the bot. txt (str, optional): Command string. Kwargs: user (str): The name of the user who sent the message. channel (str): The name of channel the message was sent to. type (str): Nature of message. Either 'msg', 'action', 'nicklist' or 'ping'. nicklist (list, optional): Set if `type='nicklist'`. This is a list of nicks returned by calling the `self.get_nicklist`. It must look for a list `self._nicklist_callers` which will contain all callers waiting for the nicklist. timings (float, optional): Set if `type='ping'`. This is the return (in seconds) of a ping request triggered with `self.ping`. The return must look for a list `self._ping_callers` which will contain all callers waiting for the ping return. """ if kwargs["type"] == "nicklist": # the return of a nicklist request if hasattr(self, "_nicklist_callers") and self._nicklist_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) nicklist = ", ".join(sorted(kwargs["nicklist"], key=lambda n: n.lower())) for obj in self._nicklist_callers: obj.msg("Nicks at %s:\n %s" % (chstr, nicklist)) self._nicklist_callers = [] return elif kwargs["type"] == "ping": # the return of a ping if hasattr(self, "_ping_callers") and self._ping_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) for obj in self._ping_callers: obj.msg("IRC ping return from %s took %ss." % (chstr, kwargs["timing"])) self._ping_callers = [] return elif kwargs["type"] == "privmsg": # A private message to the bot - a command. user = kwargs["user"] if txt.lower().startswith("who"): # return server WHO list (abbreviated for IRC) global _SESSIONS if not _SESSIONS: from evennia.server.sessionhandler import SESSIONS as _SESSIONS whos = [] t0 = time.time() for sess in _SESSIONS.get_sessions(): delta_cmd = t0 - sess.cmd_last_visible delta_conn = t0 - session.conn_time player = sess.get_player() whos.append("%s (%s/%s)" % (utils.crop("|w%s|n" % player.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1))) text = "Who list (online/idle): %s" % ", ".join(sorted(whos, key=lambda w: w.lower())) elif txt.lower().startswith("about"): # some bot info text = "This is an Evennia IRC bot connecting from '%s'." % settings.SERVERNAME else: text = "I understand 'who' and 'about'." super(IRCBot, self).msg(privmsg=((text,), {"user": user})) else: # something to send to the main channel if kwargs["type"] == "action": # An action (irc pose) text = "%s@%s %s" % (kwargs["user"], kwargs["channel"], txt) else: # msg - A normal channel message text = "%s@%s: %s" % (kwargs["user"], kwargs["channel"], txt) if not self.ndb.ev_channel and self.db.ev_channel: # cache channel lookup self.ndb.ev_channel = self.db.ev_channel if self.ndb.ev_channel: self.ndb.ev_channel.msg(text, senders=self.id)
def execute_cmd(self, session=None, txt=None, **kwargs): """ Take incoming data and make the appropriate action. This acts as a CommandHandler of sorts for the various "type" of actions the Portal bot returns to the Server. This is triggered by the bot_data_in Inputfunc. Args: session (Session, optional): Session responsible for this command. Note that this is the bot. txt (str, optional): Command string. Kwargs: user (str): The name of the user who sent the message. channel (str): The name of channel the message was sent to. nicklist (list, optional): Set if `type='nicklist'`. This is a list of nicks returned by calling the `self.get_nicklist`. It must look for a list `self._nicklist_callers` which will contain all callers waiting for the nicklist. timings (float, optional): Set if `type='ping'`. This is the return (in seconds) of a ping request triggered with `self.ping`. The return must look for a list `self._ping_callers` which will contain all callers waiting for the ping return. type (str): The type of response returned by the IRC bot. Including: "nicklist": Returned when first joining a channel. "joined": Returned when a new user joins a channel. "left": Returned when a user leaves a channel. "privmsg": Returned when the bot is directly messaged. "action": Returned when a user uses /me in IRC Everything else is assumed to be text to speak. """ if kwargs["type"] == "nicklist": """ Returned when first joining a channel. """ if hasattr(self, "_nicklist_callers") and self._nicklist_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) nicklist = ", ".join( sorted(kwargs["nicklist"], key=lambda n: n.lower())) for obj in self._nicklist_callers: obj.msg("Nicks at %s:\n %s" % (chstr, nicklist)) self._nicklist_callers = [] return else: # Prepare blank reference dictionary. self.db.puppetdict = {} # Prepare listener. self.prep_listener() # Prepare puppets. for nick in kwargs["nicklist"]: self.prep_puppet(ansi.strip_ansi(nick)) # Hide stale puppets. for puppet in search.search_tag(self.key + "-puppet"): if puppet.location is not None \ and puppet not in self.db.puppetdict.values(): puppet.move_to(None, to_none=True) return elif kwargs["type"] == "ping": """ Returned by the ping command. """ if hasattr(self, "_ping_callers") and self._ping_callers: chstr = "%s (%s:%s)" % (self.db.irc_channel, self.db.irc_network, self.db.irc_port) for obj in self._ping_callers: obj.msg("IRC ping return from %s took %ss." % (chstr, kwargs["timing"])) self._ping_callers = [] return elif kwargs["type"] == "joined": """ Returned when a new user joins a channel. """ # Prepare puppet. for nick in kwargs["nicklist"]: self.prep_puppet(ansi.strip_ansi(nick)) return elif kwargs["type"] == "renamed": """ Returned when IRC user changes nick. """ puppetdict = self.db.puppetdict newname = kwargs["newname"] oldname = kwargs["oldname"] newkey = self.db.puppetprefix + newname + self.db.puppetsuffix oldkey = self.db.puppetprefix + oldname + self.db.puppetsuffix # List of puppet objects matching newname. puppetlist = [ puppet for puppet in search.search_tag(self.key + "-puppet") if puppet.key == newkey ] # Use an existing puppet. if puppetlist: # Set up new puppet puppetdict[newname] = puppetlist[0] if not puppetdict[newname].location == self.db.ev_location: puppetdict[newname].move_to(self.db.ev_location, quiet=True) self.db.ev_location.msg_contents(oldkey + " has become " + newkey) # Pack up old puppet self.db.puppetdict[oldname].move_to(None, to_none=True) del self.db.puppetdict[oldname] # Else recycle old puppet. elif oldname in puppetdict: print('Reusing puppetbot from puppetdict: ', oldname, puppetdict[oldname]) puppetdict[oldname].key = newkey puppetdict[newname] = puppetdict.pop(oldname) self.db.ev_location.msg_contents(oldkey + " has become " + newkey) return elif kwargs["type"] == "left": """ Returned when a user leaves a channel. """ # Pack up puppet. for nick in kwargs["nicklist"]: nick = ansi.strip_ansi(nick) if nick in self.db.puppetdict: self.db.puppetdict[nick].move_to(None, to_none=True) self.db.ev_location.msg_contents( self.db.puppetdict[nick].key + self.db.puppetexitmsg) del self.db.puppetdict[nick] return elif kwargs["type"] == "privmsg": """ Returned when the bot is directly messaged. Users can issue commands to the Server bot through IRC PM. "Who" - Return a list of current users in the MUD "About" - Describes the bot and the connected MUD "Look" - Look at the Evennia location and those within it. "whisper" - Whisper in-game account "whisper user = msg" "Desc" - If empty, shows in-game bots description. Else, sets bots in-game bot description to given value. All other messages return a help message. """ user = kwargs["user"] # Who command - Returns online users in game. if txt.lower().startswith("who"): # return server WHO list (abbreviated for IRC) global _SESSIONS if not _SESSIONS: from evennia.server.sessionhandler import \ SESSIONS as _SESSIONS whos = [] t0 = time.time() for sess in _SESSIONS.get_sessions(): delta_cmd = t0 - sess.cmd_last_visible delta_conn = t0 - session.conn_time account = sess.get_account() whos.append("%s (%s/%s)" % (utils.crop("|w%s|n" % account.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1))) text = "Who list (online/idle): %s" % ", ".join( sorted(whos, key=lambda w: w.lower())) # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # About command - Return a blurb explaining origin of bot. elif txt.lower().startswith("about"): # some bot info text = self.db.botdesc # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # Look command - Look at the Evennia location and those within it. elif txt.lower().startswith("look"): # Mirror in-game look command. txt = txt.partition(" ")[2] if not txt: target = self.db.ev_location else: result = search.object_search( txt, candidates=self.db.ev_location.contents) target = result[0] if len(result) > 0 else None if not target: text = "'%s' could not be located." % txt else: text = target.return_appearance( self.db.puppetdict[user]).replace('\n', ' ') # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # Desc command - If empty, shows in-game bots description. Else, # sets bots in-game bot description to given value. elif txt.lower().startswith("desc"): # Split text - set desc as text or return current desc if none. txt = txt.partition(" ")[2] if not txt: text = self.db.puppetdict[user].db.desc else: self.db.puppetdict[user].db.desc = txt text = "Desc changed to: " + txt # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) # Whisper command - Whisper a user in game through a puppet. elif txt.lower().startswith("whisper"): # Parse input. Must be in form 'whisper nick = msg' txt = txt.split(" ", 1)[1] try: nick, msg = txt.split("=") except Exception: text = "Whisper Usage: 'Whisper Character = Msg'" super(ServerBot, self).msg(privmsg=((text, ), { "user": user })) return if not nick or not msg: text = "Whisper Usage: 'Whisper Character = Msg'" super(ServerBot, self).msg(privmsg=((text, ), { "user": user })) return puppet = self.db.puppetdict[ansi.strip_ansi(user)] target = puppet.search(nick) if not target: text = "Whisper Aborted: Character could not be found." # Return Message. super(ServerBot, self).msg(privmsg=((text, ), { "user": user })) return puppet.execute_cmd("whisper " + nick + "=" + msg) text = 'You whisper to ' + nick + ', "' + msg + '"' super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) return # Default message - Acts as help information. else: text = ( "Command list: \n" ' "Who": Return a list of online users on %s.\n' ' "About": Returns information about %s.\n' ' "Look": Look at the Evennia location and those within it.\n' ' "Desc": If empty, shows in-game bots description. Else, sets\n' ' "whisper" - Whisper in-game account "whisper user = msg"\n' ' bots in-game bot description to given value.\n' ' All other messages return this help message.') % ( settings.SERVERNAME, settings.SERVERNAME) # Return Message. super(ServerBot, self).msg(privmsg=((text, ), {"user": user})) elif kwargs["type"] == "action": """ Returned when a user uses /me in IRC """ # Cause puppet to act out pose. if ansi.strip_ansi(kwargs["user"]) in self.db.puppetdict: user = ansi.strip_ansi(kwargs["user"]) self.db.puppetdict[user].execute_cmd("pose " + txt) return else: """ Everything else is assumed to be text to speak. """ # Cause the puppet to say the message. if ansi.strip_ansi(kwargs["user"]) in self.db.puppetdict: user = ansi.strip_ansi(kwargs["user"]) self.db.puppetdict[user].execute_cmd("say " + txt) return
def test_style_4(self): """Test the style 4 of time_format.""" self.assertEqual(utils.time_format(0, 4), "0 seconds") self.assertEqual(utils.time_format(28, 4), "28 seconds") self.assertEqual(utils.time_format(92, 4), "a minute") self.assertEqual(utils.time_format(300, 4), "5 minutes") self.assertEqual(utils.time_format(660, 4), "11 minutes") self.assertEqual(utils.time_format(3600, 4), "an hour") self.assertEqual(utils.time_format(3725, 4), "an hour") self.assertEqual(utils.time_format(86350, 4), "23 hours") self.assertEqual(utils.time_format(86800, 4), "a day") self.assertEqual(utils.time_format(130800, 4), "a day") self.assertEqual(utils.time_format(530800, 4), "6 days") self.assertEqual(utils.time_format(3030800, 4), "a month") self.assertEqual(utils.time_format(7030800, 4), "2 months") self.assertEqual(utils.time_format(40030800, 4), "a year") self.assertEqual(utils.time_format(90030800, 4), "2 years")
def generate_substitutions(self, viewer): modes = (0, 1, 2, 3) return { f"style_{mode}": time_format(self.data.total_seconds(), style=mode) for mode in modes }
def func(self): """Show list.""" global _IDMAPPER if not _IDMAPPER: from evennia.utils.idmapper import models as _IDMAPPER if "flushmem" in self.switches: # flush the cache prev, _ = _IDMAPPER.cache_size() nflushed = _IDMAPPER.flush_cache() now, _ = _IDMAPPER.cache_size() string = "The Idmapper cache freed |w{idmapper}|n database objects.\n" \ "The Python garbage collector freed |w{gc}|n Python instances total." self.caller.msg(string.format(idmapper=(prev - now), gc=nflushed)) return # display active processes os_windows = os.name == "nt" pid = os.getpid() if os_windows: # Windows requires the psutil module to even get paltry # statistics like this (it's pretty much worthless, # unfortunately, since it's not specific to the process) /rant try: import psutil has_psutil = True except ImportError: has_psutil = False if has_psutil: loadavg = psutil.cpu_percent() _mem = psutil.virtual_memory() rmem = _mem.used / (1000.0 * 1000) pmem = _mem.percent if "mem" in self.switches: string = "Total computer memory usage: |w%g|n MB (%g%%)" self.caller.msg(string % (rmem, pmem)) return # Display table loadtable = EvTable("property", "statistic", align="l") loadtable.add_row("Total CPU load", "%g %%" % loadavg) loadtable.add_row("Total computer memory usage", "%g MB (%g%%)" % (rmem, pmem)) loadtable.add_row("Process ID", "%g" % pid), else: loadtable = "Not available on Windows without 'psutil' library " \ "(install with |wpip install psutil|n)." else: # Linux / BSD (OSX) - proper pid-based statistics global _RESOURCE if not _RESOURCE: import resource as _RESOURCE loadavg = os.getloadavg()[0] rmem = float( os.popen('ps -p %d -o %s | tail -1' % (pid, "rss")).read()) / 1000.0 # resident memory vmem = float( os.popen('ps -p %d -o %s | tail -1' % (pid, "vsz")).read()) / 1000.0 # virtual memory pmem = float( os.popen( 'ps -p %d -o %s | tail -1' % (pid, "%mem")).read()) # % of resident memory to total rusage = _RESOURCE.getrusage(_RESOURCE.RUSAGE_SELF) if "mem" in self.switches: string = "Memory usage: RMEM: |w%g|n MB (%g%%), VMEM (res+swap+cache): |w%g|n MB." self.caller.msg(string % (rmem, pmem, vmem)) return loadtable = EvTable("property", "statistic", align="l") loadtable.add_row("Server load (1 min)", "%g" % loadavg) loadtable.add_row("Process ID", "%g" % pid), loadtable.add_row("Memory usage", "%g MB (%g%%)" % (rmem, pmem)) loadtable.add_row("Virtual address space", "") loadtable.add_row("|x(resident+swap+caching)|n", "%g MB" % vmem) loadtable.add_row( "CPU time used (total)", "%s (%gs)" % (utils.time_format(rusage.ru_utime), rusage.ru_utime)) loadtable.add_row( "CPU time used (user)", "%s (%gs)" % (utils.time_format(rusage.ru_stime), rusage.ru_stime)) loadtable.add_row( "Page faults", "%g hard, %g soft, %g swapouts" % (rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap)) loadtable.add_row( "Disk I/O", "%g reads, %g writes" % (rusage.ru_inblock, rusage.ru_oublock)) loadtable.add_row( "Network I/O", "%g in, %g out" % (rusage.ru_msgrcv, rusage.ru_msgsnd)) loadtable.add_row( "Context switching", "%g vol, %g forced, %g signals" % (rusage.ru_nvcsw, rusage.ru_nivcsw, rusage.ru_nsignals)) # os-generic string = "|wServer CPU and Memory load:|n\n%s" % loadtable # object cache count (note that sys.getsiseof is not called so this works for pypy too. total_num, cachedict = _IDMAPPER.cache_size() sorted_cache = sorted([(key, num) for key, num in cachedict.items() if num > 0], key=lambda tup: tup[1], reverse=True) memtable = EvTable("entity name", "number", "idmapper %", align="l") for tup in sorted_cache: memtable.add_row(tup[0], "%i" % tup[1], "%.2f" % (float(tup[1]) / total_num * 100)) string += "\n|w Entity idmapper cache:|n %i items\n%s" % (total_num, memtable) # return to caller self.caller.msg(string)
def accept_callback(self): """Accept a callback.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters # If no object, display the list of callbacks to be checked if obj is None: table = EvTable("ID", "Type", "Object", "Name", "Updated by", "On", width=78) table.reformat_column(0, align="r") now = datetime.now() for obj, name, number in self.handler.db.to_valid: callbacks = self.handler.get_callbacks(obj).get(name) if callbacks is None: continue try: callback = callbacks[number] except IndexError: continue type_name = obj.typeclass_path.split(".")[-1] by = callback.get("updated_by") by = by.key if by else "|gUnknown|n" updated_on = callback.get("updated_on") if updated_on is None: updated_on = callback.get("created_on") if updated_on: updated_on = "{} ago".format(time_format( (now - updated_on).total_seconds(), 4).capitalize()) else: updated_on = "|gUnknown|n" table.add_row(obj.id, type_name, obj, name, by, updated_on) self.msg(unicode(table)) return # An object was specified callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) # If no callback name is specified, display the list of callbacks if not callback_name: self.list_callbacks() return # Check that the callback exists if callback_name not in callbacks: self.msg("The callback name {} can't be found in {}.".format( callback_name, obj)) return if not parameters: self.msg("Which callback do you wish to accept? Specify a number.") self.list_callbacks() return # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg("The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # Accept the callback if callback["valid"]: self.msg("This callback has already been accepted.") else: self.handler.accept_callback(obj, callback_name, number) self.msg("The callback {} {} of {} has been accepted.".format( callback_name, parameters, obj))
def func(self): """Get all connected accounts by polling session.""" you = self.account session_list = SESSIONS.get_sessions() cmd = self.cmdstring show_session_data = you.check_permstring( 'Immortals') and not you.attributes.has('_quell') account_count = (SESSIONS.account_count()) table = evtable.EvTable(border='none', pad_width=0, border_width=0, maxwidth=79) if cmd == 'wa' or cmd == 'where': # Example output expected: # Occ, Location, Avg Time, Top 3 Active, Directions # #3 Park 5m Rulan, Amber, Tria Taxi, Park # Other possible sort methods: Alphabetical by name, by occupant count, by activity, by distance # Nick = Global Nick (no greater than five A/N or randomly created if not a Global Nick # # WA with name parameters to pull up more extensive information about the direction # Highest Occupants (since last reboot), Last Visited, Last Busy (3+) etc. (more ideas here) table.add_header('|wOcc', '|wLocation', '|wAvg Time', '|cTop 3 Active', '|gDirections') table.reformat_column(0, width=4, align='l') table.reformat_column(1, width=25, align='l') table.reformat_column(2, width=6, align='l') table.reformat_column(3, width=16, pad_right=1, align='l') table.reformat_column(4, width=20, align='l') locations = { } # Create an empty dictionary to gather locations information. for session in session_list: # Go through connected list and see who's where. if not session.logged_in: continue character = session.get_puppet() if not character: continue if character.location not in locations: locations[character.location] = [] locations[character.location].append( character) # Build the list of who's in a location for place in locations: location = place.get_display_name( you) if place else '|222Nothingness|n' table.add_row( len(locations[place]), location, '?', ', '.join( each.get_display_name(you) for each in locations[place]), 'Summon or walk') elif cmd == 'ws': my_character = self.caller.get_puppet(self.session) if not (my_character and my_character.location): self.msg("You can't see anyone here.") return table.add_header('|wCharacter', '|wOn for', '|wIdle') table.reformat_column(0, width=45, align='l') table.reformat_column(1, width=8, align='l') table.reformat_column(2, width=7, pad_right=1, align='r') for element in my_character.location.contents: if not element.has_account: continue delta_cmd = time.time() - max( [each.cmd_last_visible for each in element.sessions.all()]) delta_con = time.time() - min( [each.conn_time for each in element.sessions.all()]) name = element.get_display_name(you) type = element.attributes.get('species', default='') table.add_row(name + ', ' + type if type else name, utils.time_format(delta_con, 0), utils.time_format(delta_cmd, 1)) elif cmd == 'what' or cmd == 'wot': table.add_header('|wCharacter - Doing', '|wIdle') table.reformat_column(0, width=72, align='l') table.reformat_column(1, width=7, align='r') for session in session_list: if not session.logged_in or not session.get_puppet(): continue delta_cmd = time.time() - session.cmd_last_visible character = session.get_puppet() doing = character.get_display_name(you, pose=True) table.add_row(doing, utils.time_format(delta_cmd, 1)) else: # Default to displaying who if show_session_data: # privileged info shown to Immortals and higher only when not quelled table.add_header('|wCharacter', '|wAccount', '|wQuell', '|wCmds', '|wProtocol', '|wAddress') table.reformat_column(0, align='l') table.reformat_column(1, align='r') table.reformat_column(2, width=7, align='r') table.reformat_column(3, width=6, pad_right=1, align='r') table.reformat_column(4, width=11, align='l') table.reformat_column(5, width=16, align='r') session_list = sorted(session_list, key=lambda o: o.account.key) for session in session_list: if not session.logged_in: continue account = session.get_account() puppet = session.get_puppet() table.add_row( puppet.get_display_name(you) if puppet else 'None', account.get_display_name(you), '|gYes|n' if account.attributes.get('_quell') else '|rNo|n', session.cmd_total, session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address) else: # unprivileged info shown to everyone, including Immortals and higher when quelled table.add_header('|wCharacter', '|wOn for', '|wIdle') table.reformat_column(0, width=40, align='l') table.reformat_column(1, width=8, align='l') table.reformat_column(2, width=7, align='r') for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time character = session.get_puppet() if not character: continue table.add_row(character.get_display_name(you), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1)) is_one = account_count == 1 string = '%s' % 'A' if is_one else str(account_count) string += ' single ' if is_one else ' unique ' plural = ' is' if is_one else 's are' string += 'account%s logged in.' % plural self.msg(table) self.msg(string)
def time_dif(at, when): diff = abs(at - when) return 'now' if diff.total_seconds() < 60 else (utils.time_format(diff.total_seconds(), 2) + (' ago' if at > when else ''))
def list_callbacks(self): """Display the list of callbacks connected to the object.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) if callback_name: # Check that the callback name can be found in this object created = callbacks.get(callback_name) if created is None: self.msg("No callback {} has been set on {}.".format( callback_name, obj)) return if parameters: # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg( "The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # Display the callback's details author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_by = callback.get("updated_by") updated_by = updated_by.key if updated_by else "|gUnknown|n" created_on = callback.get("created_on") created_on = created_on.strftime( "%Y-%m-%d %H:%M:%S") if created_on else "|gUnknown|n" updated_on = callback.get("updated_on") updated_on = updated_on.strftime( "%Y-%m-%d %H:%M:%S") if updated_on else "|gUnknown|n" msg = "Callback {} {} of {}:".format(callback_name, parameters, obj) msg += "\nCreated by {} on {}.".format(author, created_on) msg += "\nUpdated by {} on {}".format(updated_by, updated_on) if self.is_validator: if callback.get("valid"): msg += "\nThis callback is |rconnected|n and active." else: msg += "\nThis callback |rhasn't been|n accepted yet." msg += "\nCallback code:\n" msg += raw(callback["code"]) self.msg(msg) return # No parameter has been specified, display the table of callbacks cols = ["Number", "Author", "Updated", "Param"] if self.is_validator: cols.append("Valid") table = EvTable(*cols, width=78) table.reformat_column(0, align="r") now = datetime.now() for i, callback in enumerate(created): author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_on = callback.get("updated_on") if updated_on is None: updated_on = callback.get("created_on") if updated_on: updated_on = "{} ago".format( time_format((now - updated_on).total_seconds(), 4).capitalize()) else: updated_on = "|gUnknown|n" parameters = callback.get("parameters", "") row = [str(i + 1), author, updated_on, parameters] if self.is_validator: row.append("Yes" if callback.get("valid") else "No") table.add_row(*row) self.msg(unicode(table)) else: names = list(set(list(types.keys()) + list(callbacks.keys()))) table = EvTable("Callback name", "Number", "Description", valign="t", width=78) table.reformat_column(0, width=20) table.reformat_column(1, width=10, align="r") table.reformat_column(2, width=48) for name in sorted(names): number = len(callbacks.get(name, [])) lines = sum( len(e["code"].splitlines()) for e in callbacks.get(name, [])) no = "{} ({})".format(number, lines) description = types.get(name, (None, "Chained event."))[1] description = description.strip("\n").splitlines()[0] table.add_row(name, no, description) self.msg(unicode(table))
def accept_callback(self): """Accept a callback.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters # If no object, display the list of callbacks to be checked if obj is None: table = EvTable("ID", "Type", "Object", "Name", "Updated by", "On", width=78) table.reformat_column(0, align="r") now = datetime.now() for obj, name, number in self.handler.db.to_valid: callbacks = self.handler.get_callbacks(obj).get(name) if callbacks is None: continue try: callback = callbacks[number] except IndexError: continue type_name = obj.typeclass_path.split(".")[-1] by = callback.get("updated_by") by = by.key if by else "|gUnknown|n" updated_on = callback.get("updated_on") if updated_on is None: updated_on = callback.get("created_on") if updated_on: updated_on = "{} ago".format( time_format((now - updated_on).total_seconds(), 4).capitalize()) else: updated_on = "|gUnknown|n" table.add_row(obj.id, type_name, obj, name, by, updated_on) self.msg(unicode(table)) return # An object was specified callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) # If no callback name is specified, display the list of callbacks if not callback_name: self.list_callbacks() return # Check that the callback exists if not callback_name in callbacks: self.msg("The callback name {} can't be found in {}.".format( callback_name, obj)) return if not parameters: self.msg( "Which callback do you wish to accept? Specify a number.") self.list_callbacks() return # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg("The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # Accept the callback if callback["valid"]: self.msg("This callback has already been accepted.") else: self.handler.accept_callback(obj, callback_name, number) self.msg("The callback {} {} of {} has been accepted.".format( callback_name, parameters, obj))
def time_dif(at, when): diff = abs(at - when) return 'now' if diff.total_seconds < 60 else (utils.time_format(diff.total_seconds(), 2) + (' ago' if at > when else ''))
def func(self): """Show server time data in a table.""" lat, lon, ele = 33.43, -112.07, 24 here = self.character.location if here: x = float(here.tags.get(category="coordx", default=0)) y = float(here.tags.get(category="coordy", default=0)) # z = here.tags.get(category="coordz") if x and y: lat, lon = float(y/10000), float(x/10000) print('Using location coordinates: {}, {}'.format(lat, lon)) place = Astral.Location(info=('', '', lat, lon, 'UTC', ele)) place.solar_depression = 'civil' def time_dif(at, when): diff = abs(at - when) return 'now' if diff.total_seconds < 60 else (utils.time_format(diff.total_seconds(), 2) + (' ago' if at > when else '')) def moon_phase(days): """ Summarize the visible portion, given days into cycle Args: days (int or float): days into current cycle Returns: phase (str): summary of view of visible portion """ phases = ('new', 'waxing crescent', 'First quarter', 'waxing gibbous', 'full', 'waning gibbous', 'last quarter', 'waning crescent') percent = float((float(days) + 0.5) / 29.53) phase = int((percent - int(percent)) * len(phases)) return phases[phase] try: sun = place.sun(date=datetime.date.today(), local=True) except Exception: return else: past = here.tags.get('past', category='realm') moon = place.moon_phase(date=datetime.date.today()) now = timezone.now() moment = ['dawn', 'sunrise', 'noon', 'sunset', 'dusk'] events = zip([each.capitalize() + ':' for each in moment], [time_dif(now, sun[each]) for each in moment]) table1 = EvTable("|wServer", '|wtime', align='l', width=75) table1.add_row('Current uptime', utils.time_format(gametime.uptime(), 3)) table1.add_row('First start', time_dif(datetime.datetime.now(), datetime.datetime.fromtimestamp(gametime.server_epoch()))) if here.tags.get('past', category='realm'): table1.add_row('Moon phase', moon_phase(moon)) table1.reformat_column(0, width=20) if past: table2 = EvTable("|wEvent", "|wTime until", align="l", width=75) for entry in events: table2.add_row(entry[0], entry[1]) table2.reformat_column(0, width=20) if self.cmdstring == 'uptime': self.msg('Current uptime: ' + utils.time_format(gametime.uptime(), 3)) else: self.msg(unicode(table1)) if past: if self.cmdstring == 'events': self.msg(unicode(table2)) else: self.msg("\n" + unicode(table2))
def func(self): """Get all connected accounts by polling session.""" you = self.account session_list = SESSIONS.get_sessions() cmd = self.cmdstring show_session_data = you.check_permstring('Immortals') and not you.attributes.has('_quell') account_count = (SESSIONS.account_count()) table = evtable.EvTable(border='none', pad_width=0, border_width=0, maxwidth=79) if cmd == 'wa' or cmd == 'where': # Example output expected: # Occ, Location, Avg Time, Top 3 Active, Directions # #3 Park 5m Rulan, Amber, Tria Taxi, Park # Other possible sort methods: Alphabetical by name, by occupant count, by activity, by distance # Nick = Global Nick (no greater than five A/N or randomly created if not a Global Nick # # WA with name parameters to pull up more extensive information about the direction # Highest Occupants (since last reboot), Last Visited, Last Busy (3+) etc. (more ideas here) table.add_header('|wOcc', '|wLocation', '|wAvg Time', '|cTop 3 Active', '|gDirections') table.reformat_column(0, width=4, align='l') table.reformat_column(1, width=25, align='l') table.reformat_column(2, width=6, align='l') table.reformat_column(3, width=16, pad_right=1, align='l') table.reformat_column(4, width=20, align='l') locations = {} # Create an empty dictionary to gather locations information. for session in session_list: # Go through connected list and see who's where. if not session.logged_in: continue character = session.get_puppet() if not character: continue if character.location not in locations: locations[character.location] = [] locations[character.location].append(character) # Build the list of who's in a location for place in locations: location = place.get_display_name(you) if place else '|222Nothingness|n' table.add_row(len(locations[place]), location, '?', ', '.join(each.get_display_name(you) for each in locations[place]), 'Summon or walk') elif cmd == 'ws': my_character = self.caller.get_puppet(self.session) if not (my_character and my_character.location): self.msg("You can't see anyone here.") return table.add_header('|wCharacter', '|wOn for', '|wIdle') table.reformat_column(0, width=45, align='l') table.reformat_column(1, width=8, align='l') table.reformat_column(2, width=7, pad_right=1, align='r') for element in my_character.location.contents: if not element.has_account: continue delta_cmd = time.time() - max([each.cmd_last_visible for each in element.sessions.all()]) delta_con = time.time() - min([each.conn_time for each in element.sessions.all()]) name = element.get_display_name(you) type = element.attributes.get('species', default='') table.add_row(name + ', ' + type if type else name, utils.time_format(delta_con, 0), utils.time_format(delta_cmd, 1)) elif cmd == 'what' or cmd == 'wot': table.add_header('|wCharacter - Doing', '|wIdle') table.reformat_column(0, width=72, align='l') table.reformat_column(1, width=7, align='r') for session in session_list: if not session.logged_in or not session.get_puppet(): continue delta_cmd = time.time() - session.cmd_last_visible character = session.get_puppet() doing = character.get_display_name(you, pose=True) table.add_row(doing, utils.time_format(delta_cmd, 1)) else: # Default to displaying who if show_session_data: # privileged info shown to Immortals and higher only when not quelled table.add_header('|wCharacter', '|wAccount', '|wQuell', '|wCmds', '|wProtocol', '|wAddress') table.reformat_column(0, align='l') table.reformat_column(1, align='r') table.reformat_column(2, width=7, align='r') table.reformat_column(3, width=6, pad_right=1, align='r') table.reformat_column(4, width=11, align='l') table.reformat_column(5, width=16, align='r') session_list = sorted(session_list, key=lambda o: o.account.key) for session in session_list: if not session.logged_in: continue account = session.get_account() puppet = session.get_puppet() table.add_row(puppet.get_display_name(you) if puppet else 'None', account.get_display_name(you), '|gYes|n' if account.attributes.get('_quell') else '|rNo|n', session.cmd_total, session.protocol_key, isinstance(session.address, tuple) and session.address[0] or session.address) else: # unprivileged info shown to everyone, including Immortals and higher when quelled table.add_header('|wCharacter', '|wOn for', '|wIdle') table.reformat_column(0, width=40, align='l') table.reformat_column(1, width=8, align='l') table.reformat_column(2, width=7, align='r') for session in session_list: if not session.logged_in: continue delta_cmd = time.time() - session.cmd_last_visible delta_conn = time.time() - session.conn_time character = session.get_puppet() if not character: continue table.add_row(character.get_display_name(you), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1)) is_one = account_count == 1 string = '%s' % 'A' if is_one else str(account_count) string += ' single ' if is_one else ' unique ' plural = ' is' if is_one else 's are' string += 'account%s logged in.' % plural self.msg(table) self.msg(string)
def func(self): """Show list.""" global _IDMAPPER if not _IDMAPPER: from evennia.utils.idmapper import models as _IDMAPPER if "flushmem" in self.switches: # flush the cache prev, _ = _IDMAPPER.cache_size() nflushed = _IDMAPPER.flush_cache() now, _ = _IDMAPPER.cache_size() string = "The Idmapper cache freed |w{idmapper}|n database objects.\n" \ "The Python garbage collector freed |w{gc}|n Python instances total." self.caller.msg(string.format(idmapper=(prev - now), gc=nflushed)) return # display active processes os_windows = os.name == "nt" pid = os.getpid() if os_windows: # Windows requires the psutil module to even get paltry # statistics like this (it's pretty much worthless, # unfortunately, since it's not specific to the process) /rant try: import psutil has_psutil = True except ImportError: has_psutil = False if has_psutil: loadavg = psutil.cpu_percent() _mem = psutil.virtual_memory() rmem = _mem.used / (1000.0 * 1000) pmem = _mem.percent if "mem" in self.switches: string = "Total computer memory usage: |w%g|n MB (%g%%)" self.caller.msg(string % (rmem, pmem)) return # Display table loadtable = EvTable("property", "statistic", align="l") loadtable.add_row("Total CPU load", "%g %%" % loadavg) loadtable.add_row("Total computer memory usage", "%g MB (%g%%)" % (rmem, pmem)) loadtable.add_row("Process ID", "%g" % pid), else: loadtable = "Not available on Windows without 'psutil' library " \ "(install with |wpip install psutil|n)." else: # Linux / BSD (OSX) - proper pid-based statistics global _RESOURCE if not _RESOURCE: import resource as _RESOURCE loadavg = os.getloadavg()[0] rmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "rss")).read()) / 1000.0 # resident memory vmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "vsz")).read()) / 1000.0 # virtual memory pmem = float(os.popen('ps -p %d -o %s | tail -1' % (pid, "%mem")).read()) # % of resident memory to total rusage = _RESOURCE.getrusage(_RESOURCE.RUSAGE_SELF) if "mem" in self.switches: string = "Memory usage: RMEM: |w%g|n MB (%g%%), VMEM (res+swap+cache): |w%g|n MB." self.caller.msg(string % (rmem, pmem, vmem)) return loadtable = EvTable("property", "statistic", align="l") loadtable.add_row("Server load (1 min)", "%g" % loadavg) loadtable.add_row("Process ID", "%g" % pid), loadtable.add_row("Memory usage", "%g MB (%g%%)" % (rmem, pmem)) loadtable.add_row("Virtual address space", "") loadtable.add_row("|x(resident+swap+caching)|n", "%g MB" % vmem) loadtable.add_row("CPU time used (total)", "%s (%gs)" % (utils.time_format(rusage.ru_utime), rusage.ru_utime)) loadtable.add_row("CPU time used (user)", "%s (%gs)" % (utils.time_format(rusage.ru_stime), rusage.ru_stime)) loadtable.add_row("Page faults", "%g hard, %g soft, %g swapouts" % (rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap)) loadtable.add_row("Disk I/O", "%g reads, %g writes" % (rusage.ru_inblock, rusage.ru_oublock)) loadtable.add_row("Network I/O", "%g in, %g out" % (rusage.ru_msgrcv, rusage.ru_msgsnd)) loadtable.add_row("Context switching", "%g vol, %g forced, %g signals" % (rusage.ru_nvcsw, rusage.ru_nivcsw, rusage.ru_nsignals)) # os-generic string = "|wServer CPU and Memory load:|n\n%s" % loadtable # object cache count (note that sys.getsiseof is not called so this works for pypy too. total_num, cachedict = _IDMAPPER.cache_size() sorted_cache = sorted([(key, num) for key, num in cachedict.items() if num > 0], key=lambda tup: tup[1], reverse=True) memtable = EvTable("entity name", "number", "idmapper %", align="l") for tup in sorted_cache: memtable.add_row(tup[0], "%i" % tup[1], "%.2f" % (float(tup[1]) / total_num * 100)) string += "\n|w Entity idmapper cache:|n %i items\n%s" % (total_num, memtable) # return to caller self.caller.msg(string)
def test_style_0(self): """Test the style 0 of time_format.""" self.assertEqual(utils.time_format(0, 0), "00:00") self.assertEqual(utils.time_format(28, 0), "00:00") self.assertEqual(utils.time_format(92, 0), "00:01") self.assertEqual(utils.time_format(300, 0), "00:05") self.assertEqual(utils.time_format(660, 0), "00:11") self.assertEqual(utils.time_format(3600, 0), "01:00") self.assertEqual(utils.time_format(3725, 0), "01:02") self.assertEqual(utils.time_format(86350, 0), "23:59") self.assertEqual(utils.time_format(86800, 0), "1d 00:06") self.assertEqual(utils.time_format(130800, 0), "1d 12:20") self.assertEqual(utils.time_format(530800, 0), "6d 03:26")
def execute_cmd(self, session=None, txt=None, **kwargs): """ Take incoming data and send it to connected channel. This is triggered by the bot_data_in Inputfunc. Args: session (Session, optional): Session responsible for this command. Note that this is the bot. txt (str, optional): Command string. Keyword Args: user (str): The name of the user who sent the message. channel (str): The name of channel the message was sent to. type (str): Nature of message. Either 'msg', 'action', 'nicklist' or 'ping'. nicklist (list, optional): Set if `type='nicklist'`. This is a list of nicks returned by calling the `self.get_nicklist`. It must look for a list `self._nicklist_callers` which will contain all callers waiting for the nicklist. timings (float, optional): Set if `type='ping'`. This is the return (in seconds) of a ping request triggered with `self.ping`. The return must look for a list `self._ping_callers` which will contain all callers waiting for the ping return. """ if kwargs["type"] == "nicklist": # the return of a nicklist request if hasattr(self, "_nicklist_callers") and self._nicklist_callers: chstr = f"{self.db.irc_channel} ({self.db.irc_network}:{self.db.irc_port})" nicklist = ", ".join( sorted(kwargs["nicklist"], key=lambda n: n.lower())) for obj in self._nicklist_callers: obj.msg( _("Nicks at {chstr}:\n {nicklist}").format( chstr=chstr, nicklist=nicklist)) self._nicklist_callers = [] return elif kwargs["type"] == "ping": # the return of a ping if hasattr(self, "_ping_callers") and self._ping_callers: chstr = f"{self.db.irc_channel} ({self.db.irc_network}:{self.db.irc_port})" for obj in self._ping_callers: obj.msg( _("IRC ping return from {chstr} took {time}s.").format( chstr=chstr, time=kwargs["timing"])) self._ping_callers = [] return elif kwargs["type"] == "privmsg": # A private message to the bot - a command. user = kwargs["user"] if txt.lower().startswith("who"): # return server WHO list (abbreviated for IRC) global _SESSIONS if not _SESSIONS: from evennia.server.sessionhandler import SESSIONS as _SESSIONS whos = [] t0 = time.time() for sess in _SESSIONS.get_sessions(): delta_cmd = t0 - sess.cmd_last_visible delta_conn = t0 - session.conn_time account = sess.get_account() whos.append("%s (%s/%s)" % ( utils.crop("|w%s|n" % account.name, width=25), utils.time_format(delta_conn, 0), utils.time_format(delta_cmd, 1), )) text = f"Who list (online/idle): {', '.join(sorted(whos, key=lambda w: w.lower()))}" elif txt.lower().startswith("about"): # some bot info text = f"This is an Evennia IRC bot connecting from '{settings.SERVERNAME}'." else: text = "I understand 'who' and 'about'." super().msg(privmsg=((text, ), {"user": user})) else: # something to send to the main channel if kwargs["type"] == "action": # An action (irc pose) text = f"{kwargs['user']}@{kwargs['channel']} {txt}" else: # msg - A normal channel message text = f"{kwargs['user']}@{kwargs['channel']}: {txt}" if not self.ndb.ev_channel and self.db.ev_channel: # cache channel lookup self.ndb.ev_channel = self.db.ev_channel if self.ndb.ev_channel: self.ndb.ev_channel.msg(text, senders=self)
def test_style_1(self): """Test the style 1 of time_format.""" self.assertEqual(utils.time_format(0, 1), "0s") self.assertEqual(utils.time_format(28, 1), "28s") self.assertEqual(utils.time_format(92, 1), "1m") self.assertEqual(utils.time_format(300, 1), "5m") self.assertEqual(utils.time_format(660, 1), "11m") self.assertEqual(utils.time_format(3600, 1), "1h") self.assertEqual(utils.time_format(3725, 1), "1h") self.assertEqual(utils.time_format(86350, 1), "23h") self.assertEqual(utils.time_format(86800, 1), "1d") self.assertEqual(utils.time_format(130800, 1), "1d") self.assertEqual(utils.time_format(530800, 1), "6d")
def list_callbacks(self): """Display the list of callbacks connected to the object.""" obj = self.obj callback_name = self.callback_name parameters = self.parameters callbacks = self.handler.get_callbacks(obj) types = self.handler.get_events(obj) if callback_name: # Check that the callback name can be found in this object created = callbacks.get(callback_name) if created is None: self.msg("No callback {} has been set on {}.".format(callback_name, obj)) return if parameters: # Check that the parameter points to an existing callback try: number = int(parameters) - 1 assert number >= 0 callback = callbacks[callback_name][number] except (ValueError, AssertionError, IndexError): self.msg("The callback {} {} cannot be found in {}.".format( callback_name, parameters, obj)) return # Display the callback's details author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_by = callback.get("updated_by") updated_by = updated_by.key if updated_by else "|gUnknown|n" created_on = callback.get("created_on") created_on = created_on.strftime("%Y-%m-%d %H:%M:%S") if created_on else "|gUnknown|n" updated_on = callback.get("updated_on") updated_on = updated_on.strftime("%Y-%m-%d %H:%M:%S") if updated_on else "|gUnknown|n" msg = "Callback {} {} of {}:".format(callback_name, parameters, obj) msg += "\nCreated by {} on {}.".format(author, created_on) msg += "\nUpdated by {} on {}".format(updated_by, updated_on) if self.is_validator: if callback.get("valid"): msg += "\nThis callback is |rconnected|n and active." else: msg += "\nThis callback |rhasn't been|n accepted yet." msg += "\nCallback code:\n" msg += raw(callback["code"]) self.msg(msg) return # No parameter has been specified, display the table of callbacks cols = ["Number", "Author", "Updated", "Param"] if self.is_validator: cols.append("Valid") table = EvTable(*cols, width=78) table.reformat_column(0, align="r") now = datetime.now() for i, callback in enumerate(created): author = callback.get("author") author = author.key if author else "|gUnknown|n" updated_on = callback.get("updated_on") if updated_on is None: updated_on = callback.get("created_on") if updated_on: updated_on = "{} ago".format(time_format( (now - updated_on).total_seconds(), 4).capitalize()) else: updated_on = "|gUnknown|n" parameters = callback.get("parameters", "") row = [str(i + 1), author, updated_on, parameters] if self.is_validator: row.append("Yes" if callback.get("valid") else "No") table.add_row(*row) self.msg(unicode(table)) else: names = list(set(list(types.keys()) + list(callbacks.keys()))) table = EvTable("Callback name", "Number", "Description", valign="t", width=78) table.reformat_column(0, width=20) table.reformat_column(1, width=10, align="r") table.reformat_column(2, width=48) for name in sorted(names): number = len(callbacks.get(name, [])) lines = sum(len(e["code"].splitlines()) for e in callbacks.get(name, [])) no = "{} ({})".format(number, lines) description = types.get(name, (None, "Chained event."))[1] description = description.strip("\n").splitlines()[0] table.add_row(name, no, description) self.msg(unicode(table))
def test_style_2(self): """Test the style 2 of time_format.""" self.assertEqual(utils.time_format(0, 2), "0 minutes") self.assertEqual(utils.time_format(28, 2), "0 minutes") self.assertEqual(utils.time_format(92, 2), "1 minute") self.assertEqual(utils.time_format(300, 2), "5 minutes") self.assertEqual(utils.time_format(660, 2), "11 minutes") self.assertEqual(utils.time_format(3600, 2), "1 hour, 0 minutes") self.assertEqual(utils.time_format(3725, 2), "1 hour, 2 minutes") self.assertEqual(utils.time_format(86350, 2), "23 hours, 59 minutes") self.assertEqual(utils.time_format(86800, 2), "1 day, 0 hours, 6 minutes") self.assertEqual(utils.time_format(130800, 2), "1 day, 12 hours, 20 minutes") self.assertEqual(utils.time_format(530800, 2), "6 days, 3 hours, 26 minutes")
def func(self): """Display information about server or target""" sessions = self.account.sessions.get() session = sessions[-1] if sessions else None account = self.account char = self.character or account.db._last_puppet if not char: if account.db._playable_characters[0]: char = account.db._playable_characters[0] else: self.msg('You must have a character to interact with objects.') return cmd = self.cmdstring opt = self.switches args = unicode(self.args).strip() message = '' if args: obj = char.search(args, global_search=True) if obj: display_name = obj.get_display_name(char) object_summary = '' if obj.db.desc_brief or obj.db.messages and obj.db.messages.get( 'summary'): object_summary = '|w' + ( obj.db.desc_brief or obj.db.messages and obj.db.messages.get('summary', '')) object_name = (display_name + ' is |w' + repr(obj) + ' ' + object_summary + (('|wAliases: |C' + '|w, |C'.join(str(obj.aliases).split(','))) if str(obj.aliases) else '') + ' |gcreated on |g' + str(obj.db_date_created)[:10]) last_on = 0 on_count = 0 if obj.db.puppeted: times_awake = [] times_asleep = [] for each in obj.db.puppeted.values(): times_awake.append(each[0]) times_asleep.append(each[1]) on_count += each[2] time_awake = max(times_awake) if times_awake else None time_asleep = max(times_asleep) if times_asleep else None last_on_value = abs(time_awake - time_asleep) if ( time_awake and time_asleep) else 0 last_on = utils.time_format(last_on_value, 2) if last_on_value else 'None' if time_asleep: last_asleep = utils.time_format( int(time.time()) - time_asleep, 2) + ' ago' else: last_asleep = 'and is awake now' if obj.has_account else 'unknown' else: last_awake, last_asleep = 'unknown', 'unknown' if obj.has_account: # Object is awake: message = '{} is currently awake.'.format( obj.get_display_name(char)) elif obj.db.puppeted: message = '{} was last awake {} for {}.'.format( obj.get_display_name(char), last_asleep, last_on) else: message = '{} has no known last awake time.'.format( obj.get_display_name(char)) if 'last' in opt or 'last' in cmd: char.msg(message) return # If object has never been puppeted, use a different template that # does not include Awake count, awake times, and CPU use. from evennia import EvForm, EvTable if obj.db.puppeted: time_summary = (message + ' Awake ' + str(on_count) + ' time' + ('' if on_count == 1 else 's') + '. CPU use: ' + str(round(obj.traits.ct.current, 4)) + ' seconds, ' + str(obj.traits.cc.current) + ' commands, average ' + str( round( obj.traits.ct.current / obj.traits.cc.current, 4)) + ' sec each.') form_file = 'awakeformunicode' if session.protocol_flags[ 'ENCODING'] == 'utf-8' else 'awakeform' form = EvForm('commands/forms/{}.py'.format(form_file)) form.map( cells={ 1: object_name, 2: time_summary, 3: obj.db.messages and obj.db.messages.get('species', ''), 4: obj.db.messages and obj.db.messages.get('gender', ''), 5: obj.db.desc }) else: form_file = 'objectformunicode' if session.protocol_flags[ 'ENCODING'] == 'utf-8' else 'objectform' form = EvForm('commands/forms/{}.py'.format(form_file)) form.map( cells={ 1: object_name, 2: obj.db.messages and obj.db.messages.get('species', ''), 3: obj.db.messages and obj.db.messages.get('gender', ''), 4: obj.db.desc }) message = unicode(form) else: if 'last' in opt or 'last' in cmd: message = 'Usage: last <character name>' else: message = """ |cEvennia|n %s|n MUD/MUX/MU* development system |wLicense|n https://opensource.org/licenses/BSD-3-Clause |wWeb|n http://evennia.com |wIrc|n #evennia on FreeNode |wForum|n http://evennia.com/discussions |wMaintainer|n (2010-) Griatch (griatch AT gmail DOT com) |wMaintainer|n (2006-10) Greg Taylor |wOS|n %s |wPython|n %s |wTwisted|n %s |wDjango|n %s """ % (utils.get_evennia_version(), os.name, sys.version.split()[0], twisted.version.short(), django.get_version()) # char.msg(image=['https://raw.githubusercontent.com/evennia/evennia/' # 'master/evennia/web/website/static/website/images/evennia_logo.png']) self.msg((message, {"type": "help"}))
def test_style_3(self): """Test the style 3 of time_format.""" self.assertEqual(utils.time_format(0, 3), "") self.assertEqual(utils.time_format(28, 3), "28 seconds") self.assertEqual(utils.time_format(92, 3), "1 minute 32 seconds") self.assertEqual(utils.time_format(300, 3), "5 minutes 0 seconds") self.assertEqual(utils.time_format(660, 3), "11 minutes 0 seconds") self.assertEqual(utils.time_format(3600, 3), "1 hour, 0 minutes") self.assertEqual(utils.time_format(3725, 3), "1 hour, 2 minutes 5 seconds") self.assertEqual(utils.time_format(86350, 3), "23 hours, 59 minutes 10 seconds") self.assertEqual(utils.time_format(86800, 3), "1 day, 0 hours, 6 minutes 40 seconds") self.assertEqual(utils.time_format(130800, 3), "1 day, 12 hours, 20 minutes 0 seconds") self.assertEqual(utils.time_format(530800, 3), "6 days, 3 hours, 26 minutes 40 seconds")