def list_actions(self): """Lists the actions for the matching queryset""" qs = self.get_queryset_from_switches() table = EvTable("{wID", "{wplayer", "{wtldr", "{wdate", "{wcrisis", width=78, border="cells") for action in qs: if action.unanswered_questions: action_id = "{c*%s{n" % action.id else: action_id = action.id date = action.date_submitted.strftime( "%m/%d") if action.date_submitted else "----" table.add_row(action_id, action.dompc, action.topic, date, action.plot) table.reformat_column(0, width=9) table.reformat_column(1, width=10) table.reformat_column(2, width=37) table.reformat_column(3, width=8) table.reformat_column(4, width=14) arx_more.msg(self.caller, str(table), justify_kwargs=False, pages_by_char=True)
def format_script_list(scripts): """Takes a list of scripts and formats the output.""" if not scripts: return "<No scripts>" table = EvTable("|wdbref|n", "|wobj|n", "|wkey|n", "|wintval|n", "|wnext|n", "|wrept|n", "|wdb", "|wtypeclass|n", "|wdesc|n", align='r', border="tablecols") for script in scripts: nextrep = script.time_until_next_repeat() if nextrep is None: nextrep = "PAUS" if script.db._paused_time else "--" else: nextrep = "%ss" % nextrep maxrepeat = script.repeats if maxrepeat: rept = "%i/%i" % (maxrepeat - script.remaining_repeats(), maxrepeat) else: rept = "-/-" table.add_row(script.id, script.obj.key if (hasattr(script, 'obj') and script.obj) else "<Global>", script.key, script.interval if script.interval > 0 else "--", nextrep, rept, "*" if script.persistent else "-", script.typeclass_path.rsplit('.', 1)[-1], crop(script.desc, width=20)) return "%s" % table
def list_actions(self): """Prints a table of the actions we've taken""" table = EvTable("ID", "Crisis", "Date", "Owner", "Status") actions = self.actions_and_invites attending = list( actions.filter( Q(dompc=self.dompc, attending=True) | Q(assisting_actions__dompc=self.dompc, assisting_actions__attending=True))) for action in actions: date = "--" if action.date_submitted: date = action.date_submitted.strftime("%x") def color_unsubmitted(string): """Colors the status display for assisting actions of the player that aren't ready to submit""" if action.status == PlotAction.DRAFT and action.check_unready_assistant( self.dompc): return "|r%s|n" % string return string is_attending = action in attending id_str = "{w*%s{n" % action.id if is_attending else str(action.id) table.add_row(id_str, str(action.plot)[:20], date, str(action.dompc), color_unsubmitted(action.get_status_display())) msg = "\nActions you're attending will be highlighted with {w*{n." self.msg(str(table) + msg)
def func(self): """List the accounts""" caller = self.caller if self.args and self.args.isdigit(): nlim = int(self.args) else: nlim = 10 naccounts = AccountDB.objects.count() # typeclass table dbtotals = AccountDB.objects.object_totals() typetable = EvTable("|wtypeclass|n", "|wcount|n", "|w%%|n", border="cells", align="l") for path, count in dbtotals.items(): typetable.add_row(path, count, "%.2f" % ((float(count) / naccounts) * 100)) # last N table plyrs = AccountDB.objects.all().order_by("db_date_created")[max(0, naccounts - nlim):] latesttable = EvTable("|wcreated|n", "|wdbref|n", "|wname|n", "|wtypeclass|n", border="cells", align="l") for ply in plyrs: latesttable.add_row(utils.datetime_format(ply.date_created), ply.dbref, ply.key, ply.path) string = "\n|wAccount typeclass distribution:|n\n%s" % typetable string += "\n|wLast %s Accounts created:|n\n%s" % (min(naccounts, nlim), latesttable) caller.msg(string)
def list_tickets(self): """List tickets for goalupdates""" table = EvTable("{wID{n", "{wPlayer{n", "{wGoal{n") for ticket in self.tickets: table.add_row(ticket.id, str(ticket.submitting_player), ticket.goal_update.goal.summary) self.msg(str(table))
def get_text(self): """Display the app.""" try: number = self.app.phone_number pretty_number = self.app.pretty_phone_number except ValueError: self.msg("Your phone number couldn't be found.") self.back() return # Load the threads (conversations) to which "number" participated threads = Text.objects.get_threads_for(number) string = "Texts for {}".format(pretty_number) string += "\n" self.db["threads"] = {} stored_threads = self.db["threads"] if threads: len_i = 3 if len(threads) < 100 else 4 string += " Create a {new} message.\n".format( new=self.format_cmd("new")) i = 1 table = EvTable(pad_left=0, border="none") table.add_column("S", width=2) table.add_column("I", width=len_i, align="r", valign="t") table.add_column("Sender", width=21) table.add_column("Content", width=36) table.add_column("Ago", width=15) for thread_id, text in threads.items(): thread = text.db_thread stored_threads[i] = thread sender = text.recipients sender = [self.app.format(num) for num in sender] sender = ", ".join(sender) if thread.name: sender = thread.name sender = crop(sender, 20, "") content = text.content.replace("\n", " ") if text.sender.db_phone_number == number: content = "[You] " + content content = crop(content, 35) status = " " if thread.has_read(number) else "|rU|n" table.add_row(status, self.format_cmd(str(i)), sender, content, text.sent_ago.capitalize()) i += 1 lines = str(table).splitlines() del lines[0] lines = [line.rstrip() for line in lines] string += "\n" + "\n".join(lines) string += "\n\n(Type a number to open this text.)" else: string += "\n You have no texts yet. Want to create a {new} one?".format( new=self.format_cmd("new")) string += "\n\n(Enter {settings} to edit the app settings).".format( settings=self.format_cmd("settings")) count = Text.objects.get_texts_for(number).count() s = "" if count == 1 else "s" string += "\n\nText app: {} saved message{s}.".format(count, s=s) return string
def func(self): "List the players" caller = self.caller if self.args and self.args.isdigit(): nlim = int(self.args) else: nlim = 10 nplayers = PlayerDB.objects.count() # typeclass table dbtotals = PlayerDB.objects.object_totals() typetable = EvTable("{wtypeclass{n", "{wcount{n", "{w%%{n", border="cells", align="l") for path, count in dbtotals.items(): typetable.add_row(path, count, "%.2f" % ((float(count) / nplayers) * 100)) # last N table plyrs = PlayerDB.objects.all().order_by("db_date_created")[max(0, nplayers - nlim):] latesttable = EvTable("{wcreated{n", "{wdbref{n", "{wname{n", "{wtypeclass{n", border="cells", align="l") for ply in plyrs: latesttable.add_row(utils.datetime_format(ply.date_created), ply.dbref, ply.key, ply.path) string = "\n{wPlayer typeclass distribution:{n\n%s" % typetable string += "\n{wLast %s Players created:{n\n%s" % (min(nplayers, nlim), latesttable) caller.msg(string)
def list_flashbacks(self): from evennia.utils.evtable import EvTable table = EvTable("ID", "Title", "Owner", "New Posts", width=78, border="cells") for flashback in self.roster_entry.valid_flashbacks: table.add_row(flashback.id, flashback.title, flashback.owner, str(len(flashback.get_new_posts(self.roster_entry)))) self.msg(str(table))
def weekly_resonance_update(self): results = [] for practitioner in self.get_active_practitioners().all(): result = self.advance_weekly_resonance(practitioner) if result: results.append(result) from typeclasses.bulletin_board.bboard import BBoard board = BBoard.objects.get(db_key__iexact="staff") table = EvTable("{wName{n", "{wGain{n", "{wUnspent{n", "{wMax{n", border="cells", width=78) for result in results: table.add_row(result['name'], result['gain'], "%.2f" % result['resonance'], result['potential']) board.bb_post(poster_obj=self, msg=str(table), subject="Magic Resonance Gains", poster_name="Magic System") inform_staff("List of magic resonance gains posted.")
def weekly_practice_update(self): results = [] for practitioner in self.get_active_practitioners().all(): result = self.advance_weekly_practice(practitioner) if result: results.append(result) from typeclasses.bulletin_board.bboard import BBoard board = BBoard.objects.get(db_key__iexact="staff") table = EvTable(border="cells", width=78) table.add_column("|wName|n", width=20, valign='t') table.add_column("|wPractices|n", valign='t') for result in results: subtable = EvTable(border=None) for node in result['practices']: subtable.add_row(node['node'], "%.2f gain" % node['gain'], "%.2f total" % node['resonance'], node['teacher']) table.add_row(result['name'], str(subtable)) SkillNodeResonance.objects.filter( teaching_multiplier__isnull=False).update(teaching_multiplier=None, taught_by=None, taught_on=None) board.bb_post(poster_obj=self, msg=str(table), subject="Magic Practice Results", poster_name="Magic System") inform_staff("List of magic practice results posted.")
def _list_bots(): """ Helper function to produce a list of all IRC bots. Returns: bots (str): A table of bots or an error message. """ ircbots = [ bot for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="ircbot-") ] if ircbots: from evennia.utils.evtable import EvTable table = EvTable("|w#dbref|n", "|wbotname|n", "|wev-channel|n", "|wirc-channel|n", "|wSSL|n", maxwidth=_DEFAULT_WIDTH) for ircbot in ircbots: ircinfo = "%s (%s:%s)" % (ircbot.db.irc_channel, ircbot.db.irc_network, ircbot.db.irc_port) table.add_row("#%i" % ircbot.id, ircbot.db.irc_botname, ircbot.db.ev_channel, ircinfo, ircbot.db.irc_ssl) return table else: return "No irc bots found."
def pretty_print(self, looker, filter_stats=None, print_stats = True): # Get the currently equipped armor/weapons. data = [] s_width = 0; table = EvTable("|wLimb|n", "|wSlot|n", "|wItem|n", "|wLevel|n", "|wRarity|n", "|wDurability|n", border = "cells") # ISSUE 1480 - still under pull request if print_stats: table.add_column(header="|wStats|n") for slot, obj in self: wearName = slot if obj and not obj.access(looker, "view"): continue if not obj: objString = "" objLevel = "" objRarity = "" objDurability = "" else: # construct the string for the object. objString = "{name}".format(name=obj.name) objLevel = obj.get_level() objRarity = obj.get_rarity() objDurability = "{} %".format(obj.get_durability_percentage()) if (self.limbs): # For limbs, use the named limb instead. for limbName, slots in self.limbs.iteritems(): if slot in slots: # Check if limb attached to slot wearName = limbName # Set wearname to limb name. s_width = max(len(wearName), s_width) rowData = [wearName, slot, objString, objLevel, objRarity, objDurability] if print_stats and obj is not None: rowData.append(obj.pp_stats(looker=self.obj, excludeStats=["level", "rarity", "durability"])) table.add_row(*rowData) # data.append( # " |b{slot:>{swidth}.{swidth}}|n: {item:<20.20}".format( # slot=wearName.capitalize(), # swidth=s_width, # item=objName, # ) # ) return str(table)
def list_goals(self): """Displays our goals for our caller""" if "old" in self.switches: qs = self.goals.exclude(status=Goal.ACTIVE) else: qs = self.goals.filter(status=Goal.ACTIVE) table = EvTable("{wID{n", "{wSummary{n", "{wPlot{n") for ob in qs: table.add_row(ob.id, ob.summary, ob.plot) self.msg(str(table))
def page_formatter(self, page): """Input is a queryset page from django.Paginator""" caller = self._caller # get use-permissions of readonly attributes (edit is always False) display_tuples = [] table = EvTable( "|wKey|n", "|wSpawn/Edit|n", "|wTags|n", "|wDesc|n", border="tablecols", crop=True, width=self.width, ) for prototype in page: lock_use = caller.locks.check_lockstring(caller, prototype.get( "prototype_locks", ""), access_type="spawn", default=True) if not self.show_non_use and not lock_use: continue if prototype.get("prototype_key", "") in _MODULE_PROTOTYPES: lock_edit = False else: lock_edit = caller.locks.check_lockstring( caller, prototype.get("prototype_locks", ""), access_type="edit", default=True) if not self.show_non_edit and not lock_edit: continue ptags = [] for ptag in prototype.get("prototype_tags", []): if is_iter(ptag): if len(ptag) > 1: ptags.append("{}".format(ptag[0])) else: ptags.append(ptag[0]) else: ptags.append(str(ptag)) table.add_row( prototype.get("prototype_key", "<unset>"), "{}/{}".format("Y" if lock_use else "N", "Y" if lock_edit else "N"), ", ".join(list(set(ptags))), prototype.get("prototype_desc", "<unset>"), ) return str(table)
def view_plots_table(self, old=False, only_open_tickets=False, only_recruiting=False): """Returns an EvTable chock full of spicy Plots.""" from evennia.utils.evtable import EvTable qs = (self.filter(resolved=old).exclude( Q(usage=self.model.CRISIS) | Q(parent_plot__isnull=False)).distinct()) if only_open_tickets: from web.helpdesk.models import Ticket qs = qs.filter(tickets__status=Ticket.OPEN_STATUS) if only_recruiting: from .models import PCPlotInvolvement qs = qs.filter( Q(dompc_involvement__activity_status=PCPlotInvolvement.ACTIVE) & Q(dompc_involvement__admin_status__gte=PCPlotInvolvement. RECRUITER) & ~Q(dompc_involvement__recruiter_story="")).distinct() alt_header = "Resolved " if old else "" table = EvTable( "|w#|n", "|w%sPlot (owner)|n" % alt_header, "|wSummary|n", width=78, border="cells", ) for plot in qs: def get_plot_name_and_owner(plotmato): owner = (" (%s)" % plotmato.first_owner) if plotmato.first_owner else "" return "%s%s" % (str(plotmato), owner) def add_subplots_rows(subplot, color_num): sub_name = get_plot_name_and_owner(subplot) table.add_row("|%s35%s|n" % (color_num, subplot.id), sub_name, subplot.headline) color_num += 1 if color_num > 5: color_num = 0 for subplotmato in subplot.subplots.filter(resolved=old): add_subplots_rows(subplotmato, color_num) plot_name = get_plot_name_and_owner(plot) table.add_row(plot.id, plot_name, plot.headline) for subploterino in plot.subplots.filter(resolved=old): add_subplots_rows(subploterino, color_num=0) table.reformat_column(0, width=7) table.reformat_column(1, width=25) table.reformat_column(2, width=46) return table
def do_work_switches(self): """List all the works written by the character""" if self.args: work = self.get_work(self.args) self.msg(str(work.body)) return table = EvTable("|wID|n", "|wTitle|n", width=78) qs = self.caller.authored_works.all() for work in qs: table.add_row(work.id, work.pretty_title) self.msg(str(table))
def list_all_checks(self): checks = self.caller.traits.known_checks self.msg("|wAll checks:|n") table = EvTable("|wName", "|wCategory", "|wSystem", width=78, border="cells") for check in checks: table.add_row( check.name, check.category, check.dice_system.display_system_for_character(self.caller), ) self.msg(str(table))
def post_inactives(self): """Makes a board post of inactive characters""" date = datetime.now() cutoffdate = date - timedelta(days=30) qs = Account.objects.filter(roster__roster__name="Active", last_login__isnull=False).filter( last_login__lte=cutoffdate) board = BBoard.objects.get(db_key__iexact="staff") table = EvTable("{wName{n", "{wLast Login Date{n", border="cells", width=78) for ob in qs: table.add_row(ob.key.capitalize(), ob.last_login.strftime("%x")) board.bb_post(poster_obj=self, msg=str(table), subject="Inactive List", poster_name="Inactives") inform_staff("List of Inactive Characters posted.")
def page_formatter(self, scripts): """Takes a page of scripts and formats the output into an EvTable.""" if not scripts: return "<No scripts>" table = EvTable( "|wdbref|n", "|wobj|n", "|wkey|n", "|wintval|n", "|wnext|n", "|wrept|n", "|wdb", "|wtypeclass|n", "|wdesc|n", align="r", border="tablecols", width=self.width ) for script in scripts: nextrep = script.time_until_next_repeat() if nextrep is None: nextrep = "PAUSED" if script.db._paused_time else "--" else: nextrep = "%ss" % nextrep maxrepeat = script.repeats remaining = script.remaining_repeats() or 0 if maxrepeat: rept = "%i/%i" % (maxrepeat - remaining, maxrepeat) else: rept = "-/-" table.add_row( script.id, f"{script.obj.key}({script.obj.dbref})" if (hasattr(script, "obj") and script.obj) else "<Global>", script.key, script.interval if script.interval > 0 else "--", nextrep, rept, "*" if script.persistent else "-", script.typeclass_path.rsplit(".", 1)[-1], crop(script.desc, width=20), ) return str(table)
def list_crises(self): qs = self.viewable_crises resolved = "old" in self.switches qs = qs.filter(usage=Plot.CRISIS, resolved=resolved) table = EvTable("{w#{n", "{wName{n", "{wDesc{n", "{wUpdates On{n", width=78, border="cells") for ob in qs: date = "--" if not ob.end_date else ob.end_date.strftime("%m/%d") table.add_row(ob.id, ob.name, ob.headline, date) table.reformat_column(0, width=7) table.reformat_column(1, width=20) table.reformat_column(2, width=40) table.reformat_column(3, width=11) self.msg(table)
def func(self): from evennia import TICKER_HANDLER all_subs = TICKER_HANDLER.all_display() if not all_subs: self.caller.msg("No tickers are currently active.") return table = EvTable("interval (s)", "object", "path/methodname", "idstring", "db") for sub in all_subs: table.add_row(sub[3], "%s%s" % (sub[0] or "[None]", sub[0] and " (#%s)" % (sub[0].id if hasattr(sub[0], "id") else "") or ""), sub[1] if sub[1] else sub[2], sub[4] or "[Unset]", "*" if sub[5] else "-") self.caller.msg("|wActive tickers|n:\n" + unicode(table))
def func(self): def name(item): return item.name open_quests = sorted(self.caller.db.open_quests, key=name) open_quests = (quest for quest in open_quests if not quest.hidden) closed_quests = sorted(self.caller.db.closed_quests, key=name) if self.opts.type == "open": table = EvTable("Name", "Description") for quest in open_quests: table.add_row(quest.name, quest.description) elif self.opts.type == "closed": table = EvTable("Name", "Description") for quest in closed_quests: table.add_row(quest.name, quest.description) elif self.opts.type == "all": table = EvTable("Name", "Description", "Status") for quest in open_quests: table.add_row(quest.name, quest.description, "Open") for quest in closed_quests: table.add_row(quest.name, quest.description, "Closed") table.reformat(width=72) if len(table.get()) <= 3: self.caller.msg("You have no quests meeting that description.") else: self.caller.msg(table)
def list_flashbacks(self): from evennia.utils.evtable import EvTable roster = self.roster_entry flashbacks = roster.flashbacks.all() if not flashbacks: self.msg("No flashbacks available to list. Why not create one?") return table = EvTable("ID", "Flashback", "Owner", "New Posts", width=78, border="cells") for flashback in flashbacks: new_posts = str(flashback.get_new_posts(roster).count()) color = "|g" if flashback.posts_allowed_by(self.caller) else "" fb_id = "%s%s|n" % (color, flashback.id) table.add_row(fb_id, flashback.title, flashback.owner, new_posts) self.msg(str(table))
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 count_poses(self): """Makes a board post of characters with insufficient pose-counts""" qs = ObjectDB.objects.filter(roster__roster__name="Active") min_poses = 20 low_activity = [] for ob in qs: if (ob.posecount < min_poses and (ob.tags.get("rostercg")and ob.player_ob and not ob.player_ob.tags.get("staff_alt"))): low_activity.append(ob) ob.db.previous_posecount = ob.posecount ob.posecount = 0 board = BBoard.objects.get(db_key__iexact="staff") table = EvTable("{wName{n", "{wNum Poses{n", border="cells", width=78) for ob in low_activity: table.add_row(ob.key, ob.db.previous_posecount) board.bb_post(poster_obj=self, msg=str(table), subject="Inactive by Poses List")
def list_crises(self): super(CmdViewCrisis, self).list_crises() self.msg("{wYour pending actions:{n") table = EvTable("{w#{n", "{wCrisis{n") current_actions = [ob for ob in self.current_actions if ob.plot] + [ ass.plot_action for ass in self.assisted_actions.exclude( plot_action__status__in=(PlotAction.PUBLISHED, PlotAction.CANCELLED)) if ass.plot_action.plot] for ob in current_actions: table.add_row(ob.id, ob.plot) self.msg(table) past_actions = [ob for ob in self.caller.past_participated_actions if ob.plot] if past_actions: table = EvTable("{w#{n", "{wCrisis{n") self.msg("{wYour past actions:{n") for ob in past_actions: table.add_row(ob.id, ob.plot) self.msg(table)
def _list_bots(): """ Helper function to produce a list of all IRC bots. Returns: bots (str): A table of bots or an error message. """ ircbots = [bot for bot in AccountDB.objects.filter(db_is_bot=True, username__startswith="ircbot-")] if ircbots: from evennia.utils.evtable import EvTable table = EvTable("|w#dbref|n", "|wbotname|n", "|wev-channel|n", "|wirc-channel|n", "|wSSL|n", maxwidth=_DEFAULT_WIDTH) for ircbot in ircbots: ircinfo = "%s (%s:%s)" % (ircbot.db.irc_channel, ircbot.db.irc_network, ircbot.db.irc_port) table.add_row("#%i" % ircbot.id, ircbot.db.irc_botname, ircbot.db.ev_channel, ircinfo, ircbot.db.irc_ssl) return table else: return "No irc bots found."
def func(self): if "set" in self.switches: try: factor = float(self.args) gametime.set_time_factor(factor) self.msg("IC time now runs at {}:1 scale.".format(factor)) except ValueError: self.msg( "You need to provide a number for the new time factor.") return elif "history" in self.switches: from datetime import datetime from evennia.utils.evtable import EvTable table = EvTable("Real Time", "Game Date", "Multiplier") for tdict in gametime.time_intervals(): dt = datetime.fromtimestamp(tdict["real"]) ic_time = gametime._format( tdict["game"], gametime.YEAR, gametime.MONTH, gametime.WEEK, gametime.DAY, gametime.HOUR, gametime.MIN, ) month, day, year = ic_time[1] + 1, ic_time[3] + 1, ic_time[ 0] + 1001 real_time = dt.strftime("%m/%d/%Y %H:%M") ic_timestamp = "{}/{}/{} {}:{}".format(month, day, year, ic_time[4], ic_time[5]) multiplier = tdict["multiplier"] table.add_row(real_time, ic_timestamp, multiplier) self.msg(table) return factor = gametime.time_factor() self.msg("IC time is running at {}:1 scale".format(factor))
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 get_inventory(self, arg_type): owner = self.owner items = owner.contents main_hand, off_hand = owner.db.hands.values() equip_items = owner.db.equipment.values() # Remove hands and append all other items to a new list. filtered_items = [] for i in items: if i not in [main_hand, off_hand]: if i not in equip_items: filtered_items.append(i) if not filtered_items: string = "Your inventory is empty." else: # if arg_type == 0: # Generate summary # Count the number of items in the inventory. # Show the maximum number of inventory slots. # Show each category that has an item and how many items are in the category # Show items in hands. # Show currency. if arg_type == 1: table = EvTable(border="header") string = self.get_all_items(filtered_items, table) else: final_list = self.get_inv_final_list(filtered_items, arg_type) table = EvTable(border="header") for item in final_list: table.add_row(f"|C{item.name}|n {item.db.desc or ''}") category_string = self.get_category_string(arg_type) string = f"|wYou are carrying:\n{category_string}\n{table}" # Add currency string = f"{string}\n{owner.currency.return_currency(owner)}" owner.msg(string)
def func(self): "List the players" caller = self.caller if self.args and self.args.isdigit(): nlim = int(self.args) else: nlim = 10 nplayers = PlayerDB.objects.count() # typeclass table dbtotals = PlayerDB.objects.object_totals() typetable = EvTable("{wtypeclass{n", "{wcount{n", "{w%%{n", border="cells", align="l") for path, count in dbtotals.items(): typetable.add_row(path, count, "%.2f" % ((float(count) / nplayers) * 100)) # last N table plyrs = PlayerDB.objects.all().order_by( "db_date_created")[max(0, nplayers - nlim):] latesttable = EvTable("{wcreated{n", "{wdbref{n", "{wname{n", "{wtypeclass{n", border="cells", align="l") for ply in plyrs: latesttable.add_row(utils.datetime_format(ply.date_created), ply.dbref, ply.key, ply.path) string = "\n{wPlayer typeclass distribution:{n\n%s" % typetable string += "\n{wLast %s Players created:{n\n%s" % (min( nplayers, nlim), latesttable) caller.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 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): """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 func(self): "Setup the irc-channel mapping" if not settings.IRC_ENABLED: string = """IRC is not enabled. You need to activate it in game/settings.py.""" self.msg(string) return if 'list' in self.switches: # show all connections ircbots = [bot for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="ircbot-")] if ircbots: from evennia.utils.evtable import EvTable table = EvTable("{wdbid{n", "{wbotname{n", "{wev-channel{n", "{wirc-channel{n", "{wSSL{n", maxwidth=_DEFAULT_WIDTH) for ircbot in ircbots: ircinfo = "%s (%s:%s)" % (ircbot.db.irc_channel, ircbot.db.irc_network, ircbot.db.irc_port) table.add_row(ircbot.id, ircbot.db.irc_botname, ircbot.db.ev_channel, ircinfo, ircbot.db.irc_ssl) self.caller.msg(table) else: self.msg("No irc bots found.") return if('disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches): botname = "ircbot-%s" % self.lhs matches = PlayerDB.objects.filter(db_is_bot=True, username=botname) dbref = utils.dbref(self.lhs) if not matches and dbref: # try dbref match matches = PlayerDB.objects.filter(db_is_bot=True, id=dbref) if matches: matches[0].delete() self.msg("IRC connection destroyed.") else: self.msg("IRC connection/bot could not be removed, does it exist?") return if not self.args or not self.rhs: string = "Usage: @irc2chan[/switches] <evennia_channel> = <ircnetwork> <port> <#irchannel> <botname>" self.msg(string) return channel = self.lhs self.rhs = self.rhs.replace('#', ' ') # to avoid Python comment issues try: irc_network, irc_port, irc_channel, irc_botname = \ [part.strip() for part in self.rhs.split(None, 3)] irc_channel = "#%s" % irc_channel except Exception: string = "IRC bot definition '%s' is not valid." % self.rhs self.msg(string) return botname = "ircbot-%s" % irc_botname irc_ssl = "ssl" in self.switches # create a new bot bot = PlayerDB.objects.filter(username__iexact=botname) if bot: # re-use an existing bot bot = bot[0] if not bot.is_bot: self.msg("Player '%s' already exists and is not a bot." % botname) return else: bot = create.create_player(botname, None, None, typeclass=bots.IRCBot) bot.start(ev_channel=channel, irc_botname=irc_botname, irc_channel=irc_channel, irc_network=irc_network, irc_port=irc_port, irc_ssl=irc_ssl) self.msg("Connection created. Starting IRC bot.")
def func(self): """Implement command""" caller = self.caller switches = self.switches if switches and switches[0] not in ("list", "start", "stop", "delete"): caller.msg("Usage: @service/<list|start|stop|delete> [servicename]") return # get all services service_collection = SESSIONS.server.services if not switches or switches[0] == "list": # Just display the list of installed services and their # status, then exit. table = EvTable("|wService|n (use @services/start|stop|delete)", "|wstatus", align="l") for service in service_collection.services: table.add_row(service.name, service.running and "|gRunning" or "|rNot Running") caller.msg(unicode(table)) return # Get the service to start / stop try: service = service_collection.getServiceNamed(self.args) except Exception: string = 'Invalid service name. This command is case-sensitive. ' string += 'See @service/list for valid service name (enter the full name exactly).' caller.msg(string) return if switches[0] in ("stop", "delete"): # Stopping/killing a service gracefully closes it and disconnects # any connections (if applicable). delmode = switches[0] == "delete" if not service.running: caller.msg('That service is not currently running.') return if service.name[:7] == 'Evennia': if delmode: caller.msg("You cannot remove a core Evennia service (named 'Evennia***').") return string = "You seem to be shutting down a core Evennia service (named 'Evennia***'). Note that" string += "stopping some TCP port services will *not* disconnect users *already*" string += "connected on those ports, but *may* instead cause spurious errors for them. To " string += "safely and permanently remove ports, change settings file and restart the server." caller.msg(string) if delmode: service.stopService() service_collection.removeService(service) caller.msg("Stopped and removed service '%s'." % self.args) else: service.stopService() caller.msg("Stopped service '%s'." % self.args) return if switches[0] == "start": # Attempt to start a service. if service.running: caller.msg('That service is already running.') return caller.msg("Starting service '%s'." % self.args) service.startService()
def func(self): """Implement the command""" caller = self.caller nlim = int(self.args) if self.args and self.args.isdigit() else 10 nobjs = ObjectDB.objects.count() base_char_typeclass = settings.BASE_CHARACTER_TYPECLASS nchars = ObjectDB.objects.filter(db_typeclass_path=base_char_typeclass).count() nrooms = ObjectDB.objects.filter(db_location__isnull=True).exclude( db_typeclass_path=base_char_typeclass).count() nexits = ObjectDB.objects.filter(db_location__isnull=False, db_destination__isnull=False).count() nother = nobjs - nchars - nrooms - nexits nobjs = nobjs or 1 # fix zero-div error with empty database # total object sum table totaltable = EvTable("|wtype|n", "|wcomment|n", "|wcount|n", "|w%%|n", border="table", align="l") totaltable.align = 'l' totaltable.add_row("Characters", "(BASE_CHARACTER_TYPECLASS)", nchars, "%.2f" % ((float(nchars) / nobjs) * 100)) totaltable.add_row("Rooms", "(location=None)", nrooms, "%.2f" % ((float(nrooms) / nobjs) * 100)) totaltable.add_row("Exits", "(destination!=None)", nexits, "%.2f" % ((float(nexits) / nobjs) * 100)) totaltable.add_row("Other", "", nother, "%.2f" % ((float(nother) / nobjs) * 100)) # typeclass table typetable = EvTable("|wtypeclass|n", "|wcount|n", "|w%%|n", border="table", align="l") typetable.align = 'l' dbtotals = ObjectDB.objects.object_totals() for path, count in dbtotals.items(): typetable.add_row(path, count, "%.2f" % ((float(count) / nobjs) * 100)) # last N table objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim):] latesttable = EvTable("|wcreated|n", "|wdbref|n", "|wname|n", "|wtypeclass|n", align="l", border="table") latesttable.align = 'l' for obj in objs: latesttable.add_row(utils.datetime_format(obj.date_created), obj.dbref, obj.key, obj.path) string = "\n|wObject subtype totals (out of %i Objects):|n\n%s" % (nobjs, totaltable) string += "\n|wObject typeclass distribution:|n\n%s" % typetable string += "\n|wLast %s Objects created:|n\n%s" % (min(nobjs, nlim), latesttable) caller.msg(string)
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 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): """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): "Setup the rss-channel mapping" # checking we have all we need if not settings.RSS_ENABLED: string = """RSS is not enabled. You need to activate it in game/settings.py.""" self.msg(string) return try: import feedparser feedparser # to avoid checker error of not being used except ImportError: string = ("RSS requires python-feedparser (https://pypi.python.org/pypi/feedparser). " "Install before continuing.") self.msg(string) return if 'list' in self.switches: # show all connections rssbots = [bot for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="rssbot-")] if rssbots: from evennia.utils.evtable import EvTable table = EvTable("{wdbid{n", "{wupdate rate{n", "{wev-channel", "{wRSS feed URL{n", border="cells", maxwidth=_DEFAULT_WIDTH) for rssbot in rssbots: table.add_row(rssbot.id, rssbot.db.rss_rate, rssbot.db.ev_channel, rssbot.db.rss_url) self.caller.msg(table) else: self.msg("No rss bots found.") return if('disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches): botname = "rssbot-%s" % self.lhs matches = PlayerDB.objects.filter(db_is_bot=True, db_key=botname) if not matches: # try dbref match matches = PlayerDB.objects.filter(db_is_bot=True, id=self.args.lstrip("#")) if matches: matches[0].delete() self.msg("RSS connection destroyed.") else: self.msg("RSS connection/bot could not be removed, does it exist?") return if not self.args or not self.rhs: string = "Usage: @rss2chan[/switches] <evennia_channel> = <rss url>" self.msg(string) return channel = self.lhs url = self.rhs botname = "rssbot-%s" % url # create a new bot bot = PlayerDB.objects.filter(username__iexact=botname) if bot: # re-use existing bot bot = bot[0] if not bot.is_bot: self.msg("Player '%s' already exists and is not a bot." % botname) return else: bot = create.create_player(botname, None, None, typeclass=bots.RSSBot) bot.start(ev_channel=channel, rss_url=url, rss_rate=10) self.msg("RSS reporter created. Fetching RSS.")