diff --git a/data/pluscampaign-v1.sql b/data/pluscampaign-v1.sql index 24a279d..e0a74ef 100644 --- a/data/pluscampaign-v1.sql +++ b/data/pluscampaign-v1.sql @@ -2,8 +2,10 @@ BEGIN; -- Version dependency checks DO $$ - ASSERT current_module_version('PROFILES') = 1, 'Dependency version mismatch: PROFILES'; - ASSERT current_module_version('EVENT_TRACKER') = 2, 'Dependency version mismatch: EVENT_TRACKER'; + BEGIN + ASSERT current_module_version('PROFILES') = 1, 'Dependency version mismatch: PROFILES'; + ASSERT current_module_version('EVENT_TRACKER') = 2, 'Dependency version mismatch: EVENT_TRACKER'; + END; $$ LANGUAGE plpgsql; -- Plugin version history diff --git a/plugin/campaign.py b/plugin/campaign.py index 28a3a90..60b9543 100644 --- a/plugin/campaign.py +++ b/plugin/campaign.py @@ -2,6 +2,8 @@ from typing import Any, Optional import datetime as dt from datetime import datetime, timedelta +import aiohttp + from data import ORDER, Condition from data.conditions import NULL, condition from utils.lib import utc_now @@ -16,8 +18,9 @@ from . import logger class RewardCampaign: - def __init__(self, row: Campaign): + def __init__(self, row: Campaign, session: aiohttp.ClientSession | None = None): self.row = row + self._session = session self._webhook: ThreadedWebhook | None = None self._cached_webhookurl: str | None = None @@ -33,7 +36,7 @@ class RewardCampaign: if url is not None: # TODO: I don't know if these needs a client # Might be hard if so given we need to run this from Twitch client as well - self._webhook = ThreadedWebhook.from_url(url) + self._webhook = ThreadedWebhook.from_url(url, session=self._session) else: self._webhook = None return self._webhook @@ -170,8 +173,10 @@ class RewardCampaign: class CampaignRegistry: VERSION = CampaignData.VERSION - def __init__(self, data: CampaignData): + def __init__(self, data: CampaignData, session: aiohttp.ClientSession | None = None): self.data = data + # TODO: Actually pass in a session + self._session = aiohttp.ClientSession() async def init(self): await self.data.init() @@ -183,7 +188,7 @@ class CampaignRegistry: row = await Campaign.fetch(campaign_id) if row is None: raise ValueError("Campign %s doesn't exist." % campaign_id) - camp = RewardCampaign(row) + camp = RewardCampaign(row, session=self._session) return camp async def fetch_campaigns( @@ -207,7 +212,7 @@ class CampaignRegistry: condition = condition and ~active_condition rows = await Campaign.fetch_where(condition) - campaigns = [RewardCampaign(row) for row in rows] + campaigns = [RewardCampaign(row, session=self._session) for row in rows] return campaigns @@ -221,13 +226,13 @@ class CampaignRegistry: """ results = await Campaign.fetch_where( Condition._expression_equality( - LOWER(Campaign.campaign_name.expr), LOWER(asexpr(name)) + LOWER(Campaign.campaign_name), LOWER(asexpr(name)) ), - campaignid=cid, + communityid=cid, ) if results: row = results[0] - camp = RewardCampaign(row) + camp = RewardCampaign(row, session=self._session) else: camp = None return camp @@ -247,7 +252,7 @@ class CampaignRegistry: campaign_name=campaign_name, **kwargs ) - return RewardCampaign(row) + return RewardCampaign(row, session=self._session) async def update_campaign( self, @@ -261,4 +266,4 @@ class CampaignRegistry: """ campaign = await Campaign.fetch(campaign_id) await campaign.update(**kwargs) - return RewardCampaign(campaign) + return RewardCampaign(campaign, session=self._session) diff --git a/plugin/discord/cog.py b/plugin/discord/cog.py index 2fa6bb5..5aa97ba 100644 --- a/plugin/discord/cog.py +++ b/plugin/discord/cog.py @@ -1,6 +1,7 @@ from typing import Optional import asyncio +from aiohttp import client import discord from discord.ext import commands as cmds from discord import Forbidden, User, app_commands as appcmds @@ -193,6 +194,7 @@ class CampaignCog(LionCog): moderator_role_id=moderator_role.id if moderator_role else None, logging_webhook_url=logging_webhook, ) + await campaign.start() # Ack creation # TODO: Can also show dashboard @@ -256,7 +258,7 @@ class CampaignCog(LionCog): # If logging webhook is given, check that it works if logging_webhook is not None: - webhook = ThreadedWebhook.from_url(logging_webhook) + webhook = ThreadedWebhook.from_url(logging_webhook, client=self.bot) try: await webhook.test_webhook() except (discord.HTTPException, discord.Forbidden): @@ -276,9 +278,9 @@ class CampaignCog(LionCog): ) # Ack creation - # TODO: Can also show dashboard await ctx.reply( - f"Setup and started your reward campaign {campaign.row.campaign_name}! Good luck" + "Updated your campaign, good luck!", + ephemeral=True ) campaign_configure_cmd.autocomplete("campaign_name")(_campaign_acmpl) diff --git a/plugin/discord/ui/campaign.py b/plugin/discord/ui/campaign.py index 1515eac..7135c42 100644 --- a/plugin/discord/ui/campaign.py +++ b/plugin/discord/ui/campaign.py @@ -16,9 +16,8 @@ from meta import LionBot from meta.errors import UserInputError from meta.config import conf from utils.lib import tabulate, utc_now, MessageArgs, parse_duration -from utils.ui import MessageUI, AButton, AsComponents, ConfigEditor +from utils.ui import MessageUI from utils.ui.micros import FastModal -from utils.ui.pagers import BasePager, Pager from ...campaign import RewardCampaign from ...data import EarnedReward @@ -54,7 +53,7 @@ class CampaignDashboard(MessageUI): await widget.wait() self._slaves.remove(widget) - @button(emoji=conf.emojis.cancel, style=ButtonStyle.red) + @button(emoji=conf.emojis.cancel) async def quit_button(self, press: discord.Interaction, pressed: Button): """Close the UI and all children.""" await press.response.defer(thinking=False) @@ -124,7 +123,7 @@ class CampaignDashboard(MessageUI): embed.add_field( name="Rewards Summary", - value=blocks[0] or 'No Rewards Earned', + value=blocks[0] if blocks else 'No Rewards Earned', inline=True ) for block in blocks[1:]: diff --git a/plugin/discord/ui/rewards.py b/plugin/discord/ui/rewards.py index a5d72cc..c336c7f 100644 --- a/plugin/discord/ui/rewards.py +++ b/plugin/discord/ui/rewards.py @@ -196,7 +196,7 @@ class RewardList(MessageUI): self.pagen -= 1 await self.refresh() - @button(emoji=conf.emojis.cancel, style=ButtonStyle.red) + @button(emoji=conf.emojis.cancel) async def quit_button(self, press: discord.Interaction, pressed: Button): """Close the UI and all children.""" await press.response.defer(thinking=False) @@ -247,7 +247,7 @@ class RewardList(MessageUI): value = reward.earned_id return SelectOption( - label=name, value=value + label=name, value=str(value) ) async def refresh_layout(self): @@ -256,7 +256,7 @@ class RewardList(MessageUI): ) await asyncio.gather(*to_refresh) - if self.page_count > 1: + if self.page_count <= 1: self.prev_page_button.disabled = True self.next_page_button.disabled = True else: @@ -270,7 +270,24 @@ class RewardList(MessageUI): async def make_message(self) -> MessageArgs: embed = discord.Embed(title=f"{self.campaign.row.campaign_name} Reward List") - # embed.set_footer with last update + embed.set_footer(text='Last Update') + embed.timestamp = utc_now() + + campaign = self.campaign + all_rewards = await campaign.get_rewards() + rewards_earned = len(all_rewards) + reward_cap = campaign.row.target_rewards + if reward_cap is not None: + description = f"{rewards_earned} earned out of {reward_cap} available" + else: + description = f"{rewards_earned} earned so far" + + embed.description = description + + + for reward in self.page: + name, value = self._format_reward_section(reward) + embed.add_field(name=name, value=value, inline=False) return MessageArgs(embed=embed) diff --git a/plugin/lib.py b/plugin/lib.py index 4484a5e..f232fa3 100644 --- a/plugin/lib.py +++ b/plugin/lib.py @@ -62,4 +62,4 @@ class ThreadedWebhook(discord.Webhook): ) result = await self.send(embed=embed, wait=True, silent=True) asyncio.create_task(fire_and_forget(result.delete())) - await result + return result