Commit 030406d0 authored by Jeremy Pallats's avatar Jeremy Pallats 💬
Browse files

Merge branch 'snipe_command' into 'master'

FIX #92: Snipe Sheet - Spec Ops Commands.

See merge request !36
parents 34ca87cc 49a9b76b
Loading
Loading
Loading
Loading
Loading
+81 −13
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import cogdb.side
import cog.inara
import cog.tbl
import cog.util
from cogdb.schema import FortUser, UMUser
from cogdb.schema import FortUser, UMUser, EUMSheet


async def bot_shutdown(bot):  # pragma: no cover
@@ -1027,14 +1027,17 @@ class Hold(Action):
        if not self.args.system:
            raise cog.exc.InvalidCommandArgs("You forgot to specify a system to update.")

        system = cogdb.query.um_find_system(self.session, ' '.join(self.args.system))
        system = cogdb.query.um_find_system(self.session, ' '.join(self.args.system),
                                            sheet_src=self.args.sheet_src)
        self.log.info('HOLD %s - Matched system name %s: \n%s.',
                      self.duser.display_name, self.args.system, system)
        hold = cogdb.query.um_add_hold(self.session, system=system,
                                       user=self.undermine, held=self.args.amount)
                                       user=self.undermine, held=self.args.amount,
                                       sheet_src=self.args.sheet_src)

        if self.args.set:
            system.set_status(self.args.set)
            # TODO: Same payload now, but will have to switch if diverge.
            self.payloads += cogdb.scanners.UMScanner.update_systemum_dict(
                system.sheet_col, system.progress_us,
                system.progress_them, system.map_offset
@@ -1058,12 +1061,14 @@ class Hold(Action):
                      self.duser.display_name, self.duser.id, self.undermine)

        if self.args.died:
            holds = cogdb.query.um_reset_held(self.session, self.undermine)
            holds = cogdb.query.um_reset_held(self.session, self.undermine,
                                              sheet_src=self.args.sheet_src)
            self.log.info('HOLD %s - User reset merits.', self.duser.display_name)
            response = 'Sorry you died :(. Held merits reset.'

        elif self.args.redeem:
            holds, redeemed = cogdb.query.um_redeem_merits(self.session, self.undermine)
            holds, redeemed = cogdb.query.um_redeem_merits(self.session, self.undermine,
                                                           sheet_src=self.args.sheet_src)
            self.log.info('HOLD %s - Redeemed %d merits.', self.duser.display_name, redeemed)

            response = '**Redeemed Now** {}\n\n__Cycle Summary__\n'.format(redeemed)
@@ -1074,7 +1079,8 @@ class Hold(Action):

        elif self.args.redeem_systems:
            system_strs = " ".join(self.args.redeem_systems).split(",")
            holds, redeemed = cogdb.query.um_redeem_systems(self.session, self.undermine, system_strs)
            holds, redeemed = cogdb.query.um_redeem_systems(self.session, self.undermine, system_strs,
                                                            sheet_src=self.args.sheet_src)

            response = '**Redeemed Now** {}\n\n__Cycle Summary__\n'.format(redeemed)
            lines = [['System', 'Hold', 'Redeemed']]
@@ -1091,7 +1097,7 @@ class Hold(Action):
            self.payloads += cogdb.scanners.UMScanner.update_hold_dict(
                hold.system.sheet_col, hold.user.row, hold.held, hold.redeemed)

        scanner = get_scanner("hudson_undermine")
        scanner = get_scanner("hudson_undermine" if self.args.sheet_src == EUMSheet.main else "hudson_snipe")
        await scanner.send_batch(self.payloads)

        await self.bot.send_message(self.msg.channel, response)
@@ -1621,10 +1627,12 @@ class UM(Action):
                weekly_tick += datetime.timedelta(days=1)

            prefix = "**Held Merits**\n\n{}\n".format('DEADLINE **{}**'.format(weekly_tick - now))
            response = cog.tbl.format_table(cogdb.query.um_all_held_merits(self.session), header=True, prefix=prefix)[0]
            held_merits = cogdb.query.um_all_held_merits(self.session, sheet_src=self.args.sheet_src)
            response = cog.tbl.format_table(held_merits, header=True, prefix=prefix)[0]

        elif self.args.system:
            system = cogdb.query.um_find_system(self.session, ' '.join(self.args.system))
            system = cogdb.query.um_find_system(self.session, ' '.join(self.args.system),
                                                sheet_src=self.args.sheet_src)

            if self.args.offset:
                system.map_offset = self.args.offset
@@ -1633,11 +1641,12 @@ class UM(Action):
            if self.args.set or self.args.offset:
                self.session.commit()

                # TODO: Same payload now, but will have to switch if diverge.
                self.payloads += cogdb.scanners.UMScanner.update_systemum_dict(
                    system.sheet_col, system.progress_us,
                    system.progress_them, system.map_offset
                )
                scanner = get_scanner("hudson_undermine")
                scanner = get_scanner("hudson_undermine" if self.args.sheet_src == EUMSheet.main else "hudson_snipe")
                await scanner.send_batch(self.payloads)

            response = system.display()
@@ -1674,7 +1683,7 @@ class UM(Action):
            return

        else:
            systems = cogdb.query.um_get_systems(self.session)
            systems = cogdb.query.um_get_systems(self.session, sheet_src=self.args.sheet_src)
            response = '__Current UM Targets__\n\n' + '\n'.join(
                [system.display() for system in systems])

@@ -2008,7 +2017,7 @@ def get_scanner(name):
        raise cog.exc.InvalidCommandArgs("The scanners are not ready. Please try again in 15 seconds.") from exc


async def monitor_carrier_events(client, *, next_summary, last_timestamp=None, delay=60):
async def monitor_carrier_events(client, *, next_summary, last_timestamp=None, delay=60):  # pragma: no cover
    """
    Simple async task that just checks for new events every delay.

@@ -2054,7 +2063,7 @@ async def monitor_carrier_events(client, *, next_summary, last_timestamp=None, d
    )


async def monitor_ocr_sheet(client, *, delay=1800, repeat=True):
async def monitor_ocr_sheet(client, *, delay=1800, repeat=True):  # pragma: no cover
    """
    Simple async task that just checks for changes to the OCR sheet.
    This task will schedule itself infinitely on a delay.
@@ -2094,6 +2103,64 @@ async def monitor_ocr_sheet(client, *, delay=1800, repeat=True):
        )


async def monitor_snipe_merits(client, *, repeat=True):  # pragma: no cover
    """
    Schedule self to check snipe merits at the following times.
    This task will sleep until required.
        - 12 hours before tick, remind everyone with @here ping to redeem.
        - 30 minutes before tick, ping unredeemed users directly.

    Kwargs:
        repeat: If true, will schedule itself infinitely.
    """
    guild = [x for x in client.guilds if x.name == FUC_GUILD]
    if guild:
        guild = guild[0]
    chan_id = cog.util.get_config('snipe_channel', default=None)
    if not guild or not chan_id:  # Don't bother if not set
        return
    snipe_chan = client.get_channel(chan_id)
    next_cycle = cog.util.next_weekly_tick(datetime.datetime.utcnow())

    # 12 hours to tick, ping here
    next_date = next_cycle - datetime.timedelta(hours=12)
    now = datetime.datetime.utcnow()
    if now < next_date:
        diff_dates = next_date - now
        delay_seconds = diff_dates.seconds + diff_dates.days * 24 * 60 * 60
        await asyncio.sleep(delay_seconds)

        # Notify here
        with cogdb.session_scope(cogdb.Session) as session:
            if cogdb.query.get_all_snipe_holds(session):
                client.send_message(
                    snipe_chan,
                    "@here Snipe members it is tick day and there are 12 hours remaining."
                )

    # 30 mins to tick ping remaining in message
    next_date = next_cycle - datetime.timedelta(minutes=30)
    now = datetime.datetime.utcnow()
    if now < next_date:
        diff_dates = next_date - now
        delay_seconds = diff_dates.seconds + diff_dates.days * 24 * 60 * 60
        await asyncio.sleep(delay_seconds)

        # Notify members holding
        with cogdb.session_scope(cogdb.Session) as session:
            if cogdb.query.get_all_snipe_holds(session):
                to_contact = cogdb.query.get_snipe_members_holding(session, client)
                msg = """__Final Snipe Reminder__
    There are less than **30 minutes left**. The following members are still holding.
    """
                client.send_message(snipe_chan, msg + to_contact)

    if repeat:
        asyncio.ensure_future(
            monitor_snipe_merits(client, repeat=repeat)
        )


async def report_to_leadership(client, msgs):  # pragma: no cover
    """
    Send messages to the channel configured to receive reports.
@@ -2194,3 +2261,4 @@ UM_NPC_TABLE = [
    ['Archon Delaine', 'Kumo Crew Watch', 'Kumo Crew Transport', 'Kumo Crew Strike Ships']
]
TRACK_LIMIT = 20
FUC_GUILD = "Federal United Command"
+3 −0
Original line number Diff line number Diff line
@@ -182,6 +182,8 @@ class CogBot(discord.Client):
                                    ('Drop', 'Fort', 'User'))
                self.sched.register('hudson_undermine', scanners['hudson_undermine'],
                                    ('Hold', 'UM', 'User'))
                self.sched.register('hudson_snipe', scanners['hudson_snipe'],
                                    ('Hold', 'UM', 'User'))
                self.sched.register('hudson_kos', scanners['hudson_kos'], ('KOS'))
                self.sched.register('hudson_ocr', scanners['hudson_ocr'], ('OCR'))
                self.sched.schedule_all(delay=1)
@@ -201,6 +203,7 @@ class CogBot(discord.Client):
                simple_heartbeat(),
                cog.actions.monitor_carrier_events(self, next_summary=next_summary, delay=60),
                cog.actions.monitor_ocr_sheet(self),
                cog.actions.monitor_snipe_merits(self),
                cogdb.eddb.monitor_eddb_caches(),
                cogdb.monitor_pools(),
            ))
+74 −2
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ from argparse import RawDescriptionHelpFormatter as RawHelp

import cog.exc
import cog.util
from cogdb.schema import EUMSheet

PARSERS = []

@@ -327,7 +328,43 @@ def subs_hold(subs, prefix):
and 130% opposition.
    """.format(prefix=prefix)
    sub = subs.add_parser(prefix + 'hold', description=desc, formatter_class=RawHelp)
    sub.set_defaults(cmd='Hold')
    sub.set_defaults(cmd='Hold', sheet_src=EUMSheet.main)
    sub.add_argument('amount', nargs='?', type=int, help='The amount of merits held.')
    sub.add_argument('system', nargs='*', help='The system merits are held in.')
    sub.add_argument('-r', '--redeem', action='store_true', help='Redeem all held merits.')
    sub.add_argument('--redeem-systems', nargs='+', help='Redeem all held merits.')
    sub.add_argument('-d', '--died', action='store_true', help='Zero out held merits.')
    sub.add_argument('-s', '--set',
                     help='Update the galmap progress us:them. Example: --set 3500:200')


