inventwithdean commited on
Commit
c48e85d
·
1 Parent(s): 49d8086

add realtime yt chat support via pytchat

Browse files
__pycache__/audience.cpython-310.pyc ADDED
Binary file (2.05 kB). View file
 
__pycache__/guard.cpython-310.pyc ADDED
Binary file (1.13 kB). View file
 
__pycache__/host.cpython-310.pyc ADDED
Binary file (2.48 kB). View file
 
__pycache__/image_api.cpython-310.pyc ADDED
Binary file (834 Bytes). View file
 
__pycache__/prompts.cpython-310.pyc ADDED
Binary file (1.35 kB). View file
 
__pycache__/randomname.cpython-310.pyc ADDED
Binary file (625 Bytes). View file
 
__pycache__/timing.cpython-310.pyc ADDED
Binary file (1.51 kB). View file
 
__pycache__/tv_crew.cpython-310.pyc ADDED
Binary file (2 kB). View file
 
__pycache__/validity.cpython-310.pyc ADDED
Binary file (380 Bytes). View file
 
__pycache__/yt_chat.cpython-310.pyc ADDED
Binary file (3.41 kB). View file
 
yt_chat.py CHANGED
@@ -1,11 +1,11 @@
1
  import os
 
2
 
3
  # from dotenv import load_dotenv
4
  from guard import Guardian
5
  from tv_crew import TVCrew
6
  import requests
7
  import time
8
- import googleapiclient.discovery
9
 
10
  # load_dotenv()
11
  unreal_orchestrator_url = os.getenv("ORCHESTRATOR_URL")
@@ -13,7 +13,8 @@ api_key_unreal = os.getenv("API_KEY_UNREAL")
13
 
14
  API_KEY = os.getenv("YOUTUBE_API_KEY")
15
  VIDEO_ID = "xBVJIJQg1FY"
16
- POLL_INTERVAL = 15 # seconds
 
17
 
18
 
19
  class StreamChatHost:
