Akshayram1 commited on
Commit
98dd4d1
Β·
verified Β·
1 Parent(s): c92bdd2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -87
app.py CHANGED
@@ -11,43 +11,19 @@ st.set_page_config(
11
  initial_sidebar_state="expanded"
12
  )
13
 
14
- # Custom CSS styling
15
- st.markdown(r"""
16
  <style>
17
- .header {
18
- font-size: 2.5em !important;
19
- color: #FF4B4B !important;
20
- margin-bottom: 30px !important;
21
- }
22
- .sidebar .sidebar-content {
23
- background-color: #F0F2F6;
24
- }
25
- .stProgress > div > div > div > div {
26
- background-color: #FF4B4B;
27
- }
28
- .day-card {
29
- padding: 20px;
30
- border-radius: 10px;
31
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
32
- margin-bottom: 20px;
33
- background-color: white;
34
- }
35
- body {
36
- background-image: url('https://images.unsplash.com/photo-7NT4EDSI5Ok');
37
- background-size: cover;
38
- background-position: center;
39
- background-repeat: no-repeat;
40
- background-attachment: fixed;
41
- }
42
- .main > div {
43
- background-color: rgba(255, 255, 255, 0.9);
44
- padding: 20px;
45
- border-radius: 10px;
46
- }
47
  </style>
48
  """, unsafe_allow_html=True)
49
 
50
- # Initialize session state
51
  if 'content_plan' not in st.session_state:
52
  st.session_state.content_plan = None
53
 
@@ -61,41 +37,46 @@ with st.sidebar:
61
 
62
  # Main content
63
  st.markdown('<div class="header">πŸŽ₯ YouTube Content Strategist</div>', unsafe_allow_html=True)
64
- st.write("Generate data-driven content plans using YouTube audience insights")
65
 
66
  # Helper functions
67
- def get_channel_id(channel_url):
68
- """Extract channel ID from URL."""
69
  if "@" in channel_url:
70
- return channel_url.split("@")[-1]
 
71
  elif "channel/" in channel_url:
72
  return channel_url.split("channel/")[-1]
 
 
 
 
 
 
73
  return None
74
 
75
- def get_channel_videos(channel_id):
76
  """Fetch recent video IDs from the channel."""
77
- youtube = googleapiclient.discovery.build("youtube", "v3", developerKey=YOUTUBE_API_KEY)
78
  request = youtube.search().list(
79
  part="id",
80
  channelId=channel_id,
81
- maxResults=MAX_VIDEOS,
82
  order="date",
83
  type="video"
84
  )
85
  response = request.execute()
86
- return [item['id']['videoId'] for item in response['items']]
87
 
88
- def get_video_comments(video_id):
89
  """Fetch comments from a video."""
90
- youtube = googleapiclient.discovery.build("youtube", "v3", developerKey=YOUTUBE_API_KEY)
91
  request = youtube.commentThreads().list(
92
  part="snippet",
93
  videoId=video_id,
94
- maxResults=COMMENTS_PER_VIDEO,
95
  textFormat="plainText"
96
  )
97
  response = request.execute()
98
- return [item['snippet']['topLevelComment']['snippet']['textDisplay'] for item in response['items']]
99
 
100
  def analyze_comments(comments):
101
  """Analyze comments using Gemini API and generate a content plan."""
@@ -115,7 +96,7 @@ def analyze_comments(comments):
115
  response = model.generate_content(prompt)
116
  return response.text
117
 
118
- # Analysis execution
119
  channel_url = st.text_input("Enter YouTube Channel URL:", placeholder="https://www.youtube.com/@ChannelName")
120
 
121
  if st.button("Generate Content Plan πŸš€"):
@@ -123,29 +104,24 @@ if st.button("Generate Content Plan πŸš€"):
123
  st.error("Please fill all required fields!")
124
  else:
125
  try:
126
- # Initialize APIs
127
  youtube = googleapiclient.discovery.build("youtube", "v3", developerKey=YOUTUBE_API_KEY)
128
  genai.configure(api_key=GEMINI_API_KEY)
129
- model = genai.GenerativeModel('gemini-1.5-pro')
130
 
131
- # Get channel data
132
  with st.spinner("πŸ” Analyzing channel..."):
133
- channel_id = get_channel_id(channel_url)
134
  if not channel_id:
135
- st.error("Invalid channel URL")
136
  st.stop()
 
 
137
 
138
- video_ids = get_channel_videos(channel_id)
139
-
140
- # Get comments
141
  all_comments = []
142
  progress_bar = st.progress(0)
143
  for idx, video_id in enumerate(video_ids):
144
  progress = (idx + 1) / len(video_ids)
145
  progress_bar.progress(progress, text=f"πŸ“₯ Collecting comments from video {idx+1}/{len(video_ids)}...")
