コード例 #1
0
ファイル: eddn.py プロジェクト: starcraftman/cogBot
def create_parser(msg):
    """
    Factory to create msg parsers.

    Raises:
        KeyError: When the class or part of msg is not supported.

    Returns:
        A parser ready to parse the message.
    """
    key = "{} {}".format(msg['header']['softwareName'], msg["$schemaRef"])
    logging.getLogger(__name__).info("Schema Key: %s", key)
    cls_name = SCHEMA_MAP[key]
    cls = getattr(sys.modules[__name__], cls_name)

    with cogdb.session_scope(cogdb.Session) as session, \
         cogdb.session_scope(cogdb.EDDBSession, autoflush=False) as eddb_session:
        return cls(session, eddb_session, msg)
コード例 #2
0
def test_get_current_global(session, f_global_testbed):
    session.query(Global).delete()
    current = cogdb.query.get_current_global(session)
    assert current.consolidation == 0
    current.consolidation = 77
    session.commit()

    with cogdb.session_scope(cogdb.Session):
        latest = cogdb.query.get_current_global(session)
        latest == current
        latest.consolidation == 77
コード例 #3
0
async def vote_cycle(request, cycle):
    """Provide vote consolidation data for a given cycle.

    Args:
        request: The request object for flask.
        cycle: The cycle to get voting data for.
    """
    start = cog.util.cycle_to_start(cycle)
    end = start + datetime.timedelta(weeks=1)
    with cogdb.session_scope(cogdb.Session) as session:
        return sanic.response.json(get_vote_data(session, start, end))
コード例 #4
0
async def vote_range(request, start, end):
    """Provide voting information after a given datetime.

    Args:
        request: The request object for flask.
        start: The timestamp (UTC) to get data after.
        end: The timestamp (UTC) to get data before.
    """
    start = datetime.datetime.utcfromtimestamp(start)
    end = datetime.datetime.utcfromtimestamp(end)
    with cogdb.session_scope(cogdb.Session) as session:
        return sanic.response.json(get_vote_data(session, start, end))
コード例 #5
0
async def vote(request):
    """
    The route to provide vote information via charts.
    """
    cur_cycle = cog.util.current_cycle()
    start = cog.util.cycle_to_start(cur_cycle)
    end = start + datetime.timedelta(weeks=1)
    with cogdb.session_scope(cogdb.Session) as session:
        data = get_vote_data(session, start, end)

    return sanic.response.html(TEMPLATES['vote'].render(request=request,
                                                        data=data,
                                                        cycle=cur_cycle))
コード例 #6
0
ファイル: side.py プロジェクト: starcraftman/cogBot
def monitor_factions(session, faction_names=None):
    """
    Get all information on the provided factions. By default use set list.

    Returns: A list of messages to send.
    """
    current = sqla_orm.aliased(FactionState)
    pending = sqla_orm.aliased(FactionState)
    sys = sqla_orm.aliased(System)
    sys_control = sqla_orm.aliased(System)
    if not faction_names:
        faction_names = WATCH_FACTIONS
    with cogdb.session_scope(cogdb.EDDBSession) as eddb_session:
        faction_ids = [
            x[0] for x in eddb_session.query(edb.Faction.id).filter(
                edb.Faction.name.in_(faction_names)).all()
        ]

    control_state_id = session.query(PowerState.id).\
        filter(PowerState.text == "Control").\
        scalar_subquery()
    matches = session.query(Influence.influence, sys.name, Faction.name,
                            Government.text, current.text, pending.text,
                            sqla.func.ifnull(sys_control.name, 'N/A')).\
        filter(Influence.faction_id.in_(faction_ids)).\
        join(sys, Influence.system_id == sys.id).\
        join(Faction, Influence.faction_id == Faction.id).\
        join(Government, Faction.government_id == Government.id).\
        join(current, Influence.state_id == current.id).\
        join(pending, Influence.pending_state_id == pending.id).\
        outerjoin(sys_control, sqla.and_(
            sys_control.power_state_id == control_state_id,
            sys_control.dist_to(sys) < 15
        )).\
        limit(1000).\
        all()

    lines = [[
        "Control", "System", "Faction", "Gov", "Inf", "State", "Pending State"
    ]]
    for match in matches:
        lines += [[
            match[-1], match[1][:16], match[2][:16], match[3][:3],
            "{:5.2f}".format(round(match[0], 2)), match[-3], match[-2]
        ]]

    return cog.tbl.format_table(lines,
                                header=True,
                                prefix="\n\n**Monitored Factions**\n")
コード例 #7
0
ファイル: inara.py プロジェクト: starcraftman/cogBot
    async def search_inara_and_kos(self, looking_for_cmdr, msg):
        """
        Top level wrapper to search for a cmdr.
        Search both Inara and local KOS db, respond with appropriate information.
        Respond to user with information from both depending on what was found.

        Args:
            looking_for_cmdr: The cmdr's name to look on inara.
            msg: The message the user sent, tracks the channel/author to respond to.

        Returns:
            kos_info: The information on if a report for kos addition should be made to moderation.
        """
        try:
            cmdr_info = await self.search_with_api(looking_for_cmdr,
                                                   msg,
                                                   ignore_multiple_match=False)
            return await cog.inara.api.reply_with_api_result(
                cmdr_info["req_id"], cmdr_info["event_data"], msg)
        except InaraNoResult as exc:
            futs = []
            response = f"__Inara__ Could not find CMDR **{looking_for_cmdr}**"

            # Even if not on inara.cz, lookup in kos
            with cogdb.session_scope(cogdb.Session) as session:
                kos_embeds = kos_lookup_cmdr_embeds(session, looking_for_cmdr)

            if kos_embeds:
                futs += [
                    cog.util.BOT.send_message(msg.channel, embed=embed)
                    for embed in kos_embeds
                ]
                futs += [self.delete_waiting_message(exc.req_id)]
            else:
                response += f"\n\n__KOS__ Could not find CMDR **{looking_for_cmdr}**"

            for fut in [cog.util.BOT.send_message(msg.channel, response)
                        ] + futs:
                await fut

            # Not found in KOS, will ask if should be added.
            if not kos_embeds:
                return await self.should_cmdr_be_on_kos(
                    exc.req_id, looking_for_cmdr, msg)
コード例 #8
0
ファイル: side.py プロジェクト: starcraftman/cogBot
def expand_to_candidates(session, system_name):
    """
    Considering system_name, determine all controlling nearby factions that could expand to it.

    Returns:
        [[system_name, distance, influence, state, faction_name], ...]
    """

    with cogdb.session_scope(cogdb.EDDBSession) as eddb_session:
        centre = cogdb.eddb.get_systems(eddb_session, [system_name])[0]
        blacklist = session.query(Faction.id).\
            join(Influence, Influence.faction_id == Faction.id).\
            join(System, Influence.system_id == System.id).\
            filter(System.name == system_name,
                   Influence.system_id == System.id,
                   Faction.id == Influence.faction_id).\
            scalar_subquery()
        matches = session.query(System.name, System.dist_to(centre), System.population, Influence,
                                Faction, FactionState.text, Government.text).\
            join(Influence, Influence.system_id == System.id).\
            join(Faction, Influence.faction_id == Faction.id).\
            join(FactionState, Faction.state_id == FactionState.id).\
            join(Government, Faction.government_id == Government.id).\
            filter(System.dist_to(centre) <= 20,
                   System.name != centre.name,
                   Influence.is_controlling_faction == 1,
                   Faction.id.notin_(blacklist)).\
            order_by(System.dist_to(centre)).\
            all()

        lines = [["System", "Dist", "Pop", "Inf", "Gov", "State", "Faction"]]
        for sys_name, sys_dist, sys_pop, inf, fact, fact_state, gov in matches:
            lines += [[
                sys_name[:16], "{:5.2f}".format(sys_dist),
                "{:3.1f}".format(math.log(sys_pop, 10)),
                "{:5.2f}".format(inf.influence), gov[:4], fact_state, fact.name
            ]]

    return lines
コード例 #9
0
ファイル: inara.py プロジェクト: starcraftman/cogBot
def check_interaction_response(orig_author, sent, inter):
    """
    Check if a user is the original requesting author
    or if the responding user to interaction is an admin.
    Use functools.partial to leave only inter arg.

    Args:
        orig_author: The original author who made request.
        sent: The message sent with options/buttons.
        inter: The interaction argument to check.

    Returns: True ONLY if responding to same message and user allowed.
    """
    user_allowed = inter.user == orig_author
    if not user_allowed:
        with cogdb.session_scope(cogdb.Session) as session:
            try:
                cogdb.query.get_admin(session, inter.user)
                user_allowed = True
            except cog.exc.NoMatch:
                pass

    return inter.message == sent and user_allowed
コード例 #10
0
ファイル: conftest.py プロジェクト: starcraftman/cogBot
def eddb_session():
    with cogdb.session_scope(cogdb.EDDBSession) as session:
        yield session
