From 150a2a5cd48b8f77911754598d3e3332b794ba18 Mon Sep 17 00:00:00 2001 From: Anderson Singh Date: Wed, 17 Apr 2024 01:53:37 +0000 Subject: [PATCH 1/9] new file: App/controllers/testingfunctions.py modified: App/main.py modified: App/models/user.py modified: App/static/style.css modified: App/templates/index.html modified: App/templates/layout.html new file: App/templates/playlist.html modified: App/views/index.py --- App/controllers/testingfunctions.py | 58 ++++++++++++++ App/main.py | 52 +++++++++++++ App/models/user.py | 22 ++++++ App/static/style.css | 49 ++++++++++++ App/templates/index.html | 50 ++++++++++-- App/templates/layout.html | 18 +++-- App/templates/playlist.html | 38 +++++++++ App/views/index.py | 117 +++++++++++++++++++++++++++- 8 files changed, 387 insertions(+), 17 deletions(-) create mode 100644 App/controllers/testingfunctions.py create mode 100644 App/templates/playlist.html diff --git a/App/controllers/testingfunctions.py b/App/controllers/testingfunctions.py new file mode 100644 index 00000000..39c300c1 --- /dev/null +++ b/App/controllers/testingfunctions.py @@ -0,0 +1,58 @@ +from googleapiclient.discovery import build +from googleapiclient.errors import HttpError + +apiKey = 'AIzaSyAa3sah23VK9X4r0hxsC4xHvWTUeLurpv8' +youtube = build('youtube', 'v3', developerKey=apiKey) + +class Video: + def __init__(self, title, image_url, video_url, description, video_id): + self.title = title + self.image_url = image_url + self.video_url = video_url + self.description = description + self.video_id = video_id + + +def get_video_url(video_id): + return f"https://www.youtube.com/watch?v={video_id}" + +def search_by_keyword(api_key, keyword, max_results): + youtube = build("youtube", "v3", developerKey=api_key) + + try: + request = youtube.search().list( + part="id,snippet", + q=keyword, + maxResults=max_results + ) + response = request.execute() + videos = [] + if "items" in response: + for item in response["items"]: + if item["id"].get("kind") == "youtube#video": + video_id = item["id"]["videoId"] + video_url = get_video_url(video_id) + title = item["snippet"]["title"] + image = item["snippet"]["thumbnails"]["default"]["url"] + description = item["snippet"]["description"] + video = Video(title, image, video_url, description, video_id) + videos.append(video) + else: + print("This item is not a video.") + else: + print("No videos found.") + + except HttpError as e: + print("An HTTP error occurred:") + print(e.content) + + return videos + +def home(): + videos = search_by_keyword("AIzaSyAa3sah23VK9X4r0hxsC4xHvWTUeLurpv8", "fitness", 30) + print(videos) + +home() + + + diff --git a/App/main.py b/App/main.py index 5fdc15cc..63144cf0 100644 --- a/App/main.py +++ b/App/main.py @@ -4,6 +4,8 @@ from flask_cors import CORS from werkzeug.utils import secure_filename from werkzeug.datastructures import FileStorage +from googleapiclient.discovery import build +from googleapiclient.errors import HttpError from App.database import init_db from App.config import load_config @@ -15,6 +17,14 @@ from App.views import views +class Video: + def __init__(self, title, image_url, video_url, description, video_id): + self.title = title + self.image_url = image_url + self.video_url = video_url + self.description = description + self.video_id = video_id + def add_views(app): for view in views: app.register_blueprint(view) @@ -38,3 +48,45 @@ def custom_unauthorized_response(error): app.app_context().push() return app +def get_video_url(video_id): + return f"https://www.youtube.com/watch?v={video_id}" + +def search_by_keyword(api_key, keyword, max_results): + youtube = build("youtube", "v3", developerKey=api_key) + + try: + request = youtube.search().list( + part="id,snippet", + q=keyword, + maxResults=max_results + ) + response = request.execute() + videos = [] + if "items" in response: + for item in response["items"]: + if item["id"].get("kind") == "youtube#video": + video_id = item["id"]["videoId"] + video_url = get_video_url(video_id) + title = item["snippet"]["title"] + image = item["snippet"]["thumbnails"]["default"]["url"] + description = item["snippet"]["description"] + video = Video(title, image, video_url, description, video_id) + videos.append(video) + else: + print("This item is not a video.") + else: + print("No videos found.") + + except HttpError as e: + print("An HTTP error occurred:") + print(e.content) + + return videos + +app = create_app() # Create the app object + +@app.route('/home') +def home(): + videos = search_by_keyword("AIzaSyAa3sah23VK9X4r0hxsC4xHvWTUeLurpv8", "fitness", 30) + return render_template('index.html', videos=videos) + diff --git a/App/models/user.py b/App/models/user.py index 8efe083a..db93ce10 100644 --- a/App/models/user.py +++ b/App/models/user.py @@ -5,6 +5,9 @@ class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String, nullable=False, unique=True) password = db.Column(db.String(120), nullable=False) + height = db.Column(db.Double, nullable=True) + weight = db.Column(db.Double, nullable=True) + videos = db.relationship('Video', backref='user', lazy=True, cascade="all, delete-orphan") def __init__(self, username, password): self.username = username @@ -24,3 +27,22 @@ def check_password(self, password): """Check hashed password.""" return check_password_hash(self.password, password) +class Video(db.Model): + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + title = db.Column(db.String(120)) + image = db.Column(db.String(120)) + description = db.Column(db.String(120)) + url = db.Column(db.String(120)) + + def __init__(self, title, image, description, url, user_id): + self.title = title + self.image = image + self.description = description + self.url = url + self.user_id = user_id + + + + + diff --git a/App/static/style.css b/App/static/style.css index e69de29b..5b64aa96 100644 --- a/App/static/style.css +++ b/App/static/style.css @@ -0,0 +1,49 @@ +.search-bar { + margin-bottom: 10px; + overflow: hidden; +} + +.search-bar input[type="text"] { + + float: left; +} + +.search-bar button { + float: right; +} + +/* Side menu (index.html) */ +.vertical-menu { + /* Your side menu styling */ + width: 200px; + float: left; + background-color: #f8f9fa; + border-right: 1px solid #ccc; +} + +.vertical-menu a { + display: block; + padding: 10px; + text-decoration: none; +} + +/* active link (index.html) */ +.vertical-menu a.active { + background-color: #ccc; +} + +/* Grid menu contents (index.html) */ +.grid-container { + overflow: hidden; +} + +.grid-item { + + background-color: #f0f0f0; + padding: 20px; + text-align: center; + float: left; + width: calc(33.33% - 20px); + margin: 10px; + box-sizing: border-box; +} \ No newline at end of file diff --git a/App/templates/index.html b/App/templates/index.html index 96ec1967..17cb8371 100644 --- a/App/templates/index.html +++ b/App/templates/index.html @@ -2,12 +2,50 @@ {% block title %}Flask MVC App{% endblock %} {% block page %}Flask MVC App{% endblock %} -{{ super() }} - {% block content %} -

Flask MVC

+

TBD Workout Planner

{% if is_authenticated %} -

Welcome {{current_user.username}}

+

Welcome {{ current_user.username }}

{% endif %} -

This is a boileplate flask application which follows the MVC pattern for structuring the project.

-{% endblock %} \ No newline at end of file +

This is a boilerplate Flask application which follows the MVC pattern for structuring the project.

+ + + +
+ + +
+ + {% for video in videos %} +
+
+
+ +
+
+
{{ video.title }}
+

{{ video.description }}

+ Watch Video + {% if is_authenticated %} +
+ + + + + +
+ {%endif%} +
+
+
+ {% endfor %} +
+
+{% endblock %} diff --git a/App/templates/layout.html b/App/templates/layout.html index ae01fe22..f17111d7 100644 --- a/App/templates/layout.html +++ b/App/templates/layout.html @@ -15,6 +15,15 @@