@register_parser
def subs_shold(subs, prefix):
    """ Subcommand parsing for shold, snipe variant of hold """
    desc = """Update a user's held or redeemed merits.
IMPORTANT: This is the __SNIPE__ sheet.

Examples:

**{prefix}shold 1200 burr**
        Set your held merits at Burr to 1200.
**{prefix}shold 900 af leopris @Memau**
        Set held merits at System AF Leopris to 900 held for Memau.
**{prefix}shold --died**
**{prefix}shold -d**
        Reset your held merits to 0 due to dying.
**{prefix}shold --redeem**
**{prefix}shold -r**
        Move all held merits to redeemed column.
**{prefix}shold --redeem-systems Burr, Rana**
        Redeem only merits for systems listed.
**{prefix}shold 720 burr --set 60000:130**
**{prefix}shold 720 burr -s 60000:130**
        Update held merits to 720 at Burr expansion and set progress to 60000 merits for us
and 130% opposition.
    """.format(prefix=prefix)
    sub = subs.add_parser(prefix + 'shold', description=desc, formatter_class=RawHelp)
    sub.set_defaults(cmd='Hold', sheet_src=EUMSheet.snipe)
    sub.add_argument('amount', nargs='?', type=int, help='The amount of merits held.')
    sub.add_argument('system', nargs='*', help='The system merits are held in.')
    sub.add_argument('-r', '--redeem', action='store_true', help='Redeem all held merits.')
@@ -608,7 +645,42 @@ def subs_um(subs, prefix):
        List powerplay NPC ships by alligence.
    """.format(prefix=prefix)
    sub = subs.add_parser(prefix + 'um', description=desc, formatter_class=RawHelp)
    sub.set_defaults(cmd='UM')
    sub.set_defaults(cmd='UM', sheet_src=EUMSheet.main)
    sub.add_argument('system', nargs='*', help='The system to update or show.')
    sub.add_argument('-s', '--set',
                     help='Set the status of the system, us:them. Example-> --set 3500:200')
    sub.add_argument('-o', '--offset', type=int, help='Set the system galmap offset.')
    sub.add_argument('-l', '--list', action='store_true', help='Show all outstanding merits on sheet.')
    sub.add_argument('--npcs', action='store_true', help='List powerplay NPC ships by alligence.')


@register_parser
def subs_snipe(subs, prefix):
    """ Subcommand parsing for snipe, the snipe variant of um """
    desc = """Get undermining targets and update their galmap status.
IMPORTANT: This is the __SNIPE__ sheet.

Examples:

**{prefix}snipe**
        Show current active undermining targets.
**{prefix}snipe burr**
        Show the current status and information on Burr.
**{prefix}snipe afl**
        Show the current status and information on AF Leopris, matched search.
**{prefix}snipe burr --set 60000:130**
**{prefix}snipe burr -s 60000:130**
        Set the galmap status of Burr to 60000 and opposition to 130%.
**{prefix}snipe burr --offset 4000**
**{prefix}snipe burr -o 4000**
        Set the offset difference of cmdr merits and galmap.
**{prefix}snipe --list**
        Show all outstanding merits by users and system.
**{prefix}snipe --npcs**
        List powerplay NPC ships by alligence.
    """.format(prefix=prefix)
    sub = subs.add_parser(prefix + 'snipe', description=desc, formatter_class=RawHelp)
    sub.set_defaults(cmd='UM', sheet_src=EUMSheet.snipe)
    sub.add_argument('system', nargs='*', help='The system to update or show.')
    sub.add_argument('-s', '--set',
                     help='Set the status of the system, us:them. Example-> --set 3500:200')
+110 −31
Original line number Diff line number Diff line
@@ -15,7 +15,8 @@ import cog.sheets
import cogdb.eddb
from cog.util import substr_match, get_config
from cogdb.schema import (DiscordUser, FortSystem, FortPrep, FortDrop, FortUser, FortOrder,
                          UMSystem, UMUser, UMHold, KOS, AdminPerm, ChannelPerm, RolePerm,
                          UMSystem, UMUser, UMHold, EUMSheet, KOS,
                          AdminPerm, ChannelPerm, RolePerm,
                          TrackSystem, TrackSystemCached, TrackByID, OCRTracker, OCRTrigger,
                          OCRPrep, Global, Vote)
from cogdb.scanners import FortScanner
@@ -70,7 +71,7 @@ def get_duser(session, discord_id):
        NoMatch - No possible match found.
    """
    try:
        return session.query(DiscordUser).filter_by(id=discord_id).one()
        return session.query(DiscordUser).filter(DiscordUser.id == discord_id).one()
    except sqla_oexc.NoResultFound as exc:
        raise cog.exc.NoMatch(discord_id, 'DiscordUser') from exc

