diff --git a/README.md b/README.md index 4ba7c93..1fe21d0 100644 --- a/README.md +++ b/README.md @@ -179,8 +179,9 @@ import logging from colorama import Fore from TwitchChannelPointsMiner import TwitchChannelPointsMiner from TwitchChannelPointsMiner.logger import LoggerSettings, ColorPalette -from TwitchChannelPointsMiner.classes.Settings import Priority -from TwitchChannelPointsMiner.classes.entities.Bet import Strategy, BetSettings, Condition, OutcomeKeys, FilterCondition, DelayMode +from TwitchChannelPointsMiner.classes.Telegram import Telegram +from TwitchChannelPointsMiner.classes.Settings import Priority, Events +from TwitchChannelPointsMiner.classes.entities.Bet import Strategy, BetSettings, Condition, OutcomeKeys, FilterCondition from TwitchChannelPointsMiner.classes.entities.Streamer import Streamer, StreamerSettings twitch_miner = TwitchChannelPointsMiner( @@ -203,6 +204,12 @@ twitch_miner = TwitchChannelPointsMiner( STREAMER_online="GREEN", # Don't worry about lower/upper case. The script will parse all the values. streamer_offline="red", # Read more in README.md BET_wiN=Fore.MAGENTA # Color allowed are: [BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET]. + ), + telegram=Telegram( + chat_id=123456789, # Chat ID to send messages @GiveChatId + token="123456789:shfuihreuifheuifhiu34578347", # Telegram API token @BotFather + events=[Events.STREAMER_ONLINE, Events.STREAMER_OFFLINE, "BET_LOSE"], # Only these events will be sent to the chat + disable_notification=True, # Revoke the notification (sound/vibration) ) ), streamer_settings=StreamerSettings( @@ -217,9 +224,7 @@ twitch_miner = TwitchChannelPointsMiner( percentage_gap=20, # Gap difference between outcomesA and outcomesB (for SMART stragegy) max_points=50000, # If the x percentage of your channel points is gt bet_max_points set this value stealth_mode=True, # If the calculated amount of channel points is GT the highest bet, place the highest value minus 1-2 points #33 - delay_mode=DelayMode.FROM_END, # When placing a bet, we will wait until `delay` seconds before the end of the timer - delay=6, - filter_condition=FilterCondition( + filter_condition=FilterCondition( by=OutcomeKeys.TOTAL_USERS, # Where apply the filter. Allowed [PERCENTAGE_USERS, ODDS_PERCENTAGE, ODDS, TOP_POINTS, TOTAL_USERS, TOTAL_POINTS] where=Condition.LTE, # 'by' must be [GT, LT, GTE, LTE] than value value=800 @@ -252,6 +257,7 @@ twitch_miner.mine( ], # Array of streamers (order = priority) followers=False # Automatic download the list of your followers (unable to set custom settings for you followers list) ) + ``` You can also use all the default values except for your username obv. Short version: ```python @@ -297,24 +303,10 @@ You can combine all priority but keep in mind that use `ORDER` and `POINTS_ASCEN | `emoji` | bool | For Windows is False else True | On Windows, we have a problem printing emoji. Set to false if you have a problem | | `colored` | bool | True | If you want to print colored text [#45](https://github.com/Tkd-Alex/Twitch-Channel-Points-Miner-v2/issues/45) [#82](https://github.com/Tkd-Alex/Twitch-Channel-Points-Miner-v2/issues/82) | | `color_palette` | ColorPalette | All messages are Fore.RESET except WIN and LOSE bet (GREEN and RED) | Create your custom color palette. Read more above. | +| `telegram` | Telegram | None | Receive Telegram updates for multiple events list [#233](https://github.com/Tkd-Alex/Twitch-Channel-Points-Miner-v2/issues/233) | #### Color Palette -Now you can customize the color of the terminal message. We have created a default ColorPalette that provide all the message with `DEFAULT (RESET)` color and the `BET_WIN` and `BET_LOSE` message `GREEN` and `RED` respectively. -Currently you can only change the following types of messages: - - `STREAMER_ONLINE` - - `STREAMER_OFFLINE` - - `GAIN_FOR_RAID` - - `GAIN_FOR_CLAIM` - - `GAIN_FOR_WATCH` - - `BET_WIN` - - `BET_LOSE` - - `BET_REFUND` - - `BET_FILTERS` - - `BET_GENERAL` - - `BET_FAILED` - - `BET_START` - -The colors allowed are all the Fore color from Colorama: `BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.` +Now you can customize the color of the terminal message. We have created a default ColorPalette that provide all the message with `DEFAULT (RESET)` color and the `BET_WIN` and `BET_LOSE` message `GREEN` and `RED` respectively. You can change the colors of all `Events` enum class. The colors allowed are all the Fore color from Colorama: `BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.` The script was developed to handle all the human error, lower-case upper case and more, but I want to suggest using the following code-style ```python from colorama import Fore @@ -334,6 +326,46 @@ ColorPalette( ) ``` +#### Telegram +Receive logs update on Telegram. +1. Create a bot with [BotFather](https://t.me/botfather) +2. Get you `chat_id` with [GiveChatId](https://t.me/GiveChatId_Bot) + +| Key | Type | Default | Description | +|----------------------- |----------------- |--------- |------------------------------------------------------------------- | +| `chat_id` | int | | Chat ID to send messages @GiveChatId | +| `token` | string | | Telegram API token @BotFather | +| `events` | list | | Only these events will be sent to the chat. Array of Event. or str | +| `disable_notification` | bool | false | Revoke the notification (sound/vibration) | + + +```python +Telegram( + chat_id=123456789, + token="123456789:shfuihreuifheuifhiu34578347", + events=[Events.STREAMER_ONLINE, Events.STREAMER_OFFLINE, "BET_LOSE"], + disable_notification=True, +) +``` + +#### Events + - `STREAMER_ONLINE` + - `STREAMER_OFFLINE` + - `GAIN_FOR_RAID` + - `GAIN_FOR_CLAIM` + - `GAIN_FOR_WATCH` + - `BET_WIN` + - `BET_LOSE` + - `BET_REFUND` + - `BET_FILTERS` + - `BET_GENERAL` + - `BET_FAILED` + - `BET_START` + - `BONUS_CLAIM` + - `JOIN_RAID` + - `DROP_CLAIM` + - `DROP_STATUS` + ### StreamerSettings | Key | Type | Default | Description | |-------------------- |------------- |-------------------------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -350,9 +382,9 @@ ColorPalette( | `percentage_gap` | int | 20 | Gap difference between outcomesA and outcomesB (for SMART stragegy) | | `max_points` | int | 50000 | If the x percentage of your channel points is GT bet_max_points set this value | | `stealth_mode` | bool | False | If the calculated amount of channel points is GT the highest bet, place the highest value minus 1-2 points [#33](https://github.com/Tkd-Alex/Twitch-Channel-Points-Miner-v2/issues/33) | -| `join_chat` | bool | True | Join IRC-Chat to appear online in chat and attempt to get StreamElements channel points and increase view-time [#47](https://github.com/Tkd-Alex/Twitch-Channel-Points-Miner-v2/issues/47) | -| `delay_mode` | DelayMode | FROM_END | Define how is calculating the waiting time before placing a bet | -| `delay` | float | 6 | Value to be used to calculate bet delay depending on `delay_mode` value | +| `join_chat` | bool | True | Join IRC-Chat to appear online in chat and attempt to get StreamElements channel points and increase view-time [#47](https://github.com/Tkd-Alex/Twitch-Channel-Points-Miner-v2/issues/47) | +| `delay_mode` | DelayMode | FROM_END | Define how is calculating the waiting time before placing a bet | +| `delay` | float | 6 | Value to be used to calculate bet delay depending on `delay_mode` value | #### Bet strategy diff --git a/TwitchChannelPointsMiner/classes/Settings.py b/TwitchChannelPointsMiner/classes/Settings.py index c4a550f..739fe4b 100644 --- a/TwitchChannelPointsMiner/classes/Settings.py +++ b/TwitchChannelPointsMiner/classes/Settings.py @@ -13,3 +13,26 @@ class Priority(Enum): # Empty object shared between class class Settings(object): __slots__ = ["logger", "streamer_settings"] + + +class Events(Enum): + STREAMER_ONLINE = auto() + STREAMER_OFFLINE = auto() + GAIN_FOR_RAID = auto() + GAIN_FOR_CLAIM = auto() + GAIN_FOR_WATCH = auto() + GAIN_FOR_WATCH_STREAK = auto() + BET_WIN = auto() + BET_LOSE = auto() + BET_REFUND = auto() + BET_FILTERS = auto() + BET_GENERAL = auto() + BET_FAILED = auto() + BET_START = auto() + BONUS_CLAIM = auto() + JOIN_RAID = auto() + DROP_CLAIM = auto() + DROP_STATUS = auto() + + def __str__(self): + return self.name diff --git a/TwitchChannelPointsMiner/classes/Telegram.py b/TwitchChannelPointsMiner/classes/Telegram.py new file mode 100644 index 0000000..bd608b3 --- /dev/null +++ b/TwitchChannelPointsMiner/classes/Telegram.py @@ -0,0 +1,29 @@ +from textwrap import dedent + +import requests + +from TwitchChannelPointsMiner.classes.settings import Events + + +class Telegram(object): + __slots__ = ["chat_id", "telegram_api", "events", "disable_notification"] + + def __init__( + self, chat_id: int, token: str, events: list, disable_notification: bool = False + ): + self.chat_id = chat_id + self.telegram_api = f"https://api.telegram.org/bot{token}/sendMessage" + self.events = [str(e) for e in events] + self.disable_notification = disable_notification + + def send(self, message: str, event: Events) -> None: + if str(event) in self.events: + requests.post( + url=self.telegram_api, + data={ + "chat_id": self.chat_id, + "text": dedent(message), + "disable_web_page_preview": True, # include link to twitch streamer? + "disable_notification": self.disable_notification, # no sound, notif just in tray + }, + ) diff --git a/TwitchChannelPointsMiner/classes/Twitch.py b/TwitchChannelPointsMiner/classes/Twitch.py index 94aa0b0..cead486 100644 --- a/TwitchChannelPointsMiner/classes/Twitch.py +++ b/TwitchChannelPointsMiner/classes/Twitch.py @@ -10,7 +10,6 @@ import os import random import re import time -from textwrap import dedent from pathlib import Path from secrets import token_hex @@ -22,14 +21,13 @@ from TwitchChannelPointsMiner.classes.Exceptions import ( StreamerDoesNotExistException, StreamerIsOfflineException, ) -from TwitchChannelPointsMiner.classes.Settings import Priority, Settings +from TwitchChannelPointsMiner.classes.Settings import Events, Priority, Settings from TwitchChannelPointsMiner.classes.TwitchLogin import TwitchLogin from TwitchChannelPointsMiner.constants import API, CLIENT_ID, GQLOperations from TwitchChannelPointsMiner.utils import ( _millify, create_chunks, internet_connection_available, - post_telegram, ) logger = logging.getLogger(__name__) @@ -182,7 +180,7 @@ class Twitch(object): logger.info( f"Joining raid from {streamer} to {raid.target_login}!", - extra={"emoji": ":performing_arts:"}, + extra={"emoji": ":performing_arts:", "event": Events.JOIN_RAID}, ) def viewer_is_mod(self, streamer): @@ -364,17 +362,22 @@ class Twitch(object): drop.has_preconditions_met is not False and drop.is_printable is True ): - log_message = dedent( - f""" - {streamers[index]} is streaming {streamers[index].stream} - Campaign: {campaign} - Drop: {drop} - {drop.progress_bar()} - """ + logger.info( + f"{streamers[index]} is streaming {streamers[index].stream}", + extra={"event": Events.DROP_STATUS}, + ) + logger.info( + f"Campaign: {campaign}", + extra={"event": Events.DROP_STATUS}, + ) + logger.info( + f"Drop: {drop}", + extra={"event": Events.DROP_STATUS}, + ) + logger.info( + f"{drop.progress_bar()}", + extra={"event": Events.DROP_STATUS}, ) - post_telegram(log_message) - for line in log_message.split("\n"): - logger.info(line) except requests.exceptions.ConnectionError as e: logger.error(f"Error while trying to send minute watched: {e}") @@ -417,7 +420,7 @@ class Twitch(object): f"Going to complete bet for {event}", extra={ "emoji": ":four_leaf_clover:", - "color": Settings.logger.color_palette.BET_GENERAL, + "event": Events.BET_GENERAL, }, ) if event.status == "ACTIVE": @@ -427,14 +430,14 @@ class Twitch(object): f"Skip betting for the event {event}", extra={ "emoji": ":pushpin:", - "color": Settings.logger.color_palette.BET_FILTERS, + "event": Events.BET_FILTERS, }, ) logger.info( f"Skip settings {event.bet.settings.filter_condition}, current value is: {compared_value}", extra={ "emoji": ":pushpin:", - "color": Settings.logger.color_palette.BET_FILTERS, + "event": Events.BET_FILTERS, }, ) else: @@ -443,7 +446,7 @@ class Twitch(object): f"Place {_millify(decision['amount'])} channel points on: {event.bet.get_outcome(selector_index)}", extra={ "emoji": ":four_leaf_clover:", - "color": Settings.logger.color_palette.BET_GENERAL, + "event": Events.BET_GENERAL, }, ) @@ -462,14 +465,15 @@ class Twitch(object): f"Oh no! The event is not active anymore! Current status: {event.status}", extra={ "emoji": ":disappointed_relieved:", - "color": Settings.logger.color_palette.BET_FAILED, + "event": Events.BET_FAILED, }, ) def claim_bonus(self, streamer, claim_id): if Settings.logger.less is False: logger.info( - f"Claiming the bonus for {streamer}!", extra={"emoji": ":gift:"} + f"Claiming the bonus for {streamer}!", + extra={"emoji": ":gift:", "event": Events.BONUS_CLAIM}, ) json_data = copy.deepcopy(GQLOperations.ClaimCommunityPoints) @@ -551,9 +555,9 @@ class Twitch(object): return campaigns def claim_drop(self, drop): - log_message = f"Claim {drop}" - post_telegram(log_message) - logger.info(log_message, extra={"emoji": ":package:"}) + logger.info( + f"Claim {drop}", extra={"emoji": ":package:", "event": Events.DROP_CLAIM} + ) json_data = copy.deepcopy(GQLOperations.DropsPage_ClaimDropRewards) json_data["variables"] = {"input": {"dropInstanceID": drop.drop_instance_id}} diff --git a/TwitchChannelPointsMiner/classes/WebSocketsPool.py b/TwitchChannelPointsMiner/classes/WebSocketsPool.py index 183f72e..aeedfd7 100644 --- a/TwitchChannelPointsMiner/classes/WebSocketsPool.py +++ b/TwitchChannelPointsMiner/classes/WebSocketsPool.py @@ -9,13 +9,12 @@ from dateutil import parser from TwitchChannelPointsMiner.classes.entities.EventPrediction import EventPrediction from TwitchChannelPointsMiner.classes.entities.Message import Message from TwitchChannelPointsMiner.classes.entities.Raid import Raid -from TwitchChannelPointsMiner.classes.Settings import Settings +from TwitchChannelPointsMiner.classes.Settings import Events from TwitchChannelPointsMiner.classes.TwitchWebSocket import TwitchWebSocket from TwitchChannelPointsMiner.constants import WEBSOCKET from TwitchChannelPointsMiner.utils import ( get_streamer_index, internet_connection_available, - post_telegram, ) logger = logging.getLogger(__name__) @@ -190,15 +189,11 @@ class WebSocketsPool: earned = message.data["point_gain"]["total_points"] reason_code = message.data["point_gain"]["reason_code"] - log_message = f"+{earned} → {ws.streamers[streamer_index]} - Reason: {reason_code}." - post_telegram(log_message) logger.info( - log_message, + f"+{earned} → {ws.streamers[streamer_index]} - Reason: {reason_code}.", extra={ "emoji": ":rocket:", - "color": Settings.logger.color_palette.get( - f"GAIN_FOR_{reason_code}" - ), + "event": Events.get(f"GAIN_FOR_{reason_code}"), }, ) ws.streamers[streamer_index].update_history( @@ -278,13 +273,11 @@ class WebSocketsPool: place_bet_thread.daemon = True place_bet_thread.start() - log_message = f"Place the bet after: {start_after}s for {ws.events_predictions[event_id]}" - post_telegram(log_message) logger.info( - log_message, + f"Place the bet after: {start_after}s for {ws.events_predictions[event_id]}", extra={ "emoji": ":alarm_clock:", - "color": Settings.logger.color_palette.BET_START, + "event": Events.BET_START, }, ) @@ -317,16 +310,14 @@ class WebSocketsPool: decision = event_prediction.bet.get_decision() choice = event_prediction.bet.decision["choice"] - log_message = ( - f"{event_prediction} - Decision: {choice}: {decision['title']} " - f"({decision['color']}) - Result: {event_prediction.result['string']}" - ) - post_telegram(log_message) logger.info( - log_message, + ( + f"{event_prediction} - Decision: {choice}: {decision['title']} " + f"({decision['color']}) - Result: {event_prediction.result['string']}" + ), extra={ "emoji": ":bar_chart:", - "color": Settings.logger.color_palette.get( + "event": Events.get( f"BET_{event_prediction.result['type']}" ), }, diff --git a/TwitchChannelPointsMiner/classes/entities/Streamer.py b/TwitchChannelPointsMiner/classes/entities/Streamer.py index c01cd79..f948e59 100644 --- a/TwitchChannelPointsMiner/classes/entities/Streamer.py +++ b/TwitchChannelPointsMiner/classes/entities/Streamer.py @@ -8,7 +8,7 @@ from threading import Lock from TwitchChannelPointsMiner.classes.Chat import ThreadChat from TwitchChannelPointsMiner.classes.entities.Bet import BetSettings, DelayMode from TwitchChannelPointsMiner.classes.entities.Stream import Stream -from TwitchChannelPointsMiner.classes.Settings import Settings +from TwitchChannelPointsMiner.classes.Settings import Events, Settings from TwitchChannelPointsMiner.constants import URL from TwitchChannelPointsMiner.utils import _millify @@ -122,7 +122,7 @@ class Streamer(object): f"{self} is Offline!", extra={ "emoji": ":sleeping:", - "color": Settings.logger.color_palette.STREAMER_OFFLINE, + "event": Events.STREAMER_OFFLINE, }, ) @@ -137,7 +137,7 @@ class Streamer(object): f"{self} is Online!", extra={ "emoji": ":partying_face:", - "color": Settings.logger.color_palette.STREAMER_ONLINE, + "event": Events.STREAMER_ONLINE, }, ) diff --git a/TwitchChannelPointsMiner/logger.py b/TwitchChannelPointsMiner/logger.py index 895e3fe..bfe49b4 100644 --- a/TwitchChannelPointsMiner/logger.py +++ b/TwitchChannelPointsMiner/logger.py @@ -7,13 +7,14 @@ from pathlib import Path import emoji from colorama import Fore, init +from TwitchChannelPointsMiner.classes.Settings import Events +from TwitchChannelPointsMiner.classes.Telegram import Telegram from TwitchChannelPointsMiner.utils import remove_emoji class GlobalFormatter(logging.Formatter): - def __init__(self, *, fmt, datefmt=None, print_emoji=True, print_colored=False): - self.print_emoji = print_emoji - self.print_colored = print_colored + def __init__(self, *, fmt, settings, datefmt=None): + self.settings = settings logging.Formatter.__init__(self, fmt=fmt, datefmt=datefmt) def format(self, record): @@ -22,7 +23,7 @@ class GlobalFormatter(logging.Formatter): ) if ( hasattr(record, "emoji") - and self.print_emoji is True + and self.settings.print_emoji is True and record.emoji_is_present is False ): record.msg = emoji.emojize( @@ -30,7 +31,7 @@ class GlobalFormatter(logging.Formatter): ) record.emoji_is_present = True - if self.print_emoji is False: + if self.settings.print_emoji is False: if "\u2192" in record.msg: record.msg = record.msg.replace("\u2192", "-->") @@ -38,31 +39,28 @@ class GlobalFormatter(logging.Formatter): # Full remove using a method from utils. record.msg = remove_emoji(record.msg) - if self.print_colored and hasattr(record, "color"): - record.msg = f"{record.color}{record.msg}" + if hasattr(record, "event"): + if self.settings.telegram is not None: + self.settings.telegram.send(record.msg, record.event) + + if self.settings.print_colored is True: + record.msg = ( + f"{self.settings.color_palette.get(record.event)}{record.msg}" + ) return super().format(record) # Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. class ColorPalette(object): - STREAMER_ONLINE = Fore.RESET - STREAMER_OFFLINE = Fore.RESET - - GAIN_FOR_RAID = Fore.RESET - GAIN_FOR_CLAIM = Fore.RESET - GAIN_FOR_WATCH = Fore.RESET - GAIN_FOR_WATCH_STREAK = Fore.RESET - - BET_WIN = Fore.GREEN - BET_LOSE = Fore.RED - BET_REFUND = Fore.RESET - BET_FILTERS = Fore.RESET - BET_GENERAL = Fore.RESET - BET_FAILED = Fore.RESET - BET_START = Fore.RESET - def __init__(self, **kwargs): + # Init with default values RESET for all and GREEN and RED only for WIN and LOSE bet + # Then set args from kwargs + for k in Events: + setattr(self, str(k), Fore.RESET) + setattr(self, "BET_WIN", Fore.GREEN) + setattr(self, "BET_LOSE", Fore.RED) + for k in kwargs: if k.upper() in dir(self) and getattr(self, k.upper()) is not None: if kwargs[k] in [ @@ -105,6 +103,7 @@ class LoggerSettings: emoji: bool = platform.system() != "Windows", colored: bool = False, color_palette: ColorPalette = ColorPalette(), + telegram: Telegram or None = None, ): self.save = save self.less = less @@ -113,6 +112,7 @@ class LoggerSettings: self.emoji = emoji self.colored = colored self.color_palette = color_palette + self.telegram = telegram def configure_loggers(username, settings): @@ -134,8 +134,7 @@ def configure_loggers(username, settings): datefmt=( "%d/%m/%y %H:%M:%S" if settings.less is False else "%d/%m %H:%M:%S" ), - print_emoji=settings.emoji, - print_colored=settings.colored, + settings=settings, ) ) diff --git a/TwitchChannelPointsMiner/utils.py b/TwitchChannelPointsMiner/utils.py index 4c136a2..ceaef57 100644 --- a/TwitchChannelPointsMiner/utils.py +++ b/TwitchChannelPointsMiner/utils.py @@ -7,13 +7,9 @@ from datetime import datetime, timezone from random import randrange from millify import millify -import requests from TwitchChannelPointsMiner.constants import USER_AGENTS -__TOKEN = "PLACE BOT TOKEN HERE" -TG_API = f"https://api.telegram.org/bot{__TOKEN}/sendMessage" - def _millify(input, precision=2): return millify(input, precision) @@ -158,15 +154,3 @@ def percentage(a, b): def create_chunks(lst, n): return [lst[i : (i + n)] for i in range(0, len(lst), n)] # noqa: E203 - - -def post_telegram(message: str) -> None: - r = requests.post( - url=TG_API, - data={ - "chat_id": 289579584, - "text": message, - "disable_web_page_preview": True, # include link to twitch streamer? - "disable_notification": True, # no sound, notif just in tray - } - ) diff --git a/example.py b/example.py index a8eb20f..a98bcaa 100644 --- a/example.py +++ b/example.py @@ -4,7 +4,8 @@ import logging from colorama import Fore from TwitchChannelPointsMiner import TwitchChannelPointsMiner from TwitchChannelPointsMiner.logger import LoggerSettings, ColorPalette -from TwitchChannelPointsMiner.classes.Settings import Priority +from TwitchChannelPointsMiner.classes.Telegram import Telegram +from TwitchChannelPointsMiner.classes.Settings import Priority, Events from TwitchChannelPointsMiner.classes.entities.Bet import Strategy, BetSettings, Condition, OutcomeKeys, FilterCondition from TwitchChannelPointsMiner.classes.entities.Streamer import Streamer, StreamerSettings @@ -28,6 +29,12 @@ twitch_miner = TwitchChannelPointsMiner( STREAMER_online="GREEN", # Don't worry about lower/upper case. The script will parse all the values. streamer_offline="red", # Read more in README.md BET_wiN=Fore.MAGENTA # Color allowed are: [BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET]. + ), + telegram=Telegram( + chat_id=123456789, # Chat ID to send messages @GiveChatId + token="123456789:shfuihreuifheuifhiu34578347", # Telegram API token @BotFather + events=[Events.STREAMER_ONLINE, Events.STREAMER_OFFLINE, "BET_LOSE"], # Only these events will be sent to the chat + disable_notification=True, # Revoke the notification (sound/vibration) ) ), streamer_settings=StreamerSettings(