Skip to content

Commit

Permalink
Release v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
AnonymousX86 committed Dec 6, 2023
1 parent 4080425 commit 1968f3e
Show file tree
Hide file tree
Showing 16 changed files with 119 additions and 61 deletions.
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {"PYTHONPATH": "${workspaceFolder}/src"},
"justMyCode": true
}
]
Expand Down
File renamed without changes.
25 changes: 20 additions & 5 deletions yt_api/add_playlist.py → src/yt_api/add_playlist.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
# -*- coding: utf-8 -*-
"""
Creates a private playlist in the authorizing user's YouTube channel.
Creates a playlist in the authorizing user's YouTube channel.
"""
from enum import Enum

from googleapiclient.discovery import Resource
from googleapiclient.errors import HttpError

from authentication import get_authenticated_service
from models import Localization, Thumbnail


class PrivacyStatus(Enum):
PRIVATE = 'private'
PUBLIC = 'public'
UNLISTED = 'unlisted'


class Playlist:
def __init__(self, payload: dict):
self.kind: str = payload.get('kind')
Expand Down Expand Up @@ -44,8 +52,15 @@ def __init__(self, payload: dict):



def add_playlist(youtube: Resource, title: str, description: str) -> Playlist:
def add_playlist(
youtube: Resource,
title: str,
description: str,
privacy_status: PrivacyStatus = None
) -> Playlist:
"""Creates playlist then returns it as `Playlist`."""
if not privacy_status:
privacy_status = PrivacyStatus.UNLISTED
response: dict = youtube.playlists().insert(
part = 'snippet,status',
body = dict(
Expand All @@ -54,7 +69,7 @@ def add_playlist(youtube: Resource, title: str, description: str) -> Playlist:
description = description
),
status = dict(
privacyStatus = 'private'
privacyStatus = privacy_status.value
)
)
).execute()
Expand All @@ -66,8 +81,8 @@ def add_playlist(youtube: Resource, title: str, description: str) -> Playlist:
# Connect to YouTube
youtube = get_authenticated_service()

playlist_title = 'Test playlist'
playlist_description = 'Playlist created with YouTube API.'
playlist_title = input('Playlist title: ') or 'Test playlist'
playlist_description = input('Playlist description: ') or 'Playlist created with `yt_api` by AnonymousX86.'

# Create playlist
try:
Expand Down
5 changes: 3 additions & 2 deletions yt_api/add_video.py → src/yt_api/add_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ def add_video(youtube: Resource, playlist_id: str, video_id: str) -> bool:
# Connect to YouTube
youtube = get_authenticated_service()

playlist_id = 'PLHpqNKpoWiNX5Qbl0syonrL3El3Ojt9Kf'
video_id = 'dQw4w9WgXcQ'
playlist_id = input('Playlist ID: ')
video_id = input('Video ID: ') or 'dQw4w9WgXcQ'

# Add video to playlist
try:
playlist_item = add_video(youtube, playlist_id, video_id)
if playlist_item:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
31 changes: 4 additions & 27 deletions yt_api/database/playlist.py → src/yt_api/database/playlist.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
from sqlalchemy import Column, inspect, Integer, String
from sqlalchemy.orm import Session
from sqlalchemy import Column, Integer, String

from core import Base, create_session
from .core import Base, create_session


class Playlist(Base):
Expand Down Expand Up @@ -43,27 +42,5 @@ def get_playlist(cls, *, spotify_id: str = None, youtube_id: str = None) -> 'Pla
playlist = session.query(cls).filter_by(youtube_id=youtube_id).first()
return playlist


def test_playlist(session: Session) -> bool:
inspector = inspect(session.bind)
return 'playlists' in inspector.get_table_names()


if __name__ == '__main__':
from logging import basicConfig, getLogger, INFO
from rich.logging import RichHandler

basicConfig(
level=INFO,
format='%(message)s',
datefmt='[%X]',
handlers=[RichHandler(markup=True, rich_tracebacks=True)]
)
log = getLogger('sqlalchemy.engine')
log.setLevel(INFO)

session = create_session()
if (valid := test_playlist(session)):
log.info('The `playlists` table exists and is correctly structured.')
else:
log.error('The `playlists` table does not exist or is not correctly structured.')
def remove(self) -> None:
self.remove_playlist(spotify_id=self.spotify_id)
31 changes: 4 additions & 27 deletions yt_api/database/track.py → src/yt_api/database/track.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
from sqlalchemy import Column, inspect, Integer, String
from sqlalchemy.orm import Session
from sqlalchemy import Column, Integer, String

from core import Base, create_session
from .core import Base, create_session


class Track(Base):
Expand Down Expand Up @@ -43,27 +42,5 @@ def get_track(cls, *, spotify_id: str = None, youtube_id: str = None) -> 'Track
track = session.query(cls).filter_by(youtube_id=youtube_id).first()
return track


def test_track(session: Session) -> bool:
inspector = inspect(session.bind)
return 'tracks' in inspector.get_table_names()


if __name__ == '__main__':
from logging import basicConfig, getLogger, INFO
from rich.logging import RichHandler

basicConfig(
level=INFO,
format='%(message)s',
datefmt='[%X]',
handlers=[RichHandler(markup=True, rich_tracebacks=True)]
)
log = getLogger('sqlalchemy.engine')
log.setLevel(INFO)

session = create_session()
if (valid := test_track(session)):
log.info('The `tracks` table exists and is correctly structured.')
else:
log.error('The `tracks` table does not exist or is not correctly structured.')
def remove(self) -> None:
self.remove_track(spotify_id=self.spotify_id)
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file added src/yt_api/tests/__init__.py
Empty file.
15 changes: 15 additions & 0 deletions src/yt_api/tests/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from random import choice


_LOWERCASE = [*'qwertyuiopasdfghjklzxcvbnm']
_UPPER = list(map(lambda x: x.upper(), _LOWERCASE))
_LETTERS = _LOWERCASE + _UPPER
_PREFIX = 'TEST_'


def random_string(length: int) -> str:
result = _PREFIX
for _ in range(length - len(_PREFIX)):
result += choice(_LETTERS)
return result
36 changes: 36 additions & 0 deletions src/yt_api/tests/test_playlist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from unittest import TestCase, main as test_main

from yt_api.database import Playlist
from yt_api.tests.core import random_string


class TestPlaylist(TestCase):
def setUp(self) -> None:
self.spotify_id = random_string(22)
self.youtoube_id = random_string(34)

def test_add_and_get_playlist(self) -> None:
Playlist.add_playlist(
spotify_id=self.spotify_id,
youtube_id=self.youtoube_id
)
playlist_by_spotify = Playlist.get_playlist(spotify_id=self.spotify_id)
self.assertEqual(playlist_by_spotify.spotify_id, self.spotify_id)
self.assertEqual(playlist_by_spotify.youtube_id, self.youtoube_id)
playlist_by_youtube = Playlist.get_playlist(youtube_id=self.youtoube_id)
self.assertEqual(playlist_by_youtube.spotify_id, self.spotify_id)
self.assertEqual(playlist_by_youtube.youtube_id, self.youtoube_id)

def test_remove_playlist(self) -> None:
Playlist.add_playlist(
spotify_id=self.spotify_id,
youtube_id=self.youtoube_id
)
Playlist.remove_playlist(spotify_id=self.spotify_id)
playlist = Playlist.get_playlist(spotify_id=self.spotify_id)
self.assertIsNone(playlist)


if __name__ == '__main__':
test_main()
36 changes: 36 additions & 0 deletions src/yt_api/tests/test_track.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from unittest import TestCase, main as test_main

from yt_api.database import Track
from yt_api.tests.core import random_string


class TestTrack(TestCase):
def setUp(self) -> None:
self.spotify_id = random_string(22)
self.youtoube_id = random_string(11)

def test_add_and_get_track(self) -> None:
Track.add_track(
spotify_id=self.spotify_id,
youtube_id=self.youtoube_id
)
track_by_spotify = Track.get_track(spotify_id=self.spotify_id)
self.assertEqual(track_by_spotify.spotify_id, self.spotify_id)
self.assertEqual(track_by_spotify.youtube_id, self.youtoube_id)
track_by_youtube = Track.get_track(youtube_id=self.youtoube_id)
self.assertEqual(track_by_youtube.spotify_id, self.spotify_id)
self.assertEqual(track_by_youtube.youtube_id, self.youtoube_id)

def test_remove_track(self) -> None:
Track.add_track(
spotify_id=self.spotify_id,
youtube_id=self.youtoube_id
)
Track.remove_track(spotify_id=self.spotify_id)
track = Track.get_track(spotify_id=self.spotify_id)
self.assertIsNone(track)


if __name__ == '__main__':
test_main()

0 comments on commit 1968f3e

Please sign in to comment.