def system_change(self, timestamp, system):

        if self.system['text'] != system:
            self.system['text'] = system

            self.system['image'] = ''
            self.station['text'] = EDDB.system(system) and self.STATION_UNDOCKED or ''

            plug.notify_system_changed(timestamp, system)

            if config.getint('output') & config.OUT_LOG_FILE:
                flightlog.writelog(timestamp, system)
            if config.getint('output') & config.OUT_LOG_EDSM:
                try:
                    self.status['text'] = _('Sending data to EDSM...')
                    self.w.update_idletasks()
                    edsm.writelog(timestamp, system, lambda:self.edsm.lookup(system, EDDB.system(system)))	# Do EDSM lookup during EDSM export
                    self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(timestamp)).decode('utf-8')
                except Exception as e:
                    if __debug__: print_exc()
                    self.status['text'] = unicode(e)
                    if not config.getint('hotkey_mute'):
                        hotkeymgr.play_bad()
            else:
                self.edsm.link(system)
                self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(timestamp)).decode('utf-8')
            self.edsmpoll()
    def system_change(self, event):

        if not monitor.last_event:
            if __debug__: print 'spurious system_change', event	# eh?
            return

        timestamp, system = monitor.last_event	# would like to use event user_data to carry this, but not accessible in Tkinter

        if self.system['text'] != system:
            self.system['text'] = system
            self.system['image'] = ''
            self.station['text'] = EDDB.system(system) and self.STATION_UNDOCKED or ''
            if config.getint('output') & config.OUT_LOG_FILE:
                flightlog.writelog(timestamp, system)
            if config.getint('output') & config.OUT_LOG_EDSM:
                try:
                    self.status['text'] = _('Sending data to EDSM...')
                    self.w.update_idletasks()
                    edsm.writelog(timestamp, system, lambda:self.edsm.lookup(system, EDDB.system(system)))	# Do EDSM lookup during EDSM export
                    self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(timestamp)).decode('utf-8')
                except Exception as e:
                    if __debug__: print_exc()
                    self.status['text'] = unicode(e)
                    if not config.getint('hotkey_mute'):
                        hotkeymgr.play_bad()
            else:
                self.edsm.link(system)
                self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(timestamp)).decode('utf-8')
            self.edsmpoll()
Exemple #3
0
 def dashboard_event(self, event):
     entry = dashboard.status
     if entry:
         # Currently we don't do anything with these events
         err = plug.notify_dashboard_entry(monitor.cmdr, monitor.is_beta, entry)
         if err:
             self.status['text'] = err
             if not config.getint('hotkey_mute'):
                 hotkeymgr.play_bad()
 def dashboard_event(self, event):
     entry = dashboard.status
     if entry:
         # Currently we don't do anything with these events
         err = plug.notify_dashboard_entry(monitor.cmdr, monitor.is_beta, entry)
         if err:
             self.status['text'] = err
             if not config.getint('hotkey_mute'):
                 hotkeymgr.play_bad()
Exemple #5
0
    def getandsend(self, event=None, retrying=False):

        play_sound = event and event.type == '35' and not config.getint(
            'hotkey_mute')

        if not retrying:
            if time(
            ) < self.holdofftime:  # Was invoked by key while in cooldown
                self.status['text'] = ''
                if play_sound and (self.holdofftime -
                                   time()) < companion.holdoff * 0.75:
                    hotkeymgr.play_bad(
                    )  # Don't play sound in first few seconds to prevent repeats
                return
            elif play_sound:
                hotkeymgr.play_good()
        if self.get(event, retrying):
            self.send(event)
    def system_change(self, event):

        if not monitor.last_event:
            if __debug__: print 'spurious system_change', event  # eh?
            return

        timestamp, system = monitor.last_event  # would like to use event user_data to carry this, but not accessible in Tkinter

        if self.system['text'] != system:
            self.system['text'] = system
            self.system['image'] = ''
            self.station['text'] = EDDB.system(
                system) and self.STATION_UNDOCKED or ''
            if config.getint('output') & config.OUT_LOG_FILE:
                flightlog.writelog(timestamp, system)
            if config.getint('output') & config.OUT_LOG_EDSM:
                try:
                    self.status['text'] = _('Sending data to EDSM...')
                    self.w.update_idletasks()
                    edsm.writelog(
                        timestamp, system,
                        lambda: self.edsm.lookup(system, EDDB.system(
                            system)))  # Do EDSM lookup during EDSM export
                    self.status['text'] = strftime(
                        _('Last updated at {HH}:{MM}:{SS}').format(
                            HH='%H', MM='%M', SS='%S').encode('utf-8'),
                        localtime(timestamp)).decode('utf-8')
                except Exception as e:
                    if __debug__: print_exc()
                    self.status['text'] = unicode(e)
                    if not config.getint('hotkey_mute'):
                        hotkeymgr.play_bad()
            else:
                self.edsm.link(system)
                self.status['text'] = strftime(
                    _('Last updated at {HH}:{MM}:{SS}').format(
                        HH='%H', MM='%M', SS='%S').encode('utf-8'),
                    localtime(timestamp)).decode('utf-8')
            self.edsmpoll()
Exemple #7
0
    def system_change(self, timestamp, system):

        if self.system['text'] != system:
            self.system['text'] = system

            self.system['image'] = ''
            self.station['text'] = EDDB.system(
                system) and self.STATION_UNDOCKED or ''

            plug.notify_system_changed(timestamp, system)

            if config.getint('output') & config.OUT_LOG_FILE:
                flightlog.writelog(timestamp, system)
            if config.getint('output') & config.OUT_LOG_EDSM:
                try:
                    self.status['text'] = _('Sending data to EDSM...')
                    self.w.update_idletasks()
                    edsm.writelog(
                        timestamp, system,
                        lambda: self.edsm.lookup(system, EDDB.system(
                            system)))  # Do EDSM lookup during EDSM export
                    self.status['text'] = strftime(
                        _('Last updated at {HH}:{MM}:{SS}').format(
                            HH='%H', MM='%M', SS='%S').encode('utf-8'),
                        localtime(timestamp)).decode('utf-8')
                except Exception as e:
                    if __debug__: print_exc()
                    self.status['text'] = unicode(e)
                    if not config.getint('hotkey_mute'):
                        hotkeymgr.play_bad()
            else:
                self.edsm.link(system)
                self.status['text'] = strftime(
                    _('Last updated at {HH}:{MM}:{SS}').format(
                        HH='%H', MM='%M', SS='%S').encode('utf-8'),
                    localtime(timestamp)).decode('utf-8')
            self.edsmpoll()
    def system_change(self, timestamp, system):

        if self.system["text"] != system:
            self.system["text"] = system

            self.system["image"] = ""
            self.station["text"] = EDDB.system(system) and self.STATION_UNDOCKED or ""

            plug.notify_system_changed(timestamp, system)

            if config.getint("output") & config.OUT_LOG_FILE:
                flightlog.writelog(timestamp, system)
            if config.getint("output") & config.OUT_LOG_EDSM:
                try:
                    self.status["text"] = _("Sending data to EDSM...")
                    self.w.update_idletasks()
                    edsm.writelog(
                        timestamp, system, lambda: self.edsm.lookup(system, EDDB.system(system))
                    )  # Do EDSM lookup during EDSM export
                    self.status["text"] = strftime(
                        _("Last updated at {HH}:{MM}:{SS}").format(HH="%H", MM="%M", SS="%S").encode("utf-8"),
                        localtime(timestamp),
                    ).decode("utf-8")
                except Exception as e:
                    if __debug__:
                        print_exc()
                    self.status["text"] = unicode(e)
                    if not config.getint("hotkey_mute"):
                        hotkeymgr.play_bad()
            else:
                self.edsm.link(system)
                self.status["text"] = strftime(
                    _("Last updated at {HH}:{MM}:{SS}").format(HH="%H", MM="%M", SS="%S").encode("utf-8"),
                    localtime(timestamp),
                ).decode("utf-8")
            self.edsmpoll()
Exemple #9
0
    def send(self, event=None):
        data = self.data
        try:
            if True:  # validation now done in get part
                # stuff we can do when not docked
                if config.getint('output') & config.OUT_SHIP_EDS:
                    loadout.export(data)
                if config.getint('output') & config.OUT_SHIP_CORIOLIS:
                    coriolis.export(data)
                if config.getint('output') & config.OUT_LOG_FILE:
                    flightlog.export(data)
                if config.getint('output') & config.OUT_LOG_EDSM:
                    # Catch any EDSM errors here so that they don't prevent station update
                    try:
                        self.status['text'] = _('Sending data to EDSM...')
                        self.w.update_idletasks()
                        edsm.export(data, lambda: self.edsm.lookup(
                            self.system['text'],
                            EDDB.system(self.system['text']))
                                    )  # Do EDSM lookup during EDSM export
                        self.status['text'] = ''
                    except Exception as e:
                        if __debug__: print_exc()
                        self.status['text'] = unicode(e)
                else:
                    self.edsm.link(self.system['text'])
                self.edsmpoll()

                if not (config.getint('output') &
                        (config.OUT_CSV | config.OUT_TD | config.OUT_BPC
                         | config.OUT_EDDN)):
                    # no station data requested - we're done
                    pass

                elif not data['commander'].get('docked'):
                    # signal as error because the user might actually be docked but the server hosting the Companion API hasn't caught up
                    if not self.status['text']:
                        self.status['text'] = _(
                            "You're not docked at a station!")

                else:
                    # Finally - the data looks sane and we're docked at a station
                    (station_id, has_market, has_outfitting,
                     has_shipyard) = EDDB.station(self.system['text'],
                                                  self.station['text'])

                    # No EDDN output at known station?
                    if (
                            config.getint('output') & config.OUT_EDDN
                    ) and station_id and not has_market and not has_outfitting and not has_shipyard:
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have anything!")

                    # No EDDN output at unknown station?
                    elif (
                            config.getint('output') & config.OUT_EDDN
                    ) and not station_id and not data['lastStarport'].get(
                            'commodities') and not data['lastStarport'].get(
                                'modules') and not data['lastStarport'].get(
                                    'ships'):
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have anything!")

                    # No market output at known station?
                    elif not (config.getint('output') & config.OUT_EDDN
                              ) and station_id and not has_market:
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have a market!")

                    # No market output at unknown station?
                    elif not (config.getint('output') &
                              config.OUT_EDDN) and not station_id and not data[
                                  'lastStarport'].get('commodities'):
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have a market!")

                    else:
                        if data['lastStarport'].get('commodities'):
                            # Fixup anomalies in the commodity data
                            self.session.fixup(
                                data['lastStarport']['commodities'])

                            if config.getint('output') & config.OUT_CSV:
                                bpc.export(data, True)
                            if config.getint('output') & config.OUT_TD:
                                td.export(data)
                            if config.getint('output') & config.OUT_BPC:
                                bpc.export(data, False)

                        elif has_market and (
                                config.getint('output') &
                            (config.OUT_CSV | config.OUT_TD | config.OUT_BPC
                             | config.OUT_EDDN)):
                            # Overwrite any previous error message
                            self.status['text'] = _(
                                "Error: Can't get market data!")

                        if config.getint('output') & config.OUT_EDDN:
                            old_status = self.status['text']
                            if not old_status:
                                self.status['text'] = _(
                                    'Sending data to EDDN...')
                            self.w.update_idletasks()
                            eddn.export_commodities(data)
                            if has_outfitting or not station_id:
                                # Only send if eddb says that the station provides outfitting
                                eddn.export_outfitting(data)
                            elif __debug__ and data['lastStarport'].get(
                                    'modules'):
                                print 'Spurious outfitting!'
                            if has_shipyard or not station_id:
                                # Only send if eddb says that the station has a shipyard -
                                # https://github.com/Marginal/EDMarketConnector/issues/16
                                if data['lastStarport'].get('ships'):
                                    eddn.export_shipyard(data)
                                else:
                                    # API is flakey about shipyard info - silently retry if missing (<1s is usually sufficient - 5s for margin).
                                    self.w.after(int(SERVER_RETRY * 1000),
                                                 self.retry_for_shipyard)
                            elif __debug__ and data['lastStarport'].get(
                                    'ships'):
                                print 'Spurious shipyard!'
                            if not old_status:
                                self.status['text'] = ''

        except requests.exceptions.ConnectionError as e:
            if __debug__: print_exc()
            self.status['text'] = _("Error: Can't connect to EDDN")

        except requests.exceptions.Timeout as e:
            if __debug__: print_exc()
            self.status['text'] = _("Error: Connection to EDDN timed out")

        except Exception as e:
            if __debug__: print_exc()
            self.status['text'] = unicode(e)

        if not self.status['text']:  # no errors
            self.status['text'] = strftime(
                _('Last updated at {HH}:{MM}:{SS}').format(
                    HH='%H', MM='%M', SS='%S').encode('utf-8'),
                localtime(self.querytime)).decode('utf-8')
        elif play_sound:
            hotkeymgr.play_bad()

        self.holdofftime = self.querytime + companion.holdoff
        self.cooldown()
    def getandsend(self, event=None, retrying=False):

        auto_update = not event
        play_sound = (auto_update or int(event.type) == self.EVENT_VIRTUAL) and not config.getint('hotkey_mute')
        play_bad = False

        if not monitor.cmdr or not monitor.mode or monitor.state['Captain'] or not monitor.system:
            return	# In CQC or on crew - do nothing

        if companion.session.state == companion.Session.STATE_AUTH:
            # Attempt another Auth
            self.login()
            return

        if not retrying:
            if time() < self.holdofftime:	# Was invoked by key while in cooldown
                self.status['text'] = ''
                if play_sound and (self.holdofftime-time()) < companion.holdoff*0.75:
                    hotkeymgr.play_bad()	# Don't play sound in first few seconds to prevent repeats
                return
            elif play_sound:
                hotkeymgr.play_good()
            self.status['text'] = _('Fetching data...')
            self.button['state'] = self.theme_button['state'] = tk.DISABLED
            self.w.update_idletasks()

        try:
            querytime = int(time())
            data = companion.session.station()
            config.set('querytime', querytime)

            # Validation
            if not data.get('commander', {}).get('name'):
                self.status['text'] = _("Who are you?!")		# Shouldn't happen
            elif (not data.get('lastSystem', {}).get('name') or
                  (data['commander'].get('docked') and not data.get('lastStarport', {}).get('name'))):	# Only care if docked
                self.status['text'] = _("Where are you?!")		# Shouldn't happen
            elif not data.get('ship', {}).get('name') or not data.get('ship', {}).get('modules'):
                self.status['text'] = _("What are you flying?!")	# Shouldn't happen
            elif monitor.cmdr and data['commander']['name'] != monitor.cmdr:
                raise companion.CmdrError()				# Companion API return doesn't match Journal
            elif ((auto_update and not data['commander'].get('docked')) or
                  (data['lastSystem']['name'] != monitor.system) or
                  ((data['commander']['docked'] and data['lastStarport']['name'] or None) != monitor.station) or
                  (data['ship']['id'] != monitor.state['ShipID']) or
                  (data['ship']['name'].lower() != monitor.state['ShipType'])):
                raise companion.ServerLagging()

            else:

                if __debug__:	# Recording
                    if isdir('dump'):
                        with open('dump/%s%s.%s.json' % (data['lastSystem']['name'], data['commander'].get('docked') and '.'+data['lastStarport']['name'] or '', strftime('%Y-%m-%dT%H.%M.%S', localtime())), 'wt') as h:
                            h.write(json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True, separators=(',', ': ')).encode('utf-8'))

                if not monitor.state['ShipType']:	# Started game in SRV or fighter
                    self.ship['text'] = companion.ship_map.get(data['ship']['name'].lower(), data['ship']['name'])
                    monitor.state['ShipID'] =   data['ship']['id']
                    monitor.state['ShipType'] = data['ship']['name'].lower()

                if data['commander'].get('credits') is not None:
                    monitor.state['Credits'] = data['commander']['credits']
                    monitor.state['Loan'] = data['commander'].get('debt', 0)

                # stuff we can do when not docked
                err = plug.notify_newdata(data, monitor.is_beta)
                self.status['text'] = err and err or ''
                if err:
                    play_bad = True

                # Export market data
                if config.getint('output') & (config.OUT_STATION_ANY):
                    if not data['commander'].get('docked'):
                        if not self.status['text']:
                            # Signal as error because the user might actually be docked but the server hosting the Companion API hasn't caught up
                            self.status['text'] = _("You're not docked at a station!")
                            play_bad = True
                    elif (config.getint('output') & config.OUT_MKT_EDDN) and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')):	# Ignore possibly missing shipyard info
                        if not self.status['text']:
                            self.status['text'] = _("Station doesn't have anything!")
                    elif not data['lastStarport'].get('commodities'):
                        if not self.status['text']:
                            self.status['text'] = _("Station doesn't have a market!")
                    elif config.getint('output') & (config.OUT_MKT_CSV|config.OUT_MKT_TD):
                        # Fixup anomalies in the commodity data
                        fixed = companion.fixup(data)
                        if config.getint('output') & config.OUT_MKT_CSV:
                            commodity.export(fixed, COMMODITY_CSV)
                        if config.getint('output') & config.OUT_MKT_TD:
                            td.export(fixed)

                self.holdofftime = querytime + companion.holdoff

        # Companion API problem
        except companion.ServerLagging as e:
            if retrying:
                self.status['text'] = unicode(e)
                play_bad = True
            else:
                # Retry once if Companion server is unresponsive
                self.w.after(int(SERVER_RETRY * 1000), lambda:self.getandsend(event, True))
                return	# early exit to avoid starting cooldown count

        except companion.CmdrError as e:	# Companion API return doesn't match Journal
            self.status['text'] = unicode(e)
            play_bad = True
            companion.session.invalidate()
            self.login()

        except Exception as e:			# Including CredentialsError, ServerError
            if __debug__: print_exc()
            self.status['text'] = unicode(e)
            play_bad = True

        if not self.status['text']:	# no errors
            self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(querytime)).decode('utf-8')
        if play_sound and play_bad:
            hotkeymgr.play_bad()

        self.cooldown()
    def getandsend(self, event=None, retrying=False):

        play_sound = event and event.type == '35' and not config.getint(
            'hotkey_mute')

        if not retrying:
            if time(
            ) < self.holdofftime:  # Was invoked by key while in cooldown
                self.status['text'] = ''
                if play_sound and (self.holdofftime -
                                   time()) < companion.holdoff * 0.75:
                    hotkeymgr.play_bad(
                    )  # Don't play sound in first few seconds to prevent repeats
                return
            elif play_sound:
                hotkeymgr.play_good()
            self.cmdr['text'] = self.system['text'] = self.station['text'] = ''
            self.system['image'] = ''
            self.status['text'] = _('Fetching data...')
            self.button['state'] = tk.DISABLED
            self.edit_menu.entryconfigure(_('Copy'), state=tk.DISABLED)
            self.w.update_idletasks()

        try:
            querytime = int(time())
            data = self.session.query()
            config.set('querytime', querytime)

            # Validation
            if not data.get('commander') or not data['commander'].get(
                    'name', '').strip():
                self.status['text'] = _("Who are you?!")  # Shouldn't happen
            elif not data.get('lastSystem') or not data['lastSystem'].get(
                    'name', '').strip() or not data.get(
                        'lastStarport') or not data['lastStarport'].get(
                            'name', '').strip():
                self.status['text'] = _("Where are you?!")  # Shouldn't happen
            elif not data.get('ship') or not data['ship'].get(
                    'modules') or not data['ship'].get('name', '').strip():
                self.status['text'] = _(
                    "What are you flying?!")  # Shouldn't happen

            else:
                if __debug__:  # Recording
                    with open(
                            '%s%s.%s.json' %
                        (data['lastSystem']['name'],
                         data['commander'].get('docked')
                         and '.' + data['lastStarport']['name'] or '',
                         strftime('%Y-%m-%dT%H.%M.%S', localtime())),
                            'wt') as h:
                        h.write(
                            json.dumps(data,
                                       ensure_ascii=False,
                                       indent=2,
                                       sort_keys=True).encode('utf-8'))

                self.cmdr['text'] = data.get('commander') and data.get(
                    'commander').get('name') or ''
                self.system['text'] = data.get('lastSystem') and data.get(
                    'lastSystem').get('name') or ''
                self.station['text'] = data.get('commander') and data.get(
                    'commander').get('docked') and data.get(
                        'lastStarport') and data.get('lastStarport').get(
                            'name') or (EDDB.system(self.system['text'])
                                        and self.STATION_UNDOCKED or '')
                self.status['text'] = ''
                self.edit_menu.entryconfigure(_('Copy'), state=tk.NORMAL)
                self.view_menu.entryconfigure(_('Status'), state=tk.NORMAL)

                # stuff we can do when not docked
                if config.getint('output') & config.OUT_SHIP_EDS:
                    loadout.export(data)
                if config.getint('output') & config.OUT_SHIP_CORIOLIS:
                    coriolis.export(data)
                if config.getint('output') & config.OUT_LOG_FILE:
                    flightlog.export(data)
                if config.getint('output') & config.OUT_LOG_EDSM:
                    # Catch any EDSM errors here so that they don't prevent station update
                    try:
                        self.status['text'] = _('Sending data to EDSM...')
                        self.w.update_idletasks()
                        edsm.export(data, lambda: self.edsm.lookup(
                            self.system['text'],
                            EDDB.system(self.system['text']))
                                    )  # Do EDSM lookup during EDSM export
                        self.status['text'] = ''
                    except Exception as e:
                        if __debug__: print_exc()
                        self.status['text'] = unicode(e)
                else:
                    self.edsm.link(self.system['text'])
                self.edsmpoll()

                if not (config.getint('output') &
                        (config.OUT_CSV | config.OUT_TD | config.OUT_BPC
                         | config.OUT_EDDN)):
                    # no station data requested - we're done
                    pass

                elif not data['commander'].get('docked'):
                    # signal as error because the user might actually be docked but the server hosting the Companion API hasn't caught up
                    if not self.status['text']:
                        self.status['text'] = _(
                            "You're not docked at a station!")

                else:
                    # Finally - the data looks sane and we're docked at a station
                    (station_id, has_market, has_outfitting,
                     has_shipyard) = EDDB.station(self.system['text'],
                                                  self.station['text'])

                    # No EDDN output at known station?
                    if (config.getint('output')
                            & config.OUT_EDDN) and station_id and not (
                                has_market or has_outfitting or has_shipyard):
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have anything!")

                    # No EDDN output at unknown station?
                    elif (
                            config.getint('output') & config.OUT_EDDN
                    ) and not station_id and not (
                            data['lastStarport'].get('commodities')
                            or data['lastStarport'].get('modules')
                    ):  # Ignore usually spurious shipyard at unknown stations
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have anything!")

                    # No market output at known station?
                    elif not (config.getint('output') & config.OUT_EDDN
                              ) and station_id and not has_market:
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have a market!")

                    # No market output at unknown station?
                    elif not (config.getint('output') &
                              config.OUT_EDDN) and not station_id and not data[
                                  'lastStarport'].get('commodities'):
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have a market!")

                    else:
                        if data['lastStarport'].get('commodities'):
                            # Fixup anomalies in the commodity data
                            self.session.fixup(
                                data['lastStarport']['commodities'])

                            if config.getint('output') & config.OUT_CSV:
                                bpc.export(data, True)
                            if config.getint('output') & config.OUT_TD:
                                td.export(data)
                            if config.getint('output') & config.OUT_BPC:
                                bpc.export(data, False)

                        elif has_market and (
                                config.getint('output') &
                            (config.OUT_CSV | config.OUT_TD | config.OUT_BPC
                             | config.OUT_EDDN)):
                            # Overwrite any previous error message
                            self.status['text'] = _(
                                "Error: Can't get market data!")

                        if config.getint('output') & config.OUT_EDDN:
                            old_status = self.status['text']
                            if not old_status:
                                self.status['text'] = _(
                                    'Sending data to EDDN...')
                            self.w.update_idletasks()
                            eddn.export_commodities(data)
                            if has_outfitting or not station_id:
                                # Only send if eddb says that the station provides outfitting, or unknown station
                                eddn.export_outfitting(data)
                            elif __debug__ and data['lastStarport'].get(
                                    'modules'):
                                print 'Spurious outfitting!'
                            if has_shipyard:
                                # Only send if eddb says that the station has a shipyard -
                                # https://github.com/Marginal/EDMarketConnector/issues/16
                                if data['lastStarport'].get('ships'):
                                    eddn.export_shipyard(data)
                                else:
                                    # API is flakey about shipyard info - silently retry if missing (<1s is usually sufficient - 5s for margin).
                                    self.w.after(int(SERVER_RETRY * 1000),
                                                 self.retry_for_shipyard)
                            elif __debug__ and data['lastStarport'].get(
                                    'ships'):
                                print 'Spurious shipyard!'
                            if not old_status:
                                self.status['text'] = ''

        except companion.VerificationRequired:
            return prefs.AuthenticationDialog(self.w, self.verify)

        # Companion API problem
        except companion.ServerError as e:
            if retrying:
                self.status['text'] = unicode(e)
            else:
                # Retry once if Companion server is unresponsive
                self.w.after(int(SERVER_RETRY * 1000),
                             lambda: self.getandsend(event, True))
                return  # early exit to avoid starting cooldown count

        except requests.exceptions.ConnectionError as e:
            if __debug__: print_exc()
            self.status['text'] = _("Error: Can't connect to EDDN")

        except requests.exceptions.Timeout as e:
            if __debug__: print_exc()
            self.status['text'] = _("Error: Connection to EDDN timed out")

        except Exception as e:
            if __debug__: print_exc()
            self.status['text'] = unicode(e)

        if not self.status['text']:  # no errors
            self.status['text'] = strftime(
                _('Last updated at {HH}:{MM}:{SS}').format(
                    HH='%H', MM='%M', SS='%S').encode('utf-8'),
                localtime(querytime)).decode('utf-8')
        elif play_sound:
            hotkeymgr.play_bad()

        self.holdofftime = querytime + companion.holdoff
        self.cooldown()
    def journal_event(self, event):
        while True:
            entry = monitor.get_entry()
            if not entry:
                return

            system_changed = monitor.system and self.system[
                'text'] != monitor.system
            station_changed = monitor.station and self.station[
                'text'] != monitor.station

            # Update main window
            self.cmdr['text'] = monitor.cmdr or ''
            self.ship['text'] = monitor.shiptype and companion.ship_map.get(
                monitor.shiptype, monitor.shiptype) or ''
            self.station['text'] = monitor.station or (
                EDDB.system(monitor.system) and self.STATION_UNDOCKED or '')
            if system_changed or station_changed:
                self.status['text'] = ''
                if self.station['text'] == self.STATION_UNDOCKED:
                    self.ser.write('!0 \n')
                else:
                    self.ser.write('!0' +
                                   self.station['text'].encode('utf-8') +
                                   ' \n')
                self.ser.flush()
            if system_changed:
                self.system['text'] = monitor.system or ''
                self.system['image'] = ''
                self.edsm.link(monitor.system)
                self.ser.write('!1' + self.system['text'].encode('utf-8') +
                               ' \n')
                self.ser.flush()
            self.w.update_idletasks()

            # Send interesting events to EDSM
            if config.getint(
                    'output') & config.OUT_SYS_EDSM and not monitor.is_beta:
                self.status['text'] = _('Sending data to EDSM...')
                self.w.update_idletasks()
                try:
                    # Update system status on startup
                    if monitor.mode and not entry['event']:
                        self.edsm.lookup(monitor.system)

                    # Send credits to EDSM on new game (but not on startup - data might be old)
                    if entry['event'] == 'LoadGame':
                        self.edsm.setcredits(monitor.credits)

                    # Send rank info to EDSM on startup or change
                    if entry['event'] in [None, 'Progress', 'Promotion']:
                        self.edsm.setranks(monitor.ranks)

                    # Send ship info to EDSM on startup or change
                    if entry['event'] in [
                            None, 'LoadGame', 'ShipyardNew', 'ShipyardSwap'
                    ]:
                        self.edsm.setshipid(monitor.shipid)
                        self.edsm.updateship(
                            monitor.shipid, monitor.shiptype, monitor.shippaint
                            and [('paintJob', monitor.shippaint)] or [])
                    elif entry['event'] in ['ShipyardBuy', 'ShipyardSell']:
                        self.edsm.sellship(entry.get('SellShipID'))

                    # Send paintjob info to EDSM on change
                    if entry['event'] in ['ModuleBuy', 'ModuleSell'
                                          ] and entry['Slot'] == 'PaintJob':
                        self.edsm.updateship(monitor.shipid, monitor.shiptype,
                                             [('paintJob', monitor.shippaint)])

                    # Write EDSM log on change
                    if monitor.mode and entry['event'] in [
                            'Location', 'FSDJump'
                    ]:
                        self.edsm.writelog(
                            timegm(
                                strptime(entry['timestamp'],
                                         '%Y-%m-%dT%H:%M:%SZ')),
                            monitor.system, monitor.coordinates,
                            monitor.shipid)

                except Exception as e:
                    if __debug__: print_exc()
                    self.status['text'] = unicode(e)
                    if not config.getint('hotkey_mute'):
                        hotkeymgr.play_bad()
                else:
                    self.status['text'] = ''
            self.edsmpoll()

            if not entry['event'] or not monitor.mode:
                return  # Startup or in CQC

            # Plugins
            plug.notify_journal_entry(monitor.cmdr, monitor.system,
                                      monitor.station, entry)
            if system_changed:  # Backwards compatibility
                plug.notify_system_changed(
                    timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ')),
                    monitor.system, monitor.coordinates)

            # Auto-Update after docking
            if station_changed and not monitor.is_beta and not config.getint(
                    'output') & config.OUT_MKT_MANUAL and config.getint(
                        'output') & config.OUT_STATION_ANY:
                self.w.after(int(SERVER_RETRY * 1000), self.getandsend)

            # Send interesting events to EDDN
            try:
                if (config.getint('output') & config.OUT_SYS_EDDN
                        and monitor.cmdr and
                    (entry['event'] == 'FSDJump' or entry['event'] == 'Docked'
                     or entry['event'] == 'Scan' and monitor.system
                     and monitor.coordinates)):
                    # strip out properties disallowed by the schema
                    for thing in [
                            'CockpitBreach', 'BoostUsed', 'FuelLevel',
                            'FuelUsed', 'JumpDist'
                    ]:
                        entry.pop(thing, None)
                    for thing in entry.keys():
                        if thing.endswith('_Localised'):
                            entry.pop(thing, None)

                    # add planet to Docked event for planetary stations if known
                    if entry['event'] == 'Docked' and monitor.body:
                        entry['BodyName'] = monitor.body

                    # add mandatory StarSystem and StarPos properties to Scan events
                    if 'StarSystem' not in entry:
                        entry['StarSystem'] = monitor.system
                    if 'StarPos' not in entry:
                        entry['StarPos'] = list(monitor.coordinates)

                    self.status['text'] = _('Sending data to EDDN...')
                    self.w.update_idletasks()
                    eddn.export_journal_entry(monitor.cmdr, monitor.is_beta,
                                              entry)
                    self.status['text'] = ''

                elif (config.getint('output') & config.OUT_MKT_EDDN
                      and monitor.cmdr and entry['event'] == 'MarketSell'
                      and entry.get('BlackMarket')):
                    # Construct blackmarket message
                    msg = OrderedDict([
                        ('systemName', monitor.system),
                        ('stationName', monitor.station),
                        ('timestamp', entry['timestamp']),
                        ('name', entry['Type']),
                        ('sellPrice', entry['SellPrice']),
                        ('prohibited', entry.get('IllegalGoods', False)),
                    ])

                    self.status['text'] = _('Sending data to EDDN...')
                    self.w.update_idletasks()
                    eddn.export_blackmarket(monitor.cmdr, monitor.is_beta, msg)
                    self.status['text'] = ''

            except requests.exceptions.RequestException as e:
                if __debug__: print_exc()
                self.status['text'] = _("Error: Can't connect to EDDN")
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()

            except Exception as e:
                if __debug__: print_exc()
                self.status['text'] = unicode(e)
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()
    def getandsend(self, event=None, retrying=False):

        play_sound = event and event.type=='35' and not config.getint('hotkey_mute')

        if not retrying:
            if time() < self.holdofftime:	# Was invoked by key while in cooldown
                self.status['text'] = ''
                if play_sound and (self.holdofftime-time()) < companion.holdoff*0.75:
                    hotkeymgr.play_bad()	# Don't play sound in first few seconds to prevent repeats
                return
            elif play_sound:
                hotkeymgr.play_good()
            self.cmdr['text'] = self.system['text'] = self.station['text'] = ''
            self.system['image'] = ''
            self.status['text'] = _('Fetching data...')
            self.button['state'] = tk.DISABLED
            self.edit_menu.entryconfigure(_('Copy'), state=tk.DISABLED)
            self.w.update_idletasks()

        try:
            querytime = int(time())
            data = self.session.query()
            config.set('querytime', querytime)

            # Validation
            if not data.get('commander') or not data['commander'].get('name','').strip():
                self.status['text'] = _("Who are you?!")		# Shouldn't happen
            elif not data.get('lastSystem') or not data['lastSystem'].get('name','').strip() or not data.get('lastStarport') or not data['lastStarport'].get('name','').strip():
                self.status['text'] = _("Where are you?!")		# Shouldn't happen
            elif not data.get('ship') or not data['ship'].get('modules') or not data['ship'].get('name','').strip():
                self.status['text'] = _("What are you flying?!")	# Shouldn't happen

            else:
                if __debug__:	# Recording
                    with open('%s%s.%s.json' % (data['lastSystem']['name'], data['commander'].get('docked') and '.'+data['lastStarport']['name'] or '', strftime('%Y-%m-%dT%H.%M.%S', localtime())), 'wt') as h:
                        h.write(json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True).encode('utf-8'))

                self.cmdr['text'] = data.get('commander') and data.get('commander').get('name') or ''
                self.system['text'] = data.get('lastSystem') and data.get('lastSystem').get('name') or ''
                self.station['text'] = data.get('commander') and data.get('commander').get('docked') and data.get('lastStarport') and data.get('lastStarport').get('name') or (EDDB.system(self.system['text']) and self.STATION_UNDOCKED or '')
                self.status['text'] = ''
                self.edit_menu.entryconfigure(_('Copy'), state=tk.NORMAL)
                self.view_menu.entryconfigure(_('Status'), state=tk.NORMAL)

                # stuff we can do when not docked
                if config.getint('output') & config.OUT_SHIP_EDS:
                    loadout.export(data)
                if config.getint('output') & config.OUT_SHIP_CORIOLIS:
                    coriolis.export(data)
                if config.getint('output') & config.OUT_LOG_FILE:
                    flightlog.export(data)
                if config.getint('output') & config.OUT_LOG_EDSM:
                    # Catch any EDSM errors here so that they don't prevent station update
                    try:
                        self.status['text'] = _('Sending data to EDSM...')
                        self.w.update_idletasks()
                        edsm.export(data, lambda:self.edsm.lookup(self.system['text'], EDDB.system(self.system['text'])))	# Do EDSM lookup during EDSM export
                        self.status['text'] = ''
                    except Exception as e:
                        if __debug__: print_exc()
                        self.status['text'] = unicode(e)
                else:
                    self.edsm.link(self.system['text'])
                self.edsmpoll()

                if not (config.getint('output') & (config.OUT_CSV|config.OUT_TD|config.OUT_BPC|config.OUT_EDDN)):
                    # no station data requested - we're done
                    pass

                elif not data['commander'].get('docked'):
                    # signal as error because the user might actually be docked but the server hosting the Companion API hasn't caught up
                    if not self.status['text']:
                        self.status['text'] = _("You're not docked at a station!")

                else:
                    # Finally - the data looks sane and we're docked at a station
                    (station_id, has_market, has_outfitting, has_shipyard) = EDDB.station(self.system['text'], self.station['text'])


                    # No EDDN output at known station?
                    if (config.getint('output') & config.OUT_EDDN) and station_id and not (has_market or has_outfitting or has_shipyard):
                        if not self.status['text']:
                            self.status['text'] = _("Station doesn't have anything!")

                    # No EDDN output at unknown station?
                    elif (config.getint('output') & config.OUT_EDDN) and not station_id and not (data['lastStarport'].get('commodities') or data['lastStarport'].get('modules')):	# Ignore usually spurious shipyard at unknown stations
                        if not self.status['text']:
                            self.status['text'] = _("Station doesn't have anything!")

                    # No market output at known station?
                    elif not (config.getint('output') & config.OUT_EDDN) and station_id and not has_market:
                        if not self.status['text']:
                            self.status['text'] = _("Station doesn't have a market!")

                    # No market output at unknown station?
                    elif not (config.getint('output') & config.OUT_EDDN) and not station_id and not data['lastStarport'].get('commodities'):
                        if not self.status['text']:
                            self.status['text'] = _("Station doesn't have a market!")

                    else:
                        if data['lastStarport'].get('commodities'):
                            # Fixup anomalies in the commodity data
                            self.session.fixup(data['lastStarport']['commodities'])

                            if config.getint('output') & config.OUT_CSV:
                                bpc.export(data, True)
                            if config.getint('output') & config.OUT_TD:
                                td.export(data)
                            if config.getint('output') & config.OUT_BPC:
                                bpc.export(data, False)

                        elif has_market and (config.getint('output') & (config.OUT_CSV|config.OUT_TD|config.OUT_BPC|config.OUT_EDDN)):
                            # Overwrite any previous error message
                            self.status['text'] = _("Error: Can't get market data!")

                        if config.getint('output') & config.OUT_EDDN:
                            old_status = self.status['text']
                            if not old_status:
                                self.status['text'] = _('Sending data to EDDN...')
                            self.w.update_idletasks()
                            eddn.export_commodities(data)
                            if has_outfitting or not station_id:
                                # Only send if eddb says that the station provides outfitting, or unknown station
                                eddn.export_outfitting(data)
                            elif __debug__ and data['lastStarport'].get('modules'):
                                print 'Spurious outfitting!'
                            if has_shipyard:
                                # Only send if eddb says that the station has a shipyard -
                                # https://github.com/Marginal/EDMarketConnector/issues/16
                                if data['lastStarport'].get('ships'):
                                    eddn.export_shipyard(data)
                                else:
                                    # API is flakey about shipyard info - silently retry if missing (<1s is usually sufficient - 5s for margin).
                                    self.w.after(int(SERVER_RETRY * 1000), self.retry_for_shipyard)
                            elif __debug__ and data['lastStarport'].get('ships'):
                                print 'Spurious shipyard!'
                            if not old_status:
                                self.status['text'] = ''

        except companion.VerificationRequired:
            return prefs.AuthenticationDialog(self.w, self.verify)

        # Companion API problem
        except companion.ServerError as e:
            if retrying:
                self.status['text'] = unicode(e)
            else:
                # Retry once if Companion server is unresponsive
                self.w.after(int(SERVER_RETRY * 1000), lambda:self.getandsend(event, True))
                return	# early exit to avoid starting cooldown count

        except requests.exceptions.ConnectionError as e:
            if __debug__: print_exc()
            self.status['text'] = _("Error: Can't connect to EDDN")

        except requests.exceptions.Timeout as e:
            if __debug__: print_exc()
            self.status['text'] = _("Error: Connection to EDDN timed out")

        except Exception as e:
            if __debug__: print_exc()
            self.status['text'] = unicode(e)

        if not self.status['text']:	# no errors
            self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(querytime)).decode('utf-8')
        elif play_sound:
            hotkeymgr.play_bad()

        self.holdofftime = querytime + companion.holdoff
        self.cooldown()
 def plugin_error(self, event=None):
     if plug.last_error.get('msg'):
         self.status['text'] = plug.last_error['msg']
         self.w.update_idletasks()
         if not config.getint('hotkey_mute'):
             hotkeymgr.play_bad()
    def getandsend(self, event=None, retrying=False):

        auto_update = not event
        play_sound = (auto_update or int(event.type) == self.EVENT_VIRTUAL
                      ) and not config.getint('hotkey_mute')

        if (monitor.cmdr and not monitor.mode) or monitor.is_beta:
            return  # In CQC - do nothing

        if not retrying:
            if time(
            ) < self.holdofftime:  # Was invoked by key while in cooldown
                self.status['text'] = ''
                if play_sound and (self.holdofftime -
                                   time()) < companion.holdoff * 0.75:
                    hotkeymgr.play_bad(
                    )  # Don't play sound in first few seconds to prevent repeats
                return
            elif play_sound:
                hotkeymgr.play_good()
            self.status['text'] = _('Fetching data...')
            self.button['state'] = self.theme_button['state'] = tk.DISABLED
            self.edit_menu.entryconfigure(0, state=tk.DISABLED)  # Copy
            self.w.update_idletasks()

        try:
            querytime = int(time())
            data = self.session.query()
            config.set('querytime', querytime)

            # Validation
            if not data.get('commander') or not data['commander'].get(
                    'name', '').strip():
                self.status['text'] = _("Who are you?!")  # Shouldn't happen
            elif not data.get('lastSystem') or not data['lastSystem'].get(
                    'name', '').strip() or not data.get(
                        'lastStarport') or not data['lastStarport'].get(
                            'name', '').strip():
                self.status['text'] = _("Where are you?!")  # Shouldn't happen
            elif not data.get('ship') or not data['ship'].get(
                    'modules') or not data['ship'].get('name', '').strip():
                self.status['text'] = _(
                    "What are you flying?!")  # Shouldn't happen
            elif monitor.cmdr and data['commander']['name'] != monitor.cmdr:
                raise companion.CredentialsError(
                )  # Companion API credentials don't match Journal
            elif (auto_update and not data['commander'].get('docked')) or (
                    monitor.system
                    and data['lastSystem']['name'] != monitor.system
            ) or (monitor.shipid and data['ship']['id'] != monitor.shipid) or (
                    monitor.shiptype
                    and data['ship']['name'].lower() != monitor.shiptype):
                raise companion.ServerLagging()

            else:

                if __debug__:  # Recording
                    if not isdir('dump'): mkdir('dump')
                    with open(
                            'dump/%s%s.%s.json' %
                        (data['lastSystem']['name'],
                         data['commander'].get('docked')
                         and '.' + data['lastStarport']['name'] or '',
                         strftime('%Y-%m-%dT%H.%M.%S', localtime())),
                            'wt') as h:
                        h.write(
                            json.dumps(data,
                                       ensure_ascii=False,
                                       indent=2,
                                       sort_keys=True,
                                       separators=(',', ': ')).encode('utf-8'))

                self.cmdr['text'] = data['commander']['name']
                self.ship['text'] = companion.ship_map.get(
                    data['ship']['name'].lower(), data['ship']['name'])
                if not monitor.system:
                    self.system['text'] = data['lastSystem']['name']
                    self.system['image'] = ''
                self.station['text'] = data['commander'].get(
                    'docked') and data.get('lastStarport') and data[
                        'lastStarport'].get('name') or (EDDB.system(
                            self.system['text']) and self.STATION_UNDOCKED
                                                        or '')
                self.status['text'] = ''
                self.edit_menu.entryconfigure(0, state=tk.NORMAL)  # Copy

                # stuff we can do when not docked
                plug.notify_newdata(data)
                if config.getint('output') & config.OUT_SHIP_EDS:
                    loadout.export(data)
                if config.getint('output') & config.OUT_SHIP_CORIOLIS:
                    coriolis.export(data)

                if not (config.getint('output') &
                        (config.OUT_MKT_CSV | config.OUT_MKT_TD
                         | config.OUT_MKT_BPC | config.OUT_MKT_EDDN)):
                    # no station data requested - we're done
                    pass

                elif not data['commander'].get('docked'):
                    if not event and not retrying:
                        # Silently retry if we got here by 'Automatically update on docking' and the server hasn't caught up
                        self.w.after(int(SERVER_RETRY * 1000),
                                     lambda: self.getandsend(event, True))
                        return  # early exit to avoid starting cooldown count
                    else:
                        # Signal as error because the user might actually be docked but the server hosting the Companion API hasn't caught up
                        if not self.status['text']:
                            self.status['text'] = _(
                                "You're not docked at a station!")

                else:
                    # Finally - the data looks sane and we're docked at a station
                    (station_id, has_market, has_outfitting,
                     has_shipyard) = EDDB.station(self.system['text'],
                                                  self.station['text'])

                    # No EDDN output?
                    if (config.getint('output') & config.OUT_MKT_EDDN
                        ) and not (data['lastStarport'].get('commodities')
                                   or data['lastStarport'].get('modules')
                                   ):  # Ignore possibly missing shipyard info
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have anything!")

                    # No market output?
                    elif not (
                            config.getint('output') & config.OUT_MKT_EDDN
                    ) and not data['lastStarport'].get('commodities'):
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have a market!")

                    else:
                        if data['lastStarport'].get(
                                'commodities') and config.getint('output') & (
                                    config.OUT_MKT_CSV | config.OUT_MKT_TD
                                    | config.OUT_MKT_BPC):
                            # Fixup anomalies in the commodity data
                            fixed = companion.fixup(data)

                            if config.getint('output') & config.OUT_MKT_CSV:
                                commodity.export(fixed, COMMODITY_CSV)
                            if config.getint('output') & config.OUT_MKT_TD:
                                td.export(fixed)
                            if config.getint('output') & config.OUT_MKT_BPC:
                                commodity.export(fixed, COMMODITY_BPC)

                        if config.getint('output') & config.OUT_MKT_EDDN:
                            old_status = self.status['text']
                            if not old_status:
                                self.status['text'] = _(
                                    'Sending data to EDDN...')
                            self.w.update_idletasks()
                            eddn.export_commodities(data)
                            eddn.export_outfitting(data)
                            if has_shipyard and not data['lastStarport'].get(
                                    'ships'):
                                # API is flakey about shipyard info - silently retry if missing (<1s is usually sufficient - 5s for margin).
                                self.w.after(int(SERVER_RETRY * 1000),
                                             self.retry_for_shipyard)
                            else:
                                eddn.export_shipyard(data)
                            if not old_status:
                                self.status['text'] = ''

                    # Update credits and ship info and send to EDSM
                    if config.getint(
                            'output'
                    ) & config.OUT_SYS_EDSM and not monitor.is_beta:
                        try:
                            if data['commander'].get('credits') is not None:
                                monitor.credits = (
                                    data['commander']['credits'],
                                    data['commander'].get('debt', 0))
                                self.edsm.setcredits(monitor.credits)
                            ship = companion.ship(data)
                            if ship == self.edsm.lastship:
                                props = []
                            else:
                                props = [
                                    ('cargoCapacity',
                                     ship['cargo']['capacity']),
                                    ('fuelMainCapacity',
                                     ship['fuel']['main']['capacity']),
                                    ('linkToCoriolis', coriolis.url(data)),
                                    ('linkToEDShipyard', edshipyard.url(data)),
                                ]
                            if monitor.shippaint is None:
                                # Companion API server can lag, so prefer Journal. But paintjob only reported in Journal on change.
                                monitor.shipid = data['ship']['id']
                                monitor.shiptype = data['ship']['name'].lower()
                                monitor.shippaint = data['ship']['modules'][
                                    'PaintJob'] and data['ship']['modules'][
                                        'PaintJob']['module']['name'].lower(
                                        ) or ''
                                props.append(('paintJob', monitor.shippaint))
                            if props:
                                self.edsm.updateship(monitor.shipid,
                                                     monitor.shiptype, props)
                                self.edsm.lastship = ship
                        except Exception as e:
                            # Not particularly important so silent on failure
                            if __debug__: print_exc()

        except companion.VerificationRequired:
            return prefs.AuthenticationDialog(
                self.w, partial(self.verify, self.getandsend))

        # Companion API problem
        except (companion.ServerError, companion.ServerLagging) as e:
            if retrying:
                self.status['text'] = unicode(e)
            else:
                # Retry once if Companion server is unresponsive
                self.w.after(int(SERVER_RETRY * 1000),
                             lambda: self.getandsend(event, True))
                return  # early exit to avoid starting cooldown count

        except requests.RequestException as e:
            if __debug__: print_exc()
            self.status['text'] = _("Error: Can't connect to EDDN")

        except Exception as e:
            if __debug__: print_exc()
            self.status['text'] = unicode(e)

        if not self.status['text']:  # no errors
            self.status['text'] = strftime(
                _('Last updated at {HH}:{MM}:{SS}').format(
                    HH='%H', MM='%M', SS='%S').encode('utf-8'),
                localtime(querytime)).decode('utf-8')
        elif play_sound:
            hotkeymgr.play_bad()

        self.holdofftime = querytime + companion.holdoff
        self.cooldown()
    def getandsend(self, event=None, retrying=False):

        auto_update = not event
        play_sound = (auto_update or int(event.type) == self.EVENT_VIRTUAL
                      ) and not config.getint('hotkey_mute')
        play_bad = False

        if not monitor.cmdr or not monitor.mode or monitor.state[
                'Captain'] or not monitor.system:
            return  # In CQC or on crew - do nothing

        if companion.session.state == companion.Session.STATE_AUTH:
            # Attempt another Auth
            self.login()
            return

        if not retrying:
            if time(
            ) < self.holdofftime:  # Was invoked by key while in cooldown
                self.status['text'] = ''
                if play_sound and (self.holdofftime -
                                   time()) < companion.holdoff * 0.75:
                    hotkeymgr.play_bad(
                    )  # Don't play sound in first few seconds to prevent repeats
                return
            elif play_sound:
                hotkeymgr.play_good()
            self.status['text'] = _('Fetching data...')
            self.button['state'] = self.theme_button['state'] = tk.DISABLED
            self.w.update_idletasks()

        try:
            querytime = int(time())
            data = companion.session.station()
            config.set('querytime', querytime)

            # Validation
            if not data.get('commander', {}).get('name'):
                self.status['text'] = _("Who are you?!")  # Shouldn't happen
            elif (not data.get('lastSystem', {}).get('name')
                  or (data['commander'].get('docked') and not data.get(
                      'lastStarport', {}).get('name'))):  # Only care if docked
                self.status['text'] = _("Where are you?!")  # Shouldn't happen
            elif not data.get('ship', {}).get('name') or not data.get(
                    'ship', {}).get('modules'):
                self.status['text'] = _(
                    "What are you flying?!")  # Shouldn't happen
            elif monitor.cmdr and data['commander']['name'] != monitor.cmdr:
                raise companion.CmdrError(
                )  # Companion API return doesn't match Journal
            elif (
                (auto_update and not data['commander'].get('docked'))
                    or (data['lastSystem']['name'] != monitor.system) or
                ((data['commander']['docked'] and data['lastStarport']['name']
                  or None) != monitor.station)
                    or (data['ship']['id'] != monitor.state['ShipID']) or
                (data['ship']['name'].lower() != monitor.state['ShipType'])):
                raise companion.ServerLagging()

            else:

                if __debug__:  # Recording
                    if isdir('dump'):
                        with open(
                                'dump/%s%s.%s.json' %
                            (data['lastSystem']['name'],
                             data['commander'].get('docked')
                             and '.' + data['lastStarport']['name'] or '',
                             strftime('%Y-%m-%dT%H.%M.%S', localtime())),
                                'wt') as h:
                            h.write(
                                json.dumps(data,
                                           ensure_ascii=False,
                                           indent=2,
                                           sort_keys=True,
                                           separators=(',',
                                                       ': ')).encode('utf-8'))

                if not monitor.state[
                        'ShipType']:  # Started game in SRV or fighter
                    self.ship['text'] = companion.ship_map.get(
                        data['ship']['name'].lower(), data['ship']['name'])
                    monitor.state['ShipID'] = data['ship']['id']
                    monitor.state['ShipType'] = data['ship']['name'].lower()

                if data['commander'].get('credits') is not None:
                    monitor.state['Credits'] = data['commander']['credits']
                    monitor.state['Loan'] = data['commander'].get('debt', 0)

                # stuff we can do when not docked
                err = plug.notify_newdata(data, monitor.is_beta)
                self.status['text'] = err and err or ''
                if err:
                    play_bad = True

                # Export market data
                if config.getint('output') & (config.OUT_STATION_ANY):
                    if not data['commander'].get('docked'):
                        if not self.status['text']:
                            # Signal as error because the user might actually be docked but the server hosting the Companion API hasn't caught up
                            self.status['text'] = _(
                                "You're not docked at a station!")
                            play_bad = True
                    elif (config.getint('output')
                          & config.OUT_MKT_EDDN) and not (
                              data['lastStarport'].get('commodities')
                              or data['lastStarport'].get('modules')
                          ):  # Ignore possibly missing shipyard info
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have anything!")
                    elif not data['lastStarport'].get('commodities'):
                        if not self.status['text']:
                            self.status['text'] = _(
                                "Station doesn't have a market!")
                    elif config.getint('output') & (config.OUT_MKT_CSV
                                                    | config.OUT_MKT_TD):
                        # Fixup anomalies in the commodity data
                        fixed = companion.fixup(data)
                        if config.getint('output') & config.OUT_MKT_CSV:
                            commodity.export(fixed, COMMODITY_CSV)
                        if config.getint('output') & config.OUT_MKT_TD:
                            td.export(fixed)

                self.holdofftime = querytime + companion.holdoff

        # Companion API problem
        except companion.ServerLagging as e:
            if retrying:
                self.status['text'] = unicode(e)
                play_bad = True
            else:
                # Retry once if Companion server is unresponsive
                self.w.after(int(SERVER_RETRY * 1000),
                             lambda: self.getandsend(event, True))
                return  # early exit to avoid starting cooldown count

        except companion.CmdrError as e:  # Companion API return doesn't match Journal
            self.status['text'] = unicode(e)
            play_bad = True
            companion.session.invalidate()
            self.login()

        except Exception as e:  # Including CredentialsError, ServerError
            if __debug__: print_exc()
            self.status['text'] = unicode(e)
            play_bad = True

        if not self.status['text']:  # no errors
            self.status['text'] = strftime(
                _('Last updated at {HH}:{MM}:{SS}').format(
                    HH='%H', MM='%M', SS='%S').encode('utf-8'),
                localtime(querytime)).decode('utf-8')
        if play_sound and play_bad:
            hotkeymgr.play_bad()

        self.cooldown()
    def journal_event(self, event):
        def crewroletext(role):
            # Return translated crew role. Needs to be dynamic to allow for changing language.
            return {
                None: '',
                'Idle': '',
                'FighterCon': _('Fighter'),  # Multicrew role
                'FireCon': _('Gunner'),  # Multicrew role
                'FlightCon': _('Helm'),  # Multicrew role
            }.get(role, role)

        while True:
            entry = monitor.get_entry()
            if not entry:
                return

            # Update main window
            self.cooldown()
            if monitor.cmdr and monitor.state['Captain']:
                self.cmdr['text'] = '%s / %s' % (monitor.cmdr,
                                                 monitor.state['Captain'])
                self.ship_label['text'] = _(
                    'Role') + ':'  # Multicrew role label in main window
                self.ship.configure(state=tk.NORMAL,
                                    text=crewroletext(monitor.state['Role']),
                                    url=None)
            elif monitor.cmdr:
                if monitor.group:
                    self.cmdr['text'] = '%s / %s' % (monitor.cmdr,
                                                     monitor.group)
                else:
                    self.cmdr['text'] = monitor.cmdr
                self.ship_label['text'] = _('Ship') + ':'  # Main window
                self.ship.configure(
                    text=monitor.state['ShipName'] or companion.ship_map.get(
                        monitor.state['ShipType'], monitor.state['ShipType'])
                    or '',
                    url=self.shipyard_url)
            else:
                self.cmdr['text'] = ''
                self.ship_label['text'] = _('Ship') + ':'  # Main window
                self.ship['text'] = ''

            self.edit_menu.entryconfigure(0,
                                          state=monitor.system and tk.NORMAL
                                          or tk.DISABLED)  # Copy

            if entry['event'] in [
                    'Undocked', 'StartJump', 'SetUserShipName', 'ShipyardBuy',
                    'ShipyardSell', 'ShipyardSwap', 'ModuleBuy', 'ModuleSell',
                    'MaterialCollected', 'MaterialDiscarded',
                    'ScientificResearch', 'EngineerCraft', 'Synthesis',
                    'JoinACrew'
            ]:
                self.status['text'] = ''  # Periodically clear any old error
            self.w.update_idletasks()

            # Companion login
            if entry['event'] in [None, 'StartUp', 'NewCommander', 'LoadGame'
                                  ] and monitor.cmdr:
                if not config.get('cmdrs') or monitor.cmdr not in config.get(
                        'cmdrs'):
                    config.set('cmdrs',
                               (config.get('cmdrs') or []) + [monitor.cmdr])
                self.login()

            if not entry['event'] or not monitor.mode:
                return  # Startup or in CQC

            if entry['event'] in ['StartUp', 'LoadGame'] and monitor.started:
                # Disable WinSparkle automatic update checks, IFF configured to do so when in-game
                if config.getint('disable_autoappupdatecheckingame') and 1:
                    self.updater.setAutomaticUpdatesCheck(False)
                    print 'Monitor: Disable WinSparkle automatic update checks'
                # Can start dashboard monitoring
                if not dashboard.start(self.w, monitor.started):
                    print "Can't start Status monitoring"

            # Export loadout
            if entry['event'] == 'Loadout' and not monitor.state[
                    'Captain'] and config.getint('output') & config.OUT_SHIP:
                monitor.export_ship()

            # Plugins
            err = plug.notify_journal_entry(monitor.cmdr, monitor.is_beta,
                                            monitor.system, monitor.station,
                                            entry, monitor.state)
            if err:
                self.status['text'] = err
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()

            # Auto-Update after docking, but not if auth callback is pending
            if entry['event'] in [
                    'StartUp', 'Location', 'Docked'
            ] and monitor.station and not config.getint(
                    'output'
            ) & config.OUT_MKT_MANUAL and config.getint(
                    'output'
            ) & config.OUT_STATION_ANY and companion.session.state != companion.Session.STATE_AUTH:
                self.w.after(int(SERVER_RETRY * 1000), self.getandsend)

            if entry['event'] == 'ShutDown':
                # Enable WinSparkle automatic update checks
                # NB: Do this blindly, in case option got changed whilst in-game
                self.updater.setAutomaticUpdatesCheck(True)
                print 'Monitor: Enable WinSparkle automatic update checks'
    def journal_event(self, event):

        def crewroletext(role):
            # Return translated crew role. Needs to be dynamic to allow for changing language.
            return {
                None: '',
                'Idle': '',
                'FighterCon': _('Fighter'),	# Multicrew role
                'FireCon':    _('Gunner'),	# Multicrew role
                'FlightCon':  _('Helm'),	# Multicrew role
            }.get(role, role)

        while True:
            entry = monitor.get_entry()
            if not entry:
                return

            # Update main window
            self.cooldown()
            if monitor.cmdr and monitor.state['Captain']:
                self.cmdr['text'] = '%s / %s' % (monitor.cmdr, monitor.state['Captain'])
                self.ship_label['text'] = _('Role') + ':'	# Multicrew role label in main window
                self.ship.configure(state = tk.NORMAL, text = crewroletext(monitor.state['Role']), url = None)
            elif monitor.cmdr:
                if monitor.group:
                    self.cmdr['text'] = '%s / %s' % (monitor.cmdr, monitor.group)
                else:
                    self.cmdr['text'] = monitor.cmdr
                self.ship_label['text'] = _('Ship') + ':'	# Main window
                self.ship.configure(text = monitor.state['ShipName'] or companion.ship_map.get(monitor.state['ShipType'], monitor.state['ShipType']) or '',
                                    url = self.shipyard_url)
            else:
                self.cmdr['text'] = ''
                self.ship_label['text'] = _('Ship') + ':'	# Main window
                self.ship['text'] = ''

            self.edit_menu.entryconfigure(0, state=monitor.system and tk.NORMAL or tk.DISABLED)	# Copy

            if entry['event'] in ['Undocked', 'StartJump', 'SetUserShipName', 'ShipyardBuy', 'ShipyardSell', 'ShipyardSwap', 'ModuleBuy', 'ModuleSell', 'MaterialCollected', 'MaterialDiscarded', 'ScientificResearch', 'EngineerCraft', 'Synthesis', 'JoinACrew']:
                self.status['text'] = ''	# Periodically clear any old error
            self.w.update_idletasks()

            # Companion login
            if entry['event'] in [None, 'StartUp', 'NewCommander', 'LoadGame'] and monitor.cmdr:
                if not config.get('cmdrs') or monitor.cmdr not in config.get('cmdrs'):
                    config.set('cmdrs', (config.get('cmdrs') or []) + [monitor.cmdr])
                self.login()

            if not entry['event'] or not monitor.mode:
                return	# Startup or in CQC

            if entry['event'] in ['StartUp', 'LoadGame'] and monitor.started:
                # Can start dashboard monitoring
                if not dashboard.start(self.w, monitor.started):
                    print "Can't start Status monitoring"

            # Export loadout
            if entry['event'] == 'Loadout' and not monitor.state['Captain'] and config.getint('output') & config.OUT_SHIP:
                monitor.export_ship()

            # Plugins
            err = plug.notify_journal_entry(monitor.cmdr, monitor.is_beta, monitor.system, monitor.station, entry, monitor.state)
            if err:
                self.status['text'] = err
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()

            # Auto-Update after docking, but not if auth callback is pending
            if entry['event'] in ['StartUp', 'Location', 'Docked'] and monitor.station and not config.getint('output') & config.OUT_MKT_MANUAL and config.getint('output') & config.OUT_STATION_ANY and companion.session.state != companion.Session.STATE_AUTH:
                self.w.after(int(SERVER_RETRY * 1000), self.getandsend)
