Commit cd6282ba authored by Jeremy Pallats's avatar Jeremy Pallats 💬
Browse files

Add monitor to remind snipe merits before tick.

- Fix some minor issues in test and schema changes for UM sheets.
parent 84f4a51a
Loading
Loading
Loading
Loading
Loading
+55 −2
Original line number Diff line number Diff line
@@ -1970,7 +1970,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.

@@ -2016,7 +2016,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.
@@ -2056,6 +2056,58 @@ 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
        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:
            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.
@@ -2156,3 +2208,4 @@ UM_NPC_TABLE = [
    ['Archon Delaine', 'Kumo Crew Watch', 'Kumo Crew Transport', 'Kumo Crew Strike Ships']
]
TRACK_LIMIT = 20
FUC_GUILD = "Federal United Command"
+1 −0
Original line number Diff line number Diff line
@@ -203,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(),
            ))
+38 −3
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, EUMSheet, 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
@@ -114,7 +115,7 @@ def users_with_all_merits(session):
    """
    return session.query(DiscordUser, (sqla.func.ifnull(FortUser.dropped, 0) + sqla.func.ifnull(UMUser.combo, 0)).label('total')).\
        outerjoin(FortUser, DiscordUser.pref_name == FortUser.name).\
        outerjoin(UMUser, DiscordUser.pref_name == UMUser.name).\
        outerjoin(UMUser, DiscordUser.pref_name == UMUser.name,).\
        order_by(sqla.desc("total")).\
        all()

@@ -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()

@@ -597,7 +599,10 @@ def um_all_held_merits(session, *, sheet_src=EUMSheet.main):
        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:
@@ -1295,3 +1300,33 @@ def get_vote(session, discord_id, vote_type):
        session.add(the_vote)

    return the_vote


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.
    """
    snipe_holds = session.query(UMHold).\
        filter(UMHold.sheet_src == EUMSheet.snipe,
               UMHold.held > 0).\
        all()

    template_msg = "{} is holding {} merits in {}\n"
    reply = ""
    for hold in snipe_holds:
        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
+11 −4
Original line number Diff line number Diff line
@@ -534,7 +534,8 @@ class UMUser(Base):
    def held(self):
        """ Total merits held by this cmdr. """
        return sqla.select([sqla.func.sum(UMHold.held)]).\
            where(UMHold.user_id == self.id).\
            where(sqla.and_(UMHold.user_id == self.id,
                            UMHold.sheet_src != EUMSheet.snipe)).\
            label('held')

    @hybrid_property
@@ -550,7 +551,8 @@ class UMUser(Base):
    def redeemed(self):
        """ Total merits redeemed by this cmdr. """
        return sqla.select([sqla.func.sum(UMHold.redeemed)]).\
            where(UMHold.user_id == self.id).\
            where(sqla.and_(UMHold.user_id == self.id,
                            UMHold.sheet_src != EUMSheet.snipe)).\
            label('redeemed')

    @hybrid_property
@@ -570,6 +572,7 @@ class UMUser(Base):
    def __repr__(self):
        keys = ['id', 'name', 'row', 'cry']
        kwargs = ['{}={!r}'.format(key, getattr(self, key)) for key in keys]
        kwargs.insert(1, "sheet_src={}".format("EUMSheet.main" if self.sheet_src == EUMSheet.main else "EUMSheet.snipe"))

        return "{}({})".format(self.__class__.__name__, ', '.join(kwargs))

@@ -639,6 +642,7 @@ class UMSystem(Base):
        keys = ['id', 'name', 'sheet_col', 'goal', 'security', 'notes',
                'progress_us', 'progress_them', 'close_control', 'priority', 'map_offset']
        kwargs = ['{}={!r}'.format(key, getattr(self, key)) for key in keys]
        kwargs.insert(1, "sheet_src={}".format("EUMSheet.main" if self.sheet_src == EUMSheet.main else "EUMSheet.snipe"))

        return "{}({})".format(self.__class__.__name__, ', '.join(kwargs))

@@ -805,6 +809,7 @@ class UMHold(Base):
    def __repr__(self):
        keys = ['id', 'system_id', 'user_id', 'held', 'redeemed']
        kwargs = ['{}={!r}'.format(key, getattr(self, key)) for key in keys]
        kwargs.insert(1, "sheet_src={}".format("EUMSheet.main" if self.sheet_src == EUMSheet.main else "EUMSheet.snipe"))

        return "{}({})".format(self.__class__.__name__, ', '.join(kwargs))

@@ -1667,6 +1672,8 @@ def run_schema_queries(session): # pragma: no cover
                   trigger=6000, undermine=0, notes="S/M Priority, Skip"),
        FortSystem(name='Rana', sheet_col='J', sheet_order=5, fort_status=0,
                   trigger=6000, undermine=1.2, notes="Attacked"),
        FortPrep(name='Rhea', sheet_col='L', sheet_order=6, fort_status=0,
                 trigger=8000, notes="To prep"),
    )
    session.add_all(systems)
    session.flush()
@@ -1734,7 +1741,7 @@ def run_schema_queries(session): # pragma: no cover
        OCRTracker(system="Frey", updated_at=date),
        OCRTracker(system="Adeo"),
        OCRTracker(system="Sol"),
        OCRPrep(system="Othime"),
        OCRPrep(system="Rhea"),
        OCRTrigger(system="Frey")
    )
    session.add_all(ocrs_systems)
@@ -1750,7 +1757,7 @@ def run_schema_queries(session): # pragma: no cover
    print(sys.ocr_tracker)
    print(sys.ocr_trigger)

    sys = session.query(FortSystem).filter(FortSystem.name == "Othime").one()
    sys = session.query(FortPrep).one()
    print(sys.ocr_prep)


+12 −0
Original line number Diff line number Diff line
@@ -846,3 +846,15 @@ def test_vote_get(session, f_dusers, f_vote_testbed):
    the_vote = cogdb.query.get_vote(session, f_dusers[2].id, VoteType.prep)
    assert the_vote.id == f_dusers[2].id
    assert the_vote.vote == VoteType.prep


def test_get_snipe_members_holding(session, f_bot, f_dusers, f_um_testbed):
    expected = 'User3 is holding 5000 merits in ToSnipe\n'
    results = cogdb.query.get_snipe_members_holding(session, f_bot.guilds[0])
    assert results == expected


def test_get_snipe_members_holding(session, f_bot, f_dusers, f_um_testbed):
    expected = 'User3 is holding 5000 merits in ToSnipe\n'
    results = cogdb.query.get_snipe_members_holding(session, f_bot.guilds[0])
    assert results == expected
Loading