seawolf2357 commited on
Commit
7edf3cc
·
verified ·
1 Parent(s): b4bdc7a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -61
app.py CHANGED
@@ -1,9 +1,11 @@
1
  import discord
2
  import logging
3
  import os
 
4
  import asyncio
5
  from huggingface_hub import InferenceClient
6
  from googleapiclient.discovery import build
 
7
  from dotenv import load_dotenv
8
 
9
  # 환경 변수 로드
@@ -29,9 +31,6 @@ youtube_service = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY)
29
  # 특정 채널 ID
30
  SPECIFIC_CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID"))
31
 
32
- # 대화 히스토리를 저장할 전역 변수
33
- conversation_history = []
34
-
35
  class MyClient(discord.Client):
36
  def __init__(self, *args, **kwargs):
37
  super().__init__(*args, **kwargs)
@@ -43,7 +42,7 @@ class MyClient(discord.Client):
43
  # 봇이 시작될 때 안내 메시지를 전송
44
  channel = self.get_channel(SPECIFIC_CHANNEL_ID)
45
  if channel:
46
- await channel.send("트렌드 보고 싶은 주제를 입력하세요. 예) 최신 테크 뉴스")
47
 
48
  async def on_message(self, message):
49
  if message.author == self.user:
@@ -54,18 +53,17 @@ class MyClient(discord.Client):
54
  return
55
  self.is_processing = True
56
  try:
57
- # 주제 키워드 추출
58
- keywords = await extract_keywords(message)
59
- if keywords:
60
- # YouTube API로 최신 트렌드 및 인기 비디오 검색
61
- video_details = await search_trending_videos(keywords)
62
- if video_details:
63
- # 요청자와의 쓰레드 생성 및 결과 전송
64
- await create_thread_and_send_results(message, keywords, video_details)
65
  else:
66
- await message.channel.send(f"**{keywords}**에 대한 최신 트렌드 비디오를 찾을 수 없습니다.")
67
  else:
68
- await message.channel.send("키워드를 추출할 없습니다.")
69
  finally:
70
  self.is_processing = False
71
 
@@ -75,56 +73,84 @@ class MyClient(discord.Client):
75
  isinstance(message.channel, discord.Thread) and message.channel.parent_id == SPECIFIC_CHANNEL_ID
76
  )
77
 
78
- async def extract_keywords(message):
79
- user_input = message.content
80
- system_prompt = "다음 문장의 의미에 맞는 영문 키워드를 추출하세요: "
81
-
82
- logging.debug(f'Extracting keywords from user input: {user_input}')
83
-
84
- messages = [{"role": "system", "content": system_prompt + user_input}]
85
- logging.debug(f'Messages to be sent to the model: {messages}')
86
-
87
- loop = asyncio.get_event_loop()
88
- response = await loop.run_in_executor(None, lambda: hf_client.chat_completion(
89
- messages, max_tokens=10, temperature=0.7, top_p=0.85))
90
-
91
- # Hugging Face 응답 파싱
92
- if response.choices and response.choices[0].message:
93
- keywords = response.choices[0].message['content'].strip()
94
- else:
95
- keywords = ""
96
- logging.debug(f'Extracted keywords: {keywords}')
97
- return keywords
98
-
99
- async def search_trending_videos(keywords):
100
- response = youtube_service.search().list(
101
- q=keywords,
 
 
 
 
 
 
 
 
 
 
 
102
  part='snippet',
103
- type='video',
104
- order='viewCount', # 인기 있는 비디오 기준으로 정렬
105
- maxResults=5 # 원하는 결과 수
106
  ).execute()
107
-
108
- video_details = []
109
  for item in response.get('items', []):
110
- video_details.append({
111
- 'title': item['snippet']['title'],
112
- 'url': f"https://www.youtube.com/watch?v={item['id']['videoId']}",
113
- 'description': item['snippet']['description'],
114
- 'thumbnail': item['snippet']['thumbnails']['high']['url']
115
- })
116
- return video_details
117
-
118
- async def create_thread_and_send_results(message, keywords, video_details):
119
- # 쓰레드 생성
120
- thread = await message.channel.create_thread(name=f"{message.author.name}의 트렌드 검색 결과", message=message)
121
- if video_details:
122
- message_content = f"**{keywords}**에 대한 최신 트렌드 비디오 {len(video_details)}개를 찾았습니다:"
123
- await thread.send(message_content)
124
- for video in video_details:
125
- embed = discord.Embed(title=video['title'], description=video['description'], url=video['url'])
126
- embed.set_thumbnail(url=video['thumbnail'])
127
- await thread.send(embed=embed)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
  if __name__ == "__main__":
130
  discord_client = MyClient(intents=intents)
 
1
  import discord
2
  import logging
3
  import os
4
+ import re
5
  import asyncio
6
  from huggingface_hub import InferenceClient
7
  from googleapiclient.discovery import build
8
+ from youtube_transcript_api import YouTubeTranscriptApi
9
  from dotenv import load_dotenv
10
 
11
  # 환경 변수 로드
 
31
  # 특정 채널 ID
32
  SPECIFIC_CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID"))
33
 
 
 
 
34
  class MyClient(discord.Client):
35
  def __init__(self, *args, **kwargs):
36
  super().__init__(*args, **kwargs)
 
42
  # 봇이 시작될 때 안내 메시지를 전송
43
  channel = self.get_channel(SPECIFIC_CHANNEL_ID)
44
  if channel:
45
+ await channel.send("유튜브 비디오 URL을 입력하면, 자막과 댓글을 기반으로 답글을 작성합니다.")
46
 
47
  async def on_message(self, message):
48
  if message.author == self.user:
 
53
  return
54
  self.is_processing = True
55
  try:
56
+ video_id = extract_video_id(message.content)
57
+ if video_id:
58
+ transcript = await get_video_transcript(video_id)
59
+ comments = await get_video_comments(video_id)
60
+ if comments and transcript:
61
+ replies = await generate_replies(comments, transcript)
62
+ await create_thread_and_send_replies(message, video_id, comments, replies)
 
63
  else:
64
+ await message.channel.send("자막이나 댓글을 가져올 수 없습니다.")
65
  else:
66
+ await message.channel.send("유효한 유튜브 비디오 URL을 제공해 주세요.")
67
  finally:
68
  self.is_processing = False
69
 
 
73
  isinstance(message.channel, discord.Thread) and message.channel.parent_id == SPECIFIC_CHANNEL_ID
74
  )
75
 
76
+ def extract_video_id(url):
77
+ """
78
+ YouTube 비디오 URL에서 비디오 ID를 추출합니다.
79
+ """
80
+ video_id = None
81
+ youtube_regex = (
82
+ r'(https?://)?(www\.)?'
83
+ '(youtube|youtu|youtube-nocookie)\.(com|be)/'
84
+ '(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')
85
+
86
+ match = re.match(youtube_regex, url)
87
+ if match:
88
+ video_id = match.group(6)
89
+ logging.debug(f'Extracted video ID: {video_id}')
90
+ return video_id
91
+
92
+ async def get_video_transcript(video_id):
93
+ """
94
+ YouTube 비디오의 자막을 가져옵니다.
95
+ """
96
+ try:
97
+ transcript = YouTubeTranscriptApi.get_transcript(video_id)
98
+ transcript_text = " ".join([entry['text'] for entry in transcript])
99
+ logging.debug(f'Fetched transcript: {transcript_text}')
100
+ return transcript_text
101
+ except Exception as e:
102
+ logging.error(f'Error fetching transcript: {e}')
103
+ return None
104
+
105
+ async def get_video_comments(video_id):
106
+ """
107
+ YouTube 비디오의 댓글을 가져옵니다.
108
+ """
109
+ comments = []
110
+ response = youtube_service.commentThreads().list(
111
  part='snippet',
112
+ videoId=video_id,
113
+ maxResults=100 # 최대 100개의 댓글 가져오기
 
114
  ).execute()
115
+
 
116
  for item in response.get('items', []):
117
+ comment = item['snippet']['topLevelComment']['snippet']['textOriginal']
118
+ comments.append(comment)
119
+
120
+ logging.debug(f'Fetched comments: {comments}')
121
+ return comments
122
+
123
+ async def generate_replies(comments, transcript):
124
+ """
125
+ 댓글과 자막을 기반으로 LLM 답글을 생성합니다.
126
+ """
127
+ replies = []
128
+ for comment in comments:
129
+ messages = [
130
+ {"role": "system", "content": f"비디오 자막: {transcript}"},
131
+ {"role": "user", "content": comment}
132
+ ]
133
+ loop = asyncio.get_event_loop()
134
+ response = await loop.run_in_executor(None, lambda: hf_client.chat_completion(
135
+ messages, max_tokens=50, temperature=0.7, top_p=0.85))
136
+
137
+ if response.choices and response.choices[0].message:
138
+ reply = response.choices[0].message['content'].strip()
139
+ else:
140
+ reply = "답글을 생성할 수 없습니다."
141
+ replies.append(reply)
142
+
143
+ logging.debug(f'Generated replies: {replies}')
144
+ return replies
145
+
146
+ async def create_thread_and_send_replies(message, video_id, comments, replies):
147
+ """
148
+ 댓글과 답글을 새로운 쓰레드에 전송합니다.
149
+ """
150
+ thread = await message.channel.create_thread(name=f"{message.author.name}의 댓글 답글", message=message)
151
+ for comment, reply in zip(comments, replies):
152
+ embed = discord.Embed(description=f"**댓글**: {comment}\n**답글**: {reply}")
153
+ await thread.send(embed=embed)
154
 
155
  if __name__ == "__main__":
156
  discord_client = MyClient(intents=intents)