mckabue commited on
Commit
3636d4e
·
1 Parent(s): c8ea80c
Files changed (2) hide show
  1. app.py +32 -8
  2. index.html +128 -0
app.py CHANGED
@@ -1,19 +1,43 @@
1
- from flask import Flask, request
 
 
 
 
 
 
 
2
 
3
  app = Flask(__name__)
4
 
 
 
 
 
5
  @app.route('/')
6
- def hello_world():
7
  try:
8
- return 'Hello, World!'
9
  except Exception as e:
10
  return str(e)
11
-
12
  @app.route('/video_id', methods=['POST'])
13
- def get_video_id():
 
 
 
 
 
 
 
 
 
 
14
  try:
15
- title = request.json.get('title')
16
- artist = request.json.get('artist')
17
- return { 'artist': artist, 'title': title }
 
 
 
18
  except Exception as e:
19
  return str(e)
 
1
+ """Shazam Playlist to Youtube Playlist"""
2
+
3
+ import json
4
+ import pandas as pd
5
+ from pytube import Search, YouTube
6
+ from flask import Flask, render_template, request, jsonify, send_from_directory
7
+ from werkzeug.utils import secure_filename
8
+ import os
9
 
10
  app = Flask(__name__)
11
 
12
+ def get_youtube_song(title: str, artist: str) -> YouTube | None:
13
+ search_result = Search(f'{title} by {artist}')
14
+ return search_result.results[0] if search_result.results else None
15
+
16
  @app.route('/')
17
+ def index():
18
  try:
19
+ return send_from_directory('.', 'index.html')
20
  except Exception as e:
21
  return str(e)
22
+
23
  @app.route('/video_id', methods=['POST'])
24
+ def video_id() -> str:
25
+ try:
26
+ title: str = request.json.get('title')
27
+ artist: str = request.json.get('artist')
28
+ youtube: YouTube = get_youtube_song(title, artist)
29
+ return youtube.video_id
30
+ except Exception as e:
31
+ return str(e)
32
+
33
+ @app.route('/parse_csv', methods=['POST'])
34
+ def parse_csv():
35
  try:
36
+ file = request.files['file']
37
+ # Process the uploaded file
38
+ shazamlibrary_df = pd.read_csv(file, header=1)
39
+ shazamlibrary_df = shazamlibrary_df.drop_duplicates(subset=['TrackKey'])[['Title', 'Artist']]
40
+ shazamlibrary_df.insert(0, '#', shazamlibrary_df.index + 1)
41
+ return shazamlibrary_df.to_html(index=False, justify="left")
42
  except Exception as e:
43
  return str(e)
index.html ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Shazam Playlist to Youtube Playlist</title>
8
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
10
+ <script src="https://www.youtube.com/iframe_api"></script>
11
+ <style>
12
+ #youtube-player, iframe {
13
+ width: 100%;
14
+ height: 100%;
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class="container my-4">
21
+ <h1 class="text-center">Shazam Playlist to Youtube Playlist</h1>
22
+ <p class="text-center">
23
+ Download the CSV of your playlist from
24
+ <a href="https://www.shazam.com/myshazam" target="_blank">https://www.shazam.com/myshazam</a>.
25
+ </p>
26
+ <p class="text-center">Upload your Shazam Playlist CSV file.</p>
27
+ <div class="row mx-2 justify-content-center">
28
+ <div class="col-md-6">
29
+ <input type="file" class="form-control upload-form col-md-6" accept=".csv">
30
+ </div>
31
+ </div>
32
+
33
+ <div class="row mt-5">
34
+ <div class="col-md-12">
35
+ <div class="object-fit-contain border rounded ratio ratio-16x9">
36
+ <div id="youtube-player"></div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ <div class="row mt-5">
42
+ <div class="col-md-12 playlist table-responsive">
43
+ <table class="table table-striped">
44
+ <thead>
45
+ <tr>
46
+ <th>Title</th>
47
+ <th>Artist</th>
48
+ </tr>
49
+ </thead>
50
+ <tbody></tbody>
51
+ </table>
52
+ </div>
53
+ </div>
54
+ </div>
55
+
56
+ <script>
57
+ let player;
58
+ let videoIds = [];
59
+ let currentVideoIndex = 0;
60
+
61
+ function onYouTubeIframeAPIReady() {
62
+ player = new YT.Player('youtube-player', {
63
+ height: '100%',
64
+ width: '100%',
65
+ playerVars: { autoplay: 1 },
66
+ events: {
67
+ 'onReady': onPlayerReady,
68
+ 'onStateChange': onPlayerStateChange
69
+ }
70
+ });
71
+ }
72
+
73
+ function onPlayerReady(event) {
74
+ if (videoIds.length > 0) {
75
+ event.target.loadVideoById(videoIds[0]);
76
+ }
77
+ }
78
+
79
+ function onPlayerStateChange(event) {
80
+ if (event.data == YT.PlayerState.ENDED) {
81
+ playNextVideo();
82
+ }
83
+ }
84
+
85
+ function playNextVideo() {
86
+ currentVideoIndex++;
87
+ if (currentVideoIndex >= videoIds.length) {
88
+ currentVideoIndex = 0;
89
+ }
90
+ player.loadVideoById(videoIds[currentVideoIndex]);
91
+ }
92
+
93
+ function updatePlaylist(playlist) {
94
+ const tbody = $('#playlist tbody');
95
+ tbody.empty();
96
+ playlist.forEach(function (item) {
97
+ tbody.append(`<tr><td>${item.Title}</td><td>${item.Artist}</td></tr>`);
98
+ });
99
+ }
100
+
101
+ document.querySelector('.upload-form').addEventListener('input', function (e) {
102
+ e.preventDefault();
103
+ if (e.target.files.length == 0) {
104
+ return;
105
+ }
106
+ const formData = new FormData();
107
+ formData.append('file', e.target.files[0]);
108
+
109
+ fetch(
110
+ '/parse_csv',
111
+ {
112
+ method: 'POST',
113
+ body: formData
114
+ })
115
+ .then(response => response.text(), response => response.text())
116
+ .then(response => {
117
+ const playlist = document.querySelector('.playlist');
118
+ playlist.innerHTML = response
119
+ setTimeout(() => {
120
+ playlist.querySelector('table').classList.add(...['table', 'table-striped', 'table-hover']);
121
+ }, 100);
122
+ });
123
+ });
124
+
125
+ </script>
126
+ </body>
127
+
128
+ </html>