@@ -31,116 +32,79 @@ Keep your responses short, like two or three sentences, and be witty."""
31
 
32
  self.messages = [self.system_message]
33
  self.headers = {"Content-Type": "application/json", "x-api-key": api_key_unreal}
34
- self.youtube = googleapiclient.discovery.build(
35
- "youtube", "v3", developerKey=API_KEY
36
- )
37
- self.chat_id = self.get_live_chat_id(self.youtube, VIDEO_ID)
38
- self.next_page_token = None
39
 
40
  def chat_interaction_loop(self):
41
  """Checks if the Host is in lobby, then pulls chat messages from the Live Stream. The Host then replies to the message."""
42
- while True:
43
- time.sleep(POLL_INTERVAL)
44
- request = requests.get(
45
- f"{unreal_orchestrator_url}/status", headers=self.headers
46
- )
47
- in_lobby = request.json().get("in_lobby", False)
48
- if not in_lobby:
49
- continue
50
- if len(self.messages) > 20:
51
- self.messages = [self.system_message]
52
- self.tv_crew.clear_context()
53
- try:
54
- request = self.youtube.liveChatMessages().list(
55
- liveChatId=self.chat_id,
56
- part="snippet,authorDetails",
57
- maxResults=20,
58
- pageToken=self.next_page_token,
59
  )
60
- response = request.execute()
61
- user_messages = []
62
- for item in response.get("items", []):
63
- author_name = item["authorDetails"]["displayName"]
64
- message_text = item["snippet"]["displayMessage"]
65
- user_messages.append(f"{author_name}: {message_text}")
66
-
67
- first_fetch = True if self.next_page_token is None else False
68
- self.next_page_token = response.get("nextPageToken")
69
- if first_fetch:
70
- continue
71
- if len(user_messages) == 0:
72
  continue
73
- except Exception as e:
74
- continue
75
- # **************************************************************
76
-
77
- user_message = "[YouTube Chat]\n"
78
- for msg in user_messages:
79
- if len(msg) <= 500:
80
- user_message += f"{msg}\n"
81
- is_safe, _ = self.guardian.moderate_message(user_message)
82
 
83
- if not is_safe:
84
- continue
 
 
85
 
86
- self.tv_crew.add_context(user_message)
87
- image_base64, caption = self.tv_crew.suggest_image()
88
- if image_base64:
89
- is_safe, _ = self.guardian.moderate_message(caption)
90
  if not is_safe:
91
- image_base64 = None
92
- caption = None
93
- else:
94
- user_message += f"[Crew Updated Television to: {caption}]\n"
95
 
96
- self.messages.append({"role": "user", "content": user_message})
97
- try:
98
- response = self.client.responses.create(
99
- model=self.model, input=self.messages
100
- )
101
- host_response = response.output_text
102
- self.messages.append({"role": "assistant", "content": host_response})
103
- except Exception as e:
104
- print(f"Error generating host response: {e}")
105
- continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
- self.tv_crew.add_context(f"Host: {host_response}\n")
108
- # Just to make sure, that we're in the lobby
109
- request = requests.get(
110
- f"{unreal_orchestrator_url}/status", headers=self.headers
111
- )
112
- in_lobby = request.json().get("in_lobby", False)
113
- if not in_lobby:
114
- continue
 
115
 
116
- if image_base64:
117
- payload_tv = {"base64": image_base64}
 
 
 
 
 
 
 
 
118
  response = requests.post(
119
- url=f"{unreal_orchestrator_url}/television",
120
- json=payload_tv,
121
  headers=self.headers,
122
  )
123
-
124
- payload = {"text": host_response, "is_host": True}
125
- response = requests.post(
126
- url=f"{unreal_orchestrator_url}/tts",
127
- json=payload,
128
- headers=self.headers,
129
- )
130
-
131
- def get_live_chat_id(self, youtube, video_id):
132
- try:
133
- request = youtube.videos().list(part="liveStreamingDetails", id=video_id)
134
- response = request.execute()
135
- if not response["items"]:
136
- print("No video found with the given ID.")
137
- return None
138
-
139
- details = response["items"][0]["liveStreamingDetails"]
140
- if not details:
141
- print("No live streaming details found for this video.")
142
- return None
143
- return details.get("activeLiveChatId", None)
144
- except Exception as e:
145
- print(f"An error occurred: {e}")
146
- return None
 
1
  import os
2
+ import pytchat
3
 
4
  # from dotenv import load_dotenv
5
  from guard import Guardian
6
  from tv_crew import TVCrew
7
  import requests
8
  import time
 
9
 
10
  # load_dotenv()
11
  unreal_orchestrator_url = os.getenv("ORCHESTRATOR_URL")
 
13
 
14
  API_KEY = os.getenv("YOUTUBE_API_KEY")
15
  VIDEO_ID = "xBVJIJQg1FY"
16
+ POLL_INTERVAL = 3 # seconds
17
+ chat = pytchat.create(video_id=VIDEO_ID)
18
 
19
 
20
  class StreamChatHost:
 
32
 
33
  self.messages = [self.system_message]
34
  self.headers = {"Content-Type": "application/json", "x-api-key": api_key_unreal}
 
 
 
 
 
35
 
36
  def chat_interaction_loop(self):
37
  """Checks if the Host is in lobby, then pulls chat messages from the Live Stream. The Host then replies to the message."""
38
+ while chat.is_alive():
39
+ for c in chat.get().sync_items():
40
+ request = requests.get(
41
+ f"{unreal_orchestrator_url}/status", headers=self.headers
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  )
43
+ in_lobby = request.json().get("in_lobby", False)
44
+ if not in_lobby:
 
 
 
 
 
 
 
 
 
 
45
  continue
46
+ if len(self.messages) > 20:
47
+ self.messages = [self.system_message]
48
+ self.tv_crew.clear_context()
 
 
 
 
 
 
49
 
50
+ user_message = f"{c.author.name}]- {c.message}"
51
+ # print(user_message)
52
+ # print("Checking message safety...")
53
+ is_safe, _ = self.guardian.moderate_message(user_message)
54
 
 
 
 
 
55
  if not is_safe:
56
+ # print("Message flagged by Guardian, skipping...")
57
+ continue
 
 
58
 
59
+ self.tv_crew.add_context(user_message)
60
+ # print("TV Crew suggesting image...")
61
+ image_base64, caption = self.tv_crew.suggest_image()
62
+ if image_base64:
63
+ # print("Checking image caption safety...")
64
+ is_safe, _ = self.guardian.moderate_message(caption)
65
+ if not is_safe:
66
+ # print("Image caption flagged by Guardian, skipping image...")
67
+ image_base64 = None
68
+ caption = None
69
+ else:
70
+ user_message += f"[Crew Updated Television to: {caption}]\n"
71
+
72
+ self.messages.append({"role": "user", "content": user_message})
73
+ try:
74
+ # print("Generating host response...")
75
+ response = self.client.responses.create(
76
+ model=self.model, input=self.messages
77
+ )
78
+ host_response = response.output_text
79
+ self.messages.append(
80
+ {"role": "assistant", "content": host_response}
81
+ )
82
+ except Exception as e:
83
+ # print(f"Error generating host response: {e}")
84
+ continue
85
 
86
+ self.tv_crew.add_context(f"Host: {host_response}\n")
87
+ # print(f"Host Response: {host_response}")
88
+ # Just to make sure, that we're in the lobby
89
+ request = requests.get(
90
+ f"{unreal_orchestrator_url}/status", headers=self.headers
91
+ )
92
+ in_lobby = request.json().get("in_lobby", False)
93
+ if not in_lobby:
94
+ continue
95
 
96
+ if image_base64:
97
+ # print("Sending Image Unreal Orchestrator...")
98
+ payload_tv = {"base64": image_base64}
99
+ response = requests.post(
100
+ url=f"{unreal_orchestrator_url}/television",
101
+ json=payload_tv,
102
+ headers=self.headers,
103
+ )
104
+ # print("Sending Host response to Unreal Orchestrator...")
105
+ payload = {"text": host_response, "is_host": True}
106
  response = requests.post(
107
+ url=f"{unreal_orchestrator_url}/tts",
108
+ json=payload,
109
  headers=self.headers,
110
  )