seawolf2357 commited on
Commit
829fd20
·
verified ·
1 Parent(s): 029f929

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +6 -67
app.py CHANGED
@@ -3,13 +3,9 @@ import logging
3
  import os
4
  import re
5
  import asyncio
6
- import json
7
  import subprocess
8
  from huggingface_hub import InferenceClient
9
  from googleapiclient.discovery import build
10
- from google.oauth2.credentials import Credentials
11
- from google_auth_oauthlib.flow import InstalledAppFlow
12
- from google.auth.transport.requests import Request
13
  from youtube_transcript_api import YouTubeTranscriptApi
14
  from youtube_transcript_api.formatters import TextFormatter
15
  from dotenv import load_dotenv
@@ -17,10 +13,6 @@ from dotenv import load_dotenv
17
  # 환경 변수 로드
18
  load_dotenv()
19
 
20
- # JSON_TOKEN.json 파일의 경로
21
- credentials_path = 'JSON_TOKEN.json'
22
- token_path = 'token.json'
23
-
24
  # 로깅 설정
25
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(name)s:%(message)s', handlers=[logging.StreamHandler()])
26
 
@@ -34,22 +26,9 @@ intents.guild_messages = True
34
  # 추론 API 클라이언트 설정
35
  hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus", token=os.getenv("HF_TOKEN"))
36
 
37
- # OAuth 2.0 인증 설정
38
- SCOPES = ["https://www.googleapis.com/auth/youtube.force-ssl"]
39
- creds = None
40
-
41
- if os.path.exists(token_path):
42
- creds = Credentials.from_authorized_user_file(token_path, SCOPES)
43
- if not creds or not creds.valid:
44
- if creds and creds.expired and creds.refresh_token:
45
- creds.refresh(Request())
46
- else:
47
- flow = InstalledAppFlow.from_client_secrets_file(credentials_path, SCOPES)
48
- creds = flow.run_local_server(port=0)
49
- with open(token_path, 'w') as token:
50
- token.write(creds.to_json())
51
-
52
- youtube_service = build('youtube', 'v3', credentials=creds)
53
 
54
  # 특정 채널 ID
55
  SPECIFIC_CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID"))
@@ -87,7 +66,6 @@ class MyClient(discord.Client):
87
  if comments and transcript:
88
  replies = await generate_replies(comments, transcript)
89
  await create_thread_and_send_replies(message, video_id, comments, replies)
90
- await post_replies_to_youtube(video_id, comments, replies)
91
  else:
92
  await message.channel.send("자막이나 댓글을 가져올 수 없습니다.")
93
  else:
@@ -96,15 +74,11 @@ class MyClient(discord.Client):
96
  self.is_processing = False
97
 
98
  def is_message_in_specific_channel(self, message):
99
- # 메시지가 지정된 채널이거나, 해당 채널의 쓰레드인 경우 True 반환
100
  return message.channel.id == SPECIFIC_CHANNEL_ID or (
101
  isinstance(message.channel, discord.Thread) and message.channel.parent_id == SPECIFIC_CHANNEL_ID
102
  )
103
 
104
  def extract_video_id(url):
105
- """
106
- YouTube 비디오 URL에서 비디오 ID를 추출합니다.
107
- """
108
  video_id = None
109
  youtube_regex = (
110
  r'(https?://)?(www\.)?'
@@ -118,37 +92,27 @@ def extract_video_id(url):
118
  return video_id
119
 
120
  async def get_best_available_transcript(video_id):
121
- """
122
- YouTube 비디오의 자막을 가져옵니다.
123
- """
124
  try:
125
- # 한국어 자막 시도
126
  transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['ko'])
127
  except Exception as e:
128
  logging.warning(f'Error fetching Korean transcript: {e}')
129
  try:
130
- # 한국어 자막이 없으면 영어 자막 시도
131
  transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['en'])
132
  except Exception as e:
