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 data.conditions import NULL, condition
|
||||||
from utils.lib import utc_now
|
from utils.lib import utc_now
|
||||||
|
|
||||||
from .lib import LOWER, asexpr
|
from .lib import LOWER, asexpr, ThreadedWebhook
|
||||||
from .data import (
|
from .data import (
|
||||||
CampaignData,
|
CampaignData,
|
||||||
Campaign,
|
Campaign,
|
||||||
EarnedReward,
|
EarnedReward,
|
||||||
)
|
)
|
||||||
|
from . import logger
|
||||||
|
|
||||||
|
|
||||||
class RewardCampaign:
|
class RewardCampaign:
|
||||||
def __init__(self, row: Campaign):
|
def __init__(self, row: Campaign):
|
||||||
self.row = row
|
self.row = row
|
||||||
|
|
||||||
|
self._webhook: ThreadedWebhook | None = None
|
||||||
|
self._cached_webhookurl: str | None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
return self.row.started_at is not None and self.row.completed_at is None
|
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):
|
async def start(self):
|
||||||
"""Start the reward campaign."""
|
"""Start the reward campaign."""
|
||||||
if self.row.started_at is not None:
|
if self.row.started_at is not None:
|
||||||
@@ -53,15 +69,103 @@ class RewardCampaign:
|
|||||||
twitch_user_name=twitch_user_name,
|
twitch_user_name=twitch_user_name,
|
||||||
earned_at=earned_at or utc_now(),
|
earned_at=earned_at or utc_now(),
|
||||||
)
|
)
|
||||||
|
await self.try_to_log_reward(row)
|
||||||
|
|
||||||
return 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]:
|
async def get_rewards(self) -> list[EarnedReward]:
|
||||||
rows = await EarnedReward.fetch_where(
|
rows = await EarnedReward.fetch_where(
|
||||||
campaign_id=self.row.campaign_id
|
campaign_id=self.row.campaign_id
|
||||||
).order_by("earned_at", direction=ORDER.ASC)
|
).order_by("earned_at", direction=ORDER.ASC)
|
||||||
return rows
|
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:
|
class CampaignRegistry:
|
||||||
VERSION = CampaignData.VERSION
|
VERSION = CampaignData.VERSION
|
||||||
@@ -132,7 +236,7 @@ class CampaignRegistry:
|
|||||||
self,
|
self,
|
||||||
cid: int,
|
cid: int,
|
||||||
campaign_name: str,
|
campaign_name: str,
|
||||||
target_rewards: Optional[int] = None,
|
**kwargs
|
||||||
) -> RewardCampaign:
|
) -> RewardCampaign:
|
||||||
"""
|
"""
|
||||||
Create a new campaign.
|
Create a new campaign.
|
||||||
@@ -140,7 +244,21 @@ class CampaignRegistry:
|
|||||||
"""
|
"""
|
||||||
row = await Campaign.create(
|
row = await Campaign.create(
|
||||||
communityid=cid,
|
communityid=cid,
|
||||||
target_rewards=target_rewards,
|
|
||||||
campaign_name=campaign_name,
|
campaign_name=campaign_name,
|
||||||
|
**kwargs
|
||||||
)
|
)
|
||||||
return RewardCampaign(row)
|
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