コード例 #11
0
ファイル: conftest.py プロジェクト: starcraftman/cogBot
def side_session():
    with cogdb.session_scope(cogdb.SideSession) as session:
        yield session
コード例 #12
0
ファイル: conftest.py プロジェクト: starcraftman/cogBot
def session():
    with cogdb.session_scope(cogdb.Session) as session:
        yield session
コード例 #13
0
ファイル: eddn.py プロジェクト: starcraftman/cogBot
    except KeyboardInterrupt:
        msg = """Terminating ZMQ connection."""
        print(msg)


# Any time code run, need these dirs to write to
try:
    shutil.rmtree(ALL_MSGS)
except OSError:
    pass
try:
    shutil.rmtree(JOURNAL_MSGS)
except OSError:
    pass
try:
    shutil.rmtree(JOURNAL_CARS)
except OSError:
    pass
os.mkdir(ALL_MSGS)
os.mkdir(JOURNAL_MSGS)
os.mkdir(JOURNAL_CARS)
try:
    with cogdb.session_scope(cogdb.EDDBSession) as init_session:
        MAPS = create_id_maps(init_session)
except (sqla_orm.exc.NoResultFound, sqla.exc.ProgrammingError):
    MAPS = None


if __name__ == "__main__":
    main()
コード例 #14
0
ファイル: inara.py プロジェクト: starcraftman/cogBot
    async def reply_with_api_result(self, req_id, event_data, msg):
        """
        Reply using event_data from Inara API getCommanderProfile.
        Send information to user based on Inara and KOS lookup.

        Args:
            req_id: The id of the request to search.
            event_data: The event_data returned by Inara.
            msg: The original message from a user requesting search.

        Returns:
            kos_info: A KOS info object explaining if searched cmdr should be added. See should_cmdr_be_on_kos method.
        """
        # cmdr prototype, only name guaranteed. Others will display if not found.
        # keeping original prototype from regex method.
        # balance and assets are not given from api.
        cmdr = {
            'name': 'ERROR',
            'profile_picture': 'https://inara.cz/images/userportraitback.png',
            'role': EMPTY_INARA,
            'allegiance': EMPTY_INARA,
            'rank': EMPTY_INARA,
            'power': EMPTY_INARA,
            'squad': EMPTY_INARA,
            'squad_rank': EMPTY_INARA,
            'squad_count': EMPTY_INARA,
        }

        map_event = [
            ["name", "userName"],
            ["name", "commanderName"
             ],  # commanderName not always set, fallback to userName
            ["profile_picture", "avatarImageURL"],
            ["role", "preferredGameRole"],
            ["allegiance", "preferredAllegianceName"],
            ["power", "preferredPowerName"],
        ]
        for slot, data_name in map_event:
            received = event_data.get(data_name, cmdr[slot])
            if received:
                cmdr[slot] = received

        # rank, ranks are a List of Dictionaries. try to get combat rank
        if "commanderRanksPilot" in event_data:
            match = next((rank for rank in event_data["commanderRanksPilot"]
                          if rank["rankName"] == "combat"), None)
            if match:
                try:
                    cmdr["rank"] = COMBAT_RANKS[int(match["rankValue"])]
                except (ValueError, KeyError):
                    cmdr["rank"] = 'Unknown Rank'

        embeds = []
        try:
            cmdr["squad"] = event_data["commanderSquadron"].get(
                "squadronName", cmdr["squad"])
            embeds += [await squad_details_embed(event_data, cmdr)]
        except KeyError:
            pass

        cmdr_embed = discord.Embed.from_dict({
            'color':
            PP_COLORS.get(cmdr["allegiance"], PP_COLORS['default']),
            'author': {
                'name': cmdr["name"],
                'icon_url': cmdr["profile_picture"],
            },
            'provider': {
                'name': 'Inara',
                'url': SITE,
            },
            'thumbnail': {
                'url': cmdr['profile_picture']
            },
            'title':
            "Commander Profile",
            'url':
            event_data["inaraURL"],
            "fields": [
                {
                    'name': 'Allegiance',
                    'value': cmdr["allegiance"],
                    'inline': True
                },
                {
                    'name': 'Role',
                    'value': cmdr["role"],
                    'inline': True
                },
                {
                    'name': 'Combat Rank',
                    'value': cmdr["rank"],
                    'inline': True
                },
                {
                    'name': 'Squadron',
                    'value': cmdr["squad"],
                    'inline': True
                },
            ],
        })
        embeds = [cmdr_embed] + embeds

        with cogdb.session_scope(cogdb.Session) as session:
            kos_embeds = kos_lookup_cmdr_embeds(session, cmdr['name'],
                                                cmdr['profile_picture'])
            embeds += kos_embeds

        futs = [
            cog.util.BOT.send_message(msg.channel, embed=embed)
            for embed in embeds
        ]
        futs += [self.delete_waiting_message(req_id)]
        for fut in futs:
            await fut

        if not kos_embeds:
            # Not found in KOS db, ask if should be added
            kos_info = await self.should_cmdr_be_on_kos(
                req_id, cmdr['name'], msg)
            kos_info['squad'] = cmdr.get('squad', EMPTY_INARA)

        return kos_info
コード例 #15
0
ファイル: bgs_report.py プロジェクト: starcraftman/cogBot
def main():
    with cogdb.session_scope(cogdb.SideSession) as side_session:
        feudal_finder(side_session)
コード例 #16
0
ファイル: bot.py プロジェクト: starcraftman/cogBot
    async def on_message(self, message):
        """
        Intercepts every message sent to guild!

        Notes:
            message.author - Returns member object
                roles -> List of Role objects. First always @everyone.
                    roles[0].name -> String name of role.
            message.channel - Channel object.
                name -> Name of channel
                guild -> guild of channel
                    members -> Iterable of all members
                    channels -> Iterable of all channels
                    get_member_by_name -> Search for user by nick
            message.content - The text
        """
        content = message.content
        author = message.author
        channel = message.channel

        # TODO: Better filtering, use a loop and filter funcs.
        if await self.ignore_message(message):
            return

        if not message.content.startswith(self.prefix):
            await self.message_hooks(message)
            return

        log = logging.getLogger(__name__)
        log.info("guild: '%s' Channel: '%s' User: '******' | %s", channel.guild,
                 channel.name, author.name, content)

        try:
            edit_time = message.edited_at
            content = re.sub(r'<[#@]\S+>', '',
                             content).strip()  # Strip mentions from text

            with cogdb.session_scope(cogdb.Session) as session:
                # Check permissions before full parsing
                cmd = content[len(self.prefix):content.find(' ')]
                cogdb.query.check_perms(session, message, cmd)

                args = self.parser.parse_args(re.split(r'\s+', content))
                await self.dispatch_command(args=args,
                                            bot=self,
                                            msg=message,
                                            session=session)

        except cog.exc.ArgumentParseError as exc:
            log.exception("Failed to parse command. '%s' | %s", author.name,
                          content)
            exc.write_log(log, content=content, author=author, channel=channel)
            if 'invalid choice' not in exc.message:
                try:
                    self.parser.parse_args(
                        content.split(' ')[0:1] + ['--help'])
                except cog.exc.ArgumentHelpError as exc2:
                    exc.message = 'Invalid command use. Check the command help.'
                    exc.message += '\n{}\n{}'.format(
                        len(exc.message) * '-', exc2.message)

            await self.send_ttl_message(channel, str(exc))
            try:
                if edit_time == message.edited_at:
                    await message.delete()
            except discord.DiscordException:
                pass

        except cog.exc.CogException as exc:
            exc.write_log(log, content=content, author=author, channel=channel)
            if isinstance(exc, cog.exc.UserException):
                await self.send_ttl_message(channel, str(exc))
                try:
                    if edit_time == message.edited_at:
                        await message.delete()
                except discord.DiscordException:
                    pass
            else:
                await self.send_message(channel, str(exc))

        except discord.DiscordException as exc:
            if exc.args[0].startswith("BAD REQUEST (status code: 400"):
                resp = "Response would be > 2000 chars, I cannot transmit it to Discord."
                resp += "\n\nIf this useage is valid see Gears."

                await self.send_ttl_message(channel, resp)
                try:
                    if edit_time == message.edited_at:
                        await message.delete()
                except discord.DiscordException:
                    pass
            else:
                gears = self.get_member_by_substr("gearsand").mention
                await self.send_message(
                    channel, "A critical discord error! {}.".format(gears))
            line = "Discord.py Library raised an exception"
            line += cog.exc.log_format(content=content,
                                       author=author,
                                       channel=channel)
            log.exception(line)

        except apiclient.errors.Error as exc:
            line = "Google Sheets API raised an exception"
            line += "\n" + str(exc) + "\n\n"
            line += cog.exc.log_format(content=content,
                                       author=author,
                                       channel=channel)
            log.exception(line)