133
  logging.warning(f'Error fetching English transcript: {e}')
134
  try:
135
- # 영어 자막도 없으면 다른 언어 자막 시도
136
  transcripts = YouTubeTranscriptApi.list_transcripts(video_id)
137
  transcript = transcripts.find_manually_created_transcript().fetch()
138
  except Exception as e:
139
  logging.error(f'Error fetching alternative transcript: {e}')
140
  return None
141
 
142
- # 자막 포맷팅
143
  formatter = TextFormatter()
144
  transcript_text = formatter.format_transcript(transcript)
145
  logging.debug(f'Fetched transcript: {transcript_text}')
146
  return transcript_text
147
 
148
  async def get_video_comments(video_id):
149
- """
150
- YouTube 비디오의 댓글을 가져옵니다.
151
- """
152
  comments = []
153
  response = youtube_service.commentThreads().list(
154
  part='snippet',
@@ -159,15 +123,12 @@ async def get_video_comments(video_id):
159
  for item in response.get('items', []):
160
  comment = item['snippet']['topLevelComment']['snippet']['textOriginal']
161
  comment_id = item['snippet']['topLevelComment']['id']
162
- comments.append((comment, comment_id)) # 댓글과 댓글 ID를 함께 저장
163
 
164
  logging.debug(f'Fetched comments: {comments}')
165
  return comments
166
 
167
  async def generate_replies(comments, transcript):
168
- """
169
- 댓글과 자막을 기반으로 LLM 답글을 생성합니다.
170
- """
171
  replies = []
172
  for comment, _ in comments:
173
  messages = [
@@ -176,7 +137,7 @@ async def generate_replies(comments, transcript):
176
  ]
177
  loop = asyncio.get_event_loop()
178
  response = await loop.run_in_executor(None, lambda: hf_client.chat_completion(
179
- messages, max_tokens=400, temperature=0.7, top_p=0.85)) # max_tokens 값을 조정
180
 
181
  if response.choices and response.choices[0].message:
182
  reply = response.choices[0].message['content'].strip()
@@ -188,33 +149,11 @@ async def generate_replies(comments, transcript):
188
  return replies
189
 
190
  async def create_thread_and_send_replies(message, video_id, comments, replies):
191
- """
192
- 댓글과 답글을 새로운 쓰레드에 전송합니다.
193
- """
194
  thread = await message.channel.create_thread(name=f"{message.author.name}의 댓글 답글", message=message)
195
  for (comment, _), reply in zip(comments, replies):
196
  embed = discord.Embed(description=f"**댓글**: {comment}\n**답글**: {reply}")
197
  await thread.send(embed=embed)
198
 
199
- async def post_replies_to_youtube(video_id, comments, replies):
200
- """
201
- 생성된 답글을 YouTube 댓글로 게시합니다.
202
- """
203
- for (comment, comment_id), reply in zip(comments, replies):
204
- try:
205
- youtube_service.comments().insert(
206
- part='snippet',
207
- body={
208
- 'snippet': {
209
- 'parentId': comment_id,
210
- 'textOriginal': reply
211
- }
212
- }
213
- ).execute()
214
- logging.debug(f'Posted reply to comment: {comment_id}')
215
- except Exception as e:
216
- logging.error(f'Error posting reply to comment {comment_id}: {e}')
217
-
218
  if __name__ == "__main__":
219
  discord_client = MyClient(intents=intents)
220
- discord_client.run(os.getenv('DISCORD_TOKEN')) #이 코드를 기억하라: 최종적으로 답글 이 작성되었지만 유튜브에 등록이 안되고 있다.
 
3
  import os
4
  import re
5
  import asyncio
 
6
  import subprocess
7
  from huggingface_hub import InferenceClient
8
  from googleapiclient.discovery import build
 
 
 
9
  from youtube_transcript_api import YouTubeTranscriptApi
10
  from youtube_transcript_api.formatters import TextFormatter
11
  from dotenv import load_dotenv
 
13
  # 환경 변수 로드
14
  load_dotenv()
15
 
 
 
 
 
16
  # 로깅 설정
17
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)s:%(name)s:%(message)s', handlers=[logging.StreamHandler()])
18
 
 
26
  # 추론 API 클라이언트 설정
27
  hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus", token=os.getenv("HF_TOKEN"))
28
 
29
+ # YouTube API 설정
30
+ API_KEY = os.getenv("YOUTUBE_API_KEY")
31
+ youtube_service = build('youtube', 'v3', developerKey=API_KEY)
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  # 특정 채널 ID
34
  SPECIFIC_CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID"))
 
66
  if comments and transcript:
67
  replies = await generate_replies(comments, transcript)
68
  await create_thread_and_send_replies(message, video_id, comments, replies)
 
69
  else:
70
  await message.channel.send("자막이나 댓글을 가져올 수 없습니다.")
71
  else:
 
74
  self.is_processing = False
75
 
76
  def is_message_in_specific_channel(self, message):
 
77
  return message.channel.id == SPECIFIC_CHANNEL_ID or (
78
  isinstance(message.channel, discord.Thread) and message.channel.parent_id == SPECIFIC_CHANNEL_ID
79
  )
80
 
81
  def extract_video_id(url):
 
 
 
82
  video_id = None
83
  youtube_regex = (
84
  r'(https?://)?(www\.)?'
 
92
  return video_id
93
 
94
  async def get_best_available_transcript(video_id):
 
 
 
95
  try:
 
96
  transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['ko'])
97
  except Exception as e:
98
  logging.warning(f'Error fetching Korean transcript: {e}')
99
  try:
 
100
  transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['en'])
101
  except Exception as e:
102
  logging.warning(f'Error fetching English transcript: {e}')
103
  try:
 
104
  transcripts = YouTubeTranscriptApi.list_transcripts(video_id)
105
  transcript = transcripts.find_manually_created_transcript().fetch()
106
  except Exception as e:
107
  logging.error(f'Error fetching alternative transcript: {e}')
108
  return None
109
 
 
110
  formatter = TextFormatter()
111
  transcript_text = formatter.format_transcript(transcript)
112
  logging.debug(f'Fetched transcript: {transcript_text}')
113
  return transcript_text
114
 
115
  async def get_video_comments(video_id):
 
 
 
116
  comments = []
117
  response = youtube_service.commentThreads().list(
118
  part='snippet',
 
123
  for item in response.get('items', []):
124
  comment = item['snippet']['topLevelComment']['snippet']['textOriginal']
125
  comment_id = item['snippet']['topLevelComment']['id']
126
+ comments.append((comment, comment_id))
127
 
128
  logging.debug(f'Fetched comments: {comments}')
129
  return comments
130
 
131
  async def generate_replies(comments, transcript):
 
 
 
132
  replies = []
133
  for comment, _ in comments:
134
  messages = [
 
137
  ]
138
  loop = asyncio.get_event_loop()
139
  response = await loop.run_in_executor(None, lambda: hf_client.chat_completion(
140
+ messages, max_tokens=400, temperature=0.7, top_p=0.85))
141
 
142
  if response.choices and response.choices[0].message:
143
  reply = response.choices[0].message['content'].strip()
 
149
  return replies
150
 
151
  async def create_thread_and_send_replies(message, video_id, comments, replies):
 
 
 
152
  thread = await message.channel.create_thread(name=f"{message.author.name}의 댓글 답글", message=message)
153
  for (comment, _), reply in zip(comments, replies):
154
  embed = discord.Embed(description=f"**댓글**: {comment}\n**답글**: {reply}")
155
  await thread.send(embed=embed)
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  if __name__ == "__main__":
158
  discord_client = MyClient(intents=intents)
159
+ discord_client.run(os.getenv('DISCORD_TOKEN'))