Add support for "badge or emote" Twitch campaigns
This commit is contained in:
1 parent
b6a183b1e7
commit
cbc8482b53
1 file changed
+29
-3
+29
-3
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import math
|
import math
|
||||||
|
from enum import Enum
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
@@ -27,13 +28,28 @@ def remove_dimensions(url: URLType) -> URLType:
|
|||||||
return URLType(DIMS_PATTERN.sub('', url))
|
return URLType(DIMS_PATTERN.sub('', url))
|
||||||
|
|
||||||
|
|
||||||
|
class BenefitType(Enum):
|
||||||
|
UNKNOWN = "UNKNOWN"
|
||||||
|
BADGE = "BADGE"
|
||||||
|
EMOTE = "EMOTE"
|
||||||
|
DIRECT_ENTITLEMENT = "DIRECT_ENTITLEMENT"
|
||||||
|
|
||||||
|
def is_badge_or_emote(self) -> bool:
|
||||||
|
return self in (BenefitType.BADGE, BenefitType.EMOTE)
|
||||||
|
|
||||||
|
|
||||||
class Benefit:
|
class Benefit:
|
||||||
__slots__ = ("id", "name", "image_url")
|
__slots__ = ("id", "name", "type", "image_url")
|
||||||
|
|
||||||
def __init__(self, data: JsonType):
|
def __init__(self, data: JsonType):
|
||||||
benefit_data: JsonType = data["benefit"]
|
benefit_data: JsonType = data["benefit"]
|
||||||
self.id: str = benefit_data["id"]
|
self.id: str = benefit_data["id"]
|
||||||
self.name: str = benefit_data["name"]
|
self.name: str = benefit_data["name"]
|
||||||
|
self.type: BenefitType = (
|
||||||
|
BenefitType(benefit_data["distributionType"])
|
||||||
|
if benefit_data["distributionType"] in BenefitType.__members__.values()
|
||||||
|
else BenefitType.UNKNOWN
|
||||||
|
)
|
||||||
self.image_url: URLType = benefit_data["imageAssetURL"]
|
self.image_url: URLType = benefit_data["imageAssetURL"]
|
||||||
|
|
||||||
|
|
||||||
@@ -342,6 +358,16 @@ class DropsCampaign:
|
|||||||
def total_drops(self) -> int:
|
def total_drops(self) -> int:
|
||||||
return len(self.timed_drops)
|
return len(self.timed_drops)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def eligible(self) -> bool:
|
||||||
|
return self.linked or self.has_badge_or_emote
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def has_badge_or_emote(self) -> bool:
|
||||||
|
return any(
|
||||||
|
benefit.type.is_badge_or_emote() for drop in self.drops for benefit in drop.benefits
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def finished(self) -> bool:
|
def finished(self) -> bool:
|
||||||
return all(d.is_claimed for d in self.drops)
|
return all(d.is_claimed for d in self.drops)
|
||||||
@@ -385,7 +411,7 @@ class DropsCampaign:
|
|||||||
|
|
||||||
def _base_can_earn(self, channel: Channel | None = None) -> bool:
|
def _base_can_earn(self, channel: Channel | None = None) -> bool:
|
||||||
return (
|
return (
|
||||||
self.linked # account is connected
|
self.eligible # account is eligible
|
||||||
and self.active # campaign is active
|
and self.active # campaign is active
|
||||||
# channel isn't specified, or there's no ACL, or the channel is in the ACL
|
# channel isn't specified, or there's no ACL, or the channel is in the ACL
|
||||||
and (channel is None or not self.allowed_channels or channel in self.allowed_channels)
|
and (channel is None or not self.allowed_channels or channel in self.allowed_channels)
|
||||||
@@ -399,7 +425,7 @@ class DropsCampaign:
|
|||||||
# Same as can_earn, but doesn't check the channel
|
# Same as can_earn, but doesn't check the channel
|
||||||
# and uses a future timestamp to see if we can earn this campaign later
|
# and uses a future timestamp to see if we can earn this campaign later
|
||||||
return (
|
return (
|
||||||
self.linked
|
self.eligible
|
||||||
and self.ends_at > datetime.now(timezone.utc)
|
and self.ends_at > datetime.now(timezone.utc)
|
||||||
and self.starts_at < stamp
|
and self.starts_at < stamp
|
||||||
and any(drop.can_earn_within(stamp) for drop in self.drops)
|
and any(drop.can_earn_within(stamp) for drop in self.drops)
|
||||||
|
|||||||
Reference in new issue
Block a user