Teekeks / pyTwitchAPI

A Python 3.7 compatible implementation of the Twitch API, EventSub, PubSub and Chat
https://pytwitchapi.dev
MIT License
253 stars 38 forks source link

PubSub Dropping Connection after 1 request. #91

Closed mmattbtw closed 2 years ago

mmattbtw commented 2 years ago

When listening to bits, for some reason the websockets connection drops.

Code:

import os
import sys

# print(sys.argv)
# if "dev".lower() in sys.argv:
#     print("Starting in DEV mode")
# else:
#     os.system("git pull origin main")
#     os.system("pip install -U -r requirements.txt")

from twitchAPI.pubsub import PubSub
from twitchAPI.twitch import Twitch
from twitchAPI.types import AuthScope
from uuid import UUID
from dotenv import load_dotenv
from twitchAPI.oauth import UserAuthenticator
import httpx
import time
import re
import logging

from playsound import playsound
import urllib.request

load_dotenv()
log_level = logging.DEBUG if "dev".lower() in sys.argv else logging.INFO

log = logging.getLogger()

logging.basicConfig(level=log_level, format="%(name)s - %(message)s", datefmt="%X")

def callback_whisper(uuid: UUID, data: dict) -> None:
    print(data)

    message = data["data"]["chat_message"]
    message = re.sub("(?i)cheer\d*", "", message)
    if message[0] == " ":
        message = message[1:]

    print(message)

    voice = message.split(": ")[0]
    voice = voice.lower()
    print(voice)
    text = message.split(": ")[1]
    print(text)

    response = httpx.post(
        "https://api.uberduck.ai/speak",
        auth=(os.environ.get("UBERDUCK_USERNAME"), os.environ.get("UBERDUCK_SECRET")),
        json={
            "speech": text,
            "voice": voice,
        },
    )

    print(response.json())

    if response.json()["uuid"] is not None:
        print("dank0")

        danking = True
        while danking:
            ud_ai = httpx.get(
                f"https://api.uberduck.ai/speak-status?uuid={response.json()['uuid']}",
                auth=(
                    os.environ.get("UBERDUCK_USERNAME"),
                    os.environ.get("UBERDUCK_SECRET"),
                ),
            )
            print(ud_ai.url)

            print("dank1")

            print(ud_ai.json())
            if ud_ai.json()["path"] != None:
                print("DANK ALERT")
                urllib.request.urlretrieve(ud_ai.json()["path"], "AI_voice.wav")
                time.sleep(1)
                playsound("./AI_voice.wav")
                os.remove("./AI_voice.wav")
                danking = False
            else:
                print("false danking")
                time.sleep(1)

# setting up Authentication and getting your user id
twitch = Twitch(os.environ.get("TWITCH_CLIENT_ID"), os.environ.get("TWITCH_SECRET"))
target_scope = [AuthScope.BITS_READ, AuthScope.CHANNEL_READ_REDEMPTIONS]

auth = UserAuthenticator(twitch, target_scope, force_verify=False)
# this will open your default browser and prompt you with the twitch verification website
token, refresh_token = auth.authenticate()
# add User authentication
twitch.set_user_authentication(token, target_scope, refresh_token)

user_id = twitch.get_users(logins=[os.environ.get("TWITCH_USERNAME")])["data"][0]["id"]

# starting up PubSub
pubsub = PubSub(twitch)
pubsub.start()
# you can either start listening before or after you started pubsub.
uuid = pubsub.listen_bits(user_id, callback_whisper)
print("Pubsub Ready.")

Logs:

