else
This commit is contained in:
parent
15c9e1fcfd
commit
b0187f3269
14 changed files with 405 additions and 10 deletions
|
@ -3,8 +3,18 @@ Open Dir DL
|
|||
|
||||
The open directory downloader.
|
||||
|
||||
## Installation
|
||||
|
||||
pip install requirements.txt
|
||||
|
||||
## Usage
|
||||
|
||||
See inside opendirdl.py for usage instructions.
|
||||
|
||||
|
||||
|
||||
### Changelog
|
||||
|
||||
- **[addition]** A new feature was added.
|
||||
- **[bugfix]** Incorrect behavior was fixed.
|
||||
- **[change]** An existing feature was slightly modified or parameters were renamed.
|
||||
|
@ -33,7 +43,7 @@ See inside opendirdl.py for usage instructions.
|
|||
- 2016 08 10
|
||||
- **[addition]** Added clickable links to each directory on HTML tree pages.
|
||||
- **[bugfix]** Fixed bug in smart_insert caused by 404's being considered falsey, triggering the 'one and only one' exception.
|
||||
- **[bugfix]** Fixed bug in smart_insert where 404'd URLs were not being dele`ted from the database.
|
||||
- **[bugfix]** Fixed bug in smart_insert where 404'd URLs were not being deleted from the database.
|
||||
|
||||
- 2016 08 02
|
||||
- **[cleanup]** Removed the need for div IDs on the Tree pages by making the collapse button use `this.nextSibling`.
|
||||
|
@ -52,7 +62,7 @@ See inside opendirdl.py for usage instructions.
|
|||
|
||||
- 2016 07 25
|
||||
- **[change]** Bytespersecond is now parsed by `bytestring.parsebytes` rather than `eval`, so you can write "100k" as opposed to "100 * 1024" etc.
|
||||
- **[removal]** Removed the `Downloader` class after watching [this Jack Diederich talk](https://youtu.be/o9pEzgHorH0) about unecessary classes.
|
||||
- **[removal]** Removed the `Downloader` class and replaced it with a function, because it only had one real method anyway.
|
||||
|
||||
- 2016 07 19
|
||||
- **[addition]** Gave the HTML tree divs a very gentle shadow and alternating colors to help with depth perception.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import bytestring
|
||||
from voussoirkit import bytestring
|
||||
import downloady
|
||||
import ratemeter
|
||||
import requests
|
||||
|
|
|
@ -233,7 +233,7 @@ def colorama_print(text):
|
|||
alternator = False
|
||||
terminal_size = shutil.get_terminal_size()[0]
|
||||
for line in text.split('\n'):
|
||||
line += ' ' * (terminal_size - (len(line)+1))
|
||||
line = line.ljust(terminal_size, ' ')
|
||||
if HAS_COLORAMA:
|
||||
if alternator:
|
||||
sys.stdout.write(colorama.Fore.BLACK)
|
||||
|
@ -242,7 +242,8 @@ def colorama_print(text):
|
|||
sys.stdout.write(colorama.Fore.WHITE)
|
||||
sys.stdout.write(colorama.Back.BLACK)
|
||||
alternator = not alternator
|
||||
print(line)
|
||||
# \r because the ljust puts us on the next line, no need for \n
|
||||
print(line, end='\r', flush=True)
|
||||
if HAS_COLORAMA:
|
||||
sys.stdout.write(colorama.Back.RESET)
|
||||
sys.stdout.write(colorama.Fore.RESET)
|
||||
|
@ -274,11 +275,20 @@ def multi_line_input():
|
|||
return userinput.strip()
|
||||
|
||||
def nicewrap(message, width, paddingleft):
|
||||
# http://stackoverflow.com/a/26538082 ##########################
|
||||
message = '\n'.join(['\n'.join(textwrap.wrap(line, width,#######
|
||||
break_long_words=True, replace_whitespace=False))##########
|
||||
for line in message.split('\n')])##########################
|
||||
################################################################
|
||||
# http://stackoverflow.com/a/26538082
|
||||
message = message.split('\n')
|
||||
message = [
|
||||
textwrap.wrap(
|
||||
line,
|
||||
width,
|
||||
break_long_words=True,
|
||||
replace_whitespace=False,
|
||||
)
|
||||
for line in message
|
||||
]
|
||||
message = ['\n'.join(line) for line in message]
|
||||
message = '\n'.join(message)
|
||||
|
||||
message = message.strip()
|
||||
message = message.replace('\n', '\n' + (' '*paddingleft))
|
||||
return message
|
||||
|
|
49
Toolbox/bitrate_chart.py
Normal file
49
Toolbox/bitrate_chart.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
'''
|
||||
bitrate | 01 | 1:00 | 30:00 | 1:00:00 | 1:30:00 | 2:00:00
|
||||
-: | -: | -: | -: | -: | -: | -:
|
||||
128 kbps | 16.000 KiB | 960.000 KiB | 28.125 MiB | 56.250 MiB | 84.375 MiB | 112.500 MiB
|
||||
256 kbps | 32.000 KiB | 1.875 MiB | 56.250 MiB | 112.500 MiB | 168.750 MiB | 225.000 MiB
|
||||
320 kbps | 40.000 KiB | 2.344 MiB | 70.312 MiB | 140.625 MiB | 210.938 MiB | 281.250 MiB
|
||||
500 kbps | 62.500 KiB | 3.662 MiB | 109.863 MiB | 219.727 MiB | 329.590 MiB | 439.453 MiB
|
||||
640 kbps | 80.000 KiB | 4.688 MiB | 140.625 MiB | 281.250 MiB | 421.875 MiB | 562.500 MiB
|
||||
738 kbps | 92.250 KiB | 5.405 MiB | 162.158 MiB | 324.316 MiB | 486.475 MiB | 648.633 MiB
|
||||
1024 kbps | 128.000 KiB | 7.500 MiB | 225.000 MiB | 450.000 MiB | 675.000 MiB | 900.000 MiB
|
||||
2048 kbps | 256.000 KiB | 15.000 MiB | 450.000 MiB | 900.000 MiB | 1.318 GiB | 1.758 GiB
|
||||
2330 kbps | 291.271 KiB | 17.067 MiB | 512.000 MiB | 1.000 GiB | 1.500 GiB | 2.000 GiB
|
||||
3072 kbps | 384.000 KiB | 22.500 MiB | 675.000 MiB | 1.318 GiB | 1.978 GiB | 2.637 GiB
|
||||
4096 kbps | 512.000 KiB | 30.000 MiB | 900.000 MiB | 1.758 GiB | 2.637 GiB | 3.516 GiB
|
||||
4660 kbps | 582.543 KiB | 34.133 MiB | 1.000 GiB | 2.000 GiB | 3.000 GiB | 4.000 GiB
|
||||
6144 kbps | 768.000 KiB | 45.000 MiB | 1.318 GiB | 2.637 GiB | 3.955 GiB | 5.273 GiB
|
||||
8192 kbps | 1.000 MiB | 60.000 MiB | 1.758 GiB | 3.516 GiB | 5.273 GiB | 7.031 GiB
|
||||
12288 kbps | 1.500 MiB | 90.000 MiB | 2.637 GiB | 5.273 GiB | 7.910 GiB | 10.547 GiB
|
||||
16384 kbps | 2.000 MiB | 120.000 MiB | 3.516 GiB | 7.031 GiB | 10.547 GiB | 14.062 GiB
|
||||
'''
|
||||
import sys
|
||||
sys.path.append('C:\\git\\else\\bytestring')
|
||||
import bytestring
|
||||
import kbps
|
||||
times = ['01', '1:00', '30:00', '1:00:00', '1:30:00', '2:00:00']
|
||||
rates = [128, 256, 320, 500, 640, 738, 1024, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 2330.17, 4660.34]
|
||||
|
||||
times.sort(key=lambda x: kbps.hms_s(x))
|
||||
rates.sort()
|
||||
|
||||
table = []
|
||||
table.append('bitrate | ' + ' | '.join(times))
|
||||
table.append('-: | ' * (len(times)+1))
|
||||
for r in rates:
|
||||
l = []
|
||||
l.append('%d kbps' % r)
|
||||
for t in times:
|
||||
l.append(bytestring.bytestring(kbps.calc(kbps.hms_s(t), r)))
|
||||
l = ' | '.join(l)
|
||||
table.append(l)
|
||||
|
||||
#print('\n'.join(table))
|
||||
columns = [[b.strip() for b in a] for a in zip(*[x.split('|') for x in table])]
|
||||
for (index, column) in enumerate(columns):
|
||||
width = max((len(x) for x in column))
|
||||
columns[index] = [x.rjust(width, ' ') for x in column]
|
||||
table = [' | '.join(a) for a in zip(*columns)]
|
||||
#print(columns)
|
||||
print('\n'.join(table))
|
12
Toolbox/clipboard.py
Normal file
12
Toolbox/clipboard.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
import pyperclip
|
||||
import sys
|
||||
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
sys.path.append('C:\\git\\else\\Clipext'); import clipext
|
||||
stuff = clipext.resolve(sys.argv[1])
|
||||
pyperclip.copy(stuff)
|
||||
else:
|
||||
text = pyperclip.paste()
|
||||
text = text.replace('\r', '')
|
||||
print(text)
|
35
Toolbox/contentreplace.py
Normal file
35
Toolbox/contentreplace.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
import codecs
|
||||
import sys
|
||||
filename = sys.argv[1]
|
||||
replace_from = sys.argv[2]
|
||||
replace_to = sys.argv[3]
|
||||
try:
|
||||
automatic = sys.argv[4] == '-y'
|
||||
except IndexError:
|
||||
automatic = False
|
||||
|
||||
replace_from = codecs.decode(replace_from, 'unicode_escape')
|
||||
replace_to = codecs.decode(replace_to, 'unicode_escape')
|
||||
|
||||
f = open(filename, 'r', encoding='utf-8')
|
||||
with f:
|
||||
content = f.read()
|
||||
|
||||
occurances = content.count(replace_from)
|
||||
if occurances == 0:
|
||||
print('No occurances')
|
||||
exit()
|
||||
|
||||
print('Found %d occurances.' % occurances)
|
||||
if automatic:
|
||||
permission = 'y'
|
||||
else:
|
||||
permission = input('Replace? ')
|
||||
if permission.lower() not in ['y', 'yes']:
|
||||
exit()
|
||||
|
||||
content = content.replace(replace_from, replace_to)
|
||||
|
||||
f = open(filename, 'w', encoding='utf-8')
|
||||
with f:
|
||||
f.write(content)
|
43
Toolbox/ffrename.py
Normal file
43
Toolbox/ffrename.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
import converter
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
def main(filename):
|
||||
assert os.path.isfile(filename)
|
||||
ffmpeg = converter.Converter()
|
||||
probe = ffmpeg.probe(filename)
|
||||
new_name = filename
|
||||
if '_x_' in filename:
|
||||
dimensions = '%dx%d' % (probe.video.video_width, probe.video.video_height)
|
||||
new_name = new_name.replace('_x_', dimensions)
|
||||
if '___' in filename:
|
||||
video_codec = probe.video.codec
|
||||
|
||||
audios = [stream for stream in probe.streams if stream.type == 'audio']
|
||||
audio = max(audios, key=lambda x: x.bitrate)
|
||||
|
||||
audio_codec = probe.audio.codec
|
||||
|
||||
if any(not x for x in [video_codec, probe.video.bitrate, audio_codec, probe.audio.bitrate]):
|
||||
print('Could not identify media info')
|
||||
else:
|
||||
video_bitrate = probe.video.bitrate // 1000
|
||||
audio_bitrate = probe.audio.bitrate // 1000
|
||||
video = '%s-%d' % (video_codec, video_bitrate)
|
||||
audio = '%s-%d' % (audio_codec, audio_bitrate)
|
||||
|
||||
video = video.upper()
|
||||
audio = audio.upper()
|
||||
video = video.replace('H264', 'h264')
|
||||
video = video.replace('HEVC', 'h265')
|
||||
info = '{v}, {a}'.format(v=video, a=audio)
|
||||
new_name = new_name.replace('___', info)
|
||||
print(new_name)
|
||||
if input('Okay?').lower() in ['y', 'yes']:
|
||||
os.rename(filename, new_name)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1])
|
37
Toolbox/filepull.py
Normal file
37
Toolbox/filepull.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append('C:\\git\\else\\spinaltap')
|
||||
import spinal
|
||||
|
||||
def main():
|
||||
files = list(spinal.walk_generator())
|
||||
cwd = os.getcwd()
|
||||
files = [f for f in files if os.path.split(f.absolute_path)[0] != cwd]
|
||||
|
||||
if len(files) == 0:
|
||||
print('No files to move')
|
||||
return
|
||||
|
||||
duplicate_count = {}
|
||||
for f in files:
|
||||
basename = f.basename
|
||||
duplicate_count.setdefault(basename, [])
|
||||
duplicate_count[basename].append(f.absolute_path)
|
||||
|
||||
duplicates = ['\n'.join(sorted(copies)) for (basename, copies) in duplicate_count.items() if len(copies) > 1]
|
||||
duplicates = sorted(duplicates)
|
||||
if len(duplicates) > 0:
|
||||
raise Exception('duplicate names:\n' + '\n'.join(duplicates))
|
||||
|
||||
for f in files:
|
||||
print(f.basename)
|
||||
|
||||
print('Move %d files?' % len(files))
|
||||
if input('> ').lower() in ['y', 'yes']:
|
||||
for f in files:
|
||||
local = os.path.join('.', f.basename)
|
||||
os.rename(f.absolute_path, local)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
27
Toolbox/fileswith.py
Normal file
27
Toolbox/fileswith.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import fnmatch
|
||||
import glob
|
||||
import re
|
||||
import sys
|
||||
sys.path.append('C:\\git\\else\\spinaltap'); import spinal
|
||||
|
||||
filepattern = sys.argv[1]
|
||||
searchpattern = sys.argv[2]
|
||||
|
||||
for filename in spinal.walk_generator():
|
||||
filename = filename.absolute_path
|
||||
if not fnmatch.fnmatch(filename, filepattern):
|
||||
continue
|
||||
matches = []
|
||||
handle = open(filename, 'r', encoding='utf-8')
|
||||
try:
|
||||
with handle:
|
||||
for (index, line) in enumerate(handle):
|
||||
if re.search(searchpattern, line, flags=re.IGNORECASE):
|
||||
line = '%d | %s' % (index, line.strip())
|
||||
matches.append(line)
|
||||
except:
|
||||
pass
|
||||
if matches:
|
||||
print(filename)
|
||||
print('\n'.join(matches))
|
||||
print()
|
32
Toolbox/kbps.py
Normal file
32
Toolbox/kbps.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import sys
|
||||
try:
|
||||
sys.path.append('C:\\git\\else\\Bytestring')
|
||||
import bytestring
|
||||
except ImportError:
|
||||
# pip install
|
||||
# https://raw.githubusercontent.com/voussoir/else/master/_voussoirkit/voussoirkit.zip
|
||||
from vousoirkit import bytestring
|
||||
|
||||
def hms_s(hms):
|
||||
hms = hms.split(':')
|
||||
seconds = 0
|
||||
if len(hms) == 3:
|
||||
seconds += int(hms[0])*3600
|
||||
hms.pop(0)
|
||||
if len(hms) == 2:
|
||||
seconds += int(hms[0])*60
|
||||
hms.pop(0)
|
||||
if len(hms) == 1:
|
||||
seconds += int(hms[0])
|
||||
return seconds
|
||||
|
||||
def calc(seconds, kbps):
|
||||
final_kilobits = kbps * seconds
|
||||
final_bytes = final_kilobits * 128
|
||||
return final_bytes
|
||||
|
||||
if __name__ == '__main__':
|
||||
length = sys.argv[1] # HH:MM:SS
|
||||
kbps = int(sys.argv[2])
|
||||
seconds = hms_s(length)
|
||||
print(bytestring.bytestring(calc(seconds, kbps)))
|
35
Toolbox/kbpsr.py
Normal file
35
Toolbox/kbpsr.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
import sys
|
||||
|
||||
try:
|
||||
sys.path.append('C:\\git\\else\\Bytestring')
|
||||
import bytestring
|
||||
except ImportError:
|
||||
# pip install
|
||||
# https://raw.githubusercontent.com/voussoir/else/master/_voussoirkit/voussoirkit.zip
|
||||
from vousoirkit import bytestring
|
||||
|
||||
def hms_s(hms):
|
||||
hms = hms.split(':')
|
||||
seconds = 0
|
||||
if len(hms) == 3:
|
||||
seconds += int(hms[0])*3600
|
||||
hms.pop(0)
|
||||
if len(hms) == 2:
|
||||
seconds += int(hms[0])*60
|
||||
hms.pop(0)
|
||||
if len(hms) == 1:
|
||||
seconds += int(hms[0])
|
||||
return seconds
|
||||
|
||||
def calc(seconds, goal_bytes):
|
||||
goal_kibs = goal_bytes / 1024
|
||||
goal_kilobits = goal_kibs * 8
|
||||
goal_kbps = goal_kilobits / seconds
|
||||
goal_kbps = round(goal_kbps, 2)
|
||||
return goal_kbps
|
||||
|
||||
if __name__ == '__main__':
|
||||
length = sys.argv[1] # HH:MM:SS
|
||||
goal_bytes = bytestring.parsebytes(sys.argv[2])
|
||||
seconds = hms_s(length)
|
||||
print(calc(seconds, goal_bytes), 'kbps')
|
46
Toolbox/randomfile.py
Normal file
46
Toolbox/randomfile.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
import math
|
||||
import random
|
||||
import sys
|
||||
import bytestring
|
||||
CHUNK_SIZE = 512 * (2 ** 10)
|
||||
def listget(li, index, fallback=None):
|
||||
try:
|
||||
return li[index]
|
||||
except IndexError:
|
||||
return fallback
|
||||
|
||||
def rid(length=8):
|
||||
import random
|
||||
bits = length * 4
|
||||
bits = random.getrandbits(bits)
|
||||
identifier = '{:02x}'.format(bits).rjust(length, '0')
|
||||
return identifier
|
||||
|
||||
def make_randomfile(length, filename=None):
|
||||
if filename is None:
|
||||
filename = rid(8) + '.txt'
|
||||
chunks = math.ceil(length / CHUNK_SIZE)
|
||||
written = 0
|
||||
f = open(filename, 'w')
|
||||
for x in range(chunks):
|
||||
b = min(CHUNK_SIZE, length-written)
|
||||
f.write(rid(b))
|
||||
written += b
|
||||
f.close()
|
||||
print('Created %s' % filename)
|
||||
|
||||
|
||||
bytes = listget(sys.argv, 1, None)
|
||||
if bytes is None:
|
||||
bytes = 2 ** 10
|
||||
else:
|
||||
bytes = bytestring.parsebytes(bytes)
|
||||
|
||||
filecount = 1
|
||||
filename = listget(sys.argv, 2, None)
|
||||
if filename is not None and filename.isdigit():
|
||||
filecount = int(filename)
|
||||
filename = None
|
||||
|
||||
for x in range(filecount):
|
||||
make_randomfile(bytes, filename)
|
44
Toolbox/rejpg.py
Normal file
44
Toolbox/rejpg.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from voussoirkit import bytestring
|
||||
import io
|
||||
import os
|
||||
import PIL.Image
|
||||
import PIL.ImageFile
|
||||
import string
|
||||
import sys
|
||||
|
||||
PIL.ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
|
||||
if '/r' in sys.argv:
|
||||
sys.path.append('C:\\git\\else\\spinaltap')
|
||||
import spinal
|
||||
walker = spinal.walk_generator()
|
||||
files = list(walker)
|
||||
files = [f.absolute_path for f in files]
|
||||
|
||||
else:
|
||||
files = os.listdir()
|
||||
files = [f for f in files if os.path.isfile(f)]
|
||||
|
||||
files = [f for f in files if any(ext in f.lower() for ext in ['.jpg', '.jpeg'])]
|
||||
|
||||
bytes_saved = 0
|
||||
remaining_size = 0
|
||||
for filename in files:
|
||||
print(''.join(c for c in filename if c in string.printable))
|
||||
bytesio = io.BytesIO()
|
||||
i = PIL.Image.open(filename)
|
||||
i.save(bytesio, format='jpeg', quality=80)
|
||||
|
||||
bytesio.seek(0)
|
||||
new_bytes = bytesio.read()
|
||||
old_size = os.path.getsize(filename)
|
||||
new_size = len(new_bytes)
|
||||
remaining_size += new_size
|
||||
if new_size < old_size:
|
||||
bytes_saved += (old_size - new_size)
|
||||
f = open(filename, 'wb')
|
||||
f.write(new_bytes)
|
||||
f.close()
|
||||
|
||||
print('Saved', bytestring.bytestring(bytes_saved))
|
||||
print('Remaining are', bytestring.bytestring(remaining_size))
|
15
Toolbox/touch.py
Normal file
15
Toolbox/touch.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import glob
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
glob_patterns = sys.argv[1:]
|
||||
for glob_pattern in glob_patterns:
|
||||
filenames = glob.glob(glob_pattern)
|
||||
if len(filenames) == 0:
|
||||
print(glob_pattern)
|
||||
open(glob_pattern, 'a').close()
|
||||
else:
|
||||
for filename in filenames:
|
||||
print(filename)
|
||||
os.utime(filename)
|
Loading…
Reference in a new issue