Пример #1
0
def play_sound(sound):
    """Play the sound given"""
    try:
        playsound(sound)
    except Exception as e:
        eqa_settings.log("play sound: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
Пример #2
0
def process(exit_flag, log_q, action_q):
    """
    Process: log_q
    Produce action_q
    """

    try:
        while not exit_flag.is_set():
            time.sleep(0.001)
            if not log_q.empty():
                # Read raw log line
                log_line = log_q.get()
                log_q.task_done()

                # Strip line of trailing space and lowercase everything
                line = log_line.strip()
                # Split timestamp and message payload
                timestamp, payload = line[1:].split("] ", 1)
                timestamp = timestamp.split(" ")[3] + ".00"
                # Determine line type
                line_type = determine(payload)
                # Build and queue action
                new_message = eqa_struct.message(
                    timestamp, line_type, "null", "null", payload.lower()
                )
                action_q.put(new_message)

    except Exception as e:
        eqa_settings.log(
            "process_log: Error on line "
            + str(sys.exc_info()[-1].tb_lineno)
            + ": "
            + str(e)
        )
Пример #3
0
 def callback(event):
     try:
         if event.mask == pyinotify.IN_CLOSE_WRITE:
             log_q.put(eqa_parser.last_line(char_log))
     except Exception as e:
         eqa_settings.log("log watch callback: Error on line " +
                          str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
Пример #4
0
def draw_chars(stdscr, chars, char, selected):
    """Draw character selection component for settings"""
    try:
        y, x = stdscr.getmaxyx()
        charscr_width = int(x / 3)
        # Pending general scrolling method
        charscr_height = len(chars) + 2

        charscr = stdscr.derwin(charscr_height, charscr_width, 5, 3)
        charscr.clear()
        charscr.box()

        count = 0
        while count < len(chars):
            char_name, char_server = chars[count].split("_")
            if selected == count:
                charscr.addstr(
                    len(chars) - count,
                    2,
                    char_name + " " + char_server,
                    curses.color_pair(1),
                )
            else:
                charscr.addstr(
                    len(chars) - count,
                    2,
                    char_name + " " + char_server,
                    curses.color_pair(2),
                )
            count += 1

    except Exception as e:
        eqa_settings.log("draw chars: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
Пример #5
0
def draw_state(stdscr, state, raid):
    """Draw state"""
    y, x = stdscr.getmaxyx()
    center_y = int(y / 2)
    center_x = int(x / 2)

    # Clear and box
    stdscr.clear()
    stdscr.box()

    # Draw tabs
    draw_tabs(stdscr, "state")

    # Show some state
    try:
        # server state
        stdscr.addstr(5, 5, "Server", curses.color_pair(2))
        stdscr.addstr(5, 16, ": ", curses.color_pair(1))
        stdscr.addstr(5, 18, state.server.title(), curses.color_pair(3))

        # char
        stdscr.addstr(7, 5, "Character", curses.color_pair(2))
        stdscr.addstr(7, 16, ": ", curses.color_pair(1))
        stdscr.addstr(7, 18, state.char.title(), curses.color_pair(3))

        # zone
        stdscr.addstr(9, 5, "Zone", curses.color_pair(2))
        stdscr.addstr(9, 16, ": ", curses.color_pair(1))
        stdscr.addstr(9, 18, state.zone.title(), curses.color_pair(3))

        # loc
        stdscr.addstr(11, 5, "Location", curses.color_pair(2))
        stdscr.addstr(11, 16, ": ", curses.color_pair(1))
        stdscr.addstr(11, 18, str(state.loc[0]), curses.color_pair(3))
        stdscr.addstr(11, 24, " : ", curses.color_pair(2))
        stdscr.addstr(11, 26, str(state.loc[1]), curses.color_pair(3))
        stdscr.addstr(11, 32, " : ", curses.color_pair(2))
        stdscr.addstr(11, 34, str(state.loc[2]), curses.color_pair(3))

        # direction
        stdscr.addstr(13, 5, "Direction", curses.color_pair(2))
        stdscr.addstr(13, 16, ": ", curses.color_pair(1))
        stdscr.addstr(13, 18, state.direction.title(), curses.color_pair(3))

        # raid state
        stdscr.addstr(15, 5, "Raid", curses.color_pair(2))
        stdscr.addstr(15, 16, ": ", curses.color_pair(1))
        if not raid.is_set():
            stdscr.addstr(15, 18, "False", curses.color_pair(3))
        else:
            stdscr.addstr(15, 18, "True", curses.color_pair(3))

        # afk state
        stdscr.addstr(17, 5, "AFK", curses.color_pair(2))
        stdscr.addstr(17, 16, ": ", curses.color_pair(1))
        stdscr.addstr(17, 18, state.afk.title(), curses.color_pair(3))

    except Exception as e:
        eqa_settings.log("draw state: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
Пример #6
0
def last_line(character_log):
    """Reads and returns last line"""
    try:
        with open(character_log, "r") as f:
            content = deque(f, 1)
        return content[0]
    except Exception as e:
        eqa_settings.log("last_line: " + str(e))
Пример #7
0
def speak(phrase, play, sound_file_path):
    """Play a spoken phrase"""
    try:
        if not os.path.exists(sound_file_path + phrase + ".wav"):
            tts = gtts.gTTS(text=phrase, lang="en")
            tts.save(sound_file_path + phrase + ".wav")
        if play == "true":
            play_sound(sound_file_path + phrase + ".wav")

    except Exception as e:
        eqa_settings.log("speak: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
Пример #8
0
def read(exit_flag, keyboard_q, stdscr):
    """
    Consume: keyboard events
    Produce: keyboard_q
    """

    key = ""
    try:
        while not exit_flag.is_set():
            key = stdscr.getch()
            keyboard_q.put(key)
        sys.exit()
    except Exception as e:
        eqa_settings.log("read keys: " + str(e))
        sys.exit()
Пример #9
0
def draw_page(stdscr, page, events, state, setting, selected_char, raid):
    y, x = stdscr.getmaxyx()
    try:
        if x >= 80 and y >= 40:
            if page == "events":
                draw_events_frame(stdscr, state.char, state.zone, events)
            elif page == "state":
                draw_state(stdscr, state, raid)
            elif page == "settings":
                draw_settings(stdscr, state, setting, selected_char)
            elif page == "help":
                draw_help(stdscr)
        else:
            draw_toosmall(stdscr)
    except Exception as e:
        eqa_settings.log("draw_page: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
Пример #10
0
def draw_events(stdscr, events):
    """Draw events window component of events"""
    y, x = stdscr.getmaxyx()
    center_y = int(y / 2)
    bottom_y = center_y - 4
    top_y = 2

    eventscr = stdscr.derwin(center_y - 3, x - 4, 3, 2)
    eventscr.clear()

    try:
        count = 0
        while count < (bottom_y + 1) and count < len(events):
            event_num = len(events) - count - 1
            event = events[(count * -1) - 1]
            c_y = bottom_y - count
            draw_ftime(eventscr, event.timestamp, c_y)
            eventscr.addch(c_y, 14, curses.ACS_VLINE)
            eventscr.addstr(c_y, 16, str(event.payload), curses.color_pair(1))
            count += 1
    except Exception as e:
        eqa_settings.log("draw events: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
Пример #11
0
def process(config, sound_q, exit_flag, cfg_reload):
    """
    Process: sound_q
    Produce: sound event
    """

    tmp_sound_file_path = "/tmp/eqa/sound/"

    if not os.path.exists(tmp_sound_file_path):
        os.makedirs(tmp_sound_file_path)

    try:
        while not exit_flag.is_set() and not cfg_reload.is_set():
            time.sleep(0.001)
            if not sound_q.empty():
                sound_event = sound_q.get()
                sound_q.task_done()

                if sound_event.sound == "speak":
                    speak(sound_event.payload, "true", tmp_sound_file_path)
                elif sound_event.sound == "alert":
                    alert(config, sound_event.payload)
                else:
                    speak(sound_event.payload, "true", tmp_sound_file_path)
                    display_q.put(
                        eqa_struct.display(
                            eqa_settings.eqa_time(),
                            "event",
                            "events",
                            "[Malformed sound event] " + sound_event.sound,
                        ))
    except Exception as e:
        eqa_settings.log("process_sound: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
        sys.exit()

    sys.exit()
Пример #12
0
def determine(line):
    """Determine type of line"""

    try:
        # Melee Combat
        if (
            re.fullmatch(
                r"^[a-zA-Z\s]+ (hits|crushes|slashes|pierces|bashes|backstabs|bites|kicks|claws|gores|punches|strikes|slices) [a-zA-Z\s]+ for \d+ points of damage\.",
                line,
            )
            is not None
        ):
            line_type = "combat_other_melee"
        elif (
            re.fullmatch(
                r"^[a-zA-Z\s]+ tries to (hit|crush|slash|pierce|bash|backstab|bite|kick|claw|gore|punch|strike|slice) [a-zA-Z\s]+, but misses\!",
                line,
            )
            is not None
        ):
            line_type = "combat_other_melee_miss"
        elif (
            re.fullmatch(
                r"^[a-zA-Z\s]+ (hits|crushes|slashes|pierces|bashes|backstabs|bites|kicks|claws|gores|punches|strikes|slices) you for \d+ points of damage\.",
                line,
            )
            is not None
        ):
            line_type = "combat_you_receive_melee"
        elif (
            re.fullmatch(
                r"^You (hit|crush|slash|pierce|bash|backstab|bite|kick|claw|gore|punch|strike|slice) [a-zA-Z\s]+ for \d+ points of damage\.",
                line,
            )
            is not None
        ):
            line_type = "combat_you_melee"
        elif (
            re.fullmatch(
                r"^You try to (hit|crush|slash|pierce|bash|backstab|bite|kick|claw|gore|punch|strike|slice) [a-zA-Z\s]+, but miss\!",
                line,
            )
            is not None
        ):
            line_type = "combat_you_melee_miss"

        # Player Messages
        elif re.fullmatch(r"^\w+ tells you, \'.+\'$", line) is not None:
            line_type = "tell"
        elif re.fullmatch(r"^\w+ says, \'.+\'$", line) is not None:
            line_type = "say"
        elif re.fullmatch(r"^\w+ shouts, \'.+\'$", line) is not None:
            line_type = "shout"
        elif re.fullmatch(r"^\w+ tells the guild, \'.+\'$", line) is not None:
            line_type = "guild"
        elif re.fullmatch(r"^\w+ tells the group, \'.+\'$", line) is not None:
            line_type = "group"
        elif re.fullmatch(r"^\w+ says out of character, \'.+\'$", line) is not None:
            line_type = "ooc"
        elif (
            re.fullmatch(r"^\w+ auctions, \'(.+|)(WTS|selling|Selling)(.+|)\'$", line)
            is not None
        ):
            line_type = "auction_wts"
        elif (
            re.fullmatch(r"^\w+ auctions, \'(.+|)(WTB|buying|Buying)(.+|)\'$", line)
            is not None
        ):
            line_type = "auction_wtb"
        elif re.fullmatch(r"^\w+ auctions, \'.+\'$", line) is not None:
            line_type = "auction"
        elif re.fullmatch(r"^You told \w+, \'.+\'$", line) is not None:
            line_type = "you_tell"
        elif re.fullmatch(r"^You say, \'.+\'$", line) is not None:
            line_type = "you_say"
        elif re.fullmatch(r"^You shout, \'.+\'$", line) is not None:
            line_type = "you_shout"
        elif re.fullmatch(r"^You say to your guild, \'.+\'$", line) is not None:
            line_type = "you_guild"
        elif re.fullmatch(r"^You tell your party, \'.+\'$", line) is not None:
            line_type = "you_group"
        elif re.fullmatch(r"^You say out of character, \'.+\'$", line) is not None:
            line_type = "you_ooc"
        elif re.fullmatch(r"^You auction, \'.+\'$", line) is not None:
            line_type = "you_auction"

        # Player Status
        elif (
            re.fullmatch(
                r"^Your Location is [-]?(?:\d*\.)?\d+\,\ [-]?(?:\d*\.)?\d+\,\ [-]?(?:\d*\.)?\d+$",
                line,
            )
            is not None
        ):
            line_type = "location"
        elif (
            re.fullmatch(
                r"^You think you are heading (?:North(?:East|West)?|South(?:East|West)?|(?:Ea|We)st)\.$",
                line,
            )
            is not None
        ):
            line_type = "direction"
        elif (
            re.fullmatch(r"^You have no idea what direction you are facing\.$", line)
            is not None
        ):
            line_type = "direction_miss"
        elif re.fullmatch(r"^You have entered .+\.$", line) is not None:
            line_type = "you_new_zone"
        elif (
            re.fullmatch(r"^You have healed .+ for \d+ points of damage\.$", line)
            is not None
        ):
            line_type = "you_healed"
        elif (
            re.fullmatch(r"^You are now A\.F\.K\. \(Away From Keyboard\)\.", line)
            is not None
        ):
            line_type = "you_afk_on"
        elif re.fullmatch(r"^You are now Looking For a Group\.", line) is not None:
            line_type = "you_lfg_on"
        elif (
            re.fullmatch(r"^You are no longer A\.F\.K\. \(Away From Keyboard\)\.", line)
            is not None
        ):
            line_type = "you_afk_off"
        elif (
            re.fullmatch(r"^You are no longer Looking For a Group\.", line) is not None
        ):
            line_type = "you_lfg_off"
        elif re.fullmatch(r"^You are out of food\.", line) is not None:
            line_type = "you_outfood"
        elif re.fullmatch(r"^You are out of drink\.", line) is not None:
            line_type = "you_outdrink"
        elif re.fullmatch(r"^You are out of food and drink\.", line) is not None:
            line_type = "you_outfooddrink"
        elif re.fullmatch(r"^You are out of food and low on drink\.", line) is not None:
            line_type = "you_outfoodlowdrink"
        elif re.fullmatch(r"^You are out of drink and low on food\.", line) is not None:
            line_type = "you_outdrinklowfood"
        elif re.fullmatch(r"^You are thirsty\.", line) is not None:
            line_type = "you_thirsty"
        elif re.fullmatch(r"^You are hungry\.", line) is not None:
            line_type = "you_hungry"

        # Spells
        elif re.fullmatch(r"^You forget .+\.", line) is not None:
            line_type = "you_spell_forget"
        elif re.fullmatch(r"^\w+\'s spell fizzles\!$", line) is not None:
            line_type = "spell_fizzle"
        elif re.fullmatch(r"^Your spell is interrupted\.", line) is not None:
            line_type = "you_spell_fizzle"
        elif re.fullmatch(r"^\w+\'s casting is interrupted\!\.", line) is not None:
            line_type = "spell_fizzle"
        elif re.fullmatch(r"^Your target resisted the .+ spell\.$", line) is not None:
            line_type = "spell_resist"
        elif (
            re.fullmatch(
                r"^.+ w(?:ere|as) hit by non-melee for \d+ ?(points of) damage\.$", line
            )
            is not None
        ):
            line_type = "spell_damage"
        elif re.fullmatch(r"^\w+ begins to regenerate\.$", line) is not None:
            line_type = "spell_regen"
        elif re.fullmatch(r"^Your charm spell has worn off\.$", line) is not None:
            line_type = "spell_break_charm"
        elif re.fullmatch(r"^Your Ensnare spell has worn off\.$", line) is not None:
            line_type = "spell_break_ensnare"

        # Emotes
        elif re.fullmatch(r"^\w+ bows before \w+\.$", line) is not None:
            line_type = "emote_bow"
        elif re.fullmatch(r"^\w+ thanks \w+ heartily\.$", line) is not None:
            line_type = "emote_thank"
        elif re.fullmatch(r"^\w+ waves at \w+\.$", line) is not None:
            line_type = "emote_wave"
        elif (
            re.fullmatch(
                r"^\w+ grabs hold of \w+ and begins to dance with (?:h(?:er|im)|it)\.$",
                line,
            )
            is not None
        ):
            line_type = "emote_dance"
        elif re.fullmatch(r"^\w+ bonks \w+ on the head\!$", line) is not None:
            line_type = "emote_bonk"
        elif re.fullmatch(r"^\w+ beams a smile at (a|) \w+$", line) is not None:
            line_type = "emote_smile"
        elif re.fullmatch(r"^\w+ cheers at \w+$", line) is not None:
            line_type = "emote_cheer"

        # World Status
        elif re.fullmatch(r"^It begins to rain\.$", line) is not None:
            line_type = "weather_start_rain"
        elif re.fullmatch(r"^It begins to snow\.$", line) is not None:
            line_type = "weather_start_snow"
        elif re.fullmatch(r"^Players in EverQuest\:$", line) is not None:
            line_type = "who_top"
        elif re.fullmatch(r"^---------------------------------$", line) is not None:
            line_type = "who_line"
        elif (
            re.fullmatch(
                r"^\[\d+ (?:(?:(?:Shadow )?Knigh|Hierophan|Revenan)t|(?:Elemental|Phantasm)ist|High Priest|Illusionist|(?:Grandmast|P(?:athfind|reserv)|C(?:hannel|avali)|(?:Enchan|Mas)t|(?:Begu|Def)il|Conjur|Sorcer|Wa(?:nder|rd)|(?:Crusa|Outri)d|Rang|Evok|Reav)er|Necromancer|(?:B(?:lackgu)?|Wiz)ard|Grave Lord|(?:T(?:roubadou|empla)|Warrio|Vica)r|A(?:rch Mage|ssassin)|Minstrel|Virtuoso|(?:(?:Myrmid|Champi)o|Magicia|Shama)n|(?:Discipl|Oracl|R(?:ogu|ak))e|Luminary|Warlock|Heretic|Paladin|(?:Warlor|Drui)d|Cleric|Mystic|Monk)\] \w+ \((?:Barbarian|Halfling|Half\-Elf|(?:Dark|High) Elf|Wood Elf|Skeleton|Erudite|Iksar|Troll|(?:Gnom|Ogr)e|Dwarf|Human)\)(?:( \<[a-zA-Z\s]+\> ZONE\: \w+| \<[a-zA-Z\s]+\>|))$",
                line,
            )
            is not None
        ):
            line_type = "who_player"
        elif (
            re.fullmatch(
                r"^AFK \[\d+ (?:(?:(?:Shadow )?Knigh|Hierophan|Revenan)t|(?:Elemental|Phantasm)ist|High Priest|Illusionist|(?:Grandmast|P(?:athfind|reserv)|C(?:hannel|avali)|(?:Enchan|Mas)t|(?:Begu|Def)il|Conjur|Sorcer|Wa(?:nder|rd)|(?:Crusa|Outri)d|Rang|Evok|Reav)er|Necromancer|(?:B(?:lackgu)?|Wiz)ard|Grave Lord|(?:T(?:roubadou|empla)|Warrio|Vica)r|A(?:rch Mage|ssassin)|Minstrel|Virtuoso|(?:(?:Myrmid|Champi)o|Magicia|Shama)n|(?:Discipl|Oracl|R(?:ogu|ak))e|Luminary|Warlock|Heretic|Paladin|(?:Warlor|Drui)d|Cleric|Mystic|Monk)\] \w+ \((?:Barbarian|Halfling|Half\-Elf|(?:Dark|High) Elf|Wood Elf|Skeleton|Erudite|Iksar|Troll|(?:Gnom|Ogr)e|Dwarf|Human)\)(?:( \<[a-zA-Z\s]+\> ZONE\: \w+| \<[a-zA-Z\s]+\>|))$",
                line,
            )
            is not None
        ):
            line_type = "who_player_afk"
        elif (
            re.fullmatch(
                r"^\<LINKDEAD\>\[\d+ (?:(?:(?:Shadow )?Knigh|Hierophan|Revenan)t|(?:Elemental|Phantasm)ist|High Priest|Illusionist|(?:Grandmast|P(?:athfind|reserv)|C(?:hannel|avali)|(?:Enchan|Mas)t|(?:Begu|Def)il|Conjur|Sorcer|Wa(?:nder|rd)|(?:Crusa|Outri)d|Rang|Evok|Reav)er|Necromancer|(?:B(?:lackgu)?|Wiz)ard|Grave Lord|(?:T(?:roubadou|empla)|Warrio|Vica)r|A(?:rch Mage|ssassin)|Minstrel|Virtuoso|(?:(?:Myrmid|Champi)o|Magicia|Shama)n|(?:Discipl|Oracl|R(?:ogu|ak))e|Luminary|Warlock|Heretic|Paladin|(?:Warlor|Drui)d|Cleric|Mystic|Monk)\] \w+ \((?:Barbarian|Halfling|Half\-Elf|(?:Dark|High) Elf|Wood Elf|Skeleton|Erudite|Iksar|Troll|(?:Gnom|Ogr)e|Dwarf|Human)\)(?:( \<[a-zA-Z\s]+\> ZONE\: \w+| \<[a-zA-Z\s]+\>|))$",
                line,
            )
            is not None
        ):
            line_type = "who_player_linkdead"
        elif (
            re.fullmatch(
                r"^There (is|are) \d+ (player|players) in [a-zA-Z\s]+\.$", line
            )
            is not None
        ):
            line_type = "who_total"
        elif (
            re.fullmatch(
                r"^There are no players in EverQuest that match those who filters\.$",
                line,
            )
            is not None
        ):
            line_type = "who_total"
        elif (
            re.fullmatch(
                r"^Your faction standing with \w+ (?:could not possibly get any|got) (?:better|worse)\.$",
                line,
            )
            is not None
        ):
            line_type = "faction_line"
        elif re.fullmatch(r"^Your target has been cured\.$", line) is not None:
            line_type = "target_cured"
        elif (
            re.fullmatch(
                r"^It will take you about (30|25|20|15|10|5) seconds to prepare your camp\.$",
                line,
            )
            is not None
        ):
            line_type = "you_camping"
        elif (
            re.fullmatch(r"^You abandon your preparations to camp\.$", line) is not None
        ):
            line_type = "you_camping_abandoned"
        elif re.fullmatch(r"^[a-zA-Z\s]+ engages \w+\!$", line) is not None:
            line_type = "engage"
        elif re.fullmatch(r"^LOADING, PLEASE WAIT\.\.\.$", line) is not None:
            line_type = "zoning"
        elif re.fullmatch(r"^\*\*.+", line) is not None:
            line_type = "random"
        elif re.fullmatch(r"^\w+ invites you to join a group\.$", line) is not None:
            line_type = "group_invite"
        elif (
            re.fullmatch(
                r"^(Targeted \((NPC|Player)\)\: [a-zA-Z\s]+|You no longer have a target\.)",
                line,
            )
            is not None
        ):
            line_type = "target"
        else:
            line_type = "undetermined"

    except Exception as e:
        eqa_settings.log(
            "process_log (determine): Error on line "
            + str(sys.exc_info()[-1].tb_lineno)
            + ": "
            + str(e)
        )

    return line_type
Пример #13
0
def process(
    keyboard_q,
    system_q,
    display_q,
    sound_q,
    exit_flag,
    heal_parse,
    spell_parse,
    raid,
    chars,
):
    """
    Process: keyboard_q
    Produce: sound_q, display_q, system_q, heal_q, damage_q
    """

    key = ""
    page = "events"
    settings = "character"
    selected_char = 0

    while key != ord("q") and key != 27:
        try:
            # Get key
            time.sleep(0.001)
            if not keyboard_q.empty():
                key = keyboard_q.get()
                keyboard_q.task_done()

                # Handle resize event
                if key == curses.KEY_RESIZE:
                    display_q.put(
                        eqa_struct.display(eqa_settings.eqa_time(), "draw",
                                           "redraw", "null"))

                # Handle tab keys
                if key == curses.KEY_F1:
                    display_q.put(
                        eqa_struct.display(eqa_settings.eqa_time(), "draw",
                                           "events", "null"))
                    page = "events"
                elif key == curses.KEY_F2:
                    display_q.put(
                        eqa_struct.display(eqa_settings.eqa_time(), "draw",
                                           "state", "null"))
                    page = "state"
                elif key == curses.KEY_F3:
                    display_q.put(
                        eqa_struct.display(eqa_settings.eqa_time(), "draw",
                                           "settings", "null"))
                    page = "settings"
                elif key == curses.KEY_F4:
                    display_q.put(
                        eqa_struct.display(eqa_settings.eqa_time(), "draw",
                                           "help", "null"))
                    page = "help"
                elif key == curses.KEY_F12:
                    system_q.put(
                        eqa_struct.message(
                            eqa_settings.eqa_time(),
                            "system",
                            "reload_config",
                            "null",
                            "null",
                        ))

                # Events keys
                if page == "events":
                    if key == ord("c"):
                        display_q.put(
                            eqa_struct.display(eqa_settings.eqa_time(),
                                               "event", "clear", "null"))
                    elif key == ord("r"):
                        if not raid.is_set():
                            raid.set()
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "event",
                                    "events",
                                    "Raid mode enabled",
                                ))
                            sound_q.put(
                                eqa_struct.sound("speak", "Raid mode enabled"))
                        elif raid.is_set():
                            raid.clear()
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "event",
                                    "events",
                                    "Raid mode disabled",
                                ))
                            sound_q.put(
                                eqa_struct.sound("speak",
                                                 "Raid mode disabled"))
                        display_q.put(
                            eqa_struct.display(eqa_settings.eqa_time(), "draw",
                                               "events", "null"))

                # State keys
                elif page == "state":
                    pass

                # Settings keys
                elif page == "settings":
                    if settings == "character":
                        if key == curses.KEY_UP or key == ord("w"):
                            if selected_char < len(chars) - 1:
                                selected_char += 1
                                display_q.put(
                                    eqa_struct.display(
                                        eqa_settings.eqa_time(),
                                        "update",
                                        "selected_char",
                                        selected_char,
                                    ))
                        elif key == curses.KEY_DOWN or key == ord("s"):
                            if selected_char > 0:
                                selected_char -= 1
                                display_q.put(
                                    eqa_struct.display(
                                        eqa_settings.eqa_time(),
                                        "update",
                                        "selected_char",
                                        selected_char,
                                    ))
                        elif key == curses.KEY_RIGHT or key == ord("d"):
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "update",
                                    "zone",
                                    "unavailable",
                                ))
                            system_q.put(
                                eqa_struct.message(
                                    eqa_settings.eqa_time(),
                                    "system",
                                    "new_character",
                                    "null",
                                    chars[selected_char],
                                ))
                        elif key == ord(" "):
                            pass
                            # cycle to next setting

                # Help keys
                elif page == "help":
                    pass

        except Exception as e:
            eqa_settings.log("process keys: " + str(e))
            eqa_settings.log("setting exit_flag")
            exit_flag.set()
            sys.exit()

    exit_flag.set()
    sys.exit()
Пример #14
0
def process(
    action_q,
    system_q,
    display_q,
    sound_q,
    heal_q,
    damage_q,
    exit_flag,
    heal_parse,
    spell_parse,
    raid,
    cfg_reload,
    config,
    base_path,
):
    """
    Process: action_q
    Produce: sound_q, display_q, system_q, heal_q, damage_q
    """

    try:
        while not exit_flag.is_set() and not cfg_reload.is_set():
            time.sleep(0.001)
            if not action_q.empty():
                new_message = action_q.get()
                action_q.task_done()
                line_type = new_message.type
                line_time = new_message.timestamp
                line_tx = new_message.tx
                line_rx = new_message.rx
                check_line = new_message.payload
                check_line_list = new_message.payload.split(" ")

                # Line specific checks
                if line_type == "undetermined":
                    undetermined_line(check_line, base_path)
                if line_type == "location":
                    loc = [
                        float(check_line_list[3].replace(",", "")),
                        float(check_line_list[4].replace(",", "")),
                        float(check_line_list[5].replace(",", "")),
                    ]
                    system_q.put(
                        eqa_struct.message(eqa_settings.eqa_time(), "system",
                                           "loc", "null", loc))
                elif line_type == "direction":
                    direction = check_line_list[-1].replace(".", "")
                    system_q.put(
                        eqa_struct.message(
                            eqa_settings.eqa_time(),
                            "system",
                            "direction",
                            "null",
                            direction,
                        ))
                elif line_type.startswith("you_afk"):
                    if line_type == "you_afk_on":
                        display_q.put(
                            eqa_struct.display(
                                eqa_settings.eqa_time(),
                                "event",
                                "events",
                                "You are now AFK",
                            ))
                        system_q.put(
                            eqa_struct.message(eqa_settings.eqa_time(),
                                               "system", "afk", "null",
                                               "true"))
                    elif line_type == "you_afk_off":
                        display_q.put(
                            eqa_struct.display(
                                eqa_settings.eqa_time(),
                                "event",
                                "events",
                                "You are no longer AFK",
                            ))
                        system_q.put(
                            eqa_struct.message(
                                eqa_settings.eqa_time(),
                                "system",
                                "afk",
                                "null",
                                "false",
                            ))
                elif line_type == "you_new_zone":
                    nz_iter = 0
                    current_zone = ""
                    while check_line_list.index("entered") + nz_iter + 1 < len(
                            check_line_list):
                        current_zone += (
                            check_line_list[check_line_list.index("entered") +
                                            nz_iter + 1] + " ")
                        nz_iter += 1
                    current_zone = current_zone[:-2]
                    current_zone = current_zone.rstrip(".")
                    sound_q.put(eqa_struct.sound("speak", current_zone))
                    display_q.put(
                        eqa_struct.display(eqa_settings.eqa_time(), "update",
                                           "zone", current_zone))
                    system_q.put(
                        eqa_struct.message(
                            eqa_settings.eqa_time(),
                            "system",
                            "zone",
                            "null",
                            current_zone,
                        ))
                    if current_zone not in config["zones"].keys():
                        eqa_config.add_zone(current_zone, base_path)
                    elif current_zone in config["zones"].keys(
                    ) and not raid.is_set():
                        if config["zones"][current_zone] == "raid":
                            raid.set()
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "event",
                                    "events",
                                    "Raid mode auto-enabled",
                                ))
                            sound_q.put(
                                eqa_struct.sound("speak", "Raid mode enabled"))
                    elif current_zone in config["zones"].keys(
                    ) and raid.is_set():
                        if config["zones"][current_zone] != "raid":
                            raid.clear()
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "event",
                                    "events",
                                    "Raid mode auto-disabled",
                                ))
                            sound_q.put(
                                eqa_struct.sound("speak",
                                                 "Raid mode disabled"))

                # If line_type is a parsable type
                if line_type in config["line"].keys():
                    # If line_type is parsed for as true
                    if config["line"][line_type]["reaction"] == "true":
                        for keyphrase, value in config["line"][line_type][
                                "alert"].items():
                            if str(keyphrase).lower(
                            ) in check_line and value == "true":
                                sound_q.put(
                                    eqa_struct.sound("alert", line_type))
                                display_q.put(
                                    eqa_struct.display(
                                        eqa_settings.eqa_time(),
                                        "event",
                                        "events",
                                        line_type + ": " + check_line[0:65],
                                    ))
                            elif (str(keyphrase).lower() in check_line
                                  and value == "raid" and raid.is_set()):
                                if keyphrase == "assist" or keyphrase == "rampage":
                                    payload = keyphrase + " on " + check_line_list[
                                        0]
                                else:
                                    payload = keyphrase
                                sound_q.put(eqa_struct.sound("speak", payload))
                                display_q.put(
                                    eqa_struct.display(
                                        eqa_settings.eqa_time(),
                                        "event",
                                        "events",
                                        line_type + ": " + check_line[0:65],
                                    ))

                    # Or if line_type is parsed for as all
                    elif config["line"][line_type]["reaction"] == "all":
                        # Heal parse
                        if heal_parse.is_set() and line_type == "you_healed":
                            heal_q.put(
                                eqa_struct.heal(
                                    datetime.datetime.now(),
                                    "heal",
                                    "you",
                                    check_line_list[3],
                                    check_line_list[5],
                                ))

                        # Spell damage parse
                        elif spell_parse.is_set(
                        ) and line_type == "spell_damage":
                            length = check_line_list.index("was")
                            sp_iter = 0
                            name = ""
                            while sp_iter < length:
                                name = name + check_line_list[sp_iter] + " "
                                sp_iter += 1
                            damaged_q.put(
                                eqa_struct.heal(
                                    datetime.datetime.now(),
                                    "spell",
                                    "null",
                                    name,
                                    check_line_list[-4],
                                ))

                        # DoT damage parse
                        elif spell_parse.is_set(
                        ) and line_type == "dot_damage":
                            length = check_line_list.index("has")
                            dp_iter = 0
                            name = ""
                            damage = int(check_line_list[length + 2])
                            while dp_iter < length:
                                name = name + check_line_list[dp_iter] + " "
                                dp_iter += 1
                            damaged_q.put(
                                eqa_struct.heal(datetime.datetime.now(), "dot",
                                                "null", name, damage))

                        # Notify on all other all alerts
                        else:
                            sound_q.put(eqa_struct.sound("alert", line_type))
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "event",
                                    "events",
                                    line_type + ": " + check_line[0:65],
                                ))

                    # Or if line_type is parsed for as a spoken alert
                    elif config["line"][line_type]["reaction"] == "speak":
                        display_q.put(
                            eqa_struct.display(eqa_settings.eqa_time(),
                                               "event", "events", check_line))
                        sound_q.put(eqa_struct.sound("speak", check_line))

                    # For triggers requiring all line_types
                    if config["line"]["all"]["reaction"] == "true":
                        for keyphrase, value in config["alert"]["all"].items():
                            if keyphrase in check_line:
                                sound_q.put(
                                    eqa_struct.sound("alert", line_type))
                                display_q.put(
                                    eqa_struct.display(
                                        eqa_settings.eqa_time(),
                                        "event",
                                        "events",
                                        line_type + ": " + check_line[0:65],
                                    ))

                # If line_type is not a parsable type
                else:
                    eqa_config.add_type(line_type, base_path)
                    display_q.put(
                        eqa_struct.display(
                            eqa_settings.eqa_time(),
                            "event",
                            "events",
                            "added: " + line_type,
                        ))
                    system_q.put(
                        eqa_struct.message(
                            eqa_settings.eqa_time(),
                            "system",
                            "reload_config",
                            "null",
                            "null",
                        ))

    except Exception as e:
        eqa_settings.log("process action: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))

    sys.exit(0)
Пример #15
0
def main():
    """Main method, does the good stuff"""

    # Paths
    home = os.path.expanduser("~")
    base_path = home + "/.eqa/"

    # Queues
    keyboard_q = queue.Queue()
    action_q = queue.Queue()
    display_q = queue.Queue()
    sound_q = queue.Queue()
    system_q = queue.Queue()
    log_q = queue.Queue()
    heal_q = queue.Queue()
    damage_q = queue.Queue()

    # Bootstraps bootstraps
    if not os.path.exists(base_path + "config.json"):
        bootstrap(base_path)

    # Thread Events
    raid = threading.Event()
    cfg_reload = threading.Event()
    heal_parse = threading.Event()
    spell_parse = threading.Event()
    exit_flag = threading.Event()

    # Build initial state
    logging.basicConfig(filename=base_path + "log/eqalert.log",
                        level=logging.INFO)
    eqa_config.update_logs(base_path)
    config = eqa_config.read_config(base_path)
    server = config["last_state"]["server"]
    char = config["last_state"]["character"]
    char_log = (config["settings"]["paths"]["char_log"] +
                config["char_logs"][char + "_" + server]["file_name"])
    state = eqa_config.get_last_state(base_path)

    # Ensure the character log file exists
    if not os.path.exists(char_log):
        print(
            "Please review `settings > paths` in config.json, a log with that default server and character cannot be found."
        )
        exit(1)

    # Ensure the configuration is up-to-date
    if "version" not in config["settings"]:
        print(
            "Please move or delete your current configuration. A new config.json file must be generated."
        )
        exit(1)
    elif not config["settings"]["version"] == str(
            pkg_resources.get_distribution("eqalert").version):
        print(
            "Please move or delete your current configuration. A new config.json file must be generated."
        )
        exit(1)

    # Initialize curses
    screen = eqa_curses.init(state)

    ## Consume keyboard events
    ## Produce keyoard_q
    read_keys = threading.Thread(target=eqa_keys.read,
                                 args=(exit_flag, keyboard_q, screen))
    read_keys.daemon = True
    read_keys.start()

    ## Process log_q
    ## Produce action_q
    process_log = threading.Thread(target=eqa_parser.process,
                                   args=(exit_flag, log_q, action_q))
    process_log.daemon = True
    process_log.start()

    ## Process keyboard_q
    ## Produce display_q, sound_q, system_q
    process_keys = threading.Thread(
        target=eqa_keys.process,
        args=(
            keyboard_q,
            system_q,
            display_q,
            sound_q,
            exit_flag,
            heal_parse,
            spell_parse,
            raid,
            state.chars,
        ),
    )
    process_keys.daemon = True
    process_keys.start()

    ## Consume action_q
    ## Produce display_q, sound_q, system_q, heal_q, damage_q
    process_action = threading.Thread(
        target=eqa_action.process,
        args=(
            action_q,
            system_q,
            display_q,
            sound_q,
            heal_q,
            damage_q,
            exit_flag,
            heal_parse,
            spell_parse,
            raid,
            cfg_reload,
            config,
            base_path,
        ),
    )
    process_action.daemon = True
    process_action.start()

    ## Consume sound_q
    process_sound = threading.Thread(target=eqa_sound.process,
                                     args=(config, sound_q, exit_flag,
                                           cfg_reload))
    process_sound.daemon = True
    process_sound.start()

    ## Consume display_q
    process_display = threading.Thread(target=eqa_curses.display,
                                       args=(screen, display_q, state, raid,
                                             exit_flag))
    process_display.daemon = True
    process_display.start()

    ## Consume char_log
    ## Produce log_q

    def callback(event):
        try:
            if event.mask == pyinotify.IN_CLOSE_WRITE:
                log_q.put(eqa_parser.last_line(char_log))
        except Exception as e:
            eqa_settings.log("log watch callback: Error on line " +
                             str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))

    try:
        log_watch = pyinotify.WatchManager()
        log_watch.add_watch(char_log, pyinotify.IN_CLOSE_WRITE, callback)
        log_notifier = pyinotify.ThreadedNotifier(log_watch)
        log_notifier.daemon = True
        log_notifier.start()
    except Exception as e:
        eqa_settings.log("log watch callback: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))

    # And we're on
    display_q.put(
        eqa_struct.display(eqa_settings.eqa_time(), "draw", "events", "null"))
    display_q.put(
        eqa_struct.display(eqa_settings.eqa_time(), "event", "events",
                           "Initialized"))
    sound_q.put(eqa_struct.sound("speak", "initialized"))

    ## Consume system_q
    try:
        while not exit_flag.is_set():
            time.sleep(0.001)
            if not system_q.empty():
                new_message = system_q.get()
                system_q.task_done()

                if new_message.type == "system":
                    # Update zone
                    if new_message.tx == "zone":
                        state.set_zone(new_message.payload)
                        eqa_config.set_last_state(state, base_path)
                    # Update afk status
                    elif new_message.tx == "afk":
                        state.set_afk(new_message.payload)
                        eqa_config.set_last_state(state, base_path)
                    # Update location
                    elif new_message.tx == "loc":
                        state.set_loc(new_message.payload)
                        eqa_config.set_last_state(state, base_path)
                    # Update direction
                    elif new_message.tx == "direction":
                        state.set_direction(new_message.payload)
                        eqa_config.set_last_state(state, base_path)
                    # Update character
                    elif new_message.tx == "new_character":
                        new_char_log = (
                            config["settings"]["paths"]["char_log"] +
                            config["char_logs"][
                                new_message.payload]["file_name"])
                        # Ensure char/server combo exists as file
                        if os.path.exists(new_char_log):
                            # Stop watch on current log
                            log_watch.rm_watch(char_log,
                                               pyinotify.IN_CLOSE_WRITE,
                                               callback)
                            # Set new character
                            char_name, char_server = new_message.payload.split(
                                "_")
                            state.set_char(char_name)
                            state.set_server(char_server)
                            eqa_config.set_last_state(state, base_path)
                            char_log = new_char_log
                            # Start new log watch
                            log_watch.add_watch(char_log,
                                                pyinotify.IN_CLOSE_WRITE,
                                                callback)
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "event",
                                    "events",
                                    "Character changed to " + state.char +
                                    " on " + state.server,
                                ))
                            sound_q.put(
                                eqa_struct.sound(
                                    "speak",
                                    "Character changed to " + state.char +
                                    " on " + state.server,
                                ))
                        else:
                            display_q.put(
                                eqa_struct.display(
                                    eqa_settings.eqa_time(),
                                    "event",
                                    "events",
                                    "Unable to change characters, please review logs",
                                ))
                            eqa_settings.log("Could not find file: " +
                                             new_char_log)
                    # Reload config
                    elif new_message.tx == "reload_config":
                        # Reload config
                        eqa_config.update_logs(base_path)
                        config = eqa_config.read_config(base_path)
                        # Reread characters
                        state.set_chars(eqa_config.get_config_chars(config))
                        # Stop process_action and process_sound
                        cfg_reload.set()
                        process_action.join()
                        process_sound.join()
                        cfg_reload.clear()
                        # Start process_action and process_sound
                        process_action = threading.Thread(
                            target=eqa_action.process,
                            args=(
                                action_q,
                                system_q,
                                display_q,
                                sound_q,
                                heal_q,
                                damage_q,
                                exit_flag,
                                heal_parse,
                                spell_parse,
                                raid,
                                cfg_reload,
                                config,
                                base_path,
                            ),
                        )
                        process_action.daemon = True
                        process_action.start()
                        process_sound = threading.Thread(
                            target=eqa_sound.process,
                            args=(config, sound_q, exit_flag, cfg_reload),
                        )
                        process_sound.daemon = True
                        process_sound.start()
                        display_q.put(
                            eqa_struct.display(
                                eqa_settings.eqa_time(),
                                "event",
                                "events",
                                "Configuration reloaded",
                            ))
                        sound_q.put(
                            eqa_struct.sound("speak",
                                             "Configuration reloaded"))
                else:
                    display_q.put(
                        eqa_struct.display(
                            eqa_settings.eqa_time(),
                            "event",
                            "events",
                            new_message.type + ": " + new_message.payload,
                        ))

    except Exception as e:
        eqa_settings.log("main: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))
        pass

    # Exit
    display_q.put(
        eqa_struct.display(eqa_settings.eqa_time(), "event", "events",
                           "Exiting"))
    read_keys.join()
    process_log.join()
    process_keys.join()
    process_action.join()
    process_sound.join()
    process_display.join()
    log_watch.rm_watch(char_log, pyinotify.IN_CLOSE_WRITE, callback)
    log_notifier.stop()
    eqa_curses.close_screens(screen)
Пример #16
0
def display(stdscr, display_q, state, raid, exit_flag):
    """
    Process: display_q
    Produce: display event
    """
    events = []
    page = "events"
    setting = "character"
    selected_char = 0

    try:
        while not exit_flag.is_set():
            time.sleep(0.001)
            if not display_q.empty():
                display_event = display_q.get()
                display_q.task_done()

                # Display Var Update
                if display_event.type == "update":
                    if display_event.screen == "setting":
                        setting = display_event.payload
                        draw_page(stdscr, page, events, state, setting,
                                  selected_char, raid)
                    elif display_event.screen == "selected_char":
                        selected_char = display_event.payload
                        draw_page(stdscr, page, events, state, setting,
                                  selected_char, raid)
                    elif display_event.screen == "select_char":
                        selected_char = display_event.payload
                        state.char = state.chars[selected_char]
                        draw_page(stdscr, page, events, state, setting,
                                  selected_char, raid)
                    elif display_event.screen == "zone":
                        zone = display_event.payload
                        draw_page(stdscr, page, events, state, setting,
                                  selected_char, raid)
                    elif display_event.screen == "char":
                        state.char = display_event.payload
                        draw_page(stdscr, page, events, state, setting,
                                  selected_char, raid)

                # Display Draw
                elif display_event.type == "draw":
                    if display_event.screen != "redraw":
                        page = display_event.screen
                    draw_page(stdscr, page, events, state, setting,
                              selected_char, raid)

                # Draw Update
                elif display_event.type == "event":
                    if display_event.screen == "events":
                        events.append(display_event)
                        if page == "events":
                            draw_page(
                                stdscr,
                                page,
                                events,
                                state,
                                setting,
                                selected_char,
                                raid,
                            )
                    elif display_event.screen == "clear":
                        events = []
                        draw_page(stdscr, page, events, state, setting,
                                  selected_char, raid)

    except Exception as e:
        eqa_settings.log("display: Error on line " +
                         str(sys.exc_info()[-1].tb_lineno) + ": " + str(e))

    sys.exit()