generated from HoloTech/holotech-plugin-template
Compare commits
18 Commits
a18885511a
...
6122603115
| Author | SHA1 | Date | |
|---|---|---|---|
| 6122603115 | |||
| a69d45c1c2 | |||
| e11fb8f071 | |||
| c54653322e | |||
| 8189eeec05 | |||
| f2e8852d45 | |||
| 5eb0c1a712 | |||
| 300f712bfd | |||
| 05c428bcc9 | |||
| 87aec03e57 | |||
| f61d0519ee | |||
| 99d1193be6 | |||
| 1cc93d732e | |||
| e700628403 | |||
| 299618ab1d | |||
| a681da058f | |||
| 5873b0fe65 | |||
| d8817d4473 |
@@ -38,9 +38,9 @@ CREATE TABLE campaign_rewards_earned(
|
||||
fulfilled_note TEXT,
|
||||
modnote TEXT,
|
||||
reference TEXT,
|
||||
logged_messageid BIGINT,
|
||||
log_messageid BIGINT,
|
||||
earned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
earned_reason TEXT NOT NULL,
|
||||
earned_from TEXT NOT NULL,
|
||||
_timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
|
||||
+31
-38
@@ -57,7 +57,7 @@ class RewardCampaign:
|
||||
async def add_reward(
|
||||
self,
|
||||
profileid: int,
|
||||
earned_reason: str,
|
||||
earned_from: str,
|
||||
event_id: Optional[int] = None,
|
||||
twitch_user_id: Optional[str] = None,
|
||||
twitch_user_name: Optional[str] = None,
|
||||
@@ -66,7 +66,7 @@ class RewardCampaign:
|
||||
row = await EarnedReward.create(
|
||||
campaign_id=self.row.campaign_id,
|
||||
profileid=profileid,
|
||||
earned_reason=earned_reason,
|
||||
earned_from=earned_from,
|
||||
event_id=event_id,
|
||||
twitch_user_id=twitch_user_id,
|
||||
twitch_user_name=twitch_user_name,
|
||||
@@ -93,6 +93,7 @@ class RewardCampaign:
|
||||
|
||||
async def try_to_log_reward(self, reward: EarnedReward):
|
||||
import discord
|
||||
|
||||
if self.webhook:
|
||||
embed = await self._log_format_reward(reward)
|
||||
if reward.log_messageid:
|
||||
@@ -107,7 +108,9 @@ class RewardCampaign:
|
||||
await reward.update(log_messageid=message.id)
|
||||
except discord.HTTPException:
|
||||
# Couldn't send, give up.
|
||||
logger.warning(f"Failed to log campaign reward {reward!r}", exc_info=True)
|
||||
logger.warning(
|
||||
f"Failed to log campaign reward {reward!r}", exc_info=True
|
||||
)
|
||||
|
||||
async def _log_format_reward(self, reward: EarnedReward):
|
||||
"""
|
||||
@@ -118,51 +121,46 @@ class RewardCampaign:
|
||||
embed = discord.Embed(
|
||||
title=f"Reward #{reward.earned_id} in {self.row.campaign_name}",
|
||||
)
|
||||
embed.description = f"> {reward.earned_from}"
|
||||
# User Field
|
||||
embed.add_field(
|
||||
name="User Information",
|
||||
value=(
|
||||
f"Twitch user `{reward.twitch_user_name or 'Unknown'}` `(ID: {reward.twitch_user_id or 'Unknown'})`.\n"
|
||||
f"`{reward.twitch_user_name or 'Unknown'}`\n"
|
||||
f"`ID: {reward.twitch_user_id or 'Unknown'}`.\n"
|
||||
f"Internal ID `{reward.profileid}`"
|
||||
),
|
||||
inline=True
|
||||
inline=True,
|
||||
)
|
||||
|
||||
# Earning field
|
||||
embed.add_field(
|
||||
name="Reward Earned",
|
||||
value=(
|
||||
f"Earned campaign reward at {discord.utils.format_dt(reward.earned_at, 'F')}.\n"
|
||||
f"Earned reason: '{reward.earned_from}'"
|
||||
),
|
||||
inline=True
|
||||
value=(f"{discord.utils.format_dt(reward.earned_at, 'F')}."),
|
||||
inline=True,
|
||||
)
|
||||
|
||||
# Reference field
|
||||
embed.add_field(
|
||||
name="Reference",
|
||||
value=reward.reference or "No Reference information saved.",
|
||||
inline=False
|
||||
inline=False,
|
||||
)
|
||||
# Modnote field
|
||||
embed.add_field(
|
||||
name="Notes",
|
||||
value=reward.modnote or "No notes added",
|
||||
inline=False
|
||||
name="Notes", value=reward.modnote or "No notes added", inline=False
|
||||
)
|
||||
|
||||
# Fulfilled field
|
||||
fluffed_emoji = "✅" if reward.fulfilled_at else "🔳"
|
||||
if reward.fulfilled_at is not None:
|
||||
fluffed = f"Fluffed at {discord.utils.format_dt(reward.fulfilled_at, 'F')}"
|
||||
fluffed = f"{fluffed_emoji} Fluffed at {discord.utils.format_dt(reward.fulfilled_at, 'F')}"
|
||||
if reward.fulfilled_note:
|
||||
fluffed += '\n' + "Fluff Note: " + reward.fulfilled_note
|
||||
fluffed += "\n" + "Fluff Note: " + reward.fulfilled_note
|
||||
else:
|
||||
fluffed = "Not yet fluffed"
|
||||
fluffed = f"{fluffed_emoji} Not yet fluffed"
|
||||
|
||||
embed.add_field(
|
||||
name="Fulfilled",
|
||||
value=fluffed
|
||||
)
|
||||
embed.add_field(name="Fulfilled", value=fluffed)
|
||||
|
||||
embed.set_footer(text="Last Updated")
|
||||
embed.timestamp = utc_now()
|
||||
@@ -173,7 +171,9 @@ class RewardCampaign:
|
||||
class CampaignRegistry:
|
||||
VERSION = CampaignData.VERSION
|
||||
|
||||
def __init__(self, data: CampaignData, session: aiohttp.ClientSession | None = None):
|
||||
def __init__(
|
||||
self, data: CampaignData, session: aiohttp.ClientSession | None = None
|
||||
):
|
||||
self.data = data
|
||||
# TODO: Actually pass in a session
|
||||
self._session = aiohttp.ClientSession()
|
||||
@@ -204,14 +204,16 @@ class CampaignRegistry:
|
||||
|
||||
if active is not None:
|
||||
active_condition = (
|
||||
Campaign.started_at != NULL and Campaign.completed_at == NULL
|
||||
(Campaign.started_at != NULL) & (Campaign.completed_at == NULL)
|
||||
)
|
||||
if active:
|
||||
condition = condition and active_condition
|
||||
condition = condition & active_condition
|
||||
else:
|
||||
condition = condition and ~active_condition
|
||||
condition = condition & ~active_condition
|
||||
|
||||
rows = await Campaign.fetch_where(condition)
|
||||
rows = await Campaign.fetch_where(
|
||||
condition,
|
||||
)
|
||||
campaigns = [RewardCampaign(row, session=self._session) for row in rows]
|
||||
|
||||
return campaigns
|
||||
@@ -238,27 +240,18 @@ class CampaignRegistry:
|
||||
return camp
|
||||
|
||||
async def create_campaign(
|
||||
self,
|
||||
cid: int,
|
||||
campaign_name: str,
|
||||
**kwargs
|
||||
self, cid: int, campaign_name: str, **kwargs
|
||||
) -> RewardCampaign:
|
||||
"""
|
||||
Create a new campaign.
|
||||
The name must be unique (ignoring case) to facilitate easy lookup.
|
||||
"""
|
||||
row = await Campaign.create(
|
||||
communityid=cid,
|
||||
campaign_name=campaign_name,
|
||||
**kwargs
|
||||
communityid=cid, campaign_name=campaign_name, **kwargs
|
||||
)
|
||||
return RewardCampaign(row, session=self._session)
|
||||
|
||||
async def update_campaign(
|
||||
self,
|
||||
campaign_id: int,
|
||||
**kwargs
|
||||
) -> RewardCampaign:
|
||||
async def update_campaign(self, campaign_id: int, **kwargs) -> RewardCampaign:
|
||||
"""
|
||||
Update a campaign with the given data args.
|
||||
|
||||
|
||||
+51
-14
@@ -123,7 +123,9 @@ class CampaignCog(LionCog):
|
||||
return
|
||||
|
||||
# Open campaign UI
|
||||
widget = CampaignDashboard(bot=self.bot, campaign=campaign, callerid=ctx.author.id)
|
||||
widget = CampaignDashboard(
|
||||
bot=self.bot, campaign=campaign, callerid=ctx.author.id
|
||||
)
|
||||
await widget.run(ctx.interaction)
|
||||
await widget.wait()
|
||||
|
||||
@@ -179,7 +181,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):
|
||||
@@ -202,7 +204,9 @@ class CampaignCog(LionCog):
|
||||
f"Setup and started your reward campaign {campaign.row.campaign_name}! Good luck"
|
||||
)
|
||||
# Open campaign UI
|
||||
widget = CampaignDashboard(bot=self.bot, campaign=campaign, callerid=ctx.author.id)
|
||||
widget = CampaignDashboard(
|
||||
bot=self.bot, campaign=campaign, callerid=ctx.author.id
|
||||
)
|
||||
await widget.run(ctx.interaction)
|
||||
await widget.wait()
|
||||
|
||||
@@ -278,10 +282,7 @@ class CampaignCog(LionCog):
|
||||
)
|
||||
|
||||
# Ack creation
|
||||
await ctx.reply(
|
||||
"Updated your campaign, good luck!",
|
||||
ephemeral=True
|
||||
)
|
||||
await ctx.reply("Updated your campaign, good luck!", ephemeral=True)
|
||||
|
||||
campaign_configure_cmd.autocomplete("campaign_name")(_campaign_acmpl)
|
||||
|
||||
@@ -322,9 +323,19 @@ class CampaignCog(LionCog):
|
||||
)
|
||||
@appcmds.describe(
|
||||
rewardid="Earned reward to edit",
|
||||
fulfilled="Whether this reward has been completed or not.",
|
||||
reference="Reference information for this reward, e.g. image or message URL",
|
||||
notes="Any additional notes",
|
||||
)
|
||||
@appcmds.rename(rewardid="reward")
|
||||
async def campaign_editreward_cmd(self, ctx: LionContext, rewardid: str):
|
||||
async def campaign_editreward_cmd(
|
||||
self,
|
||||
ctx: LionContext,
|
||||
rewardid: str,
|
||||
fulfilled: Optional[bool] = None,
|
||||
reference: Optional[str] = None,
|
||||
notes: Optional[str] = None
|
||||
):
|
||||
# For this we'll just open the reward editor
|
||||
# Will need to identify the reward with autocomplete. Can use the reward id directly..
|
||||
if not rewardid.isdigit():
|
||||
@@ -352,11 +363,31 @@ class CampaignCog(LionCog):
|
||||
)
|
||||
return
|
||||
|
||||
# Okay, this is our reward, and author has permission to modify it. Spin the modal.
|
||||
modal = RewardEditor.from_reward(reward)
|
||||
|
||||
# Okay, this is our reward, and author has permission to modify it.
|
||||
currently_fluffed = reward.fulfilled_at is not None
|
||||
|
||||
update_args = {}
|
||||
if fulfilled is not None:
|
||||
if fulfilled and not currently_fluffed:
|
||||
# Reward has been fluffed
|
||||
update_args["fulfilled_at"] = utc_now()
|
||||
elif currently_fluffed and not fulfilled:
|
||||
# Reward has been unfluffed
|
||||
update_args["fulfilled_at"] = None
|
||||
if reference is not None and reference != reward.reference:
|
||||
update_args["reference"] = reference
|
||||
if notes is not None and notes != reward.modnote:
|
||||
update_args["modnote"] = notes
|
||||
|
||||
if update_args:
|
||||
await ctx.interaction.response.defer(thinking=True, ephemeral=True)
|
||||
await campaign.update_reward(reward.earned_id, **update_args)
|
||||
await ctx.interaction.followup.send(
|
||||
content="Reward updated!"
|
||||
)
|
||||
else:
|
||||
modal = RewardEditor.from_reward(reward)
|
||||
|
||||
@modal.submit_callback()
|
||||
async def on_editor_submit(interaction: discord.Interaction):
|
||||
update_args = {}
|
||||
@@ -368,11 +399,11 @@ class CampaignCog(LionCog):
|
||||
# Reward has been unfluffed
|
||||
update_args["fulfilled_at"] = None
|
||||
|
||||
new_ref_value = modal.reference.value or None
|
||||
new_ref_value = modal.reference.component.value or None
|
||||
if new_ref_value != reward.reference:
|
||||
update_args["reference"] = new_ref_value
|
||||
|
||||
new_notes_value = modal.notes.value or None
|
||||
new_notes_value = modal.notes.component.value or None
|
||||
if new_notes_value != reward.modnote:
|
||||
update_args["modnote"] = new_notes_value
|
||||
|
||||
@@ -385,6 +416,8 @@ class CampaignCog(LionCog):
|
||||
else:
|
||||
await interaction.response.defer(thinking=False)
|
||||
|
||||
await ctx.interaction.response.send_modal(modal)
|
||||
|
||||
def _reward_acmpl_format(
|
||||
self, campaign: RewardCampaign, reward: EarnedReward
|
||||
) -> str:
|
||||
@@ -393,7 +426,11 @@ class CampaignCog(LionCog):
|
||||
|
||||
#100: username in campaign
|
||||
"""
|
||||
...
|
||||
return "#{rewardid}: {username} in {cname}".format(
|
||||
rewardid=reward.earned_id,
|
||||
username=reward.twitch_user_name or reward.twitch_user_id or "Unknown",
|
||||
cname=campaign.row.campaign_name,
|
||||
)
|
||||
|
||||
@campaign_editreward_cmd.autocomplete("rewardid")
|
||||
async def _reward_acmpl(
|
||||
|
||||
@@ -100,31 +100,43 @@ class CampaignDashboard(MessageUI):
|
||||
table = {
|
||||
"Created at": discord.utils.format_dt(campaign.row.created_at, "F"),
|
||||
"Started at": started_at,
|
||||
"Moderator Role": f"<&@{campaign.row.moderator_role_id}>" if campaign.row.moderator_role_id else "*Not Set*",
|
||||
"Logging webhook": "*Set Up*" if campaign.row.logging_webhook_url else "*Not Set*",
|
||||
"Moderator Role": f"<@&{campaign.row.moderator_role_id}>"
|
||||
if campaign.row.moderator_role_id
|
||||
else "*Not Set*",
|
||||
"Logging webhook": "*Set Up*"
|
||||
if campaign.row.logging_webhook_url
|
||||
else "*Not Set*",
|
||||
"Rewards Earned": str(rewards_earned),
|
||||
"Rewards Cap": str(reward_cap),
|
||||
}
|
||||
if campaign.row.completed_at is not None:
|
||||
table['Finished at'] = discord.utils.format_dt(campaign.row.completed_at, "F")
|
||||
prop_table = '\n'.join(tabulate(*table.items()))
|
||||
table["Finished at"] = discord.utils.format_dt(
|
||||
campaign.row.completed_at, "F"
|
||||
)
|
||||
prop_table = "\n".join(tabulate(*table.items()))
|
||||
|
||||
embed.description = f"{description}\n\n{prop_table}"
|
||||
|
||||
# Brief summary of rewards in columns. 12 per column. Empty titles?
|
||||
rewardrows = []
|
||||
for reward in all_rewards:
|
||||
name = reward.twitch_user_name or str(reward.twitch_user_id) or str(reward.profileid)
|
||||
name = (
|
||||
reward.twitch_user_name
|
||||
or str(reward.twitch_user_id)
|
||||
or str(reward.profileid)
|
||||
)
|
||||
fluffed = reward.fulfilled_at is not None
|
||||
fluffed_emoji = '✅' if fluffed else '🔳'
|
||||
fluffed_emoji = "✅" if fluffed else "🔳"
|
||||
rewardrows.append(f"{fluffed_emoji} {name}")
|
||||
|
||||
blocks = ['\n'.join(rewardrows[i:i+12]) for i in range(0, len(rewardrows), 12)]
|
||||
blocks = [
|
||||
"\n".join(rewardrows[i : i + 12]) for i in range(0, len(rewardrows), 12)
|
||||
]
|
||||
|
||||
embed.add_field(
|
||||
name="Rewards Summary",
|
||||
value=blocks[0] if blocks else 'No Rewards Earned',
|
||||
inline=True
|
||||
value=blocks[0] if blocks else "No Rewards Earned",
|
||||
inline=True,
|
||||
)
|
||||
for block in blocks[1:]:
|
||||
embed.add_field(
|
||||
|
||||
@@ -29,15 +29,13 @@ class RewardEditor(FastModal):
|
||||
# Title is the reward we are editing
|
||||
|
||||
# Block of text with dates and user info
|
||||
blurb = discord.ui.TextDisplay(content='placeholder')
|
||||
blurb = discord.ui.TextDisplay(content="placeholder")
|
||||
|
||||
# Fulfilled is a checkbox, and supports a fulfilled note
|
||||
flufbox = discord.ui.Label(
|
||||
text="Fulfilled",
|
||||
description="Whether this reward has been completed",
|
||||
component=discord.ui.Checkbox(
|
||||
default=False
|
||||
)
|
||||
component=discord.ui.Checkbox(default=False),
|
||||
)
|
||||
|
||||
# Reference and further notes need to be editable,
|
||||
@@ -47,6 +45,7 @@ class RewardEditor(FastModal):
|
||||
description="Reference URL or other information",
|
||||
component=discord.ui.TextInput(
|
||||
style=discord.TextStyle.long,
|
||||
required=False,
|
||||
),
|
||||
)
|
||||
notes = discord.ui.Label(
|
||||
@@ -54,6 +53,7 @@ class RewardEditor(FastModal):
|
||||
description="Further notes for this user/reward",
|
||||
component=discord.ui.TextInput(
|
||||
style=discord.TextStyle.long,
|
||||
required=False,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -64,19 +64,18 @@ class RewardEditor(FastModal):
|
||||
|
||||
# blurb
|
||||
table = {
|
||||
'Earned At': discord.utils.format_dt(reward.earned_at, 'F'),
|
||||
'Earned From': reward.earned_from,
|
||||
"Earned At": discord.utils.format_dt(reward.earned_at, "F"),
|
||||
"Earned From": reward.earned_from,
|
||||
}
|
||||
prop_table = '\n'.join(tabulate(*table.items()))
|
||||
prop_table = "\n".join(tabulate(*table.items()))
|
||||
self.blurb.content = prop_table
|
||||
|
||||
|
||||
# Fulfilled
|
||||
self.flufbox.component.default = (reward.fulfilled_at is not None)
|
||||
self.flufbox.component.default = reward.fulfilled_at is not None
|
||||
|
||||
# Notes
|
||||
self.reference.component.default = reward.reference or ''
|
||||
self.notes.component.default = reward.modnote or ''
|
||||
self.reference.component.default = reward.reference or ""
|
||||
self.notes.component.default = reward.modnote or ""
|
||||
|
||||
return self
|
||||
|
||||
@@ -134,7 +133,7 @@ class RewardList(MessageUI):
|
||||
reward = next(r for r in self._rewards if r.earned_id == value)
|
||||
modal = RewardEditor.from_reward(reward)
|
||||
|
||||
currently_fluffed = (reward.fulfilled_at is not None)
|
||||
currently_fluffed = reward.fulfilled_at is not None
|
||||
|
||||
@modal.submit_callback()
|
||||
async def on_editor_submit(interaction: discord.Interaction):
|
||||
@@ -142,18 +141,18 @@ class RewardList(MessageUI):
|
||||
|
||||
if modal.flufbox.component.value and not currently_fluffed:
|
||||
# Reward has been fluffed
|
||||
update_args['fulfilled_at'] = utc_now()
|
||||
update_args["fulfilled_at"] = utc_now()
|
||||
elif currently_fluffed and not modal.flufbox.component.value:
|
||||
# Reward has been unfluffed
|
||||
update_args['fulfilled_at'] = None
|
||||
update_args["fulfilled_at"] = None
|
||||
|
||||
new_ref_value = modal.reference.value or None
|
||||
new_ref_value = modal.reference.component.value or None
|
||||
if new_ref_value != reward.reference:
|
||||
update_args['reference'] = new_ref_value
|
||||
update_args["reference"] = new_ref_value
|
||||
|
||||
new_notes_value = modal.notes.value or None
|
||||
new_notes_value = modal.notes.component.value or None
|
||||
if new_notes_value != reward.modnote:
|
||||
update_args['modnote'] = new_notes_value
|
||||
update_args["modnote"] = new_notes_value
|
||||
|
||||
if update_args:
|
||||
await interaction.response.defer(thinking=True, ephemeral=True)
|
||||
@@ -162,7 +161,6 @@ class RewardList(MessageUI):
|
||||
else:
|
||||
await interaction.response.defer(thinking=False)
|
||||
|
||||
|
||||
await selection.response.send_modal(modal)
|
||||
|
||||
await self.refresh()
|
||||
@@ -173,14 +171,10 @@ class RewardList(MessageUI):
|
||||
menu = self.reward_menu
|
||||
rewards = self.page
|
||||
if rewards:
|
||||
menu.options = [
|
||||
self._format_reward_option(r) for r in rewards
|
||||
]
|
||||
menu.options = [self._format_reward_option(r) for r in rewards]
|
||||
menu.disabled = False
|
||||
else:
|
||||
menu.options = [
|
||||
SelectOption(label='DUMMY')
|
||||
]
|
||||
menu.options = [SelectOption(label="DUMMY")]
|
||||
menu.disabled = True
|
||||
|
||||
# Meta buttons
|
||||
@@ -214,10 +208,9 @@ class RewardList(MessageUI):
|
||||
"""
|
||||
# Title is Reward #n earned by twitch_username
|
||||
# Reward, Earned at, Earned by, Fulfilled at (not fulfilled/date), Ref, Added Notes
|
||||
name = f"Reward #{reward.earned_id} earned by {reward.twitch_user_name or reward.twitch_user_id}"
|
||||
|
||||
if reward.fulfilled_at is not None:
|
||||
fat = discord.utils.format_dt(reward.fulfilled_at, 'F')
|
||||
fat = discord.utils.format_dt(reward.fulfilled_at, "F")
|
||||
if reward.fulfilled_note is not None:
|
||||
fluf = f"{fat} ({reward.fulfilled_note})"
|
||||
else:
|
||||
@@ -225,17 +218,25 @@ class RewardList(MessageUI):
|
||||
else:
|
||||
fluf = "*Not Fulfilled*"
|
||||
|
||||
table = {
|
||||
'Reward': "Plus Campaign Sketch",
|
||||
'Earned At': discord.utils.format_dt(reward.earned_at, 'F'),
|
||||
'Earned From': reward.earned_from,
|
||||
'Fulfilled At': fluf,
|
||||
'Reference': reward.reference or "*No reference set*",
|
||||
'Further notes': reward.modnote or "*No notes*",
|
||||
}
|
||||
prop_table = '\n'.join(tabulate(*table.items()))
|
||||
fluffed_emoji = "✅" if reward.fulfilled_at else "🔳"
|
||||
earned = discord.utils.format_dt(reward.earned_at, "d")
|
||||
|
||||
return (name, prop_table)
|
||||
name = f"{fluffed_emoji} #{reward.earned_id} earned by {reward.twitch_user_name or reward.twitch_user_id} at {earned}"
|
||||
|
||||
table = {
|
||||
# "Reward": "Plus Campaign Sketch",
|
||||
# "Earned From": reward.earned_from,
|
||||
# "Fulfilled At": fluf,
|
||||
"Reference": reward.reference or "*No reference set*",
|
||||
"Further notes": reward.modnote or "*No notes*",
|
||||
}
|
||||
prop_table = "\n".join(tabulate(*table.items()))
|
||||
|
||||
value = '\n'.join((
|
||||
"> {reason}",
|
||||
"{table}",
|
||||
)).format(reason=reward.earned_from, table=prop_table)
|
||||
return (name, value)
|
||||
|
||||
def _format_reward_option(self, reward: EarnedReward) -> SelectOption:
|
||||
"""
|
||||
@@ -246,14 +247,10 @@ class RewardList(MessageUI):
|
||||
name = f"Reward #{reward.earned_id} earned by {reward.twitch_user_name or reward.twitch_user_id}"
|
||||
value = reward.earned_id
|
||||
|
||||
return SelectOption(
|
||||
label=name, value=str(value)
|
||||
)
|
||||
return SelectOption(label=name, value=str(value))
|
||||
|
||||
async def refresh_layout(self):
|
||||
to_refresh = (
|
||||
self.reward_menu_refresh(),
|
||||
)
|
||||
to_refresh = (self.reward_menu_refresh(),)
|
||||
await asyncio.gather(*to_refresh)
|
||||
|
||||
if self.page_count <= 1:
|
||||
@@ -264,13 +261,18 @@ class RewardList(MessageUI):
|
||||
self.next_page_button.disabled = False
|
||||
|
||||
self.set_layout(
|
||||
(self.prev_page_button, self.refresh_button, self.next_page_button, self.quit_button),
|
||||
(
|
||||
self.prev_page_button,
|
||||
self.refresh_button,
|
||||
self.next_page_button,
|
||||
self.quit_button,
|
||||
),
|
||||
(self.reward_menu,),
|
||||
)
|
||||
|
||||
async def make_message(self) -> MessageArgs:
|
||||
embed = discord.Embed(title=f"{self.campaign.row.campaign_name} Reward List")
|
||||
embed.set_footer(text='Last Update')
|
||||
embed.set_footer(text="Last Update")
|
||||
embed.timestamp = utc_now()
|
||||
|
||||
campaign = self.campaign
|
||||
@@ -284,7 +286,6 @@ class RewardList(MessageUI):
|
||||
|
||||
embed.description = description
|
||||
|
||||
|
||||
for reward in self.page:
|
||||
name, value = self._format_reward_section(reward)
|
||||
embed.add_field(name=name, value=value, inline=False)
|
||||
@@ -296,6 +297,6 @@ class RewardList(MessageUI):
|
||||
|
||||
# TODO: Consider filter by unfulfilled or reward type
|
||||
self.reward_blocks = [
|
||||
rewards[i:i+self.blocklen]
|
||||
rewards[i : i + self.blocklen]
|
||||
for i in range(0, len(rewards), self.blocklen)
|
||||
] or [[]]
|
||||
|
||||
+9
-2
@@ -17,12 +17,14 @@ def LOWER(expression: Expression) -> RawExpr:
|
||||
|
||||
return RawExpr(final_expr, final_values)
|
||||
|
||||
|
||||
def asexpr(value: Any) -> RawExpr:
|
||||
"""
|
||||
Turn a value into an expression.
|
||||
"""
|
||||
return RawExpr(sql.Placeholder(), (value,))
|
||||
|
||||
|
||||
async def fire_and_forget(awaitable, do_in=1, ignorable=(discord.HTTPException)):
|
||||
await asyncio.sleep(do_in)
|
||||
try:
|
||||
@@ -33,6 +35,7 @@ async def fire_and_forget(awaitable, do_in=1, ignorable=(discord.HTTPException))
|
||||
# TODO: Log unexpected exceptions
|
||||
pass
|
||||
|
||||
|
||||
class ThreadedWebhook(discord.Webhook):
|
||||
__slots__ = ("thread_id",)
|
||||
|
||||
@@ -55,10 +58,14 @@ class ThreadedWebhook(discord.Webhook):
|
||||
kwargs.setdefault("thread", discord.Object(self.thread_id))
|
||||
return await super().send(*args, **kwargs)
|
||||
|
||||
async def edit_message(self, *args, **kwargs):
|
||||
if self.thread_id is not None:
|
||||
kwargs.setdefault("thread", discord.Object(self.thread_id))
|
||||
return await super().edit_message(*args, **kwargs)
|
||||
|
||||
async def test_webhook(self):
|
||||
embed = discord.Embed(
|
||||
title="Testing",
|
||||
description="Testing logging webhook, feel free to delete."
|
||||
title="Testing", description="Testing logging webhook, feel free to delete."
|
||||
)
|
||||
result = await self.send(embed=embed, wait=True, silent=True)
|
||||
asyncio.create_task(fire_and_forget(result.delete()))
|
||||
|
||||
@@ -6,6 +6,7 @@ from twitchio.ext import commands as cmds
|
||||
|
||||
from meta import Bot
|
||||
from meta.logger import log_wrap
|
||||
from meta.sockets import Channel, register_channel
|
||||
from utils.lib import utc_now
|
||||
|
||||
from . import logger
|
||||
@@ -23,7 +24,7 @@ class CampaignComponent(cmds.Component):
|
||||
self.campaigns = CampaignRegistry(self.data)
|
||||
self.channel = CampaignChannel(self.bot.profiles.profiles, self.campaigns)
|
||||
|
||||
register_channel("Campaign", self.channel)
|
||||
register_channel(self.channel.name, self.channel)
|
||||
|
||||
# ----- API -----
|
||||
async def component_load(self):
|
||||
@@ -73,7 +74,7 @@ class CampaignComponent(cmds.Component):
|
||||
# Add a reward to the database with the correct info.
|
||||
await campaign.add_reward(
|
||||
profileid=event_row["profileid"],
|
||||
earned_reason=f"(SUB) User subscribed for {duration} months at tier {tier}",
|
||||
earned_from=f"(SUB) User subscribed for {duration} months at tier {tier}",
|
||||
event_id=event_row["event_id"],
|
||||
twitch_user_id=data["chatter_user_id"],
|
||||
twitch_user_name=data["chatter_user_name"],
|
||||
@@ -82,6 +83,34 @@ class CampaignComponent(cmds.Component):
|
||||
# TODO: Webhook logging maybe.. (do this in campaign)
|
||||
# Or just general logging. (also do this in campaign, but we can do again here)
|
||||
|
||||
# @cmds.Component.listener()
|
||||
async def event_message(self, payload):
|
||||
if not payload.text.startswith("%reward%"):
|
||||
return
|
||||
|
||||
community = await self.bot.profiles.fetch_community(payload.broadcaster)
|
||||
cid = community.communityid
|
||||
profile = await self.bot.profiles.fetch_profile(payload.chatter)
|
||||
pid = profile.profileid
|
||||
campaigns = await self.campaigns.fetch_campaigns(cid)
|
||||
|
||||
for campaign in campaigns:
|
||||
reward_progress = len(await campaign.get_rewards())
|
||||
|
||||
if (
|
||||
campaign.row.target_rewards is None
|
||||
or reward_progress < campaign.row.target_rewards
|
||||
):
|
||||
# Add a reward to the database with the correct info.
|
||||
await campaign.add_reward(
|
||||
profileid=pid,
|
||||
earned_from=f"(MSG) User messaged in chat: {payload.text}",
|
||||
event_id=None,
|
||||
twitch_user_id=payload.chatter.id,
|
||||
twitch_user_name=payload.chatter.name,
|
||||
)
|
||||
await self.dispatch_update(campaign)
|
||||
|
||||
@cmds.Component.listener()
|
||||
async def event_safe_event_chat_notice_resub(self, payload):
|
||||
# Check that the end of the sub is past the threshold by adding duration to the previous sub
|
||||
@@ -136,9 +165,9 @@ class CampaignComponent(cmds.Component):
|
||||
reward_cap = campaign.row.target_rewards
|
||||
|
||||
if reward_cap is not None:
|
||||
response = f"{name}: {given} rewards earned out of {cap}!"
|
||||
response = "{name}: {given} rewards earned out of {cap}!"
|
||||
else:
|
||||
response = f"{name}: {given} rewards earned so far!"
|
||||
response = "{name}: {given} rewards earned so far!"
|
||||
formatted = response.format(
|
||||
name=campaign.row.campaign_name,
|
||||
given=rewards_earned,
|
||||
@@ -180,7 +209,9 @@ class CampaignComponent(cmds.Component):
|
||||
return
|
||||
|
||||
# Now can create
|
||||
campaign = await self.campaigns.create_campaign(cid, name, rewards)
|
||||
campaign = await self.campaigns.create_campaign(
|
||||
cid, name, target_rewards=rewards
|
||||
)
|
||||
|
||||
# Also start the campaign
|
||||
await campaign.start()
|
||||
@@ -230,9 +261,9 @@ class CampaignComponent(cmds.Component):
|
||||
reward_cap = campaign.row.target_rewards
|
||||
|
||||
if reward_cap is not None:
|
||||
response = f"Completed {name}: {given} rewards earned out of {cap}!"
|
||||
response = f"Completed {name}: {rewards_earned} rewards earned out of {reward_cap}!"
|
||||
else:
|
||||
response = f"Completed {name}: {given} rewards earned so far!"
|
||||
response = f"Completed {name}: {rewards_earned} rewards earned so far!"
|
||||
formatted = response.format(
|
||||
name=campaign.row.campaign_name,
|
||||
given=rewards_earned,
|
||||
@@ -246,7 +277,8 @@ class CampaignComponent(cmds.Component):
|
||||
async def cmd_campaign_reward(
|
||||
self,
|
||||
ctx: cmds.Context,
|
||||
user: twitchio.PartialUser,
|
||||
user: twitchio.User,
|
||||
*,
|
||||
reward_reason: str,
|
||||
):
|
||||
"""Manually reward a target user, adjusting their points."""
|
||||
|
||||
Reference in New Issue
Block a user