Merge pull request #341 from Tkd-Alex/ChannelFollows

Use GQL API to list follows
This commit is contained in:
Alessandro Maggio
2021-12-21 12:27:39 +01:00
committed by GitHub
7 changed files with 90 additions and 44 deletions

View File

@@ -183,7 +183,7 @@ from colorama import Fore
from TwitchChannelPointsMiner import TwitchChannelPointsMiner
from TwitchChannelPointsMiner.logger import LoggerSettings, ColorPalette
from TwitchChannelPointsMiner.classes.Telegram import Telegram
from TwitchChannelPointsMiner.classes.Settings import Priority, Events
from TwitchChannelPointsMiner.classes.Settings import Priority, Events, FollowersOrder
from TwitchChannelPointsMiner.classes.entities.Bet import Strategy, BetSettings, Condition, OutcomeKeys, FilterCondition, DelayMode
from TwitchChannelPointsMiner.classes.entities.Streamer import Streamer, StreamerSettings
@@ -194,11 +194,11 @@ twitch_miner = TwitchChannelPointsMiner(
priority=[ # Custom priority in this case for example:
Priority.STREAK, # - We want first of all to catch all watch streak from all streamers
Priority.DROPS, # - When we don't have anymore watch streak to catch, wait until all drops are collected over the streamers
Priority.ORDER # - When we have all of the drops claimed and no watch-streak available, use the order priority (POINTS_ASCENDING, POINTS_DESCEDING)
Priority.ORDER # - When we have all of the drops claimed and no watch-streak available, use the order priority (POINTS_ASCENDING, POINTS_DESCEDING)
],
logger_settings=LoggerSettings(
save=True, # If you want to save logs in a file (suggested)
console_level=logging.INFO, # Level of logs - use logging.DEBUG for more info)
console_level=logging.INFO, # Level of logs - use logging.DEBUG for more info
file_level=logging.DEBUG, # Level of logs - If you think the log file it's too big, use logging.INFO
emoji=True, # On Windows, we have a problem printing emoji. Set to false if you have a problem
less=False, # If you think that the logs are too verbose, set this to True
@@ -219,12 +219,12 @@ twitch_miner = TwitchChannelPointsMiner(
make_predictions=True, # If you want to Bet / Make prediction
follow_raid=True, # Follow raid to obtain more points
claim_drops=True, # We can't filter rewards base on stream. Set to False for skip viewing counter increase and you will never obtain a drop reward from this script. Issue #21
watch_streak=True, # If a streamer go online change the priotiry of streamers array and catch the watch screak. Issue #11
watch_streak=True, # If a streamer go online change the priority of streamers array and catch the watch streak. Issue #11
join_chat=True, # Join irc chat to increase watch-time
bet=BetSettings(
strategy=Strategy.SMART, # Choose you strategy!
percentage=5, # Place the x% of your channel points
percentage_gap=20, # Gap difference between outcomesA and outcomesB (for SMART stragegy)
percentage_gap=20, # Gap difference between outcomesA and outcomesB (for SMART strategy)
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 Issue #33
delay_mode=DelayMode.FROM_END, # When placing a bet, we will wait until `delay` seconds before the end of the timer
@@ -261,16 +261,18 @@ twitch_miner.mine(
"streamer-username10",
"streamer-username11"
], # Array of streamers (order = priority)
followers=False # Automatic download the list of your followers (unable to set custom settings for you followers list)
followers=False, # Automatic download the list of your followers
order=FollowersOrder.ASC # Sort the followers list by follow date. ASC or DESC
)
```
You can also use all the default values except for your username obv. Short version:
```python
from TwitchChannelPointsMiner import TwitchChannelPointsMiner
from TwitchChannelPointsMiner.classes.Settings import FollowersOrder
twitch_miner = TwitchChannelPointsMiner("your-twitch-username")
twitch_miner.mine(["streamer1", "streamer2"]) # Array of streamers OR
twitch_miner.mine(followers=True) # Automatic use the followers list OR
twitch_miner.mine(["streamer1", "streamer2"], followers=True) # Mixed
twitch_miner.mine(["streamer1", "streamer2"]) # Array of streamers OR
twitch_miner.mine(followers=True, order=FollowersOrder.ASC) # Automatic use the followers list OR
twitch_miner.mine(["streamer1", "streamer2"], followers=True, order=FollowersOrder.DESC) # Mixed
```
If you follow so many streamers on Twitch, but you don't want to mine points for all of them, you can blacklist the users with the `blacklist` keyword. [#94](https://github.com/Tkd-Alex/Twitch-Channel-Points-Miner-v2/issues/94)
```python
@@ -355,7 +357,7 @@ About the *Docker* version; the community has always shown great interest in the
### Limits
> Twitch has a limit - you can't watch more than two channels at one time. We take the first two streamers from the list as they have the highest priority.
Make sure to write the streamers array in order of priority from left to right. If you use `followers=True` Twitch return the streamers order by followed_at. So your last follow has the highest priority.
Make sure to write the streamers array in order of priority from left to right. If you use `followers=True` you can choose to download the followers sorted by follow date (ASC or DESC).
## Settings
Most of the settings are self-explained and are commented on in the example.

View File

@@ -19,7 +19,7 @@ from TwitchChannelPointsMiner.classes.entities.Streamer import (
StreamerSettings,
)
from TwitchChannelPointsMiner.classes.Exceptions import StreamerDoesNotExistException
from TwitchChannelPointsMiner.classes.Settings import Priority, Settings
from TwitchChannelPointsMiner.classes.Settings import FollowersOrder, Priority, Settings
from TwitchChannelPointsMiner.classes.Twitch import Twitch
from TwitchChannelPointsMiner.classes.WebSocketsPool import WebSocketsPool
from TwitchChannelPointsMiner.logger import LoggerSettings, configure_loggers
@@ -129,10 +129,22 @@ class TwitchChannelPointsMiner:
http_server.name = "Analytics Thread"
http_server.start()
def mine(self, streamers: list = [], blacklist: list = [], followers=False):
def mine(
self,
streamers: list = [],
blacklist: list = [],
followers: bool = False,
followers_order: FollowersOrder = FollowersOrder.ASC,
):
self.run(streamers=streamers, blacklist=blacklist, followers=followers)
def run(self, streamers: list = [], blacklist: list = [], followers=False):
def run(
self,
streamers: list = [],
blacklist: list = [],
followers: bool = False,
followers_order: FollowersOrder = FollowersOrder.ASC,
):
if self.running:
logger.error("You can't start multiple sessions of this instance!")
else:
@@ -161,7 +173,7 @@ class TwitchChannelPointsMiner:
streamers_dict[username] = streamer
if followers is True:
followers_array = self.twitch.get_followers()
followers_array = self.twitch.get_followers(order=followers_order)
logger.info(
f"Load {len(followers_array)} followers from your profile!",
extra={"emoji": ":clipboard:"},

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
__version__ = "2.0.5"
__version__ = "2.0.6"
from .TwitchChannelPointsMiner import TwitchChannelPointsMiner
__all__ = [

View File

@@ -10,6 +10,14 @@ class Priority(Enum):
POINTS_DESCEDING = auto()
class FollowersOrder(Enum):
ASC = auto()
DESC = auto()
def __str__(self):
return self.name
# Empty object shared between class
class Settings(object):
__slots__ = ["logger", "streamer_settings"]

View File

@@ -21,7 +21,12 @@ from TwitchChannelPointsMiner.classes.Exceptions import (
StreamerDoesNotExistException,
StreamerIsOfflineException,
)
from TwitchChannelPointsMiner.classes.Settings import Events, Priority, Settings
from TwitchChannelPointsMiner.classes.Settings import (
Events,
FollowersOrder,
Priority,
Settings,
)
from TwitchChannelPointsMiner.classes.TwitchLogin import TwitchLogin
from TwitchChannelPointsMiner.constants import CLIENT_ID, GQLOperations
from TwitchChannelPointsMiner.utils import (
@@ -155,22 +160,28 @@ class Twitch(object):
else:
return json_response["data"]["user"]["id"]
def get_followers(self):
json_data = copy.deepcopy(GQLOperations.PersonalSections)
json_response = self.post_gql_request(json_data)
try:
if (
"data" in json_response
and "personalSections" in json_response["data"]
and json_response["data"]["personalSections"] != []
):
return [
fw["user"]["login"]
for fw in json_response["data"]["personalSections"][0]["items"]
if fw["user"] is not None
]
except KeyError:
return []
def get_followers(
self, limit: int = 100, order: FollowersOrder = FollowersOrder.ASC
):
json_data = copy.deepcopy(GQLOperations.ChannelFollows)
json_data["variables"] = {"limit": limit, "order": str(order)}
has_next = True
last_cursor = ""
follows = []
while has_next is True and last_cursor != "":
json_data["variables"]["cursor"] = last_cursor
json_response = self.post_gql_request(json_data)
try:
follows_response = json_response["data"]["user"]["follows"]
last_cursor = None
for f in follows_response["edges"]:
follows.append(f["node"]["login"].lower())
last_cursor = f["cursor"]
has_next = follows_response["pageInfo"]["hasNextPage"]
except KeyError:
return []
return follows
def update_raid(self, streamer, raid):
if streamer.raid != raid:

View File

@@ -145,21 +145,33 @@ class GQLOperations:
}
},
}
PersonalSections = {
"operationName": "PersonalSections",
"variables": {
"input": {
"sectionInputs": ["FOLLOWED_SECTION"],
"recommendationContext": {"platform": "web"},
PersonalSections = (
{
"operationName": "PersonalSections",
"variables": {
"input": {
"sectionInputs": ["FOLLOWED_SECTION"],
"recommendationContext": {"platform": "web"},
},
"channelLogin": None,
"withChannelUser": False,
"creatorAnniversariesExperimentEnabled": False,
},
"extensions": {
"persistedQuery": {
"version": 1,
"sha256Hash": "9fbdfb00156f754c26bde81eb47436dee146655c92682328457037da1a48ed39",
}
},
"channelLogin": None,
"withChannelUser": False,
"creatorAnniversariesExperimentEnabled": False,
},
)
ChannelFollows = {
"operationName": "ChannelFollows",
"variables": {"limit": 100, "order": "ASC"},
"extensions": {
"persistedQuery": {
"version": 1,
"sha256Hash": "9fbdfb00156f754c26bde81eb47436dee146655c92682328457037da1a48ed39",
"sha256Hash": "4b9cb31b54b9213e5760f2f6e9e935ad09924cac2f78aac51f8a64d85f028ed0",
}
},
}

View File

@@ -5,7 +5,7 @@ from colorama import Fore
from TwitchChannelPointsMiner import TwitchChannelPointsMiner
from TwitchChannelPointsMiner.logger import LoggerSettings, ColorPalette
from TwitchChannelPointsMiner.classes.Telegram import Telegram
from TwitchChannelPointsMiner.classes.Settings import Priority, Events
from TwitchChannelPointsMiner.classes.Settings import Priority, Events, FollowersOrder
from TwitchChannelPointsMiner.classes.entities.Bet import Strategy, BetSettings, Condition, OutcomeKeys, FilterCondition, DelayMode
from TwitchChannelPointsMiner.classes.entities.Streamer import Streamer, StreamerSettings
@@ -83,5 +83,6 @@ twitch_miner.mine(
"streamer-username10",
"streamer-username11"
], # Array of streamers (order = priority)
followers=False # Automatic download the list of your followers (unable to set custom settings for you followers list)
followers=False, # Automatic download the list of your followers
order=FollowersOrder.ASC # Sort the followers list by follow date. ASC or DESC
)