Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add educational video submission feature #3803

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

DonnieBLT
Copy link
Collaborator

@DonnieBLT DonnieBLT commented Mar 4, 2025

User description


For more details, open the Copilot Workspace session.


PR Type

Enhancement, Tests


Description

  • Added a feature to submit educational videos.

  • Implemented backend validation for YouTube/Vimeo URLs.

  • Integrated APIs to fetch video metadata and validate educational content.

  • Created a new database model for storing educational videos.


Changes walkthrough 📝

Relevant files
Enhancement
education.html
Add educational video submission form                                       

website/templates/education/education.html

  • Added a form for submitting educational videos.
  • Included input validation and error message display.
  • +10/-0   
    forms.py
    Create video submission form class                                             

    website/forms.py

  • Created a new form class for video submission.
  • Added URL validation and input attributes.
  • +13/-0   
    0219_add_educational_video_model.py
    Add migration for EducationalVideo model                                 

    website/migrations/0219_add_educational_video_model.py

  • Added a migration for the EducationalVideo model.
  • Defined fields for video URL, title, description, and educational
    status.
  • +21/-0   
    models.py
    Define EducationalVideo model                                                       

    website/models.py

  • Created the EducationalVideo model.
  • Added fields for storing video metadata and timestamps.
  • +11/-0   
    education.py
    Add video submission backend logic                                             

    website/views/education.py

  • Implemented the add_video view for handling submissions.
  • Added functions to fetch video metadata from YouTube/Vimeo APIs.
  • Integrated OpenAI API to validate educational content.
  • +103/-2 
    Configuration changes
    urls.py
    Add URL route for video submission                                             

    blt/urls.py

  • Added a new URL route for video submission.
  • Linked the route to the add_video view.
  • +2/-0     

    Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • Copy link
    Contributor

    github-actions bot commented Mar 4, 2025

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 No relevant tests
    🔒 Security concerns

    Sensitive information exposure:
    The code includes hardcoded API keys (YOUR_YOUTUBE_API_KEY, YOUR_VIMEO_ACCESS_TOKEN, YOUR_OPENAI_API_KEY), which could lead to security vulnerabilities if not replaced with secure methods of storing and accessing sensitive information.

    ⚡ Recommended focus areas for review

    Hardcoded API Keys

    The code contains hardcoded placeholders for API keys (YOUR_YOUTUBE_API_KEY, YOUR_VIMEO_ACCESS_TOKEN, YOUR_OPENAI_API_KEY). These should be replaced with environment variables or a secure configuration management system.

        api_key = "YOUR_YOUTUBE_API_KEY"
        video_id = extract_youtube_video_id(video_url)
        if not video_id:
            return None
    
        api_url = f"https://www.googleapis.com/youtube/v3/videos?id={video_id}&key={api_key}&part=snippet"
        response = requests.get(api_url)
        if response.status_code != 200:
            return None
    
        data = response.json()
        if "items" not in data or not data["items"]:
            return None
    
        snippet = data["items"][0]["snippet"]
        return {"title": snippet["title"], "description": snippet["description"]}
    
    
    def extract_youtube_video_id(video_url):
        match = re.search(r"(?:v=|\/)([0-9A-Za-z_-]{11}).*", video_url)
        return match.group(1) if match else None
    
    
    def fetch_vimeo_video_data(video_url):
        video_id = extract_vimeo_video_id(video_url)
        if not video_id:
            return None
    
        api_url = f"https://api.vimeo.com/videos/{video_id}"
        headers = {"Authorization": "Bearer YOUR_VIMEO_ACCESS_TOKEN"}
        response = requests.get(api_url, headers=headers)
        if response.status_code != 200:
            return None
    
        data = response.json()
        return {"title": data["name"], "description": data["description"]}
    
    
    def extract_vimeo_video_id(video_url):
        match = re.search(r"vimeo\.com\/(\d+)", video_url)
        return match.group(1) if match else None
    
    
    def is_educational_video(title, description):
        openai_api_key = "YOUR_OPENAI_API_KEY"
        prompt = f"Is the following video educational?\n\nTitle: {title}\n\nDescription: {description}\n\nAnswer with 'yes' or 'no'."
        response = requests.post(
            "https://api.openai.com/v1/engines/davinci-codex/completions",
            headers={"Authorization": f"Bearer {openai_api_key}"},
    Video URL Validation

    The regular expression used to validate YouTube and Vimeo URLs may not cover all valid URL formats. This could lead to false negatives or positives.

    if not re.match(r"(https?://)?(www\.)?(youtube|vimeo)\.com/", video_url):
        return JsonResponse({"success": False, "message": "Only YouTube or Vimeo URLs are allowed."}, status=400)
    OpenAI API Dependency

    The is_educational_video function relies on the OpenAI API for determining if a video is educational. This introduces external dependency risks, such as API downtime or rate limits, which may affect functionality.

    def is_educational_video(title, description):
        openai_api_key = "YOUR_OPENAI_API_KEY"
        prompt = f"Is the following video educational?\n\nTitle: {title}\n\nDescription: {description}\n\nAnswer with 'yes' or 'no'."
        response = requests.post(
            "https://api.openai.com/v1/engines/davinci-codex/completions",
            headers={"Authorization": f"Bearer {openai_api_key}"},
            json={"prompt": prompt, "max_tokens": 5},
        )
        if response.status_code != 200:
            return False
    
        answer = response.json()["choices"][0]["text"].strip().lower()
        return answer == "yes"

    Copy link
    Contributor

    github-actions bot commented Mar 4, 2025

    PR Code Suggestions ✨

    …ng sanitization
    
    Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
    def fetch_video_data(video_url):
    parsed_url = urlparse(video_url)
    host = parsed_url.hostname
    if host and (host.endswith("youtube.com") or host == "youtu.be"):

    Check failure

    Code scanning / CodeQL

    Incomplete URL substring sanitization High

    The string
    youtube.com
    may be at an arbitrary position in the sanitized URL.

    Copilot Autofix AI 9 days ago

    To fix the problem, we need to ensure that the URL host is strictly validated against a list of allowed hosts. Instead of using host.endswith("youtube.com"), we should check if the host is exactly "youtube.com" or "www.youtube.com". This will prevent malicious URLs from bypassing the check.

    • Modify the fetch_video_data function to use a stricter check for YouTube URLs.
    • Update the condition to check if the host is exactly "youtube.com" or "www.youtube.com".
    Suggested changeset 1
    website/views/education.py

    Autofix patch

    Autofix patch
    Run the following command in your local git repository to apply this patch
    cat << 'EOF' | git apply
    diff --git a/website/views/education.py b/website/views/education.py
    --- a/website/views/education.py
    +++ b/website/views/education.py
    @@ -573,3 +573,3 @@
         host = parsed_url.hostname
    -    if host and (host.endswith("youtube.com") or host == "youtu.be"):
    +    if host and (host in ["youtube.com", "www.youtube.com", "youtu.be"]):
             return fetch_youtube_video_data(video_url)
    EOF
    @@ -573,3 +573,3 @@
    host = parsed_url.hostname
    if host and (host.endswith("youtube.com") or host == "youtu.be"):
    if host and (host in ["youtube.com", "www.youtube.com", "youtu.be"]):
    return fetch_youtube_video_data(video_url)
    Copilot is powered by AI and may make mistakes. Always verify output.
    Positive Feedback
    Negative Feedback

    Provide additional feedback

    Please help us improve GitHub Copilot by sharing more details about this comment.

    Please select one or more of the options
    host = parsed_url.hostname
    if host and (host.endswith("youtube.com") or host == "youtu.be"):
    return fetch_youtube_video_data(video_url)
    elif host and host.endswith("vimeo.com"):

    Check failure

    Code scanning / CodeQL

    Incomplete URL substring sanitization High

    The string
    vimeo.com
    may be at an arbitrary position in the sanitized URL.

    Copilot Autofix AI 9 days ago

    To fix the problem, we need to ensure that the hostname check is more stringent. Instead of using host.endswith("vimeo.com"), we should check that the hostname is exactly vimeo.com or a subdomain of vimeo.com. This can be done by ensuring that the hostname ends with .vimeo.com or is exactly vimeo.com.

    • Modify the check on line 576 to ensure that the hostname is either vimeo.com or ends with .vimeo.com.
    • No new methods or imports are needed to implement this change.
    Suggested changeset 1
    website/views/education.py

    Autofix patch

    Autofix patch
    Run the following command in your local git repository to apply this patch
    cat << 'EOF' | git apply
    diff --git a/website/views/education.py b/website/views/education.py
    --- a/website/views/education.py
    +++ b/website/views/education.py
    @@ -575,3 +575,3 @@
             return fetch_youtube_video_data(video_url)
    -    elif host and host.endswith("vimeo.com"):
    +    elif host and (host == "vimeo.com" or host.endswith(".vimeo.com")):
             return fetch_vimeo_video_data(video_url)
    EOF
    @@ -575,3 +575,3 @@
    return fetch_youtube_video_data(video_url)
    elif host and host.endswith("vimeo.com"):
    elif host and (host == "vimeo.com" or host.endswith(".vimeo.com")):
    return fetch_vimeo_video_data(video_url)
    Copilot is powered by AI and may make mistakes. Always verify output.
    Positive Feedback
    Negative Feedback

    Provide additional feedback

    Please help us improve GitHub Copilot by sharing more details about this comment.

    Please select one or more of the options
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant