generated from HoloTech/holotech-plugin-template
(campaign): Add reward webhook logging
This commit is contained in:
+121
-3
@@ -6,22 +6,38 @@ from data import ORDER, Condition
|
||||
from data.conditions import NULL, condition
|
||||
from utils.lib import utc_now
|
||||
|
||||
from .lib import LOWER, asexpr
|
||||
from .lib import LOWER, asexpr, ThreadedWebhook
|
||||
from .data import (
|
||||
CampaignData,
|
||||
Campaign,
|
||||
EarnedReward,
|
||||
)
|
||||
from . import logger
|
||||
|
||||
|
||||
class RewardCampaign:
|
||||
def __init__(self, row: Campaign):
|
||||
self.row = row
|
||||
|
||||
self._webhook: ThreadedWebhook | None = None
|
||||
self._cached_webhookurl: str | None = None
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
return self.row.started_at is not None and self.row.completed_at is None
|
||||
|
||||
@property
|
||||
def webhook(self):
|
||||
if self._cached_webhookurl != self.row.logging_webhook_url:
|
||||
url = self._cached_webhookurl = self.row.logging_webhook_url
|
||||
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)
|
||||
else:
|
||||
self._webhook = None
|
||||
return self._webhook
|
||||
|
||||
async def start(self):
|
||||
"""Start the reward campaign."""
|
||||
if self.row.started_at is not None:
|
||||
@@ -53,15 +69,103 @@ class RewardCampaign:
|
||||
twitch_user_name=twitch_user_name,
|
||||
earned_at=earned_at or utc_now(),
|
||||
)
|
||||
await self.try_to_log_reward(row)
|
||||
|
||||
return row
|
||||
|
||||
async def update_reward(self, rewardid: int, **kwargs):
|
||||
# In particular, log or update the logged message
|
||||
if kwargs:
|
||||
reward = await EarnedReward.fetch(rewardid)
|
||||
if reward is None:
|
||||
raise ValueError("Reward doesn't exist")
|
||||
await reward.update(**kwargs)
|
||||
await self.try_to_log_reward(reward)
|
||||
|
||||
async def get_rewards(self) -> list[EarnedReward]:
|
||||
rows = await EarnedReward.fetch_where(
|
||||
campaign_id=self.row.campaign_id
|
||||
).order_by("earned_at", direction=ORDER.ASC)
|
||||
return rows
|
||||
|
||||
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:
|
||||
# Try and edit message
|
||||
try:
|
||||
await self.webhook.edit_message(reward.log_messageid, embed=embed)
|
||||
except discord.HTTPException:
|
||||
await reward.update(log_messageid=None)
|
||||
if not reward.log_messageid:
|
||||
try:
|
||||
message = await self.webhook.send(embed=embed, wait=True)
|
||||
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)
|
||||
|
||||
async def _log_format_reward(self, reward: EarnedReward):
|
||||
"""
|
||||
Quick and ugly embed format for the webhook.
|
||||
"""
|
||||
import discord
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"Reward #{reward.earned_id} in {self.row.campaign_name}",
|
||||
)
|
||||
# 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"Internal ID `{reward.profileid}`"
|
||||
),
|
||||
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
|
||||
)
|
||||
|
||||
# Reference field
|
||||
embed.add_field(
|
||||
name="Reference",
|
||||
value=reward.reference or "No Reference information saved.",
|
||||
inline=False
|
||||
)
|
||||
# Modnote field
|
||||
embed.add_field(
|
||||
name="Notes",
|
||||
value=reward.modnote or "No notes added",
|
||||
inline=False
|
||||
)
|
||||
|
||||
# Fulfilled field
|
||||
if reward.fulfilled_at is not None:
|
||||
fluffed = f"Fluffed at {discord.utils.format_dt(reward.fulfilled_at, 'F')}"
|
||||
if reward.fulfilled_note:
|
||||
fluffed += '\n' + "Fluff Note: " + reward.fulfilled_note
|
||||
else:
|
||||
fluffed = "Not yet fluffed"
|
||||
|
||||
embed.add_field(
|
||||
name="Fulfilled",
|
||||
value=fluffed
|
||||
)
|
||||
|
||||
embed.set_footer(text="Last Updated")
|
||||
embed.timestamp = utc_now()
|
||||
|
||||
return embed
|
||||
|
||||
|
||||
class CampaignRegistry:
|
||||
VERSION = CampaignData.VERSION
|
||||
@@ -132,7 +236,7 @@ class CampaignRegistry:
|
||||
self,
|
||||
cid: int,
|
||||
campaign_name: str,
|
||||
target_rewards: Optional[int] = None,
|
||||
**kwargs
|
||||
) -> RewardCampaign:
|
||||
"""
|
||||
Create a new campaign.
|
||||
@@ -140,7 +244,21 @@ class CampaignRegistry:
|
||||
"""
|
||||
row = await Campaign.create(
|
||||
communityid=cid,
|
||||
target_rewards=target_rewards,
|
||||
campaign_name=campaign_name,
|
||||
**kwargs
|
||||
)
|
||||
return RewardCampaign(row)
|
||||
|
||||
async def update_campaign(
|
||||
self,
|
||||
campaign_id: int,
|
||||
**kwargs
|
||||
) -> RewardCampaign:
|
||||
"""
|
||||
Update a campaign with the given data args.
|
||||
|
||||
Registry handles this for caching and dispatch reasons.
|
||||
"""
|
||||
campaign = await Campaign.fetch(campaign_id)
|
||||
await campaign.update(**kwargs)
|
||||
return RewardCampaign(campaign)
|
||||
|
||||
Reference in New Issue
Block a user