Skip to content

Commit

Permalink
Enhances local upload process
Browse files Browse the repository at this point in the history
  • Loading branch information
asantacreu committed Feb 6, 2025
1 parent 543f748 commit 4f181e6
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 20 deletions.
18 changes: 12 additions & 6 deletions application.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ def video_uploader_not_working():
def video_uploader():
user_uid = session.get('uid')
user_data = getUserData(user_uid)
contributors = utils.MadBoulderDatabase.getContributorsList()
climbers = [data["name"] for data in contributors.values()]
contributors = utils.MadBoulderDatabase.getContributorNames()
climbers = contributors
playlists = utils.MadBoulderDatabase.getPlaylistsData()
areas = {
playlist["zone_code"]: {
Expand Down Expand Up @@ -382,11 +382,17 @@ def local_upload_hub():
isAuthenticated = utils.channel.is_authenticated()
if not isAuthenticated:
return render_template('local-upload-hub.html', authenticated=False)
contributors = utils.MadBoulderDatabase.getContributorsList()
climbers = [data["name"] for data in contributors.values()]

try:
contributors = utils.MadBoulderDatabase.getContributorNames()
climbers = contributors # Direct assignment since contributors is a list of names
except Exception as e:
print(f"Error fetching contributor names: {e}")
climbers = [] # Fallback to empty list if an error occurs

return render_template("local-upload-hub.html",
authenticated=True,
climbers=climbers
climbers=sorted(climbers)
)


Expand Down Expand Up @@ -821,7 +827,7 @@ def settings_projects():
@admin_required
def settings_admin_users():
users_list, admins_list = get_all_users()
contributors = utils.MadBoulderDatabase.getContributorsList()
contributors = utils.MadBoulderDatabase.getContributorNames()
return render_template('settings/settings-admin-users.html', users_list=users_list, contributors=contributors)


Expand Down
23 changes: 23 additions & 0 deletions templates/local-upload-hub.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ <h1>MadBoulder Local Upload Hub</h1>
{% if authenticated %}
<p>You are authenticated with Google.</p>
<form id="localUploadForm" action="/process-upload-youtube-from-local" method="post" enctype="multipart/form-data">
<!-- Add a button to refresh the video list -->
<button id="refreshVideoList" type="button">Refresh Video List</button>

<h2>Select a Video File</h2>
<select id="videoFile" name="video" required>
<option value="">Select a video...</option>
Expand Down Expand Up @@ -192,6 +195,25 @@ <h2>Enter Video Details</h2>
return result;
}

// Function to refresh the video list
async function refreshVideoList() {
const select = document.getElementById('videoFile');
select.innerHTML = '<option value="">Select a video...</option>'; // Clear existing options

try {
const response = await fetch('/list-local-videos'); // Fetch the updated video list
const data = await response.json();
data.videos.forEach(video => {
const option = document.createElement('option');
option.value = video;
option.textContent = video;
select.appendChild(option);
});
} catch (error) {
console.error('Error fetching video list:', error);
}
}

// Load video list when page loads
fetch('/list-local-videos')
.then(response => response.json())
Expand Down Expand Up @@ -301,6 +323,7 @@ <h2>Enter Video Details</h2>

// Add event listener for the refresh button
document.getElementById('checkSchedule').addEventListener('click', checkSchedule);
document.getElementById('refreshVideoList').addEventListener('click', refreshVideoList);
</script>
</body>
</html>
23 changes: 22 additions & 1 deletion utils/MadBoulderDatabase.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ def setPlaylistData(playlists):
utils.database.updateDate('playlist_data')
getPlaylistsData.cache_clear()

def setPlaylistItem(zone_code, data):
utils.database.setValue(f'playlist_data/items/{zone_code}', data)
getPlaylistsData.cache_clear()

def getAreasCount():
return utils.database.getValue('areas_count')

Expand Down Expand Up @@ -335,4 +339,21 @@ def migrateData(oldSlug, newSlug):
oldComments = getComments(oldEncodedSlug)
if oldComments:
utils.database.setValue(f'problems/{newEncodedSlug}/comments', oldComments)
utils.database.delete(f'problems/{oldEncodedSlug}/comments')
utils.database.delete(f'problems/{oldEncodedSlug}/comments')

@lru_cache(maxsize=1)
def getContributorNames():
"""Retrieve a list of contributor names from the database with caching."""
print("get_contributor_names")

# Retrieve all contributors at once
contributors = utils.database.getValue('contributors') # Retrieves all contributors

if not contributors:
print("No contributors found.")
return []

# Extract names from the retrieved data
contributor_names = [contributor['name'] for contributor in contributors.values() if 'name' in contributor]
return contributor_names

41 changes: 40 additions & 1 deletion utils/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from googleapiclient.http import MediaIoBaseUpload
from google.auth.transport.requests import Request
from datetime import datetime, timedelta
from googleapiclient.errors import HttpError

from google_auth_oauthlib.flow import Flow

Expand Down Expand Up @@ -405,4 +406,42 @@ def parse_video_description(description):
elif key == 'sector':
metadata['sector'] = value

return metadata
return metadata


def createPlaylist(area_name, privacy_status='public'):
"""Create a new playlist for the given area."""
credentials = getCredentials()
youtubeOauth = build(API_NAME, API_VERSION, credentials=credentials)
try:
# Define the request body for the playlist
request_body = {
'snippet': {
'title': area_name,
'description': f'Playlist for the bouldering area: {area_name}',
'tags': ['bouldering', 'climbing', area_name],
'defaultLanguage': 'en'
},
'status': {
'privacyStatus': privacy_status # Configurable privacy status
}
}

# Call the YouTube API to create the playlist
response = youtubeOauth.playlists().insert(
part='snippet,status',
body=request_body
).execute()

# Validate response and log
if 'id' in response:
print(f"Playlist created successfully: ID={response['id']}, Title={area_name}")
return response['id']
else:
print(f"Unexpected response structure: {response}")
return None

except HttpError as e:
error_content = e.content.decode('utf-8') if hasattr(e, 'content') else str(e)
print(f"An error occurred while creating the playlist: {error_content}")
return None
62 changes: 52 additions & 10 deletions utils/channel_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from flask import jsonify
import utils.channel
import utils.MadBoulderDatabase
import re # Add this import at the top of the file

def process_channel_upload(title, description, tags, scheduled_time, zone_code, sector_code, video_stream):
"""
Expand Down Expand Up @@ -35,25 +36,66 @@ def process_channel_upload(title, description, tags, scheduled_time, zone_code,
publish_time=publish_time
)

uploaded_video_id = response['id']
if response is None:
raise Exception("Video upload failed, no response received.")

uploaded_video_id = response.get('id')
if not uploaded_video_id:
raise Exception("Upload response does not contain video ID.")

print("video uploaded to channel")

# Add to playlists
print(f"adding video to playlist {zone_code}")
playlists = utils.MadBoulderDatabase.getPlaylistData(zone_code)
zone_playlist_id = playlists.get("id")
sector_playlists = playlists.get("sectors", {})

zone_playlist_id = playlists.get("id") if playlists else None
sector_playlists = playlists.get("sectors", {}) if playlists else {}

# Check if the zone playlist exists, if not create it
if not zone_playlist_id:
# Extract zone name from title using regex
match = re.search(r',\s*[^.]+\. (.+)', title) # Adjusted regex to capture the entire AreaName
zone_name = match.group(1).strip() if match else None # Extract AreaName or set to None if not found

if not zone_name:
print("Zone name could not be extracted from the title, falling back to zone_code.")
zone_name = zone_code # Fallback to zone_code if zone_name is not found

zone_playlist_id = utils.channel.createPlaylist(zone_name) # Use zone_name instead of zone_code
if not zone_playlist_id:
raise Exception(f"Failed to create playlist for zone: {zone_name}")
else:
print(f"Created new playlist for zone: {zone_name} with ID: {zone_playlist_id}")
# Store the new playlist ID in the database
utils.MadBoulderDatabase.setPlaylistItem(zone_code,{"id": zone_playlist_id, "sectors": {}})

# Add video to the zone playlist
if zone_playlist_id:
utils.channel.addVideoToPlaylist(uploaded_video_id, zone_playlist_id)
add_response = utils.channel.addVideoToPlaylist(uploaded_video_id, zone_playlist_id)
if not add_response:
print(f"Failed to add video {uploaded_video_id} to playlist {zone_playlist_id}")
else:
print(f"Video {uploaded_video_id} added to playlist {zone_playlist_id}")

if sector_code in sector_playlists:
print("adding video to sector playlist")
sector_playlist_id = sector_playlists[sector_code]["id"]
utils.channel.addVideoToPlaylist(uploaded_video_id, sector_playlist_id)
# Check if the sector playlist exists, if so add the video
if sector_code:
sector_playlist = sector_playlists.get(sector_code)
if sector_playlist:
sector_playlist_id = sector_playlist.get("id")
if sector_playlist_id:
add_sector_response = utils.channel.addVideoToPlaylist(uploaded_video_id, sector_playlist_id)
if not add_sector_response:
print(f"Failed to add video {uploaded_video_id} to sector playlist {sector_playlist_id}")
else:
print(f"Video {uploaded_video_id} added to sector playlist {sector_playlist_id}")
else:
print(f"Sector playlist ID not found for sector: {sector_code}")
else:
print(f"No sector playlist found for sector code: {sector_code}")

print("enabling video monetization")
utils.channel.enableMonetization(uploaded_video_id)
#print("enabling video monetization")
#utils.channel.enableMonetization(uploaded_video_id) # not working

return response, publish_time, None

Expand Down
1 change: 0 additions & 1 deletion utils/database.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
Expand Down
8 changes: 7 additions & 1 deletion utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,14 @@ def isVideoShort(file_id):
"""Determine if a video qualifies as a YouTube Short based on its metadata."""
try:
metadata = utils.drive.getFileMetadata(file_id)
if metadata is None:
print(f"Error: No metadata found for file ID {file_id}.")
return False

video_metadata = metadata.get('videoMediaMetadata', {})
if not video_metadata:
print(f"Error: No video media metadata found for file ID {file_id}.")
return False

duration_millis = video_metadata.get('durationMillis', 0)
duration_seconds = int(duration_millis) / 1000
Expand All @@ -188,7 +195,6 @@ def isVideoShort(file_id):

except Exception as e:
print(f"Error determining if video is short: {e}")
print(f"Video metadata: {metadata}") # Debug print
return False


Expand Down
1 change: 1 addition & 0 deletions utils/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class SchedulingPrompts:
3. The same zone/area should not appear multiple times on the same day
4. Try to space out videos from the same zone across different days
5. If a slot is taken or any rule is violated on a given day, recommend the next available day
6. Never propose a past date or hour
IMPORTANT: Return hours in UTC.
"""
Expand Down

0 comments on commit 4f181e6

Please sign in to comment.