Skip to content

Commit

Permalink
update: Updated download bar.
Browse files Browse the repository at this point in the history
  • Loading branch information
deepjyoti30 committed Nov 9, 2019
1 parent c9e51f4 commit a0ffc8c
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 63 deletions.
246 changes: 187 additions & 59 deletions ytmdl/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,211 @@
import sys
import time
from os import path
from ytmdl import utility
from os import popen
import argparse

# import traceback ## Required to debug at times.

def download(url, des):
try:
# Download files with a progressbar showing the percentage
u = urllib.request.urlopen(url)
f = open(des, 'wb')
meta = u.info()

file_size = int(meta["Content-Length"])
def arguments():
"""Parse the arguments."""
parser = argparse.ArgumentParser()

file_size_dl = 0
block_sz = 8192
parser.add_argument('URL', help="URL of the file",
default=None, type=str)
parser.add_argument('des', help="The name of the file\
to be saved with.", default=None, nargs='?')

beg_time = time.time()
while True:
buffer = u.read(block_sz)
if not buffer:
break
args = parser.parse_args()
return args

file_size_dl += len(buffer)
f.write(buffer)

# Calculate speed
speed = (file_size_dl / 1024) / (time.time() - beg_time)
class Download:

# Calculate time left
time_left = round(((file_size - file_size_dl) / 1024) / speed)
time_unit = 's'
def __init__(self, URL, des=None):
self.URL = URL
self.des = des
self.headers = {}
self.f_size = 0

# Convert to min or hours as req
if time_left > 3600:
time_left = round(time_left / 3600)
time_unit = 'h'
elif time_left > 60:
time_left = round(time_left / 60)
time_unit = 'm'
def _build_headers(self, rem):
"""Build headers according to requirement."""
self.headers = {"Range": "bytes={}-".format(rem)}
print("Trying to resume download at: {} bytes".format(rem))

# Calculate percentage
percent = file_size_dl * 100. / file_size
def _preprocess_conn(self):
"""Make necessary things for the connection."""
self.req = urllib.request.Request(url=self.URL, headers=self.headers)

# file_size to show
if file_size_dl > (1024 * 1024):
file_size_to_disp = file_size_dl / (1024 * 1024)
dw_unit = "MB's"
elif file_size_dl > 1024:
file_size_to_disp = file_size_dl / 1024
dw_unit = "kb's"
try:
self.conn = urllib.request.urlopen(self.req)
except Exception as e:
print("ERROR: {}".format(e))
exit()

# Basename
basename = path.basename(des)
self.f_size = int(self.conn.info()['Content-Length'])

# Calculate amount of space req in between
length = utility.get_terminal_length()
def _get_terminal_length(self):
"""Return the length of the terminal."""
rows, cols = popen('stty size', 'r').read().split()
return int(cols)

stuff_len = len(basename) + 13 + 17 + 7 + 26 + 5
space = 0
def _parse_destination(self):
# Check if the des is passed
if self.des is not None:
if path.isdir(self.des):
self.des = path.join(self.des, self._get_name())
else:
self.des = self._get_name()

if stuff_len < length:
space = length - stuff_len
elif stuff_len > length:
basename = basename[:(length - stuff_len) - 2] + '..'
# Put a check to see if file already exists.
# Try to resume it if that's true
if path.exists(self.des):
rem_size = path.getsize(self.des)
self._build_headers(rem_size)

status = r"%s %s %0.2f %s |%d kbps| ETA: %s %s |%-20s| %3.2f%%" % (basename, space * " ", file_size_to_disp, dw_unit, speed, time_left, time_unit, "-" * int(percent / 5), percent)
sys.stdout.write('\r')
sys.stdout.write(status)
sys.stdout.flush()
def _get_name(self):
"""Try to get the name of the file from the URL."""

name = 'temp'
temp_url = self.URL

f.close()
split_url = temp_url.split('/')

print()
return True
except ConnectionError:
print("Connection Error!")
return False
for name in split_url[::-1]:
if name != '':
break

return name

def _format_size(self, size):
"""Format the passed size.
If its more than an 1 Mb then return the size in Mb's
else return it in Kb's along with the unit.
"""
formatted_size = size
dw_unit = 'bytes'

if formatted_size > (1024 * 1024 * 1024):
formatted_size = size / (1024 * 1024 * 1024)
dw_unit = "GB's"
elif formatted_size > (1024 * 1024):
formatted_size = size / (1024 * 1024)
dw_unit = "MB's"
elif formatted_size > 1024:
formatted_size = size / 1024
dw_unit = "kb's"

return (formatted_size, dw_unit)

def _format_time(self, time_left):
"""Format the passed time depending."""

if time_left > 3600:
time_left = round(time_left / 3600)
time_unit = 'h'
elif time_left > 60:
time_left = round(time_left / 60)
time_unit = 'm'

return time_left, time_unit

def _get_speed_n_time(self, file_size_dl, beg_time, cur_time):
"""Return the speed and time depending on the passed arguments."""

# Calculate speed
speed = (file_size_dl / 1024) / (cur_time - beg_time)

# Calculate time left
time_left = round(((self.f_size - file_size_dl) / 1024) / speed)
time_unit = 's'

# Convert to min or hours as req
if time_left > 3600:
time_left = round(time_left / 3600)
time_unit = 'h'
elif time_left > 60:
time_left = round(time_left / 60)
time_unit = 'm'

return speed, time_left, time_unit

def download(self):
try:
self._parse_destination()

# Download files with a progressbar showing the percentage
self._preprocess_conn()
WSTREAM = open(self.des, 'wb')

formatted_file_size, dw_unit = self._format_size(self.f_size)
print("Size: {} {}".format(round(formatted_file_size), dw_unit))
print("Saving as: {}".format(self.des))

file_size_dl = 0
block_sz = 8192

beg_time = time.time()
while True:
buffer = self.conn.read(block_sz)
if not buffer:
break

file_size_dl += len(buffer)
WSTREAM.write(buffer)

# Initialize all the variables that cannot be calculated
# to ''
speed = ''
time_left = ''
time_unit = ''
percent = ''

if self.f_size is not None:
speed, time_left, time_unit = self._get_speed_n_time(
file_size_dl,
beg_time,
cur_time=time.time()
)
percent = file_size_dl * 100 / self.f_size

# Get basename
self.basename = path.basename(self.des)

# Calculate amount of space req in between
length = self._get_terminal_length()

stuff_len = len(self.basename) + 13 + 17 + 7 + 26 + 3
space = 0

if stuff_len < length:
space = length - stuff_len
elif stuff_len > length:
self.basename = self.basename[:(length - stuff_len) - 2] + '..'

f_size_disp, dw_unit = self._format_size(file_size_dl)
if self.f_size is not None:
status = r"%s %s %0.2f %s |%d kbps| ETA: %s %s |%-20s| |%3.2f%%|" % (self.basename, space * " ", f_size_disp, dw_unit, speed, time_left, time_unit, "-" * int(percent / 5), percent)
else:
status = r"%s %s %0.2f %s" %(self.basename, space * " ", f_size_disp, dw_unit)
sys.stdout.write('\r')
sys.stdout.write(status)
sys.stdout.flush()

WSTREAM.close()

print()
return True
except KeyboardInterrupt:
sys.stdout.flush()
print("Keyboard Interrupt passed. Exitting peacefully.")
exit()
except Exception as e:
print("ERROR: {}".format(e))
return False


if __name__ == "__main__":
download("http://speedtest.ftp.otenet.gr/files/test100k.db", 'nana.mkv')
args = arguments()
Download(args.URL, args.des).download()
14 changes: 10 additions & 4 deletions ytmdl/yt.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,25 @@ def dw(value, song_name='ytmdl_temp.mp3'):
# Replace the spaces with hashes
song_name = song_name.replace(' ', '#')

# The directory where we will download to.
dw_dir = defaults.DEFAULT.SONG_TEMP_DIR

if not os.path.exists(dw_dir):
os.makedirs(dw_dir)

# Name of the temp file
name = os.path.join(defaults.DEFAULT.SONG_TEMP_DIR, song_name)
name = os.path.join(dw_dir, song_name)

# Start downloading the song
"""response = requests.get(url, stream=True)
with open(name, 'wb') as out_file:
copyfileobj(response.raw, out_file)
"""
download.download(url, name)
download.Download(url, name).download()

return name
except Exception:
return False
except Exception as e:
return e


def get_href(url):
Expand Down

0 comments on commit a0ffc8c

Please sign in to comment.