def handle_end_who(match: re.Match, window: wx.Frame, skip_store=False) -> bool: who_time = match.group('time') zone = match.group('zone') if zone.lower() == "everquest": zone = None parsed_time = dateutil.parser.parse(who_time) raidtick_was = parsed_time - config.LAST_RAIDTICK raidtick_who = False if raidtick_was <= datetime.timedelta(seconds=3): raidtick_who = True # Handle reminder alerts if config.RAIDTICK_ALERT_TIMER: config.RAIDTICK_ALERT_TIMER.cancel() config.RAIDTICK_REMINDER_COUNT = 0 config.RAIDTICK_ALERT_TIMER = threading.Timer(60 * 60, raidtick_reminder_alert) config.RAIDTICK_ALERT_TIMER.start() log_entry = models.WhoLog(parsed_time, copy.copy(config.LAST_WHO_SNAPSHOT), raidtick_who, zone) if raidtick_who: # Give audio confirmation of the RaidTick detection utils.alert_sound(config.NEW_RAIDTICK_SOUND) utils.alert_message( "RaidTick Recorded", "Recorded a new RaidTick with %d player(s), %d of which are in " "your alliance." % (len(log_entry.log), log_entry.alliance_count())) config.ATTENDANCE_LOGS.append(log_entry) wx.PostEvent(window, models.WhoHistoryEvent()) wx.PostEvent(window, models.WhoEndEvent()) if not skip_store: utils.store_state() return True
def handle_drop(match: re.Match, window: wx.Frame, skip_store=False) -> list: timestamp = match.group("time") name = match.group("name") text = match.group("text") guild = config.LAST_WHO_SNAPSHOT.get(name, models.Player(name)).guild if text.lower().startswith("looted"): LOG.info("Ignoring drop message starting with 'looted'") return list() if AWARD_MESSAGE_MATCHER.match(text): LOG.info("Ignoring drop message that matches Gratss") return list() if NUMBER_MATCHER.match(text): # line contains a number, it's probably a bid, ignore it LOG.info("Ignoring drop message with a number, probably a bid") return list() if config.RESTRICT_BIDS and guild and guild not in config.ALLIANCE_MAP: # Some other guild is talking, discard line LOG.info("Ignoring ooc from guild %s", guild) return list() # Handle text to return a list of items linked found_items = utils.get_items_from_text(text) used_found_items = [] now = datetime.datetime.now() skip = False for item in found_items: if item.lower() in utils.get_active_item_names(): LOG.debug("Skipping drop %s because it is already up for auction.") continue for pending in config.PENDING_AUCTIONS: pending_time = dateutil.parser.parse(pending.timestamp) if (item.lower() == pending.name.lower() and (now - pending_time).seconds < config.DROP_COOLDOWN): skip = True LOG.debug("Skipping drop %s because of DROP_COOLDOWN config.", item) break if skip: skip = False continue drop = models.ItemDrop(item, name, timestamp) if (config.NODROP_ONLY and item in extra_data.EXTRA_ITEM_DATA and not extra_data.EXTRA_ITEM_DATA[item].get('nodrop', True)): config.IGNORED_AUCTIONS.append(drop) LOG.info("Added droppable item to IGNORED AUCTIONS: %s", drop) else: config.PENDING_AUCTIONS.append(drop) LOG.info("Added item to PENDING AUCTIONS: %s", drop) used_found_items.append(item) if not found_items: return list() if used_found_items: wx.PostEvent(window, models.DropEvent()) utils.alert_message( "New Drops Detected", '\n'.join(["\u00A0\u2022 %s" % drop for drop in used_found_items])) utils.alert_sound(config.NEW_DROP_SOUND) if not skip_store: utils.store_state() return found_items
def OnMarkRaidtick(self, e: wx.EVT_RIGHT_DCLICK): selected_object = self.attendance_list.GetSelectedObject() if not selected_object: return selected_object.raidtick = not selected_object.raidtick self.OnRaidtickOnly(e) self.attendance_list.SelectObject(selected_object) utils.store_state()
def OnRemovePlayer(self, e: wx.EVT_BUTTON): selected_player = self.attendance_record.GetSelectedObject() if not selected_player: return self.item.log.pop(selected_player.name) self.attendance_record.RemoveObject(selected_player) self.Update() utils.store_state()
def handle_kill(match: re.Match, window: wx.Frame, skip_store=False) -> bool: time = match.group('time') victim = match.group('victim') # if victim in extra_data.TIMER_MOBS: kt_obj = models.KillTimer(time, victim) config.KILL_TIMERS.append(kt_obj) wx.PostEvent(window, models.KillEvent()) if not skip_store: utils.store_state() return True
def OnIgnoreGratss(self, e: wx.Event): selected_object = self.gratss_list.GetSelectedObject() selected_index = self.gratss_list.GetFirstSelected() if not selected_object: return config.GRATSS_LOG.remove(selected_object) self.gratss_list.SetObjects(config.GRATSS_LOG) item_count = self.gratss_list.GetItemCount() if item_count > 0: self.gratss_list.Select(min(selected_index, item_count - 1)) utils.store_state()
def OnIgnoreCreditt(self, e: wx.Event): selected_object = self.creditt_list.GetSelectedObject() selected_index = self.creditt_list.GetFirstSelected() if not selected_object: return config.CREDITT_LOG.remove(selected_object) self.creditt_list.SetObjects(config.CREDITT_LOG) item_count = self.creditt_list.GetItemCount() if item_count > 0: self.creditt_list.Select(min(selected_index, item_count - 1)) utils.store_state()
def OnClearApp(self, e: wx.MenuEvent): dlg = wx.MessageDialog(self, "Are you sure you want to clear all data?", "Confirm Clear", wx.OK | wx.CANCEL | wx.ICON_QUESTION) result = dlg.ShowModal() dlg.Destroy() if result == wx.ID_OK: utils.store_state(backup=True) wx.PostEvent(self.GetParent(), models.AppClearEvent()) utils.clear_alerts()
def UndoStart(self, e: wx.Event): selected_object = self.active_list.GetSelectedObject() if not selected_object: return selected_object.cancel() config.PENDING_AUCTIONS.append(selected_object.item) config.ACTIVE_AUCTIONS.pop(selected_object.item.uuid) self.pending_list.SetObjects(config.PENDING_AUCTIONS) self.active_list.SetObjects( list(config.ACTIVE_AUCTIONS.values())) self.pending_list.SelectObject(selected_object.item) utils.store_state()
def OnIgnorePending(self, e: wx.Event): selected_object = self.pending_list.GetSelectedObject() selected_index = self.pending_list.GetFirstSelected() if not selected_object: return utils.ignore_pending_item(selected_object) self.pending_list.SetObjects(config.PENDING_AUCTIONS) item_count = self.pending_list.GetItemCount() if item_count > 0: self.pending_list.Select(min(selected_index, item_count - 1)) utils.store_state() wx.PostEvent(self.GetGrandParent(), models.IgnoreEvent())
def OnClose(self, e: wx.Event): dlg = wx.MessageDialog( self, "Do you really want to close this application?", "Confirm Exit", wx.OK | wx.CANCEL | wx.ICON_QUESTION) result = dlg.ShowModal() dlg.Destroy() if result == wx.ID_OK: utils.clear_alerts() config.WX_TASKBAR_ICON.Destroy() self.parser_thread.abort() utils.store_state() self.Destroy()
def UndoComplete(self, e: wx.Event): selected_object = self.history_list.GetSelectedObject() if not selected_object: return config.ACTIVE_AUCTIONS[selected_object.item.uuid] = ( selected_object) config.HISTORICAL_AUCTIONS.pop(selected_object.item.uuid) self.active_list.SetObjects( list(config.ACTIVE_AUCTIONS.values())) self.history_list.SetObjects( list(config.HISTORICAL_AUCTIONS.values())) self.active_list.SelectObject(selected_object) utils.store_state()
def StartAuctionRandom(self, e: wx.Event): selected_object = self.pending_list.GetSelectedObject() if not selected_object: return auc = utils.start_auction_random(selected_object) if not auc: self.DialogDuplicate() return self.pending_list.SetObjects(config.PENDING_AUCTIONS) self.active_list.SetObjects( list(config.ACTIVE_AUCTIONS.values())) self.active_list.SelectObject(auc) self.CopyBidText(e) utils.store_state()
def CompleteAuction(self, e: wx.Event): selected_object = self.active_list.GetSelectedObject() if not selected_object: return selected_object.complete() config.HISTORICAL_AUCTIONS[selected_object.item.uuid] = ( selected_object) config.ACTIVE_AUCTIONS.pop(selected_object.item.uuid) self.active_list.SetObjects( list(config.ACTIVE_AUCTIONS.values())) self.history_list.SetObjects( list(config.HISTORICAL_AUCTIONS.values())) self.OnHideRot(None) self.history_list.SelectObject(selected_object) self.CopyWinText(e) utils.store_state()
def OnAddPlayer(self, e: wx.EVT_BUTTON): name_dialog = wx.TextEntryDialog(self, "Player name:", "Add Player") result = name_dialog.ShowModal() player_name = name_dialog.GetValue().capitalize() name_dialog.Destroy() if result != wx.ID_OK or not player_name: return player_guild = config.ALLIANCES[config.DEFAULT_ALLIANCE][0] player_record = models.Player(player_name, None, None, player_guild) if player_name in config.PLAYER_DB: player_record = config.PLAYER_DB[player_name] self.item.log[player_name] = player_record self.attendance_record.AddObject(player_record) self.attendance_record.Update() utils.store_state()
def handle_rand2(match: re.Match, window: wx.Frame, skip_store=False) -> bool: name = match.group('name') rand_from = int(match.group('from')) rand_to = int(match.group('to')) rand_result = int(match.group('result')) for item_obj in config.ACTIVE_AUCTIONS.values(): if (isinstance(item_obj, models.RandomAuction) and item_obj.number == rand_to): if rand_from > 0: LOG.info("%s rolled from %d instead of 0, not counting it.", name, rand_from) return False item_obj.add(rand_result, name) wx.PostEvent(window, models.BidEvent(item_obj)) if not skip_store: utils.store_state() return True LOG.info("%s rolled %d-%d but that doesn't apply to an active auction.", name, rand_from, rand_to) return False
def replay_logs(replay_lines, progress_dialog): old_charname = config.PLAYER_NAME total_picked_lines = len(replay_lines) last_rand_player = None for idx, line in enumerate(replay_lines): keep_going, _ = progress_dialog.Update( idx, newmsg="Now parsing line %s of %s..." % (idx, total_picked_lines)) if not keep_going: LOG.debug("User cancelled log replay.") break line = line.strip() if last_rand_player: line = line + last_rand_player last_rand_player = None result = None for matcher in SELF_MESSAGE_MATCHERS: match = matcher.match(line) if match: match_func = SELF_MESSAGE_MATCHERS[matcher] try: result = match_func(match, progress_dialog.Parent, True) except Exception: LOG.exception("Failed to parse SELF line: %s", line) if result: LOG.debug("Handled SELF line: %s", line) continue for matcher in logparse.LOG_MATCHERS: match = matcher.match(line) if match: match_func = logparse.LOG_MATCHERS[matcher] result = match_func(match, progress_dialog.Parent, True) if matcher == config.MATCH_RAND1: last_rand_player = result if result: LOG.debug("Handled line: %s", line) LOG.info("Finished log replay!") config.PLAYER_NAME = old_charname utils.store_state()
def handle_bid(match: re.Match, window: wx.Frame, skip_store=False) -> bool: name = match.group("name") if name == "You": name = config.PLAYER_NAME guild = config.LAST_WHO_SNAPSHOT.get(name, models.Player(name)).guild alliance = config.ALLIANCE_MAP.get(guild) text = match.group("text") bid = int(match.group("bid")) if text.startswith("~"): return False found_items = utils.get_items_from_text(text) if not found_items: # No item found in auction LOG.info("%s might have attempted to bid but no item name found: %s", name, text) return False if len(found_items) > 1: # Can't bid on two items at once LOG.info("%s attempted to bid for two items at once: %s", name, found_items) return False item = found_items[0] for auc_item in config.ACTIVE_AUCTIONS.values(): if item.lower() == auc_item.name().lower(): if not isinstance(auc_item, models.DKPAuction): LOG.info( "Ignoring bid by %s because `%s` is a random auction.", name, item) return False if (config.RESTRICT_BIDS and guild and alliance != auc_item.alliance): # Player is not in the correct alliance LOG.info( "%s attempted to bid for %s, but is in the wrong " "guild/alliance: %s/%s", name, item, guild, alliance) return False result = auc_item.add(bid, name) wx.PostEvent(window, models.BidEvent(auc_item)) # pylint: disable=protected-access if (config.SECOND_MAIN_REMINDER_DKP and bid > config.SECOND_MAIN_REMINDER_DKP and not auc_item._second_main_cap_alerted): utils.alert_message( "%d DKP is above the Second-Main Cap" % bid, "%s's bid for %s is above the cap for second-mains. " "Please verify bidders are aware of this." % (name, item), msec=8000) auc_item._second_main_cap_alerted = True elif (config.ALT_REMINDER_DKP and bid > config.ALT_REMINDER_DKP and not auc_item._alt_cap_alerted): utils.alert_message( "%d DKP is above the Alt Bid Cap" % bid, "%s's bid for %s is above the cap for alts. " "Please verify bidders are aware of this." % (name, item), msec=8000) auc_item._alt_cap_alerted = True if not skip_store: utils.store_state() return result LOG.info("%s attempted to bid for %s but it isn't active", name, item) return False
def OnClose(self, e: wx.EVT_CLOSE): self.item.raidtick = self.raidtick_checkbox.IsChecked() self.item.tick_name = self.name_textbox.GetValue() self.GetParent().RefreshList() utils.store_state() self.Destroy()