Commit f4bb812f authored by Manuel Cortez's avatar Manuel Cortez

Added download of multiple audios from any audio buffer

parent 81963979
Pipeline #629 passed with stages
in 2 minutes and 44 seconds
......@@ -5,6 +5,7 @@
### New additions
* Socializer will ask for confirmation before closing the application.
* In all audio buffers, there is a new item in the context menu that allows downloading of the audio directly from the buffer. If there are multiple audios selected, socializer will ask for a folder where all audios should be placed. When downloading multiple audios, socializer will name those automatically by following the template "song title - artist".
### bugfixes
......@@ -14,6 +15,7 @@
### Changes
* Replaced the underlying library we were using for spelling correction as is no longer in development. Instead, we started to use a new approach in socializer, which, in theory, should allow us to switch language for spelling correction and other benefits a bit later. For now, available languages are Russian, Ukranian, English, Polish and Spanish, but more languages can be added by request.
* When downloading a file (such as an audio file or document), the download process should be relatively faster due to some optimizations made in the function.
## Changes in Version 0.23 (11.11.2019)
# -*- coding: utf-8 -*-
""" A buffer is a (virtual) list of items. All items belong to a category (wall posts, messages, persons...)"""
import os
import time
import random
import logging
......@@ -880,12 +881,12 @@ class audioBuffer(feedBuffer):
multiple = True
filename = "" # No default filename for multiple files.
path =, multiple=multiple)
call_threaded(self.download_threaded, path, multiple, audios)
self.download_threaded(path, multiple, audios)
def download_threaded(self, path, multiple, audios):
if multiple == False:
url = audios[0]["url"]
pub.sendMessage("download-file", url=url, filename=filename)
pub.sendMessage("download-file", url=url, filename=path)
downloads = []
......@@ -893,7 +894,7 @@ class audioBuffer(feedBuffer):
filename = utils.safe_filename("{0} - {1}.mp3".format(i["title"], i["artist"]))
filepath = os.path.join(path, filename)
downloads.append((utils.transform_audio_url(i["url"]), filepath))
pub.sendMessage("download-files", downloads)
pub.sendMessage("download-files", downloads=downloads)
class audioAlbum(audioBuffer):
""" this buffer was supposed to be used with audio albums
......@@ -402,10 +402,10 @@ class Controller(object):
url = utils.transform_audio_url(url)
log.debug("downloading %s URL to %s filename" % (url, filename,))
call_threaded(utils.download_file, url, filename, self.window)
call_threaded(utils.download_file, url, filename)
def download_files(self, downloads):
call_threaded(utils.download_files, downloads, self.window)
call_threaded(utils.download_files, downloads)
def view_post(self, post_object, controller_, vars=dict()):
""" Display the passed post in the passed post presenter.
......@@ -5,6 +5,7 @@ import re
import html
import logging
import requests
from pubsub import pub
log = logging.getLogger("utils")
url_re = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*")
......@@ -41,26 +42,27 @@ def seconds_to_string(seconds, precision=0):
def find_urls_in_text(text):
return [s.strip(bad_chars) for s in url_re.findall(text)]
def download_file(url, local_filename, window):
def download_file(url, local_filename):
r = requests.get(url, stream=True)
window.change_status(_("Downloading {0}").format(local_filename,))
pub.sendMessage("change_status", status=_("Downloading {0}").format(local_filename,))
total_length = r.headers.get("content-length")
dl = 0
total_length = int(total_length)
with open(local_filename, 'wb') as f:
for chunk in r.iter_content(chunk_size=64):
for chunk in r.iter_content(chunk_size=512*1024):
if chunk: # filter out keep-alive new chunks
dl += len(chunk)
done = int(100 * dl/total_length)
msg = _("Downloading {0} ({1}%)").format(os.path.basename(local_filename), done)
# print(msg)
pub.sendMessage("change_status", status=msg)
pub.sendMessage("change_status", status=_("Ready"))
return local_filename
def download_files(downloads, window):
def download_files(downloads):
for download in downloads:
download_file(download[0], download[1], window)
download_file(download[0], download[1])
def detect_users(text):
""" Detect all users and communities mentionned in any text posted in VK."""
......@@ -2,6 +2,7 @@
import wx
import wx.adv
import application
from pubsub import pub
class mainWindow(wx.Frame):
def makeMenu(self):
......@@ -83,6 +84,7 @@ class mainWindow(wx.Frame): = self.CreateStatusBar()
self.tb = wx.Treebook(self.panel, -1)
self.sizer.Add(self.tb, 1, wx.ALL|wx.EXPAND, 5)
pub.subscribe(self.change_status, "change_status")
def realize(self):
......@@ -91,7 +93,7 @@ class mainWindow(wx.Frame):
def change_status(self, status):
wx.CallAfter(, status)
def connection_error(self):
wx.MessageDialog(self, _("There is a connection error. Check your internet connection and try again later."), _("Connection error"), wx.ICON_ERROR).ShowModal()
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment