Skip to content

Commit

Permalink
Add ability to download duplicates
Browse files Browse the repository at this point in the history
  • Loading branch information
justin025 committed Nov 22, 2024
1 parent 6775bf6 commit a9c8635
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 70 deletions.
7 changes: 4 additions & 3 deletions src/onthespot/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ def __init__(self):
def run(self):
while True:
if pending:
item_id = next(iter(pending))
item = pending.pop(item_id)
local_id = next(iter(pending))
item = pending.pop(local_id)
token = get_account_token()
item_metadata = globals()[f"{item['item_service']}_get_{item['item_type']}_metadata"](token, item['item_id'])

with download_queue_lock:
download_queue[item['item_id']] = {
download_queue[local_id] = {
'local_id': local_id,
"item_service": item["item_service"],
"item_type": item["item_type"],
'item_id': item['item_id'],
Expand Down
4 changes: 2 additions & 2 deletions src/onthespot/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ def start(self):
def readd_item_to_download_queue(self, item):
with download_queue_lock:
try:
del download_queue[item['item_id']]
download_queue[item['item_id']] = item
del download_queue[item['local_id']]
download_queue[item['local_id']] = item
except (KeyError):
# Item likely cleared from queue
return
Expand Down
24 changes: 12 additions & 12 deletions src/onthespot/gui/dl_progressbtn.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@


class DownloadActionsButtons(QWidget):
def __init__(self, item_id, item_metadata, pbar, copy_btn, cancel_btn, retry_btn, open_btn, locate_btn, delete_btn, parent=None):
def __init__(self, local_id, item_metadata, pbar, copy_btn, cancel_btn, retry_btn, open_btn, locate_btn, delete_btn, parent=None):
super(DownloadActionsButtons, self).__init__(parent)
self.item_id = item_id
self.local_id = local_id
self.item_metadata = item_metadata
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
Expand Down Expand Up @@ -46,34 +46,34 @@ def copy_link(self):
pyperclip.copy(self.item_metadata['item_url'])

def cancel_item(self):
download_queue[self.item_id]['item_status'] = "Cancelled"
download_queue[self.item_id]['gui']['status_label'].setText(self.tr("Cancelled"))
download_queue[self.item_id]['gui']['progress_bar'].setValue(0)
download_queue[self.local_id]['item_status'] = "Cancelled"
download_queue[self.local_id]['gui']['status_label'].setText(self.tr("Cancelled"))
download_queue[self.local_id]['gui']['progress_bar'].setValue(0)
self.cancel_btn.hide()
self.retry_btn.show()

def retry_item(self):
download_queue[self.item_id]['item_status'] = "Waiting"
download_queue[self.item_id]['gui']['status_label'].setText(self.tr("Waiting"))
download_queue[self.item_id]['gui']['progress_bar'].setValue(0)
download_queue[self.local_id]['item_status'] = "Waiting"
download_queue[self.local_id]['gui']['status_label'].setText(self.tr("Waiting"))
download_queue[self.local_id]['gui']['progress_bar'].setValue(0)
self.retry_btn.hide()
self.cancel_btn.show()

def open_file(self):
file_path = download_queue[self.item_id]['file_path']
file_path = download_queue[self.local_id]['file_path']
file = os.path.abspath(file_path)
open_item(file)

def locate_file(self):
file_path = download_queue[self.item_id]['file_path']
file_path = download_queue[self.local_id]['file_path']
file_dir = os.path.dirname(file_path)
open_item(file_dir)

def delete_file(self):
file_path = download_queue[self.item_id]['file_path']
file_path = download_queue[self.local_id]['file_path']
file = os.path.abspath(file_path)
os.remove(file)
download_queue[self.item_id]["gui"]["status_label"].setText(self.tr("Deleted"))
download_queue[self.local_id]["gui"]["status_label"].setText(self.tr("Deleted"))
self.open_btn.hide()
self.locate_btn.hide()
self.delete_btn.hide()
72 changes: 35 additions & 37 deletions src/onthespot/gui/mainui.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ def __init__(self):
def run(self):
while True:
if pending:

item_id = next(iter(pending))
item = pending.pop(item_id)
token = get_account_token()
item_metadata = globals()[f"{item['item_service']}_get_{item['item_type']}_metadata"](token, item['item_id'])
if item_id not in download_queue:
try:
local_id = next(iter(pending))
item = pending.pop(local_id)
token = get_account_token()
item_metadata = globals()[f"{item['item_service']}_get_{item['item_type']}_metadata"](token, item['item_id'])
self.add_item_to_download_list.emit(item, item_metadata)
continue

continue
except Exception as e:
logger.error(f"Unknown Exception for {item}: {str(e)}")
pending[local_id] = item
else:
time.sleep(0.2)

Expand Down Expand Up @@ -374,7 +375,7 @@ def add_item_to_download_list(self, item, item_metadata):

status_label = QLabel(self.tbl_dl_progress)
status_label.setText(self.tr("Waiting"))
actions = DownloadActionsButtons(item['item_id'], item_metadata, pbar, copy_btn, cancel_btn, retry_btn, open_btn, locate_btn, delete_btn)
actions = DownloadActionsButtons(item['local_id'], item_metadata, pbar, copy_btn, cancel_btn, retry_btn, open_btn, locate_btn, delete_btn)

rows = self.tbl_dl_progress.rowCount()
self.tbl_dl_progress.insertRow(rows)
Expand All @@ -389,7 +390,7 @@ def add_item_to_download_list(self, item, item_metadata):
item_label = QLabel(self.tbl_dl_progress)
item_label.setText(title)
# Add To List
self.tbl_dl_progress.setItem(rows, 0, QTableWidgetItem(str(item['item_id'])))
self.tbl_dl_progress.setItem(rows, 0, QTableWidgetItem(str(item['local_id'])))
self.tbl_dl_progress.setCellWidget(rows, 1, item_label)
self.tbl_dl_progress.setItem(rows, 2, QTableWidgetItem(item_metadata['artists']))
self.tbl_dl_progress.setItem(rows, 3, QTableWidgetItem(item_category))
Expand All @@ -401,7 +402,8 @@ def add_item_to_download_list(self, item, item_metadata):
self.update_table_visibility()

with download_queue_lock:
download_queue[item['item_id']] = {
download_queue[item['local_id']] = {
'local_id': item['local_id'],
"item_service": item["item_service"],
"item_type": item["item_type"],
'item_id': item['item_id'],
Expand Down Expand Up @@ -472,21 +474,17 @@ def remove_completed_from_download_list(self):
with download_queue_lock:
check_row = 0
while check_row < self.tbl_dl_progress.rowCount():
item_id = self.tbl_dl_progress.item(check_row, 0).text()
try:
item_id = int(item_id)
except ValueError:
pass
logger.info(f'Removing Row : {check_row} and mediaid: {item_id}')
if item_id in download_queue:
if download_queue[item_id]['item_status'] in (
local_id = self.tbl_dl_progress.item(check_row, 0).text()
logger.info(f'Removing Row : {check_row} and mediaid: {local_id}')
if local_id in download_queue:
if download_queue[local_id]['item_status'] in (
"Cancelled",
"Downloaded",
"Already Exists"
):
logger.info(f'Removing Row : {check_row} and mediaid: {item_id}')
logger.info(f'Removing Row : {check_row} and mediaid: {local_id}')
self.tbl_dl_progress.removeRow(check_row)
download_queue.pop(item_id)
download_queue.pop(local_id)
else:
check_row = check_row + 1
else:
Expand All @@ -496,29 +494,29 @@ def cancel_all_downloads(self):
with download_queue_lock:
row_count = self.tbl_dl_progress.rowCount()
while row_count > 0:
for item_id in download_queue.keys():
logger.info(f'Trying to cancel : {item_id}')
if download_queue[item_id]['item_status'] == "Waiting":
download_queue[item_id]['item_status'] = "Cancelled"
download_queue[item_id]['gui']['status_label'].setText(self.tr("Cancelled"))
download_queue[item_id]['gui']['status_label'].setText(self.tr("Cancelled"))
download_queue[item_id]['gui']['progress_bar'].setValue(0)
download_queue[item_id]['gui']["btn"]['cancel'].hide()
download_queue[item_id]['gui']["btn"]['retry'].show()
for local_id in download_queue.keys():
logger.info(f'Trying to cancel : {local_id}')
if download_queue[local_id]['item_status'] == "Waiting":
download_queue[local_id]['item_status'] = "Cancelled"
download_queue[local_id]['gui']['status_label'].setText(self.tr("Cancelled"))
download_queue[local_id]['gui']['status_label'].setText(self.tr("Cancelled"))
download_queue[local_id]['gui']['progress_bar'].setValue(0)
download_queue[local_id]['gui']["btn"]['cancel'].hide()
download_queue[local_id]['gui']["btn"]['retry'].show()
row_count -= 1
self.update_table_visibility()

def retry_all_failed_downloads(self):
with download_queue_lock:
row_count = self.tbl_dl_progress.rowCount()
while row_count > 0:
for item_id in download_queue.keys():
logger.info(f'Trying to cancel : {item_id}')
if download_queue[item_id]['item_status'] == "Failed":
download_queue[item_id]['item_status'] = "Waiting"
download_queue[item_id]['gui']['status_label'].setText(self.tr("Waiting"))
download_queue[item_id]['gui']["btn"]['cancel'].show()
download_queue[item_id]['gui']["btn"]['retry'].hide()
for local_id in download_queue.keys():
logger.info(f'Trying to cancel : {local_id}')
if download_queue[local_id]['item_status'] == "Failed":
download_queue[local_id]['item_status'] = "Waiting"
download_queue[local_id]['gui']['status_label'].setText(self.tr("Waiting"))
download_queue[local_id]['gui']["btn"]['cancel'].show()
download_queue[local_id]['gui']["btn"]['retry'].hide()
row_count -= 1
self.update_table_visibility()

Expand Down
59 changes: 46 additions & 13 deletions src/onthespot/parse_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def parsingworker():

if current_service == "spotify":
if current_type == "track":
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': current_service,
'item_type': current_type,
'item_id': item_id,
Expand All @@ -85,7 +87,9 @@ def parsingworker():
tracks = spotify_get_album_tracks(token, current_id)
for index, track in enumerate(tracks):
item_id = track['id']
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': 'spotify',
'item_type': 'track',
'item_id': item_id,
Expand All @@ -100,7 +104,9 @@ def parsingworker():
try:
item_id = item['track']['id']
item_type = item['track']['type']
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': 'spotify',
'item_type': item_type,
'item_id': item_id,
Expand All @@ -120,7 +126,9 @@ def parsingworker():
continue

elif current_type == "episode":
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': current_service,
'item_type': current_type,
'item_id': item_id,
Expand All @@ -131,7 +139,9 @@ def parsingworker():
elif current_type in ['show', 'audiobook']:
episode_ids = spotify_get_show_episodes(token, current_id)
for index, episode_id in enumerate(episode_ids):
pending[episode_id] = {
local_id = format_item_id(episode_id)
pending[local_id] = {
'local_id': local_id,
'item_service': 'spotify',
'item_type': 'episode',
'item_id': episode_id,
Expand All @@ -143,7 +153,9 @@ def parsingworker():
tracks = spotify_get_liked_songs(token)
for index, track in enumerate(tracks):
item_id = track['track']['id']
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': 'spotify',
'item_type': 'track',
'item_id': item_id,
Expand All @@ -158,7 +170,9 @@ def parsingworker():
tracks = spotify_get_your_episodes(token)
for index, track in enumerate(tracks):
item_id = track['show']['id']
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': 'spotify',
'item_type': 'episode',
'item_id': item_id,
Expand All @@ -172,7 +186,9 @@ def parsingworker():
elif current_service == "soundcloud":

if current_type == "track":
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': current_service,
'item_type': current_type,
'item_id': item_id,
Expand All @@ -184,11 +200,14 @@ def parsingworker():
# Items are added to pending in function to avoid complexity
set_data = soundcloud_get_set_items(token, item['item_url'])
for index, track in enumerate(set_data['tracks']):
pending[track['id']] = {
item_id = track['id']
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_url': track.get('permalink_url', ''),
'item_service': 'soundcloud',
'item_type': 'track',
'item_id': track['id'],
'item_id': item_id,
'parent_category': 'playlist' if not set_data['is_album'] else 'album',
'playlist_name': set_data['title'],
'playlist_by': set_data['user']['username'],
Expand All @@ -198,7 +217,9 @@ def parsingworker():
elif current_service == "deezer":

if current_type == "track":
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': current_service,
'item_type': current_type,
'item_id': item_id,
Expand All @@ -209,7 +230,9 @@ def parsingworker():
tracks = deezer_get_album_items(current_id)
for index, track in enumerate(tracks):
item_id = track['id']
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': 'deezer',
'item_type': 'track',
'item_id': item_id,
Expand All @@ -221,7 +244,9 @@ def parsingworker():
playlist_name, playlist_by = deezer_get_playlist_data(current_id)
for index, track in enumerate(tracks):
item_id = track['id']
pending[item_id] = {
local_id = format_item_id(item_id)
pending[local_id] = {
'local_id': local_id,
'item_service': 'deezer',
'item_type': 'track',
'item_id': item_id,
Expand All @@ -238,3 +263,11 @@ def parsingworker():
continue
else:
time.sleep(0.2)

def format_item_id(item_id):
suffix = 0
local_id = f"{item_id}-{suffix}"
while local_id in download_queue or local_id in pending:
suffix += 1
local_id = f"{item_id}-{suffix}"
return local_id
6 changes: 3 additions & 3 deletions src/onthespot/post_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,11 @@ def add_to_m3u_file(item, item_metadata):

# Check if the item_path is already in the M3U file
with open(m3u_path, 'r') as m3u_file:
m3u_item_header = f"#EXTINF:{round(int(item_metadata['length'])/1000)}, {item['playlist_number']}. {item_metadata['artists']} - {item_metadata['title']}"
m3u_contents = m3u_file.readlines()

if item['file_path'] not in [line.strip() for line in m3u_contents]:
if m3u_item_header not in [line.strip() for line in m3u_contents]:
with open(m3u_path, 'a') as m3u_file:
m3u_file.write(f"#EXTINF:{round(int(item_metadata['length'])/1000)}, {item_metadata['artists']} - {item_metadata['title']}\n{item['file_path']}\n")
m3u_file.write(f"{m3u_item_header}\n{item['file_path']}\n")
else:
logger.info(f"{item['file_path']} already exists in the M3U file.")

Expand Down

0 comments on commit a9c8635

Please sign in to comment.