Skip to content

Instantly share code, notes, and snippets.

@thatarchguy
Last active October 3, 2015 02:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thatarchguy/e7353eefbbc5ae1c6996 to your computer and use it in GitHub Desktop.
Save thatarchguy/e7353eefbbc5ae1c6996 to your computer and use it in GitHub Desktop.
whatcd scripts
#! /usr/local/bin/node
var fs = require('fs'),
request = require('request'),
readline = require('readline');
var request = request.defaults({jar: true}),
rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("Username: ", function(user) {
rl.question("Password: ", function(pass) {
request.post('https://what.cd/login.php', {form:{username: user, password: pass}}, function(error, response, content) {
getPage(1, 7);
rl.close();
});
});
});
function getPage(page, pages) {
console.log('Getting torrent listing page ' + page);
request('https://what.cd/torrents.php?freetorrent=1&page=' + page, function(err, res, body) {
var torrents = body.match(/torrents.php\?action=download.*torrent_pass=[a-z0-9]*/g);
console.log('Parsing page ' + page);
for (var i = 0; i < torrents.length; i++) {
torrents[i] = 'https://what.cd/'.concat(torrents[i].replace(/&amp;/g, '&'));
}
console.log('Downloading torrents from page ' + page);
getTorrents(torrents, 0);
if (page < pages) {
getPage(page + 1, pages);
}
});
}
function getTorrents(torrents, i) {
request(torrents[i], function(err, res, body) {
fs.exists(res.headers['content-disposition'].match(/\".*\"/)[0].slice(1,-9) + '.' + res.request.req.path.match(/id=[0-9]*/)[0].slice(3) + '.torrent', function(exists) {
if(!exists) {
request(torrents[i]).pipe(fs.createWriteStream(res.headers['content-disposition'].match(/\".*\"/)[0].slice(1,-9) + '.' + res.request.req.path.match(/id=[0-9]*/)[0].slice(3) + '.torrent', {mode: 0770}))
}
})
})
if (i < torrents.length - 1) {
getTorrents(torrents, i + 1);
}
}
process.on('uncaughtException', function(err) {
console.log("WARNING: Error downloading torrent");
console.log(err);
});
#!/usr/bin/env python
##############################################################
# whatmp3 - Convert FLAC to mp3, create what.cd torrent.
# Created by shardz (logik.li), demonstar55, and The_Creator
##############################################################
import os
import re
import fnmatch
import shutil
from optparse import OptionParser
import threading
VERSION = "3.6"
### BEGIN CONFIGURATION ###
# Output folder unless specified: ("/home/user/Desktop/")
#output = os.path.join(os.environ['HOME'], "Desktop/")
output = os.getcwd()
# Separate torrent output folder (defaults to output):
torrent_dir = output
# Do you want to move additional files (.jpg, .log, etc)?
moveother = 1
# Do you want to zeropad tracknumbers? (1 => 01, 2 => 02 ...)
zeropad = 1
# Do you want to dither FLACs to 16/44 before encoding?
dither = 0
# Specify tracker ("http://tracker.what.cd:34000/")
tracker = "http://tracker.what.cd:34000/"
# Specify torrent passkey
passkey = ""
# Max number of threads (ex: Normal: 1, Dual-core = 2, Hyperthreaded Dual-core = 4)
max_threads = 1
# Default encoding options
enc_options = {
'320': {'enc': 'lame', 'opts': '-q 0 -b 320 --ignore-tag-errors'},
'V0': {'enc': 'lame', 'opts': '-q 0 -V 0 --vbr-new --ignore-tag-errors'},
'V2': {'enc': 'lame', 'opts': '-q 0 -V 2 --vbr-new --ignore-tag-errors'},
'Q8': {'enc': 'oggenc', 'opts': '-q 8'},
'AAC': {'enc': 'neroAacEnc', 'opts': '-br 320000'},
'ALAC': {'enc': 'ffmpeg', 'opts': '-i - -acodec alac'},
'FLAC': {'enc': 'flac', 'opts': '--best'}
}
### END CONFIGURATION ###
codecs = []
# os.system() and os.popen() have issues with `
def escape_backtick(pattern):
pattern = re.sub('`', '\`', pattern)
return pattern
def escape_quote(pattern):
pattern = re.sub('"', '\\"', pattern)
return pattern
def escape_percent(pattern):
pattern = re.sub('%', '%%', pattern)
return pattern
class Transcode(threading.Thread):
def __init__(self, file, flacdir, mp3_dir, codec, options, cv):
threading.Thread.__init__(self)
self.file = file
self.flacdir = flacdir
self.mp3_dir = mp3_dir
self.codec = codec
self.options = options
self.cv = cv
def run(self):
tags = {}
for tag in ('TITLE', 'ALBUM', 'ARTIST', 'TRACKNUMBER', 'GENRE', 'COMMENT', 'DATE'):
tagcommand = 'metaflac --show-tag=' + escape_quote(tag) + ' "' + escape_quote(self.file) + '"'
temp = re.sub('\S.*=', '', os.popen(escape_backtick(tagcommand)).read().rstrip())
tags.update({tag:temp})
del temp
if self.options.zeropad and len(tags['TRACKNUMBER']) == 1:
tags['TRACKNUMBER'] = '0' + tags['TRACKNUMBER']
mp3_filename = re.sub(re.escape(self.flacdir), self.mp3_dir, self.file)
mp3_filename = re.sub('\.flac$', '', mp3_filename)
if not os.path.exists(os.path.dirname(mp3_filename)):
os.makedirs(os.path.dirname(mp3_filename))
flac_command = ''
mp3_filename = escape_percent(mp3_filename) # string % (params) will break on filenames including an unescaped % character
if enc_options[self.codec]['enc'] == 'lame':
if self.options.skip_genre:
flac_command = 'lame -S %s --tt "%s" --tl "%s" --ta "%s" --tn "%s" --ty "%s" --add-id3v2 - "%s.mp3" 2>&1'
else:
flac_command = 'lame -S %s --tt "%s" --tl "%s" --ta "%s" --tn "%s" --tg "%s" --ty "%s" --add-id3v2 - "%s.mp3" 2>&1'
elif enc_options[self.codec]['enc'] == 'oggenc':
flac_command = 'oggenc -Q %s -t "%s" -l "%s" -a "%s" -N "%s" -G "%s" -d "%s" -o "%s.ogg" - 2>&1'
elif enc_options[self.codec]['enc'] == 'ffmpeg':
flac_command = 'ffmpeg %s -metadata title="%s" -metadata album="%s" -metadata author="%s" -metadata track="%s" -metadata genre="%s" -metadata date="%s" "%s.m4a" 2>&1'
elif enc_options[self.codec]['enc'] == 'neroAacEnc':
flac_command = 'neroAacEnc %s -if - -of "%s.m4a" 2>&1 && neroAacTag "%s.m4a" -meta:title="%s" -meta:album="%s" -meta:artist="%s" -meta:track="%s" -meta:genre="%s" -meta:year="%s"'
elif enc_options[self.codec]['enc'] == 'flac':
flac_command = 'flac %s -s -T "TITLE=%s" -T "ALBUM=%s" -T "ARTIST=%s" -T "TRACKNUMBER=%s" -T "GENRE=%s" -T "DATE=%s" -o "%s.flac" - 2>&1'
if self.options.dither:
flac_command = 'sox -t wav - -b 16 -t wav - rate 44100 dither | ' + flac_command
flac_command = 'flac -dc -- "' + escape_percent(escape_quote(self.file)) + '" | ' + flac_command
if enc_options[self.codec]['enc'] == 'neroAacEnc':
flac_command = flac_command % (escape_quote(enc_options[self.codec]['opts']), escape_quote(mp3_filename), escape_quote(mp3_filename), escape_quote(tags['TITLE']), escape_quote(tags['ALBUM']), escape_quote(tags['ARTIST']), escape_quote(tags['TRACKNUMBER']), escape_quote(tags['GENRE']), escape_quote(tags['DATE']))
else:
genre_tag = (escape_quote(tags['GENRE']),)
if enc_options[self.codec]['enc'] == 'lame' and self.options.skip_genre:
genre_tag = ()
params = (escape_quote(enc_options[self.codec]['opts']), escape_quote(tags['TITLE']), escape_quote(tags['ALBUM']), escape_quote(tags['ARTIST']), escape_quote(tags['TRACKNUMBER'])) + genre_tag + (escape_quote(tags['DATE']), escape_quote(mp3_filename))
flac_command = flac_command % params
if self.options.verbose:
print(escape_backtick(flac_command))
os.system(escape_backtick(flac_command))
self.cv.acquire()
self.cv.notify_all()
self.cv.release()
return 0
def add_enc_option(option, opt, value, parser):
codecs.append(opt[2:])
def main():
# Parse options and arguments
usage_text = "%prog [options] [--320 --V2 --Q8 --AAC ...] /path/to/FLAC"
info_text = "Depends on flac, metaflac, mktorrent, and optionally oggenc, lame, neroAacEnc, neroAacTag, mp3gain, aacgain, vorbisgain, and sox."
parser = OptionParser(usage=usage_text, version="%prog " + VERSION, epilog=info_text)
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False, help='increase verbosity (Default: False)')
parser.add_option('-n', '--notorrent', action='store_true', dest='notorrent', default=False, help='will not create a torrent after conversion (Default: False)')
parser.add_option('--nolog', action='store_true', dest='nolog', default=False, help='will not move log files after conversion (Default: False)')
parser.add_option('--nocue', action='store_true', dest='nocue', default=False, help='will not move cue files after conversion (Default: False)')
parser.add_option('--nodate', action='store_true', dest='nodate', default=False, help='do not write the creation date to the .torrent file (Default: False)')
parser.add_option('--skipgenre', action='store_true', dest='skip_genre', default=False, help='do not insert a genre tag in MP3 files (Default: False)')
parser.add_option('-m', '--moveother', action='store_true', dest='moveother', default=moveother, help='move additional files (Default: True)')
parser.add_option('-p', '--passkey', dest='passkey', default=passkey, help='tracker PASSKEY', metavar='PASSKEY')
parser.add_option('-t', '--tracker', dest='tracker', default=tracker, help='tracker URL (Default: "http://tracker.what.cd:34000/")', metavar='URL')
parser.add_option('-o', '--output', dest='output', default=output, help='set the output PATH', metavar='PATH')
parser.add_option('--torrent-dir', dest='torrent_dir', default=torrent_dir, help='set independent torrent output directory')
parser.add_option('-z', '--zeropad', action='store_true', dest='zeropad', default=zeropad, help='zeropad track numbers (Default: True)')
parser.add_option('-r', '--replaygain', action='store_true', dest='replaygain', default=False, help='add ReplayGain to new files (Default: False)')
parser.add_option('-d', '--dither', action='store_true', dest='dither', default=dither, help='dither FLACs to 16/44 before encoding (Default: False)')
parser.add_option('--threads', type="int", dest='max_threads', default=max_threads, help='set number of threads THREADS (Default: 1)', metavar='THREADS')
parser.add_option('-c', '--original', action='store_true', dest='original', default=False, help='create a torrent for the original FLAC')
for enc_opt in enc_options.keys():
parser.add_option("--" + enc_opt, action="callback", callback=add_enc_option, help='convert to %s' % (enc_opt))
(options, flacdirs) = parser.parse_args()
if len(flacdirs) < 1:
parser.error("Incorrect number of arguments")
if not options.output.endswith('/'):
options.output += '/'
if len(codecs) == 0 and not options.original:
print('You need to provide at least one format to transcode to (320, V0, Q8 ...)')
exit()
for flacdir in flacdirs:
flacdir = os.path.abspath(flacdir)
flacfiles = []
for dirpath, dirs, files in os.walk(flacdir, topdown=False):
for name in files:
if fnmatch.fnmatch(name, '*.flac') or fnmatch.fnmatch(name, '*.FLAC'):
flacfiles.append(os.path.join(dirpath, name))
if options.original:
print('Working with FLAC...')
if options.output and options.passkey and options.tracker and not options.notorrent:
if options.verbose: print('Creating torrent...')
torrent_command = 'mktorrent -p -a %s/announce -o "%s.torrent" "%s"' % (options.tracker + options.passkey, escape_quote(options.output + os.path.basename(flacdir)), escape_quote(flacdir))
if options.nodate:
torrent_command += ' -d'
if options.verbose: print(escape_backtick(torrent_command))
os.system(escape_backtick(torrent_command))
print('Finished working with FLAC')
for codec in codecs:
mp3_dir = options.output + os.path.basename(flacdir)
if 'FLAC' in flacdir:
mp3_dir = re.sub(re.compile('FLAC', re.I), codec, mp3_dir)
else:
mp3_dir = mp3_dir + " (" + codec + ")"
if not os.path.exists(mp3_dir):
os.makedirs(mp3_dir)
print('Encoding with ' + codec + ' started...')
threads = []
cv = threading.Condition()
for file in flacfiles:
cv.acquire()
while((threading.activeCount() == options.max_threads + 1) or (options.max_threads == 0 and threading.activeCount() == 2)):
cv.wait()
cv.release()
t=Transcode(file, flacdir, mp3_dir, codec, options, cv)
t.start()
threads.append(t)
for t in threads:
t.join()
print('\nEncoding with ' + codec + ' finished.')
if options.moveother:
if options.verbose: print('Moving other files...')
for dirpath, dirs, files in os.walk(flacdir, topdown=False):
for name in files:
if options.nolog and fnmatch.fnmatch(name, '*.log'):
continue
if options.nocue and fnmatch.fnmatch(name, '*.cue'):
continue
if not fnmatch.fnmatch(name, '*.flac') and not fnmatch.fnmatch(name, '*.m3u'):
d = re.sub(re.escape(flacdir), mp3_dir, dirpath)
if not os.path.exists(d):
os.makedirs(d)
shutil.copy(os.path.join(dirpath, name), d)
if options.replaygain and enc_options[codec]['enc'] != 'flac':
if options.verbose: print('Applying replay gain...')
for dirpath, dirs, files in os.walk(mp3_dir, topdown=False):
for name in dirs:
if enc_options[codec]['enc'] == 'lame':
os.system(escape_backtick('mp3gain -q -c -s i "' + os.path.join(dirpath, name) + '"/*.mp3'))
if enc_options[codec]['enc'] == 'oggenc':
os.system(escape_backtick('vorbisgain -qafrs "' + os.path.join(dirpath, name) + '"/*.ogg'))
if enc_options[codec]['enc'] == 'neroAacEnc':
os.system(escape_backtick('aacgain -q -c "' + os.path.join(dirpath, name) + '"/*.m4a'))
if options.output and options.passkey and options.tracker and not options.notorrent:
if options.verbose: print('Creating torrent...')
torrent_command = 'mktorrent -p -a %s/announce -o "%s.torrent" "%s"' % (options.tracker + options.passkey, escape_backtick(os.path.join(options.torrent_dir, os.path.basename(mp3_dir))), mp3_dir)
if options.nodate:
torrent_command += ' -d'
if options.verbose: print(escape_backtick(torrent_command))
os.system(escape_backtick(torrent_command))
if options.verbose: print('All done with ' + flacdir + ' ...')
return 0
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment