Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/twitchio/models.py
7774 views
"""1The MIT License (MIT)23Copyright (c) 2017-2021 TwitchIO45Permission is hereby granted, free of charge, to any person obtaining a6copy of this software and associated documentation files (the "Software"),7to deal in the Software without restriction, including without limitation8the rights to use, copy, modify, merge, publish, distribute, sublicense,9and/or sell copies of the Software, and to permit persons to whom the10Software is furnished to do so, subject to the following conditions:1112The above copyright notice and this permission notice shall be included in13all copies or substantial portions of the Software.1415THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS16OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER21DEALINGS IN THE SOFTWARE.22"""2324import datetime25from typing import Optional, Union, TYPE_CHECKING, List, Dict2627from . import enums28from .utils import parse_timestamp29from .user import BitLeaderboardUser, PartialUser, User3031if TYPE_CHECKING:32from .http import TwitchHTTP333435__all__ = (36"BitsLeaderboard",37"Clip",38"CheerEmote",39"CheerEmoteTier",40"HypeTrainContribution",41"HypeTrainEvent",42"BanEvent",43"FollowEvent",44"SubscriptionEvent",45"Marker",46"VideoMarkers",47"Game",48"ModEvent",49"AutomodCheckMessage",50"AutomodCheckResponse",51"Extension",52"MaybeActiveExtension",53"ActiveExtension",54"ExtensionBuilder",55"Video",56"Tag",57"WebhookSubscription",58"Prediction",59"Predictor",60"PredictionOutcome",61"Schedule",62"ScheduleSegment",63"ScheduleCategory",64"ScheduleVacation",65"Stream",66"Team",67"ChannelTeams",68"ChannelInfo",69)707172class BitsLeaderboard:73"""74Represents a Bits leaderboard from the twitch API.7576Attributes77------------78started_at: datetime.datetime79The time the leaderboard started.80ended_at: datetime.datetime81The time the leaderboard ended.82leaders: List[:class:`BitLeaderboardUser`]83The current leaders of the Leaderboard.84"""8586__slots__ = "_http", "leaders", "started_at", "ended_at"8788def __init__(self, http: "TwitchHTTP", data: dict):89self._http = http90self.started_at = datetime.datetime.fromisoformat(data["date_range"]["started_at"])91self.ended_at = datetime.datetime.fromisoformat(data["date_range"]["ended_at"])92self.leaders = [BitLeaderboardUser(http, x) for x in data["data"]]9394def __repr__(self):95return f"<BitsLeaderboard started_at={self.started_at} ended_at={self.ended_at}>"969798class CheerEmoteTier:99100__slots__ = "min_bits", "id", "colour", "images", "can_cheer", "show_in_bits_card"101102def __init__(self, data: dict):103self.min_bits: int = data["min_bits"]104self.id: str = data["id"]105self.colour: str = data["colour"]106self.images = data["images"]107self.can_cheer: bool = data["can_cheer"]108self.show_in_bits_card: bool = data["show_in_bits_card"]109110def __repr__(self):111return f"<CheerEmoteTier id={self.id} min_bits={self.min_bits}>"112113114class CheerEmote:115116__slots__ = "_http", "prefix", "tiers", "type", "order", "last_updated", "charitable"117118def __init__(self, http: "TwitchHTTP", data: dict):119self._http = http120self.prefix: str = data["prefix"]121self.tiers = [CheerEmoteTier(x) for x in data["tiers"]]122self.type: str = data["type"]123self.order: str = data["order"]124self.last_updated = parse_timestamp(data["last_updated"])125self.charitable: bool = data["is_charitable"]126127def __repr__(self):128return f"<CheerEmote prefix={self.prefix} type={self.type} order={self.order}>"129130131class Clip:132133__slots__ = (134"id",135"url",136"embed_url",137"broadcaster",138"creator",139"video_id",140"game_id",141"language",142"title",143"views",144"created_at",145"thumbnail_url",146)147148def __init__(self, http: "TwitchHTTP", data: dict):149self.id = data["id"]150self.url = data["url"]151self.embed_url = data["embed_url"]152self.broadcaster = PartialUser(http, data["broadcaster_id"], data["broadcaster_name"])153self.creator = PartialUser(http, data["creator_id"], data["creator_name"])154self.video_id = data["video_id"]155self.game_id = data["game_id"]156self.language = data["language"]157self.title = data["title"]158self.views = data["view_count"]159self.created_at = parse_timestamp(data["created_at"])160self.thumbnail_url = data["thumbnail_url"]161162def __repr__(self):163return f"<Clip id={self.id} broadcaster={self.broadcaster} creator={self.creator}>"164165166class HypeTrainContribution:167168__slots__ = "total", "type", "user"169170def __init__(self, http: "TwitchHTTP", data: dict):171self.total: int = data["total"]172self.type: str = data["type"]173self.user = PartialUser(http, id=data["user"], name=None) # we'll see how this goes174175def __repr__(self):176return f"<HypeTrainContribution total={self.total} type={self.type} user={self.user}>"177178179class HypeTrainEvent:180181__slots__ = (182"id",183"type",184"timestamp",185"version",186"broadcaster",187"expiry",188"event_id",189"goal",190"level",191"started_at",192"top_contributions",193"contributions_total",194"cooldown_end_time",195"last_contribution",196)197198def __init__(self, http: "TwitchHTTP", data: dict):199self.id: str = data["id"]200self.event_id: str = data["event_data"]["id"]201self.type: str = data["event_type"]202self.version: str = data["version"]203self.broadcaster = PartialUser(http, id=data["event_data"]["broadcaster_id"], name=None)204self.timestamp = parse_timestamp(data["event_timestamp"])205self.cooldown_end_time = parse_timestamp(data["event_data"]["cooldown_end_time"])206self.expiry = parse_timestamp(data["expires_at"])207self.started_at = parse_timestamp(data["event_data"]["started_at"])208self.last_contribution = HypeTrainContribution(http, data["event_data"]["last_contribution"])209self.level: int = data["event_data"]["level"]210self.top_contributions = [HypeTrainContribution(http, x) for x in data["event_data"]["top_contributions"]]211self.contributions_total: int = data["event_data"]["total"]212213def __repr__(self):214return f"<HypeTrainEvent id={self.id} type={self.type} level={self.level} broadcaster={self.broadcaster}>"215216217class BanEvent:218219__slots__ = "id", "type", "timestamp", "version", "broadcaster", "user", "expires_at"220221def __init__(self, http: "TwitchHTTP", data: dict, broadcaster: Optional[Union[PartialUser, User]]):222self.id: str = data["id"]223self.type: str = data["event_type"]224self.timestamp = parse_timestamp(data["event_timestamp"])225self.version: float = float(data["version"])226self.broadcaster = broadcaster or PartialUser(227http, data["event_data"]["broadcaster_id"], data["event_data"]["broadcaster_name"]228)229self.user = PartialUser(http, data["event_data"]["user_id"], data["event_data"]["user_name"])230self.expires_at = (231parse_timestamp(data["event_data"]["expires_at"]) if data["event_data"]["expires_at"] else None232)233234def __repr__(self):235return f"<BanEvent id={self.id} type={self.type} broadcaster={self.broadcaster} user={self.user}>"236237238class FollowEvent:239240__slots__ = "from_user", "to_user", "followed_at"241242def __init__(243self,244http: "TwitchHTTP",245data: dict,246from_: Union[User, PartialUser] = None,247to: Union[User, PartialUser] = None,248):249self.from_user = from_ or PartialUser(http, data["from_id"], data["from_name"])250self.to_user = to or PartialUser(http, data["to_id"], data["to_name"])251self.followed_at = parse_timestamp(data["followed_at"])252253def __repr__(self):254return f"<FollowEvent from_user={self.from_user} to_user={self.to_user} followed_at={self.followed_at}>"255256257class SubscriptionEvent:258259__slots__ = "broadcaster", "gift", "tier", "plan_name", "user"260261def __init__(262self,263http: "TwitchHTTP",264data: dict,265broadcaster: Union[User, PartialUser] = None,266user: Union[User, PartialUser] = None,267):268self.broadcaster = broadcaster or PartialUser(http, data["broadcaster_id"], data["broadcaster_name"])269self.user = user or PartialUser(http, data["user_id"], data["user_name"])270self.tier = int(data["tier"]) / 1000271self.plan_name: str = data["plan_name"]272self.gift: bool = data["is_gift"]273274def __repr__(self):275return (276f"<SubscriptionEvent broadcaster={self.broadcaster} user={self.user} tier={self.tier} "277f"plan_name={self.plan_name} gift={self.gift}>"278)279280281class Marker:282283__slots__ = "id", "created_at", "description", "position", "url"284285def __init__(self, data: dict):286self.id: int = data["id"]287self.created_at = parse_timestamp(data["created_at"])288self.description: str = data["description"]289self.position: int = data["position_seconds"]290self.url: Optional[str] = data.get("URL")291292def __repr__(self):293return f"<Marker id={self.id} created_at={self.created_at} position={self.position} url={self.url}>"294295296class VideoMarkers:297298__slots__ = "id", "markers"299300def __init__(self, data: dict):301self.id: str = data["video_id"]302self.markers = [Marker(d) for d in data]303304def __repr__(self):305return f"<VideoMarkers id={self.id}>"306307308class Game:309310__slots__ = "id", "name", "box_art_url"311312def __init__(self, data: dict):313self.id: int = int(data["id"])314self.name: str = data["name"]315self.box_art_url: str = data["box_art_url"]316317def __repr__(self):318return f"<Game id={self.id} name={self.name}>"319320def art_url(self, width: int, height: int) -> str:321"""322Adds width and height into the box art url323324Parameters325-----------326width: :class:`int`327The width of the image328height: :class:`int`329The height of the image330331Returns332--------333:class:`str`334"""335return self.box_art_url.format(width=width, height=height)336337338class ModEvent:339340__slots__ = "id", "type", "timestamp", "version", "broadcaster", "user"341342def __init__(self, http: "TwitchHTTP", data: dict, broadcaster: Union[PartialUser, User]):343self.id: int = data["id"]344self.type = enums.ModEventEnum(value=data["event_type"])345self.timestamp = parse_timestamp(data["event_timestamp"])346self.version: str = data["version"]347self.broadcaster = broadcaster348self.user = PartialUser(http, data["event_data"]["user_id"], data["event_data"]["user_name"])349350def __repr__(self):351return f"<ModEvent id={self.id} type={self.type} broadcaster={self.broadcaster} user={self.user}>"352353354class AutomodCheckMessage:355356__slots__ = "id", "text", "user_id"357358def __init__(self, id: str, text: str, user: Union[PartialUser, int]):359self.id = id360self.text = text361self.user_id = user.id if isinstance(user, PartialUser) else user362363def _to_dict(self):364return {"msg_id": self.id, "msg_text": self.text, "user_id": str(self.user_id)}365366def __repr__(self):367return f"<AutomodCheckMessage id={self.id} user_id={self.user_id}>"368369370class AutomodCheckResponse:371372__slots__ = "id", "permitted"373374def __init__(self, data: dict):375self.id: str = data["msg_id"]376self.permitted: bool = data["is_permitted"]377378def __repr__(self):379return f"<AutomodCheckResponse id={self.id} permitted={self.permitted}>"380381382class Extension:383384__slots__ = "id", "active", "version", "_x", "_y"385386def __init__(self, data):387self.id: str = data["id"]388self.version: str = data["version"]389self.active: bool = data["active"]390self._x = None391self._y = None392393def __repr__(self):394return f"<Extension id={self.id} version={self.version} active={self.active}>"395396@classmethod397def new(cls, active: bool, version: str, id: str, x: int = None, y: int = None) -> "Extension":398self = cls.__new__(cls)399self.active = active400self.version = version401self.id = id402self._x = x403self._y = y404return self405406def _to_dict(self):407v = {"active": self.active, "id": self.id, "version": self.version}408if self._x is not None:409v["x"] = self._x410if self._y is not None:411v["y"] = self._y412return v413414415class MaybeActiveExtension(Extension):416417__slots__ = "id", "version", "name", "can_activate", "types"418419def __init__(self, data):420self.id: str = data["id"]421self.version: str = data["version"]422self.name: str = data["name"]423self.can_activate: bool = data["can_activate"]424self.types: List[str] = data["type"]425426def __repr__(self):427return f"<MaybeActiveExtension id={self.id} version={self.version} name={self.name}>"428429430class ActiveExtension(Extension):431432__slots__ = "id", "active", "name", "version", "x", "y"433434def __init__(self, data):435self.active: bool = data["active"]436self.id: Optional[str] = data.get("id", None)437self.version: Optional[str] = data.get("version", None)438self.name: Optional[str] = data.get("name", None)439self.x: Optional[int] = data.get("x", None) # x and y only show for component extensions.440self.y: Optional[int] = data.get("y", None)441442def __repr__(self):443return f"<ActiveExtension id={self.id} version={self.version} name={self.name}>"444445446class ExtensionBuilder:447448__slots__ = "panels", "overlays", "components"449450def __init__(451self, panels: List[Extension] = None, overlays: List[Extension] = None, components: List[Extension] = None452):453self.panels = panels or []454self.overlays = overlays or []455self.components = components or []456457def _to_dict(self):458return {459"panel": {str(x): y._to_dict() for x, y in enumerate(self.panels)},460"overlay": {str(x): y._to_dict() for x, y in enumerate(self.overlays)},461"component": {str(x): y._to_dict() for x, y in enumerate(self.components)},462}463464465class Video:466467__slots__ = (468"_http",469"id",470"user",471"title",472"description",473"created_at",474"published_at",475"url",476"thumbnail_url",477"viewable",478"view_count",479"language",480"type",481"duration",482)483484def __init__(self, http: "TwitchHTTP", data: dict, user: Union[PartialUser, User] = None):485self._http = http486self.id: id = int(data["id"])487self.user = user or PartialUser(http, data["user_id"], data["user_name"])488self.title: str = data["title"]489self.description: str = data["description"]490self.created_at = parse_timestamp(data["created_at"])491self.published_at = parse_timestamp(data["published_at"])492self.url: str = data["url"]493self.thumbnail_url: str = data["thumbnail_url"]494self.viewable: str = data["viewable"]495self.view_count: int = data["view_count"]496self.language: str = data["language"]497self.type: str = data["type"]498self.duration: str = data["duration"]499500def __repr__(self):501return f"<Video id={self.id} title={self.title} url={self.url}>"502503async def delete(self, token: str):504"""|coro|505506Deletes the video. For bulk deletion see :func:`Client.delete_videos`507508Parameters509-----------510token: :class:`str`511The users oauth token with the channel:manage:videos512"""513await self._http.delete_videos(token, ids=[str(self.id)])514515516class Tag:517518__slots__ = "id", "auto", "localization_names", "localization_descriptions"519520def __init__(self, data: dict):521self.id: str = data["tag_id"]522self.auto: bool = data["is_auto"]523self.localization_names: Dict[str, str] = data["localization_names"]524self.localization_descriptions: Dict[str, str] = data["localization_descriptions"]525526def __repr__(self):527return f"<Tag id={self.id}>"528529530class WebhookSubscription:531532__slots__ = "callback", "expires_at", "topic"533534def __init__(self, data: dict):535self.callback: str = data["callback"]536self.expires_at = parse_timestamp(data["expired_at"])537self.topic: str = data["topic"]538539def __repr__(self):540return f"<WebhookSubscription callback={self.callback} topic={self.topic} expires_at={self.expires_at}>"541542543class Stream:544545__slots__ = (546"id",547"user",548"game_id",549"game_name",550"type",551"title",552"viewer_count",553"started_at",554"language",555"thumbnail_url",556"tag_ids",557"is_mature",558)559560def __init__(self, http: "TwitchHTTP", data: dict):561self.id: int = data["id"]562self.user = PartialUser(http, data["user_id"], data["user_name"])563self.game_id: int = data["game_id"]564self.game_name: str = data["game_name"]565self.type: str = data["type"]566self.title: str = data["title"]567self.viewer_count: int = data["viewer_count"]568self.started_at = parse_timestamp(data["started_at"])569self.language: str = data["language"]570self.thumbnail_url: str = data["thumbnail_url"]571self.tag_ids: List[str] = data["tag_ids"]572self.is_mature: bool = data["is_mature"]573574def __repr__(self):575return f"<Stream id={self.id} user={self.user} title={self.title} started_at={self.started_at}>"576577578class ChannelInfo:579580__slots__ = ("user", "game_id", "game_name", "title", "language", "delay")581582def __init__(self, http: "TwitchHTTP", data: dict):583self.user = PartialUser(http, data["broadcaster_id"], data["broadcaster_name"])584self.game_id: int = data["game_id"]585self.game_name: str = data["game_name"]586self.title: str = data["title"]587self.language: str = data["broadcaster_language"]588self.delay: int = data["delay"]589590def __repr__(self):591return f"<ChannelInfo user={self.user} game_id={self.game_id} game_name={self.game_name} title={self.title} language={self.language} delay={self.delay}>"592593594class Prediction:595596__slots__ = (597"user",598"prediction_id",599"title",600"winning_outcome_id",601"outcomes",602"prediction_window",603"prediction_status",604"created_at",605"ended_at",606"locked_at",607)608609def __init__(self, http: "TwitchHTTP", data: dict):610self.user = PartialUser(http, data["broadcaster_id"], data["broadcaster_name"])611self.prediction_id: str = data["id"]612self.title: str = data["title"]613self.winning_outcome_id: str = data["winning_outcome_id"]614self.outcomes: List[PredictionOutcome] = [PredictionOutcome(http, x) for x in data["outcomes"]]615self.prediction_window: int = data["prediction_window"]616self.prediction_status: str = data["status"]617self.created_at = self._parse_time(data, "created_at")618self.ended_at = self._parse_time(data, "ended_at")619self.locked_at = self._parse_time(data, "locked_at")620621def _parse_time(self, data, field) -> Optional["Datetime"]:622if field not in data or data[field] is None:623return None624625time = data[field].split(".")[0]626return datetime.datetime.fromisoformat(time)627628def __repr__(self):629return f"<Prediction user={self.user} prediction_id={self.prediction_id} winning_outcome_id={self.winning_outcome_id} title={self.title}>"630631632class Predictor:633634__slots__ = ("outcome_id", "title", "channel_points", "color")635636def __init__(self, http: "TwitchHTTP", data: dict):637self.channel_points_used: int = data["channel_points_used"]638self.channel_points_won: int = data["channel_points_won"]639self.user = PartialUser(http, data["user"]["id"], data["user"]["name"])640641642class PredictionOutcome:643644__slots__ = ("outcome_id", "title", "channel_points", "color", "users", "top_predictors")645646def __init__(self, http: "TwitchHTTP", data: dict):647self.outcome_id: str = data["id"]648self.title: str = data["title"]649self.channel_points: int = data["channel_points"]650self.color: str = data["color"]651self.users: int = data["users"]652if data["top_predictors"]:653self.top_predictors: List[Predictor] = [Predictor(http, x) for x in data["top_predictors"]]654else:655self.top_predictors: List[Predictor] = None656657@property658def colour(self) -> str:659"""The colour of the prediction. Alias to color."""660return self.color661662def __repr__(self):663return f"<PredictionOutcome outcome_id={self.outcome_id} title={self.title} channel_points={self.channel_points} color={self.color}>"664665666class Schedule:667668__slots__ = ("segments", "user", "vacation")669670def __init__(self, http: "TwitchHTTP", data: dict):671self.segments = [ScheduleSegment(d) for d in data["data"]["segments"]]672self.user = PartialUser(http, data["data"]["broadcaster_id"], data["data"]["broadcaster_login"])673self.vacation = ScheduleVacation(data["data"]["vacation"]) if data["data"]["vacation"] else None674675def __repr__(self):676return f"<Schedule segments={self.segments} user={self.user} vacation={self.vacation}>"677678679class ScheduleSegment:680681__slots__ = ("id", "start_time", "end_time", "title", "canceled_until", "category", "is_recurring")682683def __init__(self, data: dict):684self.id: str = data["id"]685self.start_time = parse_timestamp(data["start_time"])686self.end_time = parse_timestamp(data["end_time"])687self.title: str = data["title"]688self.canceled_until = parse_timestamp(data["canceled_until"]) if data["canceled_until"] else None689self.category = ScheduleCategory(data["category"]) if data["category"] else None690self.is_recurring: bool = data["is_recurring"]691692def __repr__(self):693return f"<Segment id={self.id} start_time={self.start_time} end_time={self.end_time} title={self.title} canceled_until={self.canceled_until} category={self.category} is_recurring={self.is_recurring}>"694695696class ScheduleCategory:697698__slots__ = ("id", "name")699700def __init__(self, data: dict):701self.id: str = data["id"]702self.name: str = data["name"]703704def __repr__(self):705return f"<ScheduleCategory id={self.id} name={self.name}>"706707708class ScheduleVacation:709710__slots__ = ("start_time", "end_time")711712def __init__(self, data: dict):713self.start_time = parse_timestamp(data["start_time"])714self.end_time = parse_timestamp(data["end_time"])715716def __repr__(self):717return f"<ScheduleVacation start_time={self.start_time} end_time={self.end_time}>"718719720class Team:721722__slots__ = (723"users",724"background_image_url",725"banner",726"created_at",727"updated_at",728"info",729"thumbnail_url",730"team_name",731"team_display_name",732"id",733)734735def __init__(self, http: "TwitchHTTP", data: dict):736737self.users: List[PartialUser] = [PartialUser(http, x["user_id"], x["user_login"]) for x in data["users"]]738self.background_image_url = data["background_image_url"]739self.banner = data["banner"]740self.created_at = parse_timestamp(data["created_at"].split(" ")[0])741self.updated_at = parse_timestamp(data["updated_at"].split(" ")[0])742self.info = data["info"]743self.thumbnail_url = data["thumbnail_url"]744self.team_name = data["team_name"]745self.team_display_name = data["team_display_name"]746self.id = data["id"]747748def __repr__(self):749return f"<Team users={self.users} team_name={self.team_name} team_display_name={self.team_display_name} id={self.id} created_at={self.created_at}>"750751752class ChannelTeams:753754__slots__ = (755"broadcaster",756"background_image_url",757"banner",758"created_at",759"updated_at",760"info",761"thumbnail_url",762"team_name",763"team_display_name",764"id",765)766767def __init__(self, http: "TwitchHTTP", data: dict):768769self.broadcaster: PartialUser = PartialUser(http, data["broadcaster_id"], data["broadcaster_login"])770self.background_image_url = data["background_image_url"]771self.banner = data["banner"]772self.created_at = parse_timestamp(data["created_at"].split(" ")[0])773self.updated_at = parse_timestamp(data["updated_at"].split(" ")[0])774self.info = data["info"]775self.thumbnail_url = data["thumbnail_url"]776self.team_name = data["team_name"]777self.team_display_name = data["team_display_name"]778self.id = data["id"]779780def __repr__(self):781return f"<ChannelTeams user={self.broadcaster} team_name={self.team_name} team_display_name={self.team_display_name} id={self.id} created_at={self.created_at}>"782783784