mirror of
https://github.com/godotengine/godot-showreel-voting.git
synced 2025-12-31 17:49:06 +03:00
* initial backend setup
* copied db setup
* added login
* added autoincrement to ids
* update db again
* added script to populate with test data
* added functionality to fetch videos
* added vote functionality
* added logic to update video info
* added history
* updated readme
* Update thank you page
* fixed small bugs
* small improvements
* added admin view, UI fix
* fix vote buttons style
* added pagination
* added command to load sample data from csv
* Autoplay videos
* Adding before you vote page
* added yt video id extractor
* improve visibility for the history page votes
* added logic for before you vote disclaimer
* Remind people to set videos to unlisted and allowed for embed
* Update home.html
* Update home.html
* Add progress bar to total
* Small adjustments
* fix home {% if user %}
* Update macros.html
* limit vote views to users with specific roles
* added endpoint to delete votes
* added confirmation to the delete vote action
* Update non-fund members CTA
* allow voting to specific fund members
* added result csv endpoint
* updated auth
* revert adding 'vote_allowed' column, merged it into is_staff
* added `is_fund_member` attribute to table and updated code
* refactored code
* update style for voting page
* updated readme
* Add static files
* remove options from dropdown for users that can't vote
* added keyboard shortcuts to vote buttons
* added azerty support for shortcuts
* update skip to S key
* remove placeholder
---------
Co-authored-by: Emi <2206700+coppolaemilio@users.noreply.github.com>
123 lines
4.1 KiB
Python
123 lines
4.1 KiB
Python
from urllib.parse import parse_qs, urlparse
|
|
from werkzeug.exceptions import NotFound
|
|
|
|
from typing import Dict, List, Optional, Tuple
|
|
from sqlalchemy import and_, func
|
|
from gdshowreelvote.database import DB, Showreel, ShowreelStatus, User, Video, Vote
|
|
|
|
|
|
def choose_random_video(user: User, skip_videos: List[int]=[]) -> Video:
|
|
""" Choose a random video from the showreel that the user has not voted on yet. """
|
|
# Is there any chance that there are multiple showreels in VOTE status?
|
|
# Should we choose the showreel with a specific ID?
|
|
random_video_without_votes = (
|
|
DB.session.query(Video)
|
|
.join(Showreel, Video.showreel_id == Showreel.id) # join explicitly
|
|
.outerjoin(Vote, and_(Video.id == Vote.video_id, Vote.user_id == user.id))
|
|
.filter(Showreel.status == ShowreelStatus.VOTE) # filter on Showreel column
|
|
.filter(Vote.id == None) # exclude videos already voted on by this user
|
|
.filter(Video.id.notin_(skip_videos)) # exclude skipped videos
|
|
.order_by(func.random())
|
|
.first()
|
|
)
|
|
|
|
return random_video_without_votes
|
|
|
|
|
|
def upvote_video(user: User, video: Video):
|
|
""" Cast an upvote for a video by a user. """
|
|
vote = DB.session.query(Vote).filter(and_(Vote.user_id == user.id, Vote.video_id == video.id)).first()
|
|
if vote:
|
|
vote.rating = 1
|
|
else:
|
|
vote = Vote(user_id=user.id, video_id=video.id, rating=1)
|
|
DB.session.add(vote)
|
|
DB.session.commit()
|
|
return vote
|
|
|
|
|
|
def downvote_video(user: User, video: Video):
|
|
""" Cast a downvote for a video by a user. """
|
|
vote = DB.session.query(Vote).filter(and_(Vote.user_id == user.id, Vote.video_id == video.id)).first()
|
|
if vote:
|
|
vote.rating = -1
|
|
else:
|
|
vote = Vote(user_id=user.id, video_id=video.id, rating=-1)
|
|
DB.session.add(vote)
|
|
DB.session.commit()
|
|
return vote
|
|
|
|
|
|
def _video_data(video: Video) -> Dict:
|
|
data = {
|
|
'id': video.id,
|
|
'game': video.game,
|
|
'author': video.author_name,
|
|
'follow_me_link': video.follow_me_link,
|
|
'video_link': video.video_link,
|
|
'store_link': video.store_link,
|
|
'category': video.showreel.title,
|
|
}
|
|
|
|
youtube_id = parse_youtuvbe_video_id(video.video_link)
|
|
data['youtube_embed'] = f'https://www.youtube.com/embed/{youtube_id}'
|
|
return data
|
|
|
|
|
|
def vote_data(user: User, video: Video) -> Tuple[Dict, Dict]:
|
|
total_video_count = DB.session.query(Video).count()
|
|
total_user_votes = DB.session.query(Vote).filter(Vote.user_id == user.id).count()
|
|
|
|
data = _video_data(video) if video else None
|
|
|
|
progress = {
|
|
'total': total_video_count,
|
|
'current': total_user_votes,
|
|
}
|
|
|
|
return data, progress
|
|
|
|
|
|
def get_total_votes(page: int) -> List[Tuple[Video, int, int]]:
|
|
query = (
|
|
DB.session.query(
|
|
Video,
|
|
func.coalesce(func.sum(Vote.rating), 0).label("vote_sum"),
|
|
func.count(Vote.id).label("vote_count"),
|
|
)
|
|
.outerjoin(Vote, Vote.video_id == Video.id)
|
|
.group_by(Video.id)
|
|
.order_by(func.coalesce(func.sum(Vote.rating), 0).desc())
|
|
)
|
|
|
|
try:
|
|
results = query.paginate(page=page, per_page=30)
|
|
except NotFound:
|
|
results = query.paginate(page=1, per_page=30)
|
|
|
|
return results
|
|
|
|
|
|
def parse_youtuvbe_video_id(yt_url: str) -> Optional[str]:
|
|
"""
|
|
Source: https://stackoverflow.com/questions/4356538/how-can-i-extract-video-id-from-youtubes-link-in-python/7936523#7936523
|
|
Examples:
|
|
- http://youtu.be/SA2iWivDJiE
|
|
- http://www.youtube.com/watch?v=_oPAwA_Udwc&feature=feedu
|
|
- http://www.youtube.com/embed/SA2iWivDJiE
|
|
- http://www.youtube.com/v/SA2iWivDJiE?version=3&hl=en_US
|
|
"""
|
|
query = urlparse(yt_url)
|
|
if query.hostname == 'youtu.be':
|
|
return query.path[1:]
|
|
if query.hostname in ('www.youtube.com', 'youtube.com', 'm.youtube.com'):
|
|
if query.path == '/watch':
|
|
p = parse_qs(query.query)
|
|
return p['v'][0]
|
|
if query.path[:7] == '/embed/':
|
|
return query.path.split('/')[2]
|
|
if query.path[:3] == '/v/':
|
|
return query.path.split('/')[2]
|
|
# fail?
|
|
return None
|