146
- all_comments.extend(get_video_comments(video_id))
147
-
148
- # Generate content plan
149
  with st.spinner("🧠 Analyzing comments and generating plan..."):
150
  content_plan = analyze_comments(all_comments)
151
  st.session_state.content_plan = content_plan
@@ -158,31 +134,24 @@ if st.button("Generate Content Plan πŸš€"):
158
  if st.session_state.content_plan:
159
  st.markdown("## πŸ“… 10-Day Content Plan")
160
  st.success("Here's your personalized content strategy based on audience insights!")
161
-
162
- # Create date cards
163
  start_date = datetime.now()
164
  for day in range(10):
165
  current_date = start_date + timedelta(days=day)
166
- with st.expander(f"Day {day+1} - {current_date.strftime('%b %d')}", expanded=True if day==0 else False):
167
- # Use .split('\n') instead of f-string splitting
168
- plan_lines = st.session_state.content_plan.split('\n')
169
-
170
- # Calculate start index, accounting for potential inconsistent line counts
171
  start_index = day * 5
172
  if start_index + 4 < len(plan_lines):
173
- st.markdown(f"""
174
-
175
- <div class="day-card">
176
- <h3>{plan_lines[start_index] if start_index < len(plan_lines) else 'No Topic'}</h3>
177
- <p>🎯 Objective: {plan_lines[start_index+1] if start_index+1 < len(plan_lines) else 'N/A'}</p>
178
- <p>πŸ“Ή Format: {plan_lines[start_index+2] if start_index+2 < len(plan_lines) else 'N/A'}</p>
179
- <p>πŸ’‘ Engagement Strategy: {plan_lines[start_index+3] if start_index+3 < len(plan_lines) else 'N/A'}</p>
180
- <p>πŸ“ˆ Success Metrics: {plan_lines[start_index+4] if start_index+4 < len(plan_lines) else 'N/A'}</p>
181
- </div>
182
- """, unsafe_allow_html=True)
183
 
184
-
185
- # Download button
186
  st.download_button(
187
  label="πŸ“₯ Download Full Plan",
188
  data=st.session_state.content_plan,
@@ -190,22 +159,14 @@ if st.session_state.content_plan:
190
  mime="text/plain"
191
  )
192
 
193
- # Instructions
194
  with st.expander("ℹ️ How to use this tool"):
195
  st.markdown("""
196
  1. **Get API Keys**:
197
  - YouTube Data API: [Get it here](https://console.cloud.google.com/)
198
  - Gemini API: [Get it here](https://makersuite.google.com/)
199
-
200
  2. **Enter Channel URL**:
201
- - Supports both channel IDs (@ChannelName) and custom URLs
202
-
203
  3. **Adjust Settings**:
204
- - Control number of videos/comments analyzed in sidebar
205
-
206
  4. **Generate Plan**:
207
- - Click the rocket button to create your strategy
208
-
209
- 5. **Implement & Track**:
210
- - Download the plan and track performance in YouTube Analytics
211
- """)
 
11
  initial_sidebar_state="expanded"
12
  )
13
 
14
+ # Custom CSS
15
+ st.markdown("""
16
  <style>
17
+ .header { font-size: 2.5em !important; color: #FF4B4B !important; margin-bottom: 30px !important; }
18
+ .sidebar .sidebar-content { background-color: #F0F2F6; }
19
+ .stProgress > div > div > div > div { background-color: #FF4B4B; }
20
+ .day-card { padding: 20px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin-bottom: 20px; background-color: white; }
21
+ body { background-size: cover; background-position: center; background-repeat: no-repeat; background-attachment: fixed; }
22
+ .main > div { background-color: rgba(255, 255, 255, 0.9); padding: 20px; border-radius: 10px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  </style>
24
  """, unsafe_allow_html=True)
25
 
26
+ # Session state for content plan
27
  if 'content_plan' not in st.session_state:
28
  st.session_state.content_plan = None
29
 
 
37
 
38
  # Main content
39
  st.markdown('<div class="header">πŸŽ₯ YouTube Content Strategist</div>', unsafe_allow_html=True)
40
+ st.write("Generate data-driven content plans using YouTube audience insights.")
41
 
42
  # Helper functions
43
+ def get_actual_channel_id(youtube, channel_url):
44
+ """Extract real channel ID from a handle (@username) or custom URL."""
45
  if "@" in channel_url:
46
+ username = channel_url.split("@")[-1]
47
+ request = youtube.channels().list(part="id", forHandle=username)
48
  elif "channel/" in channel_url:
49
  return channel_url.split("channel/")[-1]
50
+ else:
51
+ return None
52
+
53
+ response = request.execute()
54
+ if "items" in response and response["items"]:
55
+ return response["items"][0]["id"]
56
  return None
57
 
58
+ def get_channel_videos(youtube, channel_id):
59
  """Fetch recent video IDs from the channel."""
 
60
  request = youtube.search().list(
61
  part="id",
62
  channelId=channel_id,
63
+ maxResults=min(MAX_VIDEOS, 50), # Ensure within API limit
64
  order="date",
65
  type="video"
66
  )
67
  response = request.execute()
68
+ return [item['id']['videoId'] for item in response.get("items", [])]
69
 
70
+ def get_video_comments(youtube, video_id):
71
  """Fetch comments from a video."""
 
72
  request = youtube.commentThreads().list(
73
  part="snippet",
74
  videoId=video_id,
75
+ maxResults=min(COMMENTS_PER_VIDEO, 100), # Ensure within API limit
76
  textFormat="plainText"
77
  )
78
  response = request.execute()
79
+ return [item['snippet']['topLevelComment']['snippet']['textDisplay'] for item in response.get("items", [])]
80
 
81
  def analyze_comments(comments):
82
  """Analyze comments using Gemini API and generate a content plan."""
 
96
  response = model.generate_content(prompt)
97
  return response.text
98
 
99
+ # Get channel URL
100
  channel_url = st.text_input("Enter YouTube Channel URL:", placeholder="https://www.youtube.com/@ChannelName")
101
 
102
  if st.button("Generate Content Plan πŸš€"):
 
104
  st.error("Please fill all required fields!")
105
  else:
106
  try:
 
107
  youtube = googleapiclient.discovery.build("youtube", "v3", developerKey=YOUTUBE_API_KEY)
108
  genai.configure(api_key=GEMINI_API_KEY)
 
109
 
 
110
  with st.spinner("πŸ” Analyzing channel..."):
111
+ channel_id = get_actual_channel_id(youtube, channel_url)
112
  if not channel_id:
113
+ st.error("Invalid channel URL!")
114
  st.stop()
115
+
116
+ video_ids = get_channel_videos(youtube, channel_id)
117
 
 
 
 
118
  all_comments = []
119
  progress_bar = st.progress(0)
120
  for idx, video_id in enumerate(video_ids):
121
  progress = (idx + 1) / len(video_ids)
122
  progress_bar.progress(progress, text=f"πŸ“₯ Collecting comments from video {idx+1}/{len(video_ids)}...")
123
+ all_comments.extend(get_video_comments(youtube, video_id))
124
+
 
125
  with st.spinner("🧠 Analyzing comments and generating plan..."):
126
  content_plan = analyze_comments(all_comments)
127
  st.session_state.content_plan = content_plan
 
134
  if st.session_state.content_plan:
135
  st.markdown("## πŸ“… 10-Day Content Plan")
136
  st.success("Here's your personalized content strategy based on audience insights!")
137
+
 
138
  start_date = datetime.now()
139
  for day in range(10):
140
  current_date = start_date + timedelta(days=day)
141
+ with st.expander(f"Day {day+1} - {current_date.strftime('%b %d')}", expanded=True if day == 0 else False):
142
+ plan_lines = st.session_state.content_plan.split("\n")
 
 
 
143
  start_index = day * 5
144
  if start_index + 4 < len(plan_lines):
145
+ st.markdown(f"""
146
+ <div class="day-card">
147
+ <h3>{plan_lines[start_index] if start_index < len(plan_lines) else 'No Topic'}</h3>
148
+ <p>🎯 Objective: {plan_lines[start_index+1] if start_index+1 < len(plan_lines) else 'N/A'}</p>
149
+ <p>πŸ“Ή Format: {plan_lines[start_index+2] if start_index+2 < len(plan_lines) else 'N/A'}</p>
150
+ <p>πŸ’‘ Engagement Strategy: {plan_lines[start_index+3] if start_index+3 < len(plan_lines) else 'N/A'}</p>
151
+ <p>πŸ“ˆ Success Metrics: {plan_lines[start_index+4] if start_index+4 < len(plan_lines) else 'N/A'}</p>
152
+ </div>
153
+ """, unsafe_allow_html=True)
 
154
 
 
 
155
  st.download_button(
156
  label="πŸ“₯ Download Full Plan",
157
  data=st.session_state.content_plan,
 
159
  mime="text/plain"
160
  )
161
 
 
162
  with st.expander("ℹ️ How to use this tool"):
163
  st.markdown("""
164
  1. **Get API Keys**:
165
  - YouTube Data API: [Get it here](https://console.cloud.google.com/)
166
  - Gemini API: [Get it here](https://makersuite.google.com/)
 
167
  2. **Enter Channel URL**:
 
 
168
  3. **Adjust Settings**:
 
 
169
  4. **Generate Plan**:
170
+ 5. **Download & Track Results**.
171
+ """)
172
+