Exemple #19
0
    def journal_event(self, event):

        def crewroletext(role):
            # Return translated crew role. Needs to be dynamic to allow for changing language.
            return {
                None: '',
                'Idle': '',
                'FighterCon': _('Fighter'),	# Multicrew role
                'FireCon':    _('Gunner'),	# Multicrew role
                'FlightCon':  _('Helm'),	# Multicrew role
            }.get(role, role)

        while True:
            entry = monitor.get_entry()
            if not entry:
                return

            # Update main window
            self.cooldown()
            if monitor.cmdr and monitor.state['Captain']:
                self.cmdr['text'] = '%s / %s' % (monitor.cmdr, monitor.state['Captain'])
                self.ship_label['text'] = _('Role') + ':'	# Multicrew role label in main window
                self.ship.configure(state = tk.NORMAL, text = crewroletext(monitor.state['Role']), url = None)
            elif monitor.cmdr:
                if monitor.group:
                    self.cmdr['text'] = '%s / %s' % (monitor.cmdr, monitor.group)
                else:
                    self.cmdr['text'] = monitor.cmdr
                self.ship_label['text'] = _('Ship') + ':'	# Main window
                self.ship.configure(text = monitor.state['ShipName'] or companion.ship_map.get(monitor.state['ShipType'], monitor.state['ShipType']) or '',
                                    url = self.shipyard_url)
            else:
                self.cmdr['text'] = ''
                self.ship_label['text'] = _('Ship') + ':'	# Main window
                self.ship['text'] = ''

            self.edit_menu.entryconfigure(0, state=monitor.system and tk.NORMAL or tk.DISABLED)	# Copy

            if entry['event'] in ['Undocked', 'StartJump', 'SetUserShipName', 'ShipyardBuy', 'ShipyardSell', 'ShipyardSwap', 'ModuleBuy', 'ModuleSell', 'MaterialCollected', 'MaterialDiscarded', 'ScientificResearch', 'EngineerCraft', 'Synthesis', 'JoinACrew']:
                self.status['text'] = ''	# Periodically clear any old error
            self.w.update_idletasks()

            # Companion login
            if entry['event'] in [None, 'StartUp', 'NewCommander', 'LoadGame'] and monitor.cmdr:
                if config.get('cmdrs') and monitor.cmdr in config.get('cmdrs'):
                    prefs.make_current(monitor.cmdr)
                    self.login()
                elif config.get('cmdrs') and entry['event'] == 'NewCommander':
                    cmdrs = config.get('cmdrs')
                    cmdrs[0] = monitor.cmdr	# New Cmdr uses same credentials as old
                    config.set('cmdrs', cmdrs)
                elif not self.prefsdialog:
                    self.prefsdialog = prefs.PreferencesDialog(self.w, self.postprefs)	# First run or failed migration

            if not entry['event'] or not monitor.mode:
                return	# Startup or in CQC

            if entry['event'] in ['StartUp', 'LoadGame'] and monitor.started:
                # Can start dashboard monitoring
                if not dashboard.start(self.w, monitor.started):
                    print "Can't start Status monitoring"

            # Export loadout
            if entry['event'] == 'Loadout' and not monitor.state['Captain'] and config.getint('output') & config.OUT_SHIP:
                monitor.export_ship()

            # Plugins
            err = plug.notify_journal_entry(monitor.cmdr, monitor.is_beta, monitor.system, monitor.station, entry, monitor.state)
            if err:
                self.status['text'] = err
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()

            # Auto-Update after docking
            if entry['event'] in ['StartUp', 'Location', 'Docked'] and monitor.station and not config.getint('output') & config.OUT_MKT_MANUAL and config.getint('output') & config.OUT_STATION_ANY:
                self.w.after(int(SERVER_RETRY * 1000), self.getandsend)
 def plugin_error(self, event=None):
     if plug.last_error.get('msg'):
         self.status['text'] = plug.last_error['msg']
         self.w.update_idletasks()
         if not config.getint('hotkey_mute'):
             hotkeymgr.play_bad()
    def journal_event(self, event):
        while True:
            entry = monitor.get_entry()
            system_changed  = monitor.system  and self.system['text']  != monitor.system
            station_changed = monitor.station and self.station['text'] != monitor.station

            # Update main window
            self.cmdr['text'] = monitor.cmdr or ''
            self.system['text'] = monitor.system or ''
            self.station['text'] = monitor.station or (EDDB.system(monitor.system) and self.STATION_UNDOCKED or '')
            if system_changed or station_changed:
                self.status['text'] = ''

            if config.getint('output') & config.OUT_SYS_EDSM and not monitor.is_beta:
                # Send credits to EDSM on startup
                if monitor.credits and (not entry or entry['event'] == 'LoadGame'):
                    try:
                        self.status['text'] = _('Sending balance/loan to EDSM...')
                        self.w.update_idletasks()
                        self.edsm.setcredits(monitor.credits)
                        self.status['text'] = ''
                    except Exception as e:
                        if __debug__: print_exc()
                        self.status['text'] = unicode(e)
                        if not config.getint('hotkey_mute'):
                            hotkeymgr.play_bad()
                
                # Send shipid to EDSM on startup or change
                if monitor.shipid and (not entry or entry['event'] in ['LoadGame', 'ShipyardSwap']):
                    try:
                        self.status['text'] = _('Sending shipId to EDSM...')
                        self.w.update_idletasks()
                        self.edsm.setshipid(monitor.shipid)
                        self.status['text'] = ''
                    except Exception as e:
                        if __debug__: print_exc()
                        self.status['text'] = unicode(e)
                        if not config.getint('hotkey_mute'):
                            hotkeymgr.play_bad()
                
                # Send rank info to EDSM on startup or change
                if monitor.ranks and (not entry or entry['event'] in ['Progress', 'Promotion']):
                    try:
                        self.status['text'] = _('Sending ranks to EDSM...')
                        self.w.update_idletasks()
                        self.edsm.setranks(monitor.ranks)
                        self.status['text'] = ''
                    except Exception as e:
                        if __debug__: print_exc()
                        self.status['text'] = unicode(e)
                        if not config.getint('hotkey_mute'):
                            hotkeymgr.play_bad()

            if not entry or not monitor.mode:
                return	# Fake event or in CQC

            plug.notify_journal_entry(monitor.cmdr, monitor.system, monitor.station, entry)

            if system_changed:
                self.system['image'] = ''
                timestamp = timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ'))

                # Backwards compatibility
                plug.notify_system_changed(timestamp, monitor.system, monitor.coordinates)

                # Update EDSM if we have coordinates - i.e. Location or FSDJump events
                if config.getint('output') & config.OUT_SYS_EDSM and monitor.coordinates:
                    try:
                        self.status['text'] = _('Sending flight log to EDSM...')
                        self.w.update_idletasks()
                        self.edsm.writelog(timestamp, monitor.system, monitor.coordinates)
                        self.status['text'] = ''
                    except Exception as e:
                        if __debug__: print_exc()
                        self.status['text'] = unicode(e)
                        if not config.getint('hotkey_mute'):
                            hotkeymgr.play_bad()
                else:
                    self.edsm.link(monitor.system)
                self.edsmpoll()

            # Auto-Update after docking
            if station_changed and not monitor.is_beta and not config.getint('output') & config.OUT_MKT_MANUAL and config.getint('output') & config.OUT_STATION_ANY:
                self.w.after(int(SERVER_RETRY * 1000), self.getandsend)

            # Send interesting events to EDDN
            try:
                if (config.getint('output') & config.OUT_SYS_EDDN and monitor.cmdr and
                    (entry['event'] == 'FSDJump' and system_changed  or
                     entry['event'] == 'Docked'  and station_changed or
                     entry['event'] == 'Scan'    and monitor.system and monitor.coordinates)):
                    # strip out properties disallowed by the schema
                    for thing in ['CockpitBreach', 'BoostUsed', 'FuelLevel', 'FuelUsed', 'JumpDist']:
                        entry.pop(thing, None)
                    for thing in entry.keys():
                        if thing.endswith('_Localised'):
                            entry.pop(thing, None)

                    # add mandatory StarSystem and StarPos properties to Scan events
                    if 'StarSystem' not in entry:
                        entry['StarSystem'] = monitor.system
                    if 'StarPos' not in entry:
                        entry['StarPos'] = list(monitor.coordinates)

                    self.status['text'] = _('Sending data to EDDN...')
                    eddn.export_journal_entry(monitor.cmdr, monitor.is_beta, entry)
                    self.status['text'] = ''

                elif (config.getint('output') & config.OUT_MKT_EDDN and monitor.cmdr and
                      entry['event'] == 'MarketSell' and entry.get('BlackMarket')):
                    # Construct blackmarket message
                    msg = OrderedDict([
                        ('systemName',  monitor.system),
                        ('stationName', monitor.station),
                        ('timestamp',   entry['timestamp']),
                        ('name',        entry['Type']),
                        ('sellPrice',   entry['SellPrice']),
                        ('prohibited' , entry.get('IllegalGoods', False)),
                    ])

                    self.status['text'] = _('Sending data to EDDN...')
                    eddn.export_blackmarket(monitor.cmdr, monitor.is_beta, msg)
                    self.status['text'] = ''

            except requests.exceptions.RequestException as e:
                if __debug__: print_exc()
                self.status['text'] = _("Error: Can't connect to EDDN")
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()

            except Exception as e:
                if __debug__: print_exc()
                self.status['text'] = unicode(e)
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()
Exemple #22
0
    def journal_event(self, event):

        def crewroletext(role):
            # Return translated crew role. Needs to be dynamic to allow for changing language.
            return {
                None: '',
                'Idle': '',
                'FighterCon': _('Fighter'),	# Multicrew role
                'FireCon':    _('Gunner'),	# Multicrew role
                'FlightCon':  _('Helm'),	# Multicrew role
            }.get(role, role)

        while True:
            entry = monitor.get_entry()
            if not entry:
                return

            # Update main window
            self.cooldown()
            if monitor.cmdr and monitor.state['Captain']:
                self.cmdr['text'] = '%s / %s' % (monitor.cmdr, monitor.state['Captain'])
                self.ship_label['text'] = _('Role') + ':'	# Multicrew role label in main window
                self.ship.configure(state = tk.NORMAL, text = crewroletext(monitor.state['Role']), url = None)
            elif monitor.cmdr:
                if monitor.group:
                    self.cmdr['text'] = '%s / %s' % (monitor.cmdr, monitor.group)
                elif monitor.mode.lower() == 'solo':
                    self.cmdr['text'] = '%s / %s' % (monitor.cmdr, 'Solo')	# Game mode - not Open or Group. Don't translate
                else:
                    self.cmdr['text'] = monitor.cmdr
                self.ship_label['text'] = _('Ship') + ':'	# Main window
                self.ship.configure(text = monitor.state['ShipName'] or companion.ship_map.get(monitor.state['ShipType'], monitor.state['ShipType']) or '',
                                    url = self.shipyard_url)
            else:
                self.cmdr['text'] = ''
                self.ship_label['text'] = _('Ship') + ':'	# Main window
                self.ship['text'] = ''

            self.edit_menu.entryconfigure(0, state=monitor.system and tk.NORMAL or tk.DISABLED)	# Copy

            if entry['event'] in ['Undocked', 'StartJump', 'SetUserShipName', 'ShipyardBuy', 'ShipyardSell', 'ShipyardSwap', 'ModuleBuy', 'ModuleSell', 'MaterialCollected', 'MaterialDiscarded', 'ScientificResearch', 'EngineerCraft', 'Synthesis', 'JoinACrew']:
                self.status['text'] = ''	# Periodically clear any old error
            self.w.update_idletasks()

            # Companion login
            if entry['event'] in [None, 'StartUp', 'NewCommander', 'LoadGame'] and monitor.cmdr:
                if config.get('cmdrs') and monitor.cmdr in config.get('cmdrs'):
                    prefs.make_current(monitor.cmdr)
                    self.login()
                elif config.get('cmdrs') and entry['event'] == 'NewCommander':
                    cmdrs = config.get('cmdrs')
                    cmdrs[0] = monitor.cmdr	# New Cmdr uses same credentials as old
                    config.set('cmdrs', cmdrs)
                else:
                    prefs.PreferencesDialog(self.w, self.postprefs)	# First run or failed migration

            if not entry['event'] or not monitor.mode:
                return	# Startup or in CQC

            # Plugins
            err = plug.notify_journal_entry(monitor.cmdr, monitor.is_beta, monitor.system, monitor.station, entry, monitor.state)
            if err:
                self.status['text'] = err
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()

            if entry['event'] in ['StartUp', 'LoadGame'] and monitor.started:
                # Can start dashboard monitoring
                if not dashboard.start(self.w, monitor.started):
                    print "Can't start Status monitoring"

            # Don't send to EDDN while on crew
            if monitor.state['Captain']:
                return

            # Plugin backwards compatibility
            if monitor.mode and entry['event'] in ['StartUp', 'Location', 'FSDJump']:
                plug.notify_system_changed(timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ')), monitor.system, monitor.coordinates)

            # Auto-Update after docking
            if monitor.mode and monitor.station and entry['event'] in ['StartUp', 'Location', 'Docked'] and not config.getint('output') & config.OUT_MKT_MANUAL and config.getint('output') & config.OUT_STATION_ANY:
                self.w.after(int(SERVER_RETRY * 1000), self.getandsend)

            # Send interesting events to EDDN
            try:
                if (config.getint('output') & config.OUT_SYS_EDDN and monitor.cmdr and monitor.mode and
                    (entry['event'] == 'Location' or
                     entry['event'] == 'FSDJump' or
                     entry['event'] == 'Docked'  or
                     entry['event'] == 'Scan'    and monitor.system and monitor.coordinates)):
                    # strip out properties disallowed by the schema
                    for thing in ['CockpitBreach', 'BoostUsed', 'FuelLevel', 'FuelUsed', 'JumpDist', 'Latitude', 'Longitude']:
                        entry.pop(thing, None)
                    for thing in entry.keys():
                        if thing.endswith('_Localised'):
                            entry.pop(thing, None)

                    # add planet to Docked event for planetary stations if known
                    if entry['event'] == 'Docked' and monitor.planet:
                        entry['Body'] = monitor.planet
                        entry['BodyType'] = 'Planet'

                    # add mandatory StarSystem and StarPos properties to Scan events
                    if 'StarSystem' not in entry:
                        entry['StarSystem'] = monitor.system
                    if 'StarPos' not in entry:
                        entry['StarPos'] = list(monitor.coordinates)

                    self.eddn.export_journal_entry(monitor.cmdr, monitor.is_beta, entry)

            except requests.exceptions.RequestException as e:
                if __debug__: print_exc()
                self.status['text'] = _("Error: Can't connect to EDDN")
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()

            except Exception as e:
                if __debug__: print_exc()
                self.status['text'] = unicode(e)
                if not config.getint('hotkey_mute'):
                    hotkeymgr.play_bad()