PS C:\Users\psieg\Desktop\TTS\ai-tts-donations> python bot.py dev
twitchAPI.twitch - generating fresh app token
urllib3.connectionpool - Starting new HTTPS connection (1): id.twitch.tv:443
urllib3.connectionpool - https://id.twitch.tv:443 "POST /oauth2/token?client_id=[REDACTED]&client_secret=[REDACTED]&grant_type=client_credentials&scope= HTTP/1.1" 200 93
asyncio - Using proactor: IocpProactor
twitchAPI.oauth - running oauth Webserver
twitchAPI.oauth - got callback with state [REDACTED]
aiohttp.access - 127.0.0.1 [06/Oct/2021:01:23:11 +0000] "GET /?code=[REDACTED]&scope=bits%3Aread+channel%3Aread%3Aredemptions&state=[REDACTED] HTTP/1.1" 200 387 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"
urllib3.connectionpool - Starting new HTTPS connection (1): id.twitch.tv:443
urllib3.connectionpool - https://id.twitch.tv:443 "POST /oauth2/token?client_id=[REDACTED]&client_secret=[REDACTED]&code=[REDACTED]&grant_type=authorization_code&redirect_uri=http%3A//localhost%3A17563 HTTP/1.1" 200 209
urllib3.connectionpool - Starting new HTTPS connection (1): id.twitch.tv:443
urllib3.connectionpool - https://id.twitch.tv:443 "GET /oauth2/validate HTTP/1.1" 200 154
twitchAPI.twitch - making GET request to https://api.twitch.tv/helix/users?login=[REDACTED]
urllib3.connectionpool - Starting new HTTPS connection (1): api.twitch.tv:443
urllib3.connectionpool - https://api.twitch.tv:443 "GET /helix/users?login=[REDACTED] HTTP/1.1" 200 517
asyncio - Using proactor: IocpProactor
websockets.client - = connection is CONNECTING
websockets.client - > GET / HTTP/1.1
websockets.client - > Host: pubsub-edge.twitch.tv
websockets.client - > Upgrade: websocket
websockets.client - > Connection: Upgrade
websockets.client - > Sec-WebSocket-Key: [REDACTED]
websockets.client - > Sec-WebSocket-Version: 13
websockets.client - > Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=12; client_max_window_bits=12
websockets.client - > User-Agent: Python/3.9 websockets/10.0
websockets.client - < HTTP/1.1 101 Switching Protocols
websockets.client - < Date: Wed, 06 Oct 2021 01:23:11 GMT
websockets.client - < Connection: upgrade
websockets.client - < Upgrade: websocket
websockets.client - < Sec-WebSocket-Accept: [REDACTED]
websockets.client - = connection is OPEN
asyncio - Using proactor: IocpProactor
twitchAPI.pubsub - sending listen for topics ['channel-bits-events-v2.639195300'] with nonce a[REDACTED]
websockets.client - > TEXT '{"type": "LISTEN", "nonce": "[REDACTED]"}}' [173 bytes]
websockets.client - < TEXT '{"type":"RESPONSE","error":"","nonce":"[REDACTED]"}\r\n' [79 bytes]
twitchAPI.pubsub - got response for nonce a[REDACTED]: PubSubResponseError.NONE
Pubsub Ready.
websockets.client - %% sending keepalive ping
websockets.client - > PING f4 ca 2b da [binary, 4 bytes]
websockets.client - < PONG f4 ca 2b da [binary, 4 bytes]
websockets.client - %% received keepalive pong
websockets.client - %% sending keepalive ping
websockets.client - > PING 'rBr:' [text, 4 bytes]
websockets.client - < PONG 'rBr:' [text, 4 bytes]
websockets.client - %% received keepalive pong
websockets.client - < TEXT '{"type":"MESSAGE","data":{"topic":"channel-bits...[REDACTED]\\"}"}}\r\n' [521 bytes]
{'data': {'user_name': 'mmattbtw', 'channel_name': '[REDACTED]', 'user_id': '640348450', 'channel_id': '639195300', 'time': '2021-10-06T01:23:59.979817113Z', 'chat_message': 'cheer1 drake: one last time!', 'bits_used': 1, 'total_bits_used': 1019, 'is_anonymous': False, 'context': 'cheer', 'badge_entitlement': None}, 'version': '1.0', 'message_type': 'bits_event', 'message_id': 'a[REDACTED][REDACTED]'}
drake: one last time!
drake
one last time!
httpx._client - HTTP Request: POST https://api.uberduck.ai/speak "HTTP/1.1 200 OK"
{'uuid': '[REDACTED]'}
dank0
httpx._client - HTTP Request: GET https://api.uberduck.ai/speak-status?uuid=[REDACTED] "HTTP/1.1 200 OK"
https://api.uberduck.ai/speak-status?uuid=[REDACTED]
dank1
{'started_at': '2021-10-06T01:24:02.012667', 'failed_at': None, 'finished_at': None, 'path': None, 'meta': None}
false danking
httpx._client - HTTP Request: GET https://api.uberduck.ai/speak-status?uuid=[REDACTED] "HTTP/1.1 200 OK"
https://api.uberduck.ai/speak-status?uuid=[REDACTED]
dank1
{'started_at': '2021-10-06T01:24:02.012667', 'failed_at': None, 'finished_at': None, 'path': None, 'meta': None}
false danking
httpx._client - HTTP Request: GET https://api.uberduck.ai/speak-status?uuid=[REDACTED] "HTTP/1.1 200 OK"
https://api.uberduck.ai/speak-status?uuid=[REDACTED]
dank1
{'started_at': '2021-10-06T01:24:02.012667', 'failed_at': None, 'finished_at': '2021-10-06T01:24:04.316579', 'path': 'https://uberduck-audio-outputs.s3-us-west-2.amazonaws.com/[REDACTED]/audio.wav', 'meta': None}
DANK ALERT
websockets.client - < TEXT '{"type":"MESSAGE","data":{"topic":"channel-bits...[REDACTED]\\"}"}}\r\n' [520 bytes]
{'data': {'user_name': '[REDACTED]bot', 'channel_name': '[REDACTED]', 'user_id': '271030317', 'channel_id': '639195300', 'time': '2021-10-06T01:24:01.678538266Z', 'chat_message': 'Cheer1 drake: my dick is hard', 'bits_used': 1, 'total_bits_used': 19, 'is_anonymous': False, 'context': 'cheer', 'badge_entitlement': None}, 'version': '1.0', 'message_type': 'bits_event', 'message_id': '[REDACTED][REDACTED]'}
drake: my dick is hard
drake
my dick is hard
httpx._client - HTTP Request: POST https://api.uberduck.ai/speak "HTTP/1.1 200 OK"
{'uuid': '[REDACTED]'}
dank0
dank1
{'started_at': '2021-10-06T01:24:07.299097', 'failed_at': None, 'finished_at': None, 'path': None, 'meta': None}
false danking
httpx._client - HTTP Request: GET https://api.uberduck.ai/speak-status?uuid=[REDACTED] "HTTP/1.1 200 OK"
https://api.uberduck.ai/speak-status?uuid=[REDACTED]
dank1
{'started_at': '2021-10-06T01:24:07.299097', 'failed_at': None, 'finished_at': '2021-10-06T01:24:13.604428', 'path': 'https://uberduck-audio-outputs.s3-us-west-2.amazonaws.com/[REDACTED]/audio.wav', 'meta': None}
DANK ALERT
websockets.client - %% sending keepalive ping
websockets.client - > PING 8f fa 0e bb [binary, 4 bytes]
websockets.client - < PONG 8f fa 0e bb [binary, 4 bytes]
websockets.client - %% received keepalive pong

# After this, websockets stop responding.

I redacted a lot of things in the logs just in case.

Another error commonly gotten is this:

I'm not sure what is causing this, but it's not happening on my machine (Python 3.9.2, macOS), but it's happening on another person's machine (Python 3.9.7, Windows 10).

Any help would be appreciated, but understandable if you didn't know the cause of the issue.

Teekeks commented 2 years ago

Good catch! In the next version this will be fixed (should be ready later this week)