@@ -147,6 +148,7 @@ def users_with_um_merits(session):
    """
    return session.query(DiscordUser, UMUser.combo).\
        join(UMUser, UMUser.name == DiscordUser.pref_name).\
        filter(UMUser.sheet_src == EUMSheet.main).\
        order_by(UMUser.combo.desc()).\
        all()

@@ -263,7 +265,7 @@ def fort_find_system(session, system_name, search_all=True):
        MoreThanOneMatch - Too many matches possible, ask user to resubmit.
    """
    try:
        return session.query(FortSystem).filter_by(name=system_name).one()
        return session.query(FortSystem).filter(FortSystem.name == system_name).one()
    except (sqla_oexc.NoResultFound, sqla_oexc.MultipleResultsFound):
        index = 0 if search_all else fort_find_current_index(session)
        systems = fort_get_systems(session)[index:] + fort_get_preps(session)
@@ -379,7 +381,10 @@ def fort_add_drop(session, *, user, system, amount):
        raise cog.exc.InvalidCommandArgs('Drop amount must be in range [-{num}, {num}]'.format(num=MAX_DROP))

    try:
        drop = session.query(FortDrop).filter_by(user_id=user.id, system_id=system.id).one()
        drop = session.query(FortDrop).\
            filter(FortDrop.user_id == user.id,
                   FortDrop.system_id == system.id).\
            one()
    except sqla_oexc.NoResultFound:
        drop = FortDrop(user_id=user.id, system_id=system.id, amount=0)
        session.add(drop)
@@ -446,15 +451,19 @@ def fort_order_drop(session):
    session.commit()


def um_find_system(session, system_name):
def um_find_system(session, system_name, *, sheet_src=EUMSheet.main):
    """
    Find the UMSystem with system_name
    """
    try:
        return session.query(UMSystem).filter_by(name=system_name).one()
        return session.query(UMSystem).\
            filter(UMSystem.name == system_name,
                   UMSystem.sheet_src == sheet_src).\
            one()
    except (sqla_oexc.NoResultFound, sqla_oexc.MultipleResultsFound) as exc:
        systems = session.query(UMSystem).\
            filter(UMSystem.name.ilike('%{}%'.format(system_name))).\
            filter(UMSystem.name.ilike('%{}%'.format(system_name)),
                   UMSystem.sheet_src == sheet_src).\
            all()

        if len(systems) > 1:
@@ -466,25 +475,29 @@ def um_find_system(session, system_name):
        return systems[0]


def um_get_systems(session, exclude_finished=True):
def um_get_systems(session, exclude_finished=True, *, sheet_src=EUMSheet.main):
    """
    Return a list of all current undermining targets.

    kwargs:
        finished: Return just the finished targets.
    """
    systems = session.query(UMSystem).all()
    systems = session.query(UMSystem).\
        filter(UMSystem.sheet_src == sheet_src).\
        all()
    if exclude_finished:
        systems = [system for system in systems if not system.is_undermined]

    return systems


def um_reset_held(session, user):
def um_reset_held(session, user, *, sheet_src=EUMSheet.main):
    """
    Reset all held merits to 0.
    """
    holds = session.query(UMHold).filter_by(user_id=user.id).all()
    holds = session.query(UMHold).\
        filter(UMHold.user_id == user.id,
               UMHold.sheet_src == sheet_src).all()
    for hold in holds:
        hold.held = 0

@@ -492,12 +505,14 @@ def um_reset_held(session, user):
    return holds


def um_redeem_merits(session, user):
def um_redeem_merits(session, user, *, sheet_src=EUMSheet.main):
    """
    Redeem all held merits for user.
    """
    total = 0
    holds = session.query(UMHold).filter_by(user_id=user.id).all()
    holds = session.query(UMHold).\
        filter(UMHold.user_id == user.id).\
        all()
    for hold in holds:
        total += hold.held
        hold.redeemed = hold.redeemed + hold.held
@@ -507,13 +522,14 @@ def um_redeem_merits(session, user):
    return (holds, total)


def um_redeem_systems(session, user, systems):
def um_redeem_systems(session, user, systems, *, sheet_src=EUMSheet.main):
    """
    Redeem merits only for the specified user and the systems that matched exactly.
    """
    total = 0
    subq = session.query(UMSystem.id).\
        filter(UMSystem.name.in_(systems)).\
        filter(UMSystem.name.in_(systems),
               UMSystem.sheet_src == sheet_src).\
        scalar_subquery()
    holds = session.query(UMHold).filter(UMHold.user_id == user.id,
                                         UMHold.system_id.in_(subq)).all()
@@ -526,7 +542,7 @@ def um_redeem_systems(session, user, systems):
    return (holds, total)


def um_add_hold(session, **kwargs):
def um_add_hold(session, *, sheet_src=EUMSheet.main, **kwargs):
    """
    Add or update the user's Hold, that is their UM merits held or redeemed.
        System.name and SUser.name
@@ -545,10 +561,13 @@ def um_add_hold(session, **kwargs):
        raise cog.exc.InvalidCommandArgs('Hold amount must be in range [0, \u221E]')

    try:
        hold = session.query(UMHold).filter_by(user_id=user.id,
                                               system_id=system.id).one()
        hold = session.query(UMHold).\
            filter(UMHold.user_id == user.id,
                   UMHold.system_id == system.id,
                   UMHold.sheet_src == sheet_src).\
            one()
    except sqla_oexc.NoResultFound:
        hold = UMHold(user_id=user.id, system_id=system.id, held=0, redeemed=0)
        hold = UMHold(user_id=user.id, system_id=system.id, held=0, redeemed=0, sheet_src=sheet_src)
        session.add(hold)

    hold.held = held
@@ -557,7 +576,7 @@ def um_add_hold(session, **kwargs):
    return hold


def um_all_held_merits(session):
def um_all_held_merits(session, *, sheet_src=EUMSheet.main):
    """
    Return a list of lists that show all users with merits still held.

@@ -569,13 +588,21 @@ def um_all_held_merits(session):
    ]
    """
    c_dict = {}
    for merit in session.query(UMHold).filter(UMHold.held > 0).order_by(UMHold.system_id).all():
    held_merits = session.query(UMHold).\
        filter(UMHold.held > 0,
               UMHold.sheet_src == sheet_src).\
        order_by(UMHold.system_id).\
        all()
    for merit in held_merits:
        try:
            c_dict[merit.user.name][merit.system.name] = merit
        except KeyError:
            c_dict[merit.user.name] = {merit.system.name: merit}

    systems = session.query(UMSystem).order_by(UMSystem.id).all()
    systems = session.query(UMSystem).\
        filter(UMSystem.sheet_src == EUMSheet.main).\
        order_by(UMSystem.id).\
        all()
    system_names = [sys.name for sys in systems]
    rows = []
    for cmdr in c_dict:
@@ -597,7 +624,7 @@ def get_admin(session, member):
    Otherwise, raise NoMatch.
    """
    try:
        return session.query(AdminPerm).filter_by(id=member.id).one()
        return session.query(AdminPerm).filter(AdminPerm.id == member.id).one()
    except sqla_oexc.NoResultFound as exc:
        raise cog.exc.NoMatch(member.display_name, 'Admin') from exc

@@ -631,8 +658,12 @@ def add_role_perm(session, cmd, server, role):

def remove_channel_perm(session, cmd, server, channel):
    try:
        session.delete(session.query(ChannelPerm).
                       filter_by(cmd=cmd, server_id=server.id, channel_id=channel.id).one())
        perm = session.query(ChannelPerm).\
            filter(ChannelPerm.cmd == cmd,
                   ChannelPerm.server_id == server.id,
                   ChannelPerm.channel_id == channel.id).\
            one()
        session.delete(perm)
        session.commit()
    except sqla_oexc.NoResultFound as exc:
        raise cog.exc.InvalidCommandArgs("Channel permission does not exist.") from exc
@@ -640,8 +671,12 @@ def remove_channel_perm(session, cmd, server, channel):

def remove_role_perm(session, cmd, server, role):
    try:
        session.delete(session.query(RolePerm).
                       filter_by(cmd=cmd, server_id=server.id, role_id=role.id).one())
        perm = session.query(RolePerm).\
            filter(RolePerm.cmd == cmd,
                   RolePerm.server_id == server.id,
                   RolePerm.role_id == role.id).\
            one()
        session.delete(perm)
        session.commit()
    except sqla_oexc.NoResultFound as exc:
        raise cog.exc.InvalidCommandArgs("Role permission does not exist.") from exc
@@ -666,8 +701,11 @@ def check_channel_perms(session, cmd, server, channel):

    Raises InvalidPerms if fails permission check.
    """
    channels = [perm.channel_id for perm in session.query(ChannelPerm).
                filter_by(cmd=cmd, server_id=server.id)]
    perms = session.query(ChannelPerm).\
        filter(ChannelPerm.cmd == cmd,
               ChannelPerm.server_id == server.id).\
        all()
    channels = [perm.channel_id for perm in perms]
    if channels and channel.id not in channels:
        raise cog.exc.InvalidPerms("The '{}' command is not permitted on this channel.".format(
            cmd.lower()))
@@ -681,8 +719,11 @@ def check_role_perms(session, cmd, server, member_roles):

    Raises InvalidPerms if fails permission check.
    """
    perm_roles = {perm.role_id for perm in session.query(RolePerm).
                  filter_by(cmd=cmd, server_id=server.id)}
    perms = session.query(RolePerm).\
        filter(RolePerm.cmd == cmd,
               RolePerm.server_id == server.id).\
        all()
    perm_roles = {perm.role_id for perm in perms}
    member_roles = {role.id for role in member_roles}
    if perm_roles and len(member_roles - perm_roles) == len(member_roles):
        raise cog.exc.InvalidPerms("You do not have the roles for the command.")
@@ -1259,3 +1300,41 @@ def get_vote(session, discord_id, vote_type):
        session.add(the_vote)

    return the_vote


def get_all_snipe_holds(session):
    """
    Args:
        session: A session onto the db.

    Returns: A list of UMHolds for the snipe sheet. Empty by default.
    """
    return session.query(UMHold).\
        filter(UMHold.sheet_src == EUMSheet.snipe,
               UMHold.held > 0).\
        all()


def get_snipe_members_holding(session, guild):
    """
    Find the members who are holding merits on the snipe sheet.
    For each found member, attempt to resolve them with the guild to mention them.
    If we cannot resolve their name with guild, just write the name.
    Format one large message reminding the users and return it.

    Args:
        session: A session onto the db.
        guild: The guild of the server in question.

    Returns:
        A string formatted mentioning or naming all users with snipe merits.
    """
    template_msg = "{} is holding {} merits in {}\n"
    reply = ""
    for hold in get_all_snipe_holds(session):
        duser = hold.user.discord_user
        found = guild.get_member_named(duser.pref_name)
        mention = found.mention if found else duser.pref_name
        reply += template_msg.format(mention, hold.held, hold.system.name)

    return reply
+114 −7

File changed.

Preview size limit exceeded, changes collapsed.

Loading