|
@@ -1,19 +1,11 @@
|
|
|
-import datetime
|
|
|
-
|
|
|
-import requests
|
|
|
from django.contrib.auth.models import User
|
|
|
-from allauth.socialaccount.models import SocialAccount, SocialApp, SocialToken
|
|
|
-from apps.users.models import Profile
|
|
|
from .util import *
|
|
|
import pytz
|
|
|
-from UnTube.secrets import SECRETS
|
|
|
from django.db import models
|
|
|
-from google.oauth2.credentials import Credentials
|
|
|
-from google.auth.transport.requests import Request
|
|
|
-from datetime import timedelta
|
|
|
from googleapiclient.discovery import build
|
|
|
import googleapiclient.errors
|
|
|
from django.db.models import Q, Sum
|
|
|
+from ..general.utils.misc import print_
|
|
|
|
|
|
|
|
|
def get_message_from_httperror(e):
|
|
@@ -21,24 +13,24 @@ def get_message_from_httperror(e):
|
|
|
|
|
|
|
|
|
class PlaylistManager(models.Manager):
|
|
|
- def getCredentials(self, user):
|
|
|
- app = SocialApp.objects.get(provider='google')
|
|
|
- credentials = Credentials(
|
|
|
- token=user.profile.access_token,
|
|
|
- refresh_token=user.profile.refresh_token,
|
|
|
- token_uri="https://oauth2.googleapis.com/token",
|
|
|
- client_id=app.client_id,
|
|
|
- client_secret=app.secret,
|
|
|
- scopes=['https://www.googleapis.com/auth/youtube']
|
|
|
- )
|
|
|
-
|
|
|
- if not credentials.valid:
|
|
|
- credentials.refresh(Request())
|
|
|
- user.profile.access_token = credentials.token
|
|
|
- user.profile.refresh_token = credentials.refresh_token
|
|
|
- user.save()
|
|
|
-
|
|
|
- return credentials
|
|
|
+ # def getCredentials(self, user):
|
|
|
+ # app = SocialApp.objects.get(provider='google')
|
|
|
+ # credentials = Credentials(
|
|
|
+ # token=user.profile.access_token,
|
|
|
+ # refresh_token=user.profile.refresh_token,
|
|
|
+ # token_uri="https://oauth2.googleapis.com/token",
|
|
|
+ # client_id=app.client_id,
|
|
|
+ # client_secret=app.secret,
|
|
|
+ # scopes=['https://www.googleapis.com/auth/youtube']
|
|
|
+ # )
|
|
|
+ #
|
|
|
+ # if not credentials.valid:
|
|
|
+ # credentials.refresh(Request())
|
|
|
+ # user.profile.access_token = credentials.token
|
|
|
+ # user.profile.refresh_token = credentials.refresh_token
|
|
|
+ # user.save()
|
|
|
+ #
|
|
|
+ # return credentials
|
|
|
|
|
|
def getPlaylistId(self, playlist_link):
|
|
|
if "?" not in playlist_link:
|
|
@@ -53,7 +45,11 @@ class PlaylistManager(models.Manager):
|
|
|
# Used to check if the user has a vaild YouTube channel
|
|
|
# Will return -1 if user does not have a YouTube channel
|
|
|
def getUserYTChannelID(self, user):
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ user_profile = user.profile
|
|
|
+ if user_profile.yt_channel_id != "":
|
|
|
+ return 0
|
|
|
+
|
|
|
+ credentials = user_profile.get_credentials()
|
|
|
|
|
|
with build('youtube', 'v3', credentials=credentials) as youtube:
|
|
|
pl_request = youtube.channels().list(
|
|
@@ -63,14 +59,14 @@ class PlaylistManager(models.Manager):
|
|
|
|
|
|
pl_response = pl_request.execute()
|
|
|
|
|
|
- print(pl_response)
|
|
|
+ print_(pl_response)
|
|
|
|
|
|
if pl_response['pageInfo']['totalResults'] == 0:
|
|
|
- print("Looks like do not have a channel on youtube. Create one to import all of your playlists. Retry?")
|
|
|
+ print_("Looks like do not have a channel on youtube. Create one to import all of your playlists. Retry?")
|
|
|
return -1
|
|
|
else:
|
|
|
- user.profile.yt_channel_id = pl_response['items'][0]['id']
|
|
|
- user.save()
|
|
|
+ user_profile.yt_channel_id = pl_response['items'][0]['id']
|
|
|
+ user_profile.save(update_fields=['yt_channel_id'])
|
|
|
|
|
|
return 0
|
|
|
|
|
@@ -91,7 +87,7 @@ class PlaylistManager(models.Manager):
|
|
|
"error_message": "",
|
|
|
"playlist_ids": []}
|
|
|
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
|
|
|
playlist_ids = []
|
|
|
with build('youtube', 'v3', credentials=credentials) as youtube:
|
|
@@ -102,7 +98,7 @@ class PlaylistManager(models.Manager):
|
|
|
maxResults=50
|
|
|
)
|
|
|
else:
|
|
|
- print("GETTING ALL USER AUTH PLAYLISTS")
|
|
|
+ print_("GETTING ALL USER AUTH PLAYLISTS")
|
|
|
pl_request = youtube.playlists().list(
|
|
|
part='contentDetails, snippet, id, player, status',
|
|
|
mine=True, # get playlist details for this playlist id
|
|
@@ -113,15 +109,15 @@ class PlaylistManager(models.Manager):
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
except googleapiclient.errors.HttpError as e:
|
|
|
- print("YouTube channel not found if mine=True")
|
|
|
- print("YouTube playlist not found if id=playlist_id")
|
|
|
+ print_("YouTube channel not found if mine=True")
|
|
|
+ print_("YouTube playlist not found if id=playlist_id")
|
|
|
result["status"] = -1
|
|
|
result["error_message"] = get_message_from_httperror(e)
|
|
|
return result
|
|
|
|
|
|
- print(pl_response)
|
|
|
+ print_(pl_response)
|
|
|
if pl_response["pageInfo"]["totalResults"] == 0:
|
|
|
- print("No playlists created yet on youtube.")
|
|
|
+ print_("No playlists created yet on youtube.")
|
|
|
result["status"] = -2
|
|
|
return result
|
|
|
|
|
@@ -150,7 +146,7 @@ class PlaylistManager(models.Manager):
|
|
|
# check if this playlist already exists in user's untube collection
|
|
|
if user.playlists.filter(Q(playlist_id=playlist_id) & Q(is_in_db=True)).exists():
|
|
|
playlist = user.playlists.get(playlist_id=playlist_id)
|
|
|
- print(f"PLAYLIST {playlist.name} ({playlist_id}) ALREADY EXISTS IN DB")
|
|
|
+ print_(f"PLAYLIST {playlist.name} ({playlist_id}) ALREADY EXISTS IN DB")
|
|
|
|
|
|
# POSSIBLE CASES:
|
|
|
# 1. PLAYLIST HAS DUPLICATE VIDEOS, DELETED VIDS, UNAVAILABLE VIDS
|
|
@@ -164,7 +160,7 @@ class PlaylistManager(models.Manager):
|
|
|
result["status"] = -3
|
|
|
return result
|
|
|
else: # no such playlist in database
|
|
|
- print(f"CREATING {item['snippet']['title']} ({playlist_id})")
|
|
|
+ print_(f"CREATING {item['snippet']['title']} ({playlist_id})")
|
|
|
if user.playlists.filter(Q(playlist_id=playlist_id) & Q(is_in_db=False)).exists():
|
|
|
unimported_playlist = user.playlists.filter(Q(playlist_id=playlist_id) & Q(is_in_db=False)).first()
|
|
|
unimported_playlist.delete()
|
|
@@ -196,7 +192,7 @@ class PlaylistManager(models.Manager):
|
|
|
return result
|
|
|
|
|
|
def getAllVideosForPlaylist(self, user, playlist_id):
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
|
|
|
playlist = user.playlists.get(playlist_id=playlist_id)
|
|
|
|
|
@@ -265,7 +261,7 @@ class PlaylistManager(models.Manager):
|
|
|
|
|
|
else: # video found in user's db
|
|
|
if playlist.playlist_items.filter(playlist_item_id=playlist_item_id).exists():
|
|
|
- print("PLAYLIST ITEM ALREADY EXISTS")
|
|
|
+ print_("PLAYLIST ITEM ALREADY EXISTS")
|
|
|
continue
|
|
|
|
|
|
video = user.videos.get(video_id=video_id)
|
|
@@ -463,14 +459,14 @@ class PlaylistManager(models.Manager):
|
|
|
If full_scan is False, only the playlist count difference on YT and UT is checked on every visit
|
|
|
to the playlist page. This is done everytime.
|
|
|
"""
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
|
|
|
playlist = user.playlists.get(playlist_id=pl_id)
|
|
|
|
|
|
# if its been a week since the last full scan, do a full playlist scan
|
|
|
# basically checks all the playlist video for any updates
|
|
|
if playlist.last_full_scan_at + datetime.timedelta(minutes=1) < datetime.datetime.now(pytz.utc):
|
|
|
- print("DOING A FULL SCAN")
|
|
|
+ print_("DOING A FULL SCAN")
|
|
|
current_playlist_item_ids = [playlist_item.playlist_item_id for playlist_item in
|
|
|
playlist.playlist_items.all()]
|
|
|
|
|
@@ -551,10 +547,10 @@ class PlaylistManager(models.Manager):
|
|
|
|
|
|
return [1, deleted_videos, unavailable_videos, added_videos]
|
|
|
else:
|
|
|
- print("YOU CAN DO A FULL SCAN AGAIN IN",
|
|
|
+ print_("YOU CAN DO A FULL SCAN AGAIN IN",
|
|
|
str(datetime.datetime.now(pytz.utc) - (playlist.last_full_scan_at + datetime.timedelta(minutes=1))))
|
|
|
"""
|
|
|
- print("DOING A SMOL SCAN")
|
|
|
+ print_("DOING A SMOL SCAN")
|
|
|
|
|
|
with build('youtube', 'v3', credentials=credentials) as youtube:
|
|
|
pl_request = youtube.playlists().list(
|
|
@@ -567,11 +563,11 @@ class PlaylistManager(models.Manager):
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
except googleapiclient.errors.HttpError:
|
|
|
- print("YouTube channel not found if mine=True")
|
|
|
- print("YouTube playlist not found if id=playlist_id")
|
|
|
+ print_("YouTube channel not found if mine=True")
|
|
|
+ print_("YouTube playlist not found if id=playlist_id")
|
|
|
return -1
|
|
|
|
|
|
- print("PLAYLIST", pl_response)
|
|
|
+ print_("PLAYLIST", pl_response)
|
|
|
|
|
|
playlist_items = []
|
|
|
|
|
@@ -593,7 +589,7 @@ class PlaylistManager(models.Manager):
|
|
|
# check if this playlist already exists in database
|
|
|
if user.playlists.filter(playlist_id=playlist_id).exists():
|
|
|
playlist = user.playlists.get(playlist_id__exact=playlist_id)
|
|
|
- print(f"PLAYLIST {playlist.name} ALREADY EXISTS IN DB")
|
|
|
+ print_(f"PLAYLIST {playlist.name} ALREADY EXISTS IN DB")
|
|
|
|
|
|
# POSSIBLE CASES:
|
|
|
# 1. PLAYLIST HAS DUPLICATE VIDEOS, DELETED VIDS, UNAVAILABLE VIDS
|
|
@@ -608,7 +604,7 @@ class PlaylistManager(models.Manager):
|
|
|
return [0, "no change"]
|
|
|
|
|
|
def updatePlaylist(self, user, playlist_id):
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
|
|
|
playlist = user.playlists.get(playlist_id__exact=playlist_id)
|
|
|
|
|
@@ -632,10 +628,10 @@ class PlaylistManager(models.Manager):
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
except googleapiclient.errors.HttpError:
|
|
|
- print("Playist was deleted on YouTube")
|
|
|
+ print_("Playist was deleted on YouTube")
|
|
|
return [-1, [], [], []]
|
|
|
|
|
|
- print("ESTIMATED VIDEO IDS FROM RESPONSE", len(pl_response["items"]))
|
|
|
+ print_("ESTIMATED VIDEO IDS FROM RESPONSE", len(pl_response["items"]))
|
|
|
updated_playlist_video_count += len(pl_response["items"])
|
|
|
for item in pl_response['items']:
|
|
|
playlist_item_id = item["id"]
|
|
@@ -914,7 +910,7 @@ class PlaylistManager(models.Manager):
|
|
|
"""
|
|
|
Takes in playlist itemids for the videos in a particular playlist
|
|
|
"""
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
playlist = user.playlists.get(playlist_id=playlist_id)
|
|
|
|
|
|
# new_playlist_duration_in_seconds = playlist.playlist_duration_in_seconds
|
|
@@ -925,13 +921,13 @@ class PlaylistManager(models.Manager):
|
|
|
)
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
- print(pl_response)
|
|
|
+ print_(pl_response)
|
|
|
except googleapiclient.errors.HttpError as e: # failed to delete playlist
|
|
|
# possible causes:
|
|
|
# playlistForbidden (403)
|
|
|
# playlistNotFound (404)
|
|
|
# playlistOperationUnsupported (400)
|
|
|
- print(e.error_details, e.status_code)
|
|
|
+ print_(e.error_details, e.status_code)
|
|
|
return [-1, get_message_from_httperror(e), e.status_code]
|
|
|
|
|
|
# playlistItem was successfully deleted if no HttpError, so delete it from db
|
|
@@ -948,7 +944,7 @@ class PlaylistManager(models.Manager):
|
|
|
"""
|
|
|
Takes in playlist itemids for the videos in a particular playlist
|
|
|
"""
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
playlist = user.playlists.get(playlist_id=playlist_id)
|
|
|
playlist_items = user.playlists.get(playlist_id=playlist_id).playlist_items.select_related('video').filter(
|
|
|
playlist_item_id__in=playlist_item_ids)
|
|
@@ -960,16 +956,16 @@ class PlaylistManager(models.Manager):
|
|
|
pl_request = youtube.playlistItems().delete(
|
|
|
id=playlist_item.playlist_item_id
|
|
|
)
|
|
|
- print(pl_request)
|
|
|
+ print_(pl_request)
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
- print(pl_response)
|
|
|
+ print_(pl_response)
|
|
|
except googleapiclient.errors.HttpError as e: # failed to delete playlist item
|
|
|
# possible causes:
|
|
|
# playlistItemsNotAccessible (403)
|
|
|
# playlistItemNotFound (404)
|
|
|
# playlistOperationUnsupported (400)
|
|
|
- print(e, e.error_details, e.status_code)
|
|
|
+ print_(e, e.error_details, e.status_code)
|
|
|
continue
|
|
|
|
|
|
# playlistItem was successfully deleted if no HttpError, so delete it from db
|
|
@@ -1032,7 +1028,7 @@ class PlaylistManager(models.Manager):
|
|
|
"""
|
|
|
Takes in playlist details and creates a new private playlist in the user's account
|
|
|
"""
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
result = {
|
|
|
"status": 0,
|
|
|
"playlist_id": None
|
|
@@ -1054,7 +1050,7 @@ class PlaylistManager(models.Manager):
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
except googleapiclient.errors.HttpError as e: # failed to create playlist
|
|
|
- print(e.status_code, e.error_details)
|
|
|
+ print_(e.status_code, e.error_details)
|
|
|
if e.status_code == 400: # maxPlaylistExceeded
|
|
|
result["status"] = 400
|
|
|
result["status"] = -1
|
|
@@ -1066,7 +1062,7 @@ class PlaylistManager(models.Manager):
|
|
|
"""
|
|
|
Takes in playlist itemids for the videos in a particular playlist
|
|
|
"""
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
playlist = user.playlists.get(playlist_id=playlist_id)
|
|
|
|
|
|
with build('youtube', 'v3', credentials=credentials) as youtube:
|
|
@@ -1084,7 +1080,7 @@ class PlaylistManager(models.Manager):
|
|
|
},
|
|
|
)
|
|
|
|
|
|
- print(details["description"])
|
|
|
+ print_(details["description"])
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
except googleapiclient.errors.HttpError as e: # failed to update playlist details
|
|
@@ -1094,10 +1090,10 @@ class PlaylistManager(models.Manager):
|
|
|
# playlistOperationUnsupported (400)
|
|
|
# errors i ran into:
|
|
|
# runs into HttpError 400 "Invalid playlist snippet." when the description contains <, >
|
|
|
- print("ERROR UPDATING PLAYLIST DETAILS", e, e.status_code, e.error_details)
|
|
|
+ print_("ERROR UPDATING PLAYLIST DETAILS", e, e.status_code, e.error_details)
|
|
|
return -1
|
|
|
|
|
|
- print(pl_response)
|
|
|
+ print_(pl_response)
|
|
|
playlist.name = pl_response['snippet']['title']
|
|
|
playlist.description = pl_response['snippet']['description']
|
|
|
playlist.is_private_on_yt = True if pl_response['status']['privacyStatus'] == "private" else False
|
|
@@ -1109,7 +1105,7 @@ class PlaylistManager(models.Manager):
|
|
|
"""
|
|
|
Takes in playlist itemids for the videos in a particular playlist
|
|
|
"""
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
playlist_items = user.playlists.get(playlist_id=from_playlist_id).playlist_items.select_related('video').filter(
|
|
|
playlist_item_id__in=playlist_item_ids)
|
|
|
|
|
@@ -1145,7 +1141,7 @@ class PlaylistManager(models.Manager):
|
|
|
# playlistOperationUnsupported (400)
|
|
|
# errors i ran into:
|
|
|
# runs into HttpError 400 "Invalid playlist snippet." when the description contains <, >
|
|
|
- print("ERROR UPDATING PLAYLIST DETAILS", e.status_code, e.error_details)
|
|
|
+ print_("ERROR UPDATING PLAYLIST DETAILS", e.status_code, e.error_details)
|
|
|
if e.status_code == 400:
|
|
|
pl_request = youtube.playlistItems().insert(
|
|
|
part="snippet",
|
|
@@ -1179,7 +1175,7 @@ class PlaylistManager(models.Manager):
|
|
|
"""
|
|
|
Takes in playlist itemids for the videos in a particular playlist
|
|
|
"""
|
|
|
- credentials = self.getCredentials(user)
|
|
|
+ credentials = user.profile.get_credentials()
|
|
|
|
|
|
result = {
|
|
|
"num_added": 0,
|
|
@@ -1207,7 +1203,7 @@ class PlaylistManager(models.Manager):
|
|
|
try:
|
|
|
pl_response = pl_request.execute()
|
|
|
except googleapiclient.errors.HttpError as e: # failed to update add video to playlis
|
|
|
- print("ERROR ADDDING VIDEOS TO PLAYLIST", e.status_code, e.error_details)
|
|
|
+ print_("ERROR ADDDING VIDEOS TO PLAYLIST", e.status_code, e.error_details)
|
|
|
if e.status_code == 400: # manualSortRequired - see errors https://developers.google.com/youtube/v3/docs/playlistItems/insert
|
|
|
pl_request = youtube.playlistItems().insert(
|
|
|
part="snippet",
|
|
@@ -1398,18 +1394,18 @@ class Playlist(models.Model):
|
|
|
|
|
|
return [num_channels, channels_list]
|
|
|
|
|
|
- def generate_playlist_thumbnail_url(self):
|
|
|
- """
|
|
|
- Generates a playlist thumnail url based on the playlist name
|
|
|
- """
|
|
|
- pl_name = self.name
|
|
|
- response = requests.get(
|
|
|
- f'https://api.unsplash.com/search/photos/?client_id={SECRETS["UNSPLASH_API_ACCESS_KEY"]}&page=1&query={pl_name}')
|
|
|
- image = response.json()["results"][0]["urls"]["small"]
|
|
|
-
|
|
|
- print(image)
|
|
|
-
|
|
|
- return image
|
|
|
+ # def generate_playlist_thumbnail_url(self):
|
|
|
+ # """
|
|
|
+ # Generates a playlist thumnail url based on the playlist name
|
|
|
+ # """
|
|
|
+ # pl_name = self.name
|
|
|
+ # response = requests.get(
|
|
|
+ # f'https://api.unsplash.com/search/photos/?client_id={SECRETS["UNSPLASH_API_ACCESS_KEY"]}&page=1&query={pl_name}')
|
|
|
+ # image = response.json()["results"][0]["urls"]["small"]
|
|
|
+ #
|
|
|
+ # print_(image)
|
|
|
+ #
|
|
|
+ # return image
|
|
|
|
|
|
def get_playlist_thumbnail_url(self):
|
|
|
playlist_items = self.playlist_items.filter(
|