Pārlūkot izejas kodu

Merge branch 'new_saving_routine' of DebenOldert/Music-Downloader into master

Deben Oldert 6 gadi atpakaļ
vecāks
revīzija
0cc28636ae
9 mainītis faili ar 133 papildinājumiem un 34 dzēšanām
  1. 2 1
      console.py
  2. 2 0
      main.py
  3. 1 0
      settings.py
  4. 0 1
      sites/czne.py
  5. 3 2
      sites/default.py
  6. 29 13
      sites/helper/download.py
  7. 85 8
      sites/helper/item.py
  8. 9 7
      sites/helper/structure.py
  9. 2 2
      sites/helper/tagging.py

+ 2 - 1
console.py

@@ -68,7 +68,8 @@ def option_picker(question, options, objects=None, selected=None, quit=False, ta
                 _row += '[{{{name}:{size}.{size}}}]'.format(name=str(objects[j]), size=str(table[j][1]))
                 # _row += '[{' + str(objects[j]) + ':' + str(table[j][1]) + '.' + str(table[j][1]) + '}] '
 
-            output(_row.format(__id__=str(i), x=option).strip())
+            output(_row.format(__id__=str(i), x=option))
+            # output(_row.format(__id__=str(i), x=dict(map(lambda s: s if s is not None else '', option.__dict__.items()))).strip())
 
         else:
             if i == selected:

+ 2 - 0
main.py

@@ -12,6 +12,8 @@ def init():
     else:
         Settings.Debuglvl = console.DBG_ERROR
 
+    Settings.tmpDir = os.path.expanduser(os.getenv('MD_TMP', '/tmp'))
+
     directory(os.getenv('MD_SAVEDIR', '~/Music/iTunes/iTunes Media/Automatically Add to iTunes'))
 
 

+ 1 - 0
settings.py

@@ -3,4 +3,5 @@ import console as console
 
 class Settings:
     SaveDir = None
+    tmpDir = '/tmp'
     Debuglvl = None

+ 0 - 1
sites/czne.py

@@ -14,7 +14,6 @@ class Czne(DefaultSite):
             .set_container_path('div#dle-content')\
             .set_item_path('article.short-story')\
             .set_title_path('div.short-title')\
-            .set_duration_path('div.news-text div.wpisplayer div.total-time') \
             .set_url_path('div.wpisplayer script:first')
         self.request\
             .add_header('Referer', self.url + '/')\

+ 3 - 2
sites/default.py

@@ -2,6 +2,7 @@ import console
 from sites.helper.request import Request
 from sites.helper.query import Query
 from sites.helper.structure import Structure
+from sites.helper.item import Empty
 
 import sites.helper.download as Download
 
@@ -33,12 +34,12 @@ class DefaultSite:
 
     def format_duration(self, field):
         if field is None:
-            return ''
+            return Empty
         return field.text()
 
     def format_size(self, field):
         if field is None:
-            return ''
+            return Empty
         return field.text()
 
     def format_url(self, field):

+ 29 - 13
sites/helper/download.py

@@ -1,5 +1,6 @@
 import console
 import sites.helper.tagging as tagging
+from sites.helper.item import Empty
 from .request import RawRequest
 from pyquery import PyQuery
 from settings import Settings
@@ -7,6 +8,7 @@ from settings import Settings
 import math
 import urllib.parse
 import json
+import os
 
 
 def download(item, type='GET', parameters=None, headers=None, cookies=None, stream=True):
@@ -28,28 +30,40 @@ def download(item, type='GET', parameters=None, headers=None, cookies=None, stre
         notExist(item)
         return
 
-    name = urllib.parse.unquote(item.title)
+    name = urllib.parse.unquote('{x.artist} - {x.title}'.format(x=item))
 
     if not name.endswith('.mp3'):
         console.output('Assuming it\'s a mp3 file', console.DBG_INFO)
         name = name + '.mp3'
 
-    full_name = '{0}/{1}'.format(Settings.SaveDir, name)
+    full_name = '{0}/{1}'.format(Settings.tmpDir, name)
 
-    size = file.headers.get('content-length')
+    if item.bitrate is Empty and item.bytes is None:
+        size = file.headers.get('content-length')
+        if size is not None:
+            item.set_bytes(int(size))
+
+            console.output('File size: {0}'.format(console.format_bytes(item.bytes)))
+
+            if item.duration_seconds is not None:
+                item.calculate_bitrate()
+
+                console.output('Bitrate: {0}kbps'.format(int(item.bitrate)))
+
+            ans = console.ask_input('Continue downloading? [y/n]')
 
-    savefileprogress(name, full_name, file, size, item)
+            if ans != 'y':
+                return
 
+    savefileprogress(name, full_name, file, item)
 
-def savefileprogress(name, full_name, file, size, item):
-    if size is not None:
-        size = int(size)
-        console.output('Size: {0}'.format(console.format_bytes(size)))
-    console.output('Saving to: {0}'.format(full_name))
+
+def savefileprogress(name, full_name, file, item):
+    console.output('Saving to: {0}'.format(full_name), level=console.DBG_INFO)
     with open(full_name, 'wb') as f:
         progress = 0
-        if size is not None:
-            bar = console.ProgressBar(total=size)
+        if item.bytes is not None:
+            bar = console.ProgressBar(total=item.bytes)
 
             for chunk in file.iter_content(chunk_size=4096):
                 progress += len(chunk)
@@ -71,6 +85,10 @@ def savefileprogress(name, full_name, file, size, item):
 
             tagging.write_tags_to_file(f, item)
 
+    full_save_name = '{0}/{1}'.format(Settings.SaveDir, name)
+    os.rename(full_name, full_save_name)
+    console.output('Moved to {0}'.format(full_save_name), level=console.DBG_INFO)
+
     console.output('Download of {0} completed!'.format(name))
 
 
@@ -133,8 +151,6 @@ def krakenfiles(item, returnurl=False):
 
     item.set_download_url('https:{0}'.format(form.attr('action')))
 
-    name = pq('span.dfilename').text()
-
     parameters = {}
 
     parameters['token'] = pq('input#dl-token').val()

+ 85 - 8
sites/helper/item.py

@@ -1,19 +1,52 @@
 import console
+import re
+
+
+class EmptyAttr:
+    def __str__(self):
+        return ''
+
+    def __format__(self, format_spec):
+        return ''.__format__(format_spec)
+
+    def __getattr__(self, item):
+        return None
+
+    def __getitem__(self, item):
+        return None
+
+    def __eq__(self, other):
+        if other is None or other is Empty:
+            return True
+
+        return False
+
+
+Empty = EmptyAttr()
 
 
 class Item:
-    def __init__(self, site, title, url, duration='00:00', size=0, artist=None):
+    def __init__(self, site):
         self.site = site
-        self.original_url = url
+
+        self.title = Empty
+        self.artist = Empty
+
+        self.original_url = Empty
         self.download_url = None
-        self.title = title
-        self.duration = duration
-        self.size = size
-        self.artist = artist
+        self.url_formatted = False
 
         self.tag_item = None
 
-        self.url_formatted = False
+        self.size = Empty
+        self.duration = Empty
+        self.bitrate = Empty
+        self.bytes = None
+        self.duration_seconds = None
+
+        # self.calculate_duration_seconds()
+        # self.calculate_bytes()
+        # self.calculate_bitrate()
 
     def format_original_url(self):
         if not self.url_formatted:
@@ -21,9 +54,53 @@ class Item:
             console.output('Setting original URL to: {0}'.format(self.original_url), console.DBG_INFO)
             self.url_formatted = True
 
+    def set_title(self, title):
+        self.title = title
+
+    def set_artist(self, artist):
+        self.artist = artist
+
+    def set_original_url(self, url):
+        self.original_url = url
+
+    def set_duration_string(self, duration):
+        self.duration = duration
+        self.calculate_duration_seconds()
+
+    def set_size_string(self, size):
+        self.size = size
+        self.calculate_bytes()
+
+        self.calculate_bitrate()
+
+
     def set_download_url(self, url):
         console.output('Setting download url to: {0}'.format(url), console.DBG_INFO)
         self.download_url = url
 
+    def set_bytes(self, bytes):
+        self.bytes = bytes
+
     def link_tag_item(self, tagitem):
-        self.tag_item = tagitem
+        self.tag_item = tagitem
+
+    def calculate_duration_seconds(self):
+        if self.duration is not Empty:
+            _split = self.duration.split(':')
+            minutes = int(_split[0])
+            seconds = int(_split[1])
+
+            self.duration_seconds = (minutes * 60) + seconds
+
+    def calculate_bytes(self):
+        if self.size is not Empty:
+            match = re.search('\d+\.?\d+', self.size)
+
+            if match is not None:
+                mbytes = float(match.group())
+                self.bytes = mbytes * 1048576  # 1024^2 -> MB to B
+
+    def calculate_bitrate(self):
+        if self.duration_seconds is not None and self.bytes is not None:
+            self.bitrate = self.bytes / self.duration_seconds / 1024 * 8  # bytes / seconds / 1024 * 8
+

+ 9 - 7
sites/helper/structure.py

@@ -1,6 +1,6 @@
 from pyquery import PyQuery
 
-from sites.helper.item import Item
+from sites.helper.item import Item, Empty
 
 
 class Structure:
@@ -79,11 +79,13 @@ class Structure:
             size = result.find(self.item_size_path) if self.item_size_path is not None else None
 
             if title is not None and url is not None:
-                items.append(Item(self.site,
-                                  self.site.format_title(title),
-                                  url,
-                                  self.site.format_duration(duration),
-                                  self.site.format_size(size),
-                                  self.site.format_artist(title)))
+                item = Item(self.site)
+                item.set_title(self.site.format_title(title))
+                item.set_artist(self.site.format_artist(title))
+                item.set_original_url(url)
+                item.set_duration_string(self.site.format_duration(duration))
+                item.set_size_string(self.site.format_size(size))
+
+                items.append(item)
 
         return items

+ 2 - 2
sites/helper/tagging.py

@@ -36,8 +36,8 @@ def search_tags(item):
                                            ('ID', 2),
                                            ('Title', 50),
                                            ('Artist', 40),
-                                           ('Album', 50),
-                                           ('Label', 19)
+                                           ('Album', 40),
+                                           ('Label', 29)
                                        ])
     if picked_tag is not None:
         return items[picked_tag]