def handle_lifecycle_events(ed_player, entry): if entry["event"] in ["Music"] and entry["MusicTrack"] == "MainMenu" and not ed_player.is_crew_member(): # Checking for 'is_crew_member' because "MainMenu" shows up when joining a multicrew session # Assumption: being a crew member while main menu happens means that a multicrew session is about to start. # { "timestamp":"2018-06-19T13:06:04Z", "event":"QuitACrew", "Captain":"Dummy" } # { "timestamp":"2018-06-19T13:06:16Z", "event":"Music", "MusicTrack":"MainMenu" } EDR_CLIENT.clear() ed_player.game_mode = None ed_player.leave_wing() ed_player.leave_crew() EDRLOG.log(u"Player is on the main menu.", "DEBUG") return if entry["event"] == "Shutdown": EDRLOG.log(u"Shutting down in-game features...", "INFO") EDR_CLIENT.shutdown() return if entry["event"] == "Resurrect": EDR_CLIENT.clear() ed_player.resurrect() EDRLOG.log(u"Player has been resurrected.", "DEBUG") return if entry["event"] in ["Fileheader"] and entry["part"] == 1: EDR_CLIENT.clear() ed_player.inception() EDR_CLIENT.status = _(u"initialized.") EDRLOG.log(u"Journal player got created: accurate picture of friends/wings.", "DEBUG") if entry["event"] in ["LoadGame"]: EDR_CLIENT.clear() ed_player.inception() ed_player.game_mode = entry["GameMode"] EDRLOG.log(u"Game mode is {}".format(ed_player.game_mode), "DEBUG") if not ed_player.in_solo_or_private(): EDR_CLIENT.warmup()
def short_profile(self): result = u"{name}: {karma}".format(name=self.name, karma=self.karma_title()) alignment = self.crowd_alignment() if not (alignment is None or alignment == ""): result += u" {}".format(alignment) if not (self.squadron is None or self.squadron == ""): result += u", {squadron}".format(squadron=self.squadron) if not (self.role is None or self.role == ""): result += u", {role}".format(role=self.role) if not (self.powerplay is None or self.powerplay == ""): result += u", {powerplay}".format(powerplay=self.powerplay) if not (self.patreon is None or self.patreon == ""): result += u", Patreon:{patreon}".format(patreon=self.patreon) if self.dex_profile: if self.dex_profile.friend: result += _(u" [friend]") tags = self.dex_profile.tags if tags: result += u", #{}".format(" #".join(tags)) memo = self.dex_profile.memo if memo: result += u", {}".format(memo) updated_jse = self.dex_profile.updated if updated_jse: updated_edt = edtime.EDTime() updated_edt.from_js_epoch(updated_jse) result += u" ({})".format(updated_edt.as_immersive_date()) return result
def check_version(self): version_range = self.server.server_version() self.motd = _edr(version_range["l10n_motd"]) if version_range is None: # Translators: this is shown on EDMC's status bar when the version check fails self.status = _(u"check for version update has failed.") return if self.is_obsolete(version_range["min"]): EDRLOG.log( u"Mandatory update! {version} vs. {min}".format( version=self.edr_version, min=version_range["min"]), "ERROR") self.mandatory_update = True self.__status_update_pending() elif self.is_obsolete(version_range["latest"]): EDRLOG.log( u"EDR update available! {version} vs. {latest}".format( version=self.edr_version, latest=version_range["latest"]), "INFO") self.mandatory_update = False self.__status_update_pending()
def pretty_print_timespan(timespan, short=False, verbose=False): if timespan < 0: raise ValueError('Invalid input') remaining = timespan days = remaining / 86400 remaining -= days * 86400 hours = (remaining / 3600) % 24 remaining -= hours * 3600 minutes = (remaining / 60) % 60 remaining -= minutes * 60 seconds = (remaining % 60) readable = "" if days > 0: suffix = (_c(u"suffix| days") if days > 1 else _c(u"suffix| day")) if verbose else _c(u"short suffix|d") readable = _(u"{nb_days}{suffix}").format(nb_days=days, suffix=suffix) if hours > 0 and not short: suffix = (_c(u"suffix| hours") if hours > 1 else _c(u"suffix| hour")) if verbose else _c(u"short suffix|h") readable += _(u":{nb_hours}{suffix}").format(nb_hours=hours, suffix=suffix) elif hours > 0: suffix = (_c(u"suffix| hours") if hours > 1 else _c(u"suffix| hour")) if verbose else _c(u"short suffix|h") readable = _(u"{nb_hours}{suffix}").format(nb_hours=hours, suffix=suffix) if minutes > 0 and not short: suffix = (_c(u"suffix| minutes") if minutes > 1 else _c(u"suffix| minute")) if verbose else _c(u"short suffix|m") readable += _(u":{nb_minutes}{suffix}").format(nb_minutes=minutes, suffix=suffix) elif minutes > 0: suffix = (_c(u"suffix| minutes") if minutes > 1 else _c(u"suffix| minute")) if verbose else _c(u"short suffix|m") readable = _(u"{nb_minutes}{suffix}").format(nb_minutes=minutes, suffix=suffix) if seconds > 0 and not short: suffix = (_c(u"suffix| seconds") if seconds > 1 else _c(u"suffix| second")) if verbose else _c(u"short suffix|s") readable += _(u":{nb_seconds}{suffix}").format(nb_seconds=seconds, suffix=suffix) else: suffix = (_c(u"suffix| seconds") if seconds > 1 else _c(u"suffix| second")) if verbose else _c(u"short suffix|s") readable = _(u"{nb_seconds}{suffix}").format(nb_seconds=seconds, suffix=suffix) return readable
def pretty_print(self): readable = u"" if self.value >= 10000000000: # Translators: this is a short representation for a bounty >= 10 000 000 000 credits (b stands for billion) readable = _(u"{} b").format(self.value // 1000000000) elif self.value >= 1000000000: # Translators: this is a short representation for a bounty >= 1 000 000 000 credits (b stands for billion) readable = _(u"{:.1f} b").format(self.value / 1000000000.0) elif self.value >= 10000000: # Translators: this is a short representation for a bounty >= 10 000 000 credits (m stands for million) readable = _(u"{} m").format(self.value // 1000000) elif self.value > 1000000: # Translators: this is a short representation for a bounty >= 1 000 000 credits (m stands for million) readable = _(u"{:.1f} m").format(self.value / 1000000.0) elif self.value >= 10000: # Translators: this is a short representation for a bounty >= 10 000 credits (k stands for kilo, i.e. thousand) readable = _(u"{} k").format(self.value // 1000) elif self.value >= 1000: # Translators: this is a short representation for a bounty >= 1000 credits (k stands for kilo, i.e. thousand) readable = _(u"{:.1f} k").format(self.value / 1000.0) else: # Translators: this is a short representation for a bounty < 1000 credits (i.e. shows the whole bounty, unabbreviated) readable = _(u"{}").format(self.value) return readable
def mining_guidance(self, mining_stats): self.clear_mining_guidance() if "panel" in self.cfg["mining"]: self.__shape("mining", self.cfg["mining"]["panel"]) if "panel" in self.cfg["mining-graphs"] and self.cfg["mining-graphs"].get("enabled", False): self.__shape("mining-graphs", self.cfg["mining-graphs"]["panel"]) header = _(u"Mining Stats") details = [] has_stuff = mining_stats.last["proportion"] > 0 details.append(_(u"ITM %: {:>6.2f} [{}/{}; {}]".format(mining_stats.last["proportion"], 1 if has_stuff else 0, mining_stats.last["materials"], mining_stats.last["raw"]))) details.append(_(u"MAX %: {:>6.2f}".format(mining_stats.max))) details.append(_(u"AVG %: {:>6.2f}".format(mining_stats.mineral_yield_average()))) details.append(_(u"ITM/H: {:>6.0f} [TGT: {:.0f}]".format(mining_stats.mineral_per_hour(), mining_stats.max_efficiency))) details.append(_(u"ITM #: {:>6}".format(mining_stats.refined_nb))) self.__msg_header("mining", header) self.__msg_body("mining", details) if not self.cfg["mining-graphs"].get("enabled", None): return self.__mining_vizualization(mining_stats)
def journal_entry(cmdr, is_beta, system, station, entry, state): """ :param cmdr: :param system: :param station: :param entry: :param state: :return: """ ed_player = EDR_CLIENT.player ed_player.friends = state["Friends"] if not prerequisites(EDR_CLIENT, is_beta): return if entry["event"] in ["Music", "Resurrect", "Fileheader", "LoadGame"]: handle_lifecycle_events(ed_player, entry) if ed_player.in_solo_or_private(): EDR_CLIENT.status = _(u"disabled in Solo/Private.") EDRLOG.log(u"Game mode is {}: skip!".format(ed_player.game_mode), "INFO") return if entry["event"] in ["WingAdd", "WingJoin", "WingLeave"]: handle_wing_events(ed_player, entry) EDR_CLIENT.player_name(cmdr) ship = state["ShipType"] status_outcome = {"updated": False, "reason": "Unspecified"} status_outcome["updated"] = ed_player.update_ship_if_obsolete( ship, entry["timestamp"]) status_outcome["updated"] |= ed_player.update_star_system_if_obsolete( system, entry["timestamp"]) if entry["event"] in [ "Location", "Undocked", "Docked", "DockingCancelled", "DockingDenied", "DockingGranted", "DockingRequested", "DockingTimeout" ]: outcome = handle_change_events(ed_player, entry) if outcome["updated"]: status_outcome["updated"] = True status_outcome["reason"] = outcome["reason"] if entry["event"] in [ "SupercruiseExit", "FSDJump", "SupercruiseEntry", "StartJump", "ApproachSettlement" ]: outcome = handle_movement_events(ed_player, entry) if outcome["updated"]: status_outcome["updated"] = True status_outcome["reason"] = outcome["reason"] if entry["event"] in [ "Interdicted", "Died", "EscapeInterdiction", "Interdiction", "PVPKill" ]: report_crime(ed_player, entry) if entry["event"] in [ "ShipTargeted" ] and "ScanStage" in entry and entry["ScanStage"] > 0: handle_scan_events(ed_player, entry) if entry["event"] in ["ReceiveText", "SendText"]: report_comms(ed_player, entry) if entry["event"] in ["SendText"]: handle_commands(ed_player, entry) if status_outcome["updated"]: edr_update_cmdr_status(ed_player, status_outcome["reason"])
def handle_multicrew_events(ed_player, entry): if entry["event"] in ["CrewMemberJoins", "CrewMemberRoleChange", "CrewLaunchFighter"]: crew = plain_cmdr_name(entry["Crew"]) success = ed_player.add_to_crew(crew) if success: # only show intel on the first add EDR_CLIENT.status = _(u"added to crew: ").format(crew) EDRLOG.log(u"Addition to crew: {}".format(ed_player.crew.members), "INFO") EDR_CLIENT.who(crew, autocreate=True) if entry["event"] in ["CrewMemberQuits", "KickCrewMember"]: crew = plain_cmdr_name(entry["Crew"]) duration = ed_player.crew_time_elapsed(crew) kicked = entry["event"] == "KickCrewMember" crimes = False if not "OnCrimes" in entry else entry["OnCrimes"] ed_player.remove_from_crew(crew) EDR_CLIENT.status = _(u"{} left the crew.".format(crew)) EDRLOG.log(u"{} left the crew.".format(crew), "INFO") edt = EDTime() edt.from_journal_timestamp(entry["timestamp"]) report = { "captain": ed_player.crew.captain, "timestamp": edt.as_js_epoch(), "crew" : crew, "duration": duration, "kicked": kicked, "crimes": crimes, "destroyed": ed_player.destroyed if ed_player.is_captain() else False } edr_submit_multicrew_session(ed_player, report) if entry["event"] in ["JoinACrew"]: captain = plain_cmdr_name(entry["Captain"]) ed_player.join_crew(captain) EDR_CLIENT.status = _(u"joined a crew.") EDRLOG.log(u"Joined captain {}'s crew".format(captain), "INFO") EDR_CLIENT.who(captain, autocreate=True) if entry["event"] in ["QuitACrew"] and ed_player.crew: for member in ed_player.crew.members: duration = ed_player.crew_time_elapsed(member) edt = EDTime() edt.from_journal_timestamp(entry["timestamp"]) report = { "captain": ed_player.crew.captain, "timestamp": edt.as_js_epoch(), "crew" : member, "duration": duration, "kicked": False, "crimes": False, "destroyed": ed_player.destroyed if ed_player.is_captain() else False } edr_submit_multicrew_session(ed_player, report) ed_player.leave_crew() EDR_CLIENT.status = _(u"left crew.") EDRLOG.log(u"Left the crew.", "INFO") if entry["event"] in ["EndCrewSession"] and ed_player.crew: crimes = False if not "OnCrimes" in entry else entry["OnCrimes"] for member in ed_player.crew.members: duration = ed_player.crew_time_elapsed(member) edt = EDTime() edt.from_journal_timestamp(entry["timestamp"]) report = { "captain": ed_player.crew.captain, "timestamp": edt.as_js_epoch(), "crew" : member, "duration": duration, "kicked": False, "crimes": crimes, "destroyed": ed_player.destroyed if ed_player.is_captain() else False } edr_submit_multicrew_session(ed_player, report) ed_player.disband_crew() EDR_CLIENT.status = _(u"crew disbanded.") EDRLOG.log(u"Crew disbanded.", "INFO")
def journal_entry(cmdr, is_beta, system, station, entry, state): """ :param cmdr: :param system: :param station: :param entry: :param state: :return: """ ed_player = EDR_CLIENT.player ed_player.friends = state["Friends"] if not prerequisites(EDR_CLIENT, is_beta): return if entry["event"] in ["Shutdown", "ShutDown", "Music", "Resurrect", "Fileheader", "LoadGame"]: handle_lifecycle_events(ed_player, entry) if entry["event"].startswith("Powerplay"): EDRLOG.log(u"Powerplay event: {}".format(entry), "INFO") handle_powerplay_events(ed_player, entry) if entry["event"] == "Statistics" and not ed_player.powerplay: # There should be a Powerplay event before the Statistics event # if not then the player is not pledged and we should reflect that on the server EDR_CLIENT.pledged_to(None) if entry["event"] == "Friends": handle_friends_events(ed_player, entry) if ed_player.in_solo_or_private(): EDR_CLIENT.status = _(u"disabled in Solo/Private.") EDRLOG.log(u"Game mode is {}: skip!".format(ed_player.game_mode), "INFO") return if "Crew" in entry["event"]: handle_multicrew_events(ed_player, entry) if entry["event"] in ["WingAdd", "WingJoin", "WingLeave"]: handle_wing_events(ed_player, entry) EDR_CLIENT.player_name(cmdr) if ed_player.is_crew_member(): ship = u"Unknown" else: ship = edentities.EDVehicles.canonicalize(state["ShipType"]) status_outcome = {"updated": False, "reason": "Unspecified"} status_outcome["updated"] = ed_player.update_ship_if_obsolete(ship, entry["timestamp"]) status_outcome["updated"] |= ed_player.update_star_system_if_obsolete(system, entry["timestamp"]) if entry["event"] in ["Location", "Undocked", "Docked", "DockingCancelled", "DockingDenied", "DockingGranted", "DockingRequested", "DockingTimeout"]: outcome = handle_change_events(ed_player, entry) if outcome["updated"]: status_outcome["updated"] = True status_outcome["reason"] = outcome["reason"] if entry["event"] in ["SupercruiseExit", "FSDJump", "SupercruiseEntry", "StartJump", "ApproachSettlement"]: outcome = handle_movement_events(ed_player, entry) if outcome["updated"]: status_outcome["updated"] = True status_outcome["reason"] = outcome["reason"] if entry["event"] in ["Interdicted", "Died", "EscapeInterdiction", "Interdiction", "PVPKill"]: report_crime(ed_player, entry) if entry["event"] in ["ShipTargeted"]: if "ScanStage" in entry and entry["ScanStage"] > 0: handle_scan_events(ed_player, entry) elif ("ScanStage" in entry and entry["ScanStage"] == 0) or ("TargetLocked" in entry and not entry["TargetLocked"]): ed_player.target = None if entry["event"] in ["ReceiveText", "SendText"]: report_comms(ed_player, entry) if entry["event"] in ["SendText"]: handle_commands(ed_player, entry) if status_outcome["updated"]: edr_update_cmdr_status(ed_player, status_outcome["reason"]) if ed_player.in_a_crew(): for member in ed_player.crew.members: if member == ed_player.name: continue source = u"Multicrew (captain)" if ed_player.is_captain(member) else u"Multicrew (crew)" edr_submit_contact(member, ship, entry["timestamp"], source, ed_player)
class HelpContent(object): DEFAULT_CONTENT = { "": { "header": _(u"Help sections"), "details": [ _(u" - !help about: what is EDR, who is behind it, etc"), _(u" - !help basics: getting started with EDR"), _(u" - !help account: doing more with an EDR account (free)"), _(u" - !help system: star system related features"), _(u" - !help cmdr: commander related features"), _(u" - !help enforcers: features for enforcers / bounty hunters"), _(u" - !help cmdrdex: personalizing EDR's commanders database"), _(u" - !help config: configuration options"), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "about": { "header": _(u"About EDR"), "details": [ _(u"ED Recon is a third party plugin for Elite Dangerous. Its purpose is to provide insights about outlaws to traders, explorers, and bounty hunters."), _(u" - EDR is in beta, is developed by LeKeno from Cobra Kai, and uses a customized version of Ian Norton's EDMCOverlay for the overlay."), _(u" - It is TOS compliant because it uses Elite Dangerous's player journal which has been designed for third party consumption."), _(u" - EDR is free to use but you can support EDR's development and server costs at https://patreon.com/lekeno"), _(u" - Got feedback or questions? Please file bugs, feature requests or questions at https://github.com/lekeno/edr/issues/"), u"⚶", _(u"Translations (see https://github.com/lekeno/edr/issues/135)."), _(u" - Contributions by : Juniper Nomi'Tar [UGC], Tomski [bbFA]"), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "basics": { "header": _(u"Getting started with EDR"), "details": [ _(u"EDR will proactively show various insights as you fly around and scan other commanders:"), _(u" - A summary of recent activity as you jump into a system."), _(u" - EDR and Inara profile for known outlaws as they are sighted (e.g. scanned) or detected (e.g. chat)."), u"⚶", _(u"You can ask EDR for insights by issuing various commands via the in-game chat:"), _(u" - '!sitrep Lave' to find out if Lave has seen some recent activity."), _(u" - '!notams' to find out which systems are considered hotspots."), _(u"Learn more with '!help system' and '!help cmdr'"), u"⚶", _(u"You can also customize EDR to your needs with the cmdrdex features, send '!help cmdrdex' to learn more."), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "account": { "header": _(u"EDR account"), "details": [ _(u"While EDR provides useful information without any credentials, it has a lot more to offer with an account."), u"⚶", _(u"Important: with an account EDR may report your location to the backend. However, this information will not be shown to other EDR users."), _(u"In the future, this might be used to help enforcers join forces or for check and balance reasons, e.g. reporting outlaw EDR users."), u"⚶", _(u"An EDR account is free and unlocks all of EDR's features. For instance:"), _(u" - personalizing / augmenting EDR's commanders database."), _(u" - reporting of traffic, outlaws and crimes."), _(u" - reporting scans of commanders with legal status and bounties."), u"⚶", _(u"These insights will also help other EDR users so consider applying for an EDR account at https://lekeno.github.io/"), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "system": { "header": _(u"Star system related features"), "details": [ _(u"When jumping to a system, EDR will show a sitrep for the system: active notices, i.e. NOTAM, summary of recent activity, etc."), _(u"Send the following command via the in-game chat to get intel about recent activity or specific systems:"), _(u" - '!sitreps': to display a list of star systems with sitreps."), _(u" - '!sitrep': to display the sitrep for the current system."), _(u" - '!sitrep system_name': to display the sitrep for the star system called system_name."), _(u" - '!notams': to display a list of star systems with active notices, i.e. Notice To Air Men."), _(u" - '!notam system_name': to display any active notice the star system called system_name."), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "cmdr": { "header": _(u"Commander related features"), "details": [ _(u"Use the following chat commands to lookup a commander's profile:"), _(u" - 'o7': direct message a commander with a salute emoji to see their EDR and Inara profile."), _(u" - '!who cmdr_name': to see cmdr_name's EDR and Inara profile."), _(u"These commands will show the following information:"), _(u" - EDR alignment: wanted, neutral, enforcer with grades, e.g. wanted ++++."), _(u" - User tags: [!12, ?1, +0], i.e. 12 users marked that commander as an outlaw, 1 as neutral, 0 as enforcer."), _(u" - Inara info: squadron and role if any (sometimes superseded by EDR)."), _(u" - Personal tags/info from your CmdrDex if any (see !help cmdrdex)."), _(u" - Legal record: # of clean vs. wanted scans, max and latest known bounties"), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "enforcers": { "header": _(u"Enforcers"), "details": [ _(u"Chat commands for enforcers:"), _(u" - '!outlaws': to display a list of most recently sighted outlaws and their locations."), _(u" - '!where cmdr_name': to display the last sighting of the cmdr called cmdr_name provided that EDR considers them an outlaw."), _(u" - '#!' or '#?' or '#+': to mark a cmdr as an outlaw, neutral or enforcer (see !help cmdrdex for more details)."), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "cmdrdex": { "header": _(u"Personalizing EDR's commanders database"), "details": [ _(u"The CmdrDex allows you to customize EDR and helps EDR users make informed guesses about other commanders."), _(u"Your CmdrDex is personal, EDR will only show aggregated stats for the alignment tags."), _(u"General rules for the cmdrdex chat commands:"), _(u" - '#something' or '#something cmdr_name': to tag a contact or cmdr_name with the 'something' tag, e.g. #pirate jack sparrow."), _(u" - '-#something' or '-#something cmdr_name': to remove the 'something' tag from a contact or cmdr_name."), _(u" - '-#' or '-# cmdr_name': to remove a contact or cmdr_name from your cmdrdex."), u"⚶", _(u"EDR pre-defined tags:"), _(u" - 'outlaw' or '!': for cmdrs who either attacked you or someone despite being clean and non pledged to an enemy power."), _(u" - 'enforcer' or '+': for cmdrs who are on the good side of the law and hunt outlaws."), _(u" - 'neutral' or '?': if you disagree with EDR's classification and want to suppress its warning, or if a commander just seems to go about their own business."), _(u" - 'friend' or '=': to tag like-minded cmdrs, EDR may infer a social graph from these in the future."), u"⚶", _(u"Attaching a note:"), _(u" - '@# <memo>' or '@# cmdr_name memo=something': to attach a note to a contact or cmdr_name, e.g. '@# friendly trader."), _(u" - '-@#' or '-@# cmdr_name': to remove the custom note from a contact or cmdr_name."), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] }, "config": { "header": _(u"Configuration options"), "details": [ _(u"EDR offers the following configuration options:"), _(u" - !crimes [off|on]: to disable/enable crime reporting, e.g. '!crimes off' before an agreed upon duel."), _(u" - !audiocue [on|off|loud|soft] to control the audio cues, e.g. '!audiocue soft' for soft cues."), _(u" - !overlay [on|off|] to enable/disable or verify the overlay, e.g. '!overlay' to check if it is enabled/working."), _(u" - check the instructions in config/igm_config.v2.ini to customize the layout and timeouts."), u"⚶", _(u"Send !clear in chat to clear everything on the overlay.") ] } } def __init__(self, help_file=None): if help_file: self.content = json.loads(open(os.path.join( os.path.abspath(os.path.dirname(__file__)), help_file)).read()) else: self.content = HelpContent.DEFAULT_CONTENT def get(self, category): if category in self.content.keys(): return self.content[category] return None
def soft_audio_feedback(self): config.set("EDRAudioFeedbackVolume", "soft") self.AUDIO_FEEDBACK.soft() # Translators: this is shown on EDMC's status bar when a user enables soft audio cues self.status = _(u"soft audio cues.")
def scanned(self, cmdr_name, scan): cmdr_id = self.cmdr_id(cmdr_name) if cmdr_id is None: self.status = _(u"cmdr unknown to EDR.") EDRLOG.log( u"Can't submit scan (no cmdr id for {}).".format(cmdr_name), "ERROR") return if self.novel_enough_scan(cmdr_id, scan, cognitive=True): profile = self.cmdr(cmdr_name) legal = self.edrlegal.summarize_recents(profile.cid) bounty = edentities.EDBounty( scan["bounty"]) if scan["bounty"] else None if profile and (self.player.name != cmdr_name): if profile.is_dangerous(): # Translators: this is shown via EDMC's EDR status line upon contact with a known outlaw self.status = _(u"{} is bad news.").format(cmdr_name) details = [profile.short_profile()] if bounty: details.append( _(u"Wanted for {} cr").format( edentities.EDBounty( scan["bounty"]).pretty_print())) elif scan["wanted"]: details.append( _(u"Wanted somewhere. A Kill-Warrant-Scan will reveal their highest bounty." )) if legal: details.append(legal) self.__warning(_(u"Warning!"), details) elif self.intel_even_if_clean or (scan["wanted"] and bounty.is_significant()): self.status = _(u"Intel for cmdr {}.").format(cmdr_name) details = [profile.short_profile()] if bounty: details.append( _(u"Wanted for {} cr").format( edentities.EDBounty( scan["bounty"]).pretty_print())) elif scan["wanted"]: details.append( _(u"Wanted somewhere but it could be minor offenses." )) if legal: details.append(legal) self.__intel(_(u"Intel"), details) if (self.is_anonymous() and (profile.is_dangerous() or (scan["wanted"] and bounty.is_significant()))): # Translators: this is shown to users who don't yet have an EDR account self.advertise_full_account( _(u"You could have helped other EDR users by reporting this outlaw!" )) self.cognitive_scans_cache.set(cmdr_id, scan) if not self.novel_enough_scan(cmdr_id, scan): self.status = _(u"not novel enough (scan).") EDRLOG.log(u"Scan is not novel enough to warrant reporting", "INFO") return True if self.is_anonymous(): EDRLOG.log("Skipping reporting scan since the user is anonymous.", "INFO") self.scans_cache.set(cmdr_id, scan) return False success = self.server.scanned(cmdr_id, scan) if success: self.status = _(u"scan reported for {}.").format(cmdr_name) self.scans_cache.set(cmdr_id, scan) return success
def __init__(self): super(EDREncodedTraderCheck, self).__init__() self.name = 'Encoded data trader' self.hint = _(u"Look for systems with medium-high security, a 'high tech' or 'military' economy, and a rather large population (>= 1 million)")
def tip(self): category = random.choice(self.tips.keys()) return edri18n._(random.choice(self.tips[category]))
def add_file(self, filename, name): with open(filename, "rb") as f: self.files.append({"file": f.read(), "filename":name) class EDRDiscordEmbed(object): def __init__(self): self.title = "" self.url = "" self.description = "" self.color = 14177041 self.author = { "name": "", "url": "", "icon_url": "" } self.fields = [] self.image = { "url": "" } self.thumbnail = { "url": "" } self.footer = { "text": "Message sent via ED Recon", "icon_url": "https://lekeno.github.io/favicon-16x16.png" } self.timestamp = datetime.now().isoformat() class EDRDiscordField(object): def __init__(self): self.name = "" self.value = "" self.inline = False def json(self): return self.__dict__ class EDRDiscordWebhook(object): SESSION = requests.Session() def __init__(self, webhook_url): self.webhook_url = webhook_url #self.backoff = backoff.Backoff(u"Discord"), def send_text(self, text): if not self.webhook_url: return False #if self.backoff.throttled(): # return False message = DiscordSimpleMessage(text) payload_json = message.json() resp = EDRDiscordWebhook.SESSION.post(self.webhook_url, json=payload_json) return self.__check_response(resp) def send(self, discord_message): if not self.webhook_url: return False #if self.backoff.throttled(): # return False resp = None payload_json = discord_message.json() if discord_message.files: files = discord_message.files files["payload_json"] = (None, json.dumps(payload_json)) resp = EDRDiscordWebhook.SESSION.post(self.webhook_url, files=files) else: resp = EDRDiscordWebhook.SESSION.post(self.webhook_url, json=payload_json) return self.__check_response(resp) def __check_response(self, response): if not response: return False if response.status_code in [200, 204, 404, 401, 403, 204]: #self.backoff.reset() pass elif response.status_code in [429, 500]: #self.backoff.throttle() pass return response.status_code in [200, 204] class EDRDiscordIntegration(object): # TODO pass the player itself since that would be handy to show system, location etc. def __init__(self, player): self.player = player self.afk_detector = EDRAfkDetector() user_config = EDRUserConfig() self.afk_wh = EDRDiscordWebhook(user_config.discord_afk_webhook()) self.broadcast_wh = EDRDiscordWebhook(user_config.discord_broadcast_webhook()) self.squadron_wh = EDRDiscordWebhook(user_config.discord_squadron_webhook()) self.squadron_leaders_wh = EDRDiscordWebhook(user_config.discord_squadron_leaders_webhook()) def process(self, entry): self.afk_detector.process(entry) # TODO move AFK state to player. if entry["event"] == "ReceiveText": return self.__process_incoming(entry) elif entry["event"] == "SendText": return self.__process_outgoing(entry) return False def __process_incoming(self, entry): if entry.get("Channel", None) in ["player", "friend"] and self.afk_detector.is_afk() and self.afk_wh: # TODO verify the friend thing dm = EDRDiscordMessage() dm.content = _(u"Direct message received while AFK") dm.timestamp = entry["timestamp"] de = EDRDiscordEmbed() de.title = _("To Cmdr `{}`").format(self.player.name) de.description = entry["Message"] de.author = { "name": entry["From"], "url": "", "icon_url": "" } de.color = self.__cmdrname_to_discord_color(entry["From"]) dm.add_embed(de) return self.afk_wh.send(dm) # TODO other: report my target? return False def __cmdrname_to_discord_color(self, name): saturation = [0.35, 0.5, 0.65] lightness = [0.35, 0.5, 0.65] hash = crc32(name.encode("utf-8")) & 0xFFFFFFFF h = hash % 359 hash //= 360 s = saturation[hash % len(saturation)] hash //= len(saturation) l = lightness[hash % len(lightness)] h /= 360 q = l * (1 + s) if l < 0.5 else l + s - l * s p = 2 * l - q rgb = [] for c in (h + 1 / 3, h, h - 1 / 3): if c < 0: c += 1 elif c > 1: c -= 1 if c < 1 / 6: c = p + (q - p) * 6 * c elif c < 0.5: c = q elif c < 2 / 3: c = p + (q - p) * 6 * (2 / 3 - c) else: c = p rgb.append(round(c * 255)) return (rgb[0] << 16) + (rgb[1] << 8) + rgb[2] def __process_outgoing(self, entry): # TODO simplify if self.squadron_leaders_wh and entry["To"] == "squadleaders": dm = EDRDiscordMessage() dm.content = _(u"Squadron Leaders message") dm.timestamp = entry["timestamp"] de = EDRDiscordEmbed() de.title = _("Channel `{}`").format(entry["To"]) de.description = entry["Message"] de.author = { "name": self.player.name, "url": "", "icon_url": "" } de.color = self.__cmdrname_to_discord_color(self.player.name) dm.add_embed(de) return self.broadcast_wh.send(dm) if self.squadron_wh and entry["To"] == "squadron": dm = EDRDiscordMessage() dm.content = _(u"Squadron message") dm.timestamp = entry["timestamp"] de = EDRDiscordEmbed() de.title = _("Channel `{}`").format(entry["To"]) de.description = entry["Message"] de.author = { "name": self.player.name, "url": "", "icon_url": "" } de.color = self.__cmdrname_to_discord_color(self.player.name) dm.add_embed(de) return self.broadcast_wh.send(dm) command_parts = entry["Message"].split(" ", 1) command = command_parts[0].lower() if not command: return False if not command[0] == "!" or len(command_parts) < 2: return False if command == "!discord": if self.broadcast_wh: dm = EDRDiscordMessage() dm.content = _(u"Incoming broadcast") dm.timestamp = entry["timestamp"] de = EDRDiscordEmbed() de.title = _("Channel `{}`").format(entry["To"]) de.description = " ".join(command_parts[1:]) de.author = { "name": self.player.name, "url": "", "icon_url": "" } de.color = self.__cmdrname_to_discord_color(self.player.name) dm.add_embed(de) return self.broadcast_wh.send(dm) # TODO other return False
def tip(self): category = random.choice(list(self.tips)) return edri18n._(random.choice(self.tips[category]))
def __init__(self): super(EDRGuardianTechBrokerCheck, self).__init__('Technology Broker') self.name = _(u'Guardian Technology Broker') self.hint = _(u"Look for systems with a 'high tech' economy', and a rather large population (>= 1 million)")
def docking(self, system, station, pad): self.clear_docking() if not station: return if "panel" in self.cfg["docking"]: self.__shape("docking", self.cfg["docking"]["panel"]) if "panel" in self.cfg["docking-station"] and self.cfg["docking-station"].get("enabled", False): self.__shape("docking-station", self.cfg["docking-station"]["panel"]) economy = u"{}/{}".format(station["economy"], station["secondEconomy"]) if station["secondEconomy"] else station["economy"] header = u"{} ({})".format(station["name"], economy) station_type = (station.get("type","N/A") or "N/A").lower() station_other_services = (station.get("otherServices", []) or []) station_economy = (station.get('economy', "") or "").lower() station_second_economy = (station.get('secondEconomy', "") or "").lower() details = [] a = u"◌" if station_type in ["outpost"] else u"●" b = u"●" if station.get("haveOutfitting", False) else u"◌" c = u"●" if station.get("haveShipyard", False) else u"◌" details.append(_(u"LG. Pad:{} Outfit:{} Shipyard:{}").format(a,b,c)) a = u"●" if "Refuel" in station_other_services else u"◌" b = u"●" if "Repair" in station_other_services else u"◌" c = u"●" if "Restock" in station_other_services else u"◌" details.append(_(u"Refuel:{} Repair:{} Restock:{}").format(a,b,c)) a = u"●" if station.get("haveMarket", False) else u"◌" b = u"●" if "Black Market" in station_other_services else u"◌" c = u"◌" m = _c(u"material trader|M.") if "Material Trader" in station_other_services: c = u"●" if station_economy in ['extraction', 'refinery']: if not station["secondEconomy"]: m = _(u"RAW") elif station_second_economy == "industrial": m = _(u"R/M") elif station_second_economy in ["high tech", "military"]: m = _(u"R/E") elif station_economy == 'industrial': if not station["secondEconomy"]: m = _(u"MAN") elif station_second_economy in ["extraction", "refinery"]: m = _(u"M/R") elif station_second_economy in ["high tech", "military"]: m = _(u"M/E") elif station_economy in ['high tech', 'military']: if not station["secondEconomy"]: m = _(u"ENC") elif station_second_economy in ["extraction", "refinery"]: m = _(u"E/R") elif station_second_economy == "industrial": m = _(u"E/M") details.append(_(u"Market:{} B.Market:{} {} Trad:{}").format(a,b,m,c)) a = u"●" if "Interstellar Factors Contact" in station_other_services else u"◌" t = _c(u"tech broker|T.") b = u"◌" if "Technology Broker" in station_other_services: b = u"●" if station_economy == 'high tech': if not station["secondEconomy"]: t = _c(u"guardian tech|GT.") elif station_second_economy == "industrial": t = _c(u"ambiguous tech|T.") elif station_economy == 'industrial': if not station["secondEconomy"]: t = _c(u"human tech|HT.") elif station_second_economy == "high tech": t = _c(u"ambiguous tech|T.") details.append(_(u"I.Factor:{} {} Broker:{}").format(a,t,b)) details.append(_(u"as of {date}").format(date=station['updateTime']['information'])) self.__msg_header("docking", header) self.__msg_body("docking", details) if not self.cfg["docking-station"]["enabled"]: return {"header": header, "body": details} if station_type in ["asteroid base", 'bernal starport', "coriolis starport", "ocellus starport", "orbis starport", "bernal", "bernal statioport"]: self.__station_schematic(pad) else: self.__landable_schematic(system, station, pad) return {"header": header, "body": details}
def alignment(self): lut = { u"outlaw": _(u"outlaw"), u"neutral": _(u"neutral"), u"enforcer": _(u"enforcer") } return lut.get(self._alignment, None)
def nearby(self): servicePrime = None serviceAlt = None system = self.edr_systems.system(self.star_system) if not system: return None system = system[0] system['distance'] = 0 possibility = self.checker.check_system(system) accessible = not system.get('requirePermit', False) or (system.get( 'requirePermit', False) and system['name'] in self.permits) EDRLOG.log( u"System {}: possibility {}, accessible {}".format( system['name'], possibility, accessible), "DEBUG") if possibility and accessible: candidate = self.__service_in_system(system) if candidate: ambiguous = self.checker.is_service_availability_ambiguous( candidate) check_sc_distance = candidate[ 'distanceToArrival'] <= self.sc_distance check_landing_pads = self.__has_large_lading_pads( candidate['type']) if self.large_pad_required else True EDRLOG.log( u"System {} is a candidate: ambiguous {}, sc_distance {}, landing_pads {}" .format(system['name'], ambiguous, check_sc_distance, check_landing_pads), "DEBUG") if check_sc_distance and check_landing_pads and not ambiguous: EDRLOG.log( u"System {} is a prime candidate. Stopping here.". format(system['name']), "DEBUG") servicePrime = system servicePrime['station'] = candidate return servicePrime else: serviceAlt = system serviceAlt['station'] = candidate if ambiguous: serviceAlt['comment'] = _(u"[Confidence: LOW]") systems = self.edr_systems.systems_within_radius( self.star_system, self.radius) if not systems: return None candidates = {'prime': servicePrime, 'alt': serviceAlt} candidates = self.__search(systems, candidates) if candidates and candidates.get('prime', None): serviceAlt = candidates['alt'] servicePrime = candidates['prime'] else: EDRLOG.log( u"Couldn't find any candidate so far. Trying again after a shuffle", "DEBUG") shuffle(systems) candidates = self.__search(systems, candidates) if candidates: serviceAlt = candidates['alt'] servicePrime = candidates['prime'] return servicePrime if servicePrime else serviceAlt
def __readable_name(name): lut = { "int_hyperdrive": _(u"FSD"), "int_engine": _(u"thruster"), "int_shieldgenerator": _(u"shield"), 'int_dockingcomputer_standard': _(u"docking computer"), 'int_dockingcomputer_advanced': _(u"docking computer"), 'int_dockingcomputer': _(u"docking computer"), 'hpt_cargoscanner': _(u"cargo scanner"), 'int_fuelscoop': _(u"fuel scoop"), 'hpt_crimescanner': _(u"bounty scanner"), 'int_supercruiseassist': _(u"supercruise assist"), 'int_detailedsurfacescanner_tiny': _(u"surface scanner"), } return lut.get(name, name)
def iff(self): lut = {u"enemy": _(u"enemy"), u"ally": _(u"ally")} return lut.get(self._iff, None)
def prefs_ui(self, parent): frame = notebook.Frame(parent) frame.columnconfigure(1, weight=1) # Translators: this is shown in the preferences panel ttkHyperlinkLabel.HyperlinkLabel( frame, text=_(u"EDR website"), background=notebook.Label().cget('background'), url="https://github.com/lekeno/edr/", underline=True).grid(padx=10, sticky=tk.W) # Translators: this is shown in the preferences panel notebook.Label(frame, text=_(u'Credentials')).grid(padx=10, sticky=tk.W) ttk.Separator(frame, orient=tk.HORIZONTAL).grid(columnspan=2, padx=10, pady=2, sticky=tk.EW) # Translators: this is shown in the preferences panel cred_label = notebook.Label( frame, text=_(u'Log in with your EDR account for full access')) cred_label.grid(padx=10, columnspan=2, sticky=tk.W) notebook.Label(frame, text=_(u"Email")).grid(padx=10, row=11, sticky=tk.W) notebook.Entry(frame, textvariable=self._email).grid(padx=10, row=11, column=1, sticky=tk.EW) notebook.Label(frame, text=_(u"Password")).grid(padx=10, row=12, sticky=tk.W) notebook.Entry(frame, textvariable=self._password, show=u'*').grid(padx=10, row=12, column=1, sticky=tk.EW) # Translators: this is shown in the preferences panel as a heading for feedback options (e.g. overlay, audio cues) notebook.Label(frame, text=_(u"EDR Feedback:")).grid(padx=10, row=14, sticky=tk.W) ttk.Separator(frame, orient=tk.HORIZONTAL).grid(columnspan=2, padx=10, pady=2, sticky=tk.EW) notebook.Checkbutton(frame, text=_(u"Overlay"), variable=self._visual_feedback).grid(padx=10, row=16, sticky=tk.W) notebook.Checkbutton(frame, text=_(u"Sound"), variable=self._audio_feedback).grid(padx=10, row=17, sticky=tk.W) if self.server.is_authenticated(): self.status = _(u"authenticated.") else: self.status = _(u"not authenticated.") return frame
def __init__(self): super(EDRManufacturedTraderCheck, self).__init__() self.name = 'Manufactured material trader' self.hint = _(u"Look for systems with medium-high security, an 'industrial' economy, and a rather large population (>= 1 million)")
def loud_audio_feedback(self): config.set("EDRAudioFeedbackVolume", "loud") self.AUDIO_FEEDBACK.loud() # Translators: this is shown on EDMC's status bar when a user enables loud audio cues self.status = _(u"loud audio cues.")
def __init__(self): super(EDRHumanTechBrokerCheck, self).__init__('Technology Broker') self.name = _(u'Human Technology Broker') self.hint = _(u"Look for systems with an 'Industrial' economy', and a rather large population (>= 1 million)")
def short_profile(self, powerplay=None): edr_parts = [] mapped_index = int(10 * (self._karma + self.max_karma()) / (2.0 * self.max_karma())) lut = [ _(u"Outlaw++++"), _(u"Outlaw+++"), _(u"Outlaw++"), _(u"Outlaw+"), _(u"Outlaw"), _(u"Ambiguous"), _(u"Lawful"), _(u"Lawful+"), _(u"Lawful++"), _(u"Lawful+++"), _(u"Lawful++++") ] karma = "" if self.dyn_karma: karma += u"≈ " karma += lut[mapped_index] edr_parts.append(karma) alignment = self.crowd_alignment() if not (alignment is None or alignment == ""): edr_parts.append(alignment) if not (self.patreon is None or self.patreon == ""): edr_parts.append(u"${patreon}".format(patreon=self.patreon)) inara_parts = [] if not (self.squadron is None or self.squadron == ""): inara_parts.append(self.squadron) if not (self.role is None or self.role == ""): inara_parts.append(self.role) powerplay_parts = [] if not (self.powerplay is None or self.powerplay == ""): inara_parts.append(self.powerplay) if powerplay and powerplay.is_enemy(self.powerplay): powerplay_parts.append(_c(u"powerplay|enemy")) sqdex_parts = [] iff = self.sqdrdex_profile.iff if self.sqdrdex_profile else None iff_by = self.sqdrdex_profile.iff_by if self.sqdrdex_profile else None if iff and iff_by: sqdex_parts.append( _(u"{iff} by {tagged_by}").format(iff=iff, tagged_by=iff_by)) elif iff: sqdex_parts.append(iff) cdex_parts = [] if self.dex_profile: alignment = self.dex_profile.alignment if self.dex_profile else None if alignment: cdex_parts.append(u"#{}".format(alignment)) if self.dex_profile.friend: cdex_parts.append(_(u"#friend")) tags = self.dex_profile.tags if tags: cdex_parts.append(u"#{}".format(" #".join(tags))) memo = self.dex_profile.memo if memo: cdex_parts.append(memo) result = u"" if edr_parts: result += u"✪EDR {} ".format(", ".join(edr_parts)) if inara_parts: result += u"✪INR {} ".format(", ".join(inara_parts)) if sqdex_parts: result += u"✪SQN {} ".format(", ".join(sqdex_parts)) if cdex_parts: result += u"✪CMD {} ".format(", ".join(cdex_parts)) if powerplay_parts: result += u"✪PP {} ".format(", ".join(powerplay_parts)) return result
def __init__(self, max_distance): super(EDRStagingCheck, self).__init__() self.max_distance = max_distance self.name = _(u"Staging station") self.hint = None
def as_immersive_date(self): immersive_datetime = self.__immmersive() return immersive_datetime.strftime(_('%Y-%m-%d'))
def __init__(self): super(EDRRawTraderCheck, self).__init__() self.name = 'Raw material trader' self.hint = _(u"Look for systems with medium-high security, an 'extraction' or 'refinery' economy, a rather large population (>= 1 million)")