|
11 | 11 | import re
|
12 | 12 | import string
|
13 | 13 | import time
|
14 |
| -# from datetime import datetime |
| 14 | +# import json |
| 15 | +import requests |
| 16 | +import validators |
15 | 17 | from pathlib import Path
|
16 | 18 | from secrets import choice, token_hex
|
17 |
| - |
18 |
| -# import json |
| 19 | +# from urllib.parse import quote |
19 | 20 | # from base64 import urlsafe_b64decode
|
20 |
| - |
21 |
| -import requests |
| 21 | +# from datetime import datetime |
22 | 22 |
|
23 | 23 | from TwitchChannelPointsMiner.classes.entities.Campaign import Campaign
|
24 | 24 | from TwitchChannelPointsMiner.classes.entities.Drop import Drop
|
@@ -433,7 +433,8 @@ def send_minute_watched_events(self, streamers, priority, chunk_size=3):
|
433 | 433 | )
|
434 | 434 | > 30
|
435 | 435 | )
|
436 |
| - and streamers[index].stream.minute_watched < 7 # fix #425 |
| 436 | + # fix #425 |
| 437 | + and streamers[index].stream.minute_watched < 7 |
437 | 438 | ):
|
438 | 439 | streamers_watching.append(index)
|
439 | 440 | if len(streamers_watching) == 2:
|
@@ -467,14 +468,87 @@ def send_minute_watched_events(self, streamers, priority, chunk_size=3):
|
467 | 468 | streamers_watching = streamers_watching[:2]
|
468 | 469 |
|
469 | 470 | for index in streamers_watching:
|
470 |
| - next_iteration = time.time() + 60 / len(streamers_watching) |
| 471 | + # next_iteration = time.time() + 60 / len(streamers_watching) |
| 472 | + next_iteration = time.time() + 20 / len(streamers_watching) |
471 | 473 |
|
472 | 474 | try:
|
| 475 | + #################################### |
| 476 | + # Start of fix for 2024/5 API Change |
| 477 | + # Create the JSON data for the GraphQL request |
| 478 | + json_data = copy.deepcopy( |
| 479 | + GQLOperations.PlaybackAccessToken) |
| 480 | + json_data["variables"] = { |
| 481 | + "login": streamers[index].username, |
| 482 | + "isLive": True, |
| 483 | + "isVod": False, |
| 484 | + "vodID": "", |
| 485 | + # "playerType": "site" |
| 486 | + "playerType": "picture-by-picture" |
| 487 | + } |
| 488 | + |
| 489 | + # Get signature and value using the post_gql_request method |
| 490 | + responsePlaybackAccessToken = self.post_gql_request( |
| 491 | + json_data) |
| 492 | + logger.debug( |
| 493 | + f"Sent PlaybackAccessToken request for {streamers[index]}" |
| 494 | + ) |
| 495 | + signature = responsePlaybackAccessToken["data"]['streamPlaybackAccessToken']["signature"] |
| 496 | + value = responsePlaybackAccessToken["data"]['streamPlaybackAccessToken']["value"] |
| 497 | + if not signature or not value: |
| 498 | + continue |
| 499 | + |
| 500 | + # encoded_value = quote(json.dumps(value)) |
| 501 | + |
| 502 | + # Construct the URL for the broadcast qualities |
| 503 | + RequestBroadcastQualitiesURL = f"https://usher.ttvnw.net/api/channel/hls/{streamers[index].username}.m3u8?sig={signature}&token={value}" |
| 504 | + |
| 505 | + # Get list of video qualities |
| 506 | + responseBroadcastQualities = requests.get(RequestBroadcastQualitiesURL, headers={ |
| 507 | + "User-Agent": self.user_agent}, timeout=20) # timeout=60 |
| 508 | + logger.debug( |
| 509 | + f"Send RequestBroadcastQualitiesURL request for {streamers[index]} - Status code: {responseBroadcastQualities.status_code}" |
| 510 | + ) |
| 511 | + if responseBroadcastQualities.status_code != 200: |
| 512 | + continue |
| 513 | + BroadcastQualities = responseBroadcastQualities.text |
| 514 | + |
| 515 | + # Just takes the last line, which should be the URL for the lowest quality |
| 516 | + BroadcastLowestQualityURL = BroadcastQualities.split( |
| 517 | + "\n")[-1] |
| 518 | + if not validators.url(BroadcastLowestQualityURL): |
| 519 | + continue |
| 520 | + |
| 521 | + # Get list of video URLs |
| 522 | + responseStreamURLList = requests.get(BroadcastLowestQualityURL, headers={ |
| 523 | + "User-Agent": self.user_agent}, timeout=20) # timeout=60 |
| 524 | + logger.debug( |
| 525 | + f"Send BroadcastLowestQualityURL request for {streamers[index]} - Status code: {responseStreamURLList.status_code}" |
| 526 | + ) |
| 527 | + if responseStreamURLList.status_code != 200: |
| 528 | + continue |
| 529 | + StreamURLList = responseStreamURLList.text |
| 530 | + |
| 531 | + # Just takes the last line, which should be the URL for the lowest quality |
| 532 | + StreamLowestQualityURL = StreamURLList.split("\n")[-2] |
| 533 | + if not validators.url(StreamLowestQualityURL): |
| 534 | + continue |
| 535 | + |
| 536 | + # Perform a HEAD request to simulate watching the stream |
| 537 | + responseStreamLowestQualityURL = requests.head(StreamLowestQualityURL, headers={ |
| 538 | + "User-Agent": self.user_agent}, timeout=20) # timeout=60 |
| 539 | + logger.debug( |
| 540 | + f"Send StreamLowestQualityURL request for {streamers[index]} - Status code: {responseStreamLowestQualityURL.status_code}" |
| 541 | + ) |
| 542 | + if responseStreamLowestQualityURL.status_code != 200: |
| 543 | + continue |
| 544 | + # End of fix for 2024/5 API Change |
| 545 | + ################################## |
473 | 546 | response = requests.post(
|
474 | 547 | streamers[index].stream.spade_url,
|
475 | 548 | data=streamers[index].stream.encode_payload(),
|
476 | 549 | headers={"User-Agent": self.user_agent},
|
477 |
| - timeout=60, |
| 550 | + # timeout=60, |
| 551 | + timeout=20, |
478 | 552 | )
|
479 | 553 | logger.debug(
|
480 | 554 | f"Send minute watched request for {streamers[index]} - Status code: {response.status_code}"
|
@@ -543,7 +617,8 @@ def send_minute_watched_events(self, streamers, priority, chunk_size=3):
|
543 | 617 | )
|
544 | 618 |
|
545 | 619 | if streamers_watching == []:
|
546 |
| - self.__chuncked_sleep(60, chunk_size=chunk_size) |
| 620 | + # self.__chuncked_sleep(60, chunk_size=chunk_size) |
| 621 | + self.__chuncked_sleep(20, chunk_size=chunk_size) |
547 | 622 | except Exception:
|
548 | 623 | logger.error(
|
549 | 624 | "Exception raised in send minute watched", exc_info=True)
|
|
0 commit comments