Browse Source

fix output_path lambda error, support pip (Thanks @lonelyhentai #19)

master
nondanee 5 years ago
parent
commit
c05ab65228
  1. 63
      README.md
  2. 1
      ncmdump/__init__.py
  3. 80
      ncmdump/app.py
  4. 29
      ncmdump/core.py
  5. 24
      setup.py

63
README.md

@ -13,40 +13,63 @@
- [JamieDummy/NCM_dump](https://github.com/JamieDummy/NCM_dump): Add GUI - [JamieDummy/NCM_dump](https://github.com/JamieDummy/NCM_dump): Add GUI
- [mnilzg/ncmdump](https://github.com/mnilzg/ncmdump): Speed up with NumPy - [mnilzg/ncmdump](https://github.com/mnilzg/ncmdump): Speed up with NumPy
### Contributor
- [@kalteblau](https://github.com/kalteblau): Validate path & collision
- [@HarrisonXi](https://github.com/HarrisonXi): Add missing identifier
- [@leconio](https://github.com/leconio): handle dict key missing exception
- [@lonelyhentai](https://github.com/lonelyhentai): Add pip support
## Dependency ## Dependency
``` ```
$ pip install pycryptodome mutagen $ pip install pycryptodome mutagen
``` ```
## Usage ## Install
### Specify files
``` ```
$ python ncmdump.py [file ...] $ pip install git+https://github.com/nondanee/ncmdump.git
``` ```
### Traverse working directory
``` ## Usage
$ python ncmdump.py
``` ### Execute
### More options
``` ```sh
$ python app.py -h $ ncmdump -h # equivalent to "python ncmdump/app.py -h"
usage: ncmdump [-h] [-f format] [-o output] [-d] [-c | -s] [input [input ...]] usage: ncmdump [-h] [-f format] [-o output] [-d] [-c | -r] [input [input ...]]
positional arguments: positional arguments:
input ncm file or folder path input ncm file or folder path
optional arguments: optional arguments:
-h, --help show this help message and exit -h show this help message and exit
-f format customize naming format -f format customize naming format
-o output customize saving folder -o output customize saving folder
-d delete source after conversion -d delete source after conversion
-c overwrite file with the same name -c overwrite file with the same name
-s skip conversion if file exist -r auto rename if file name conflicts
``` ```
> Supported name holder: %artist%, %title%, %album% > Supported name format holder: `%artist%`, `%title%`, `%album%`
### Import
```python
from ncmdump import dump
```
```python
def dump(input_path, output_path = None, skip = True):
'''
args:
input_path: a string of input file path
output_path: a string of output file path or a naming function
skip: a boolean controls conversion skipping when output file exists
returns:
a string of output file path or none if conversion is skipped
'''
```

1
ncmdump/__init__.py

@ -0,0 +1 @@
from .core import dump

80
app.py → ncmdump/app.py

@ -5,11 +5,15 @@ Created on Fri Sep 28 13:32:51 2018
@author: Nzix @author: Nzix
""" """
import argparse, os, sys, re import argparse, os, sys, traceback, re
import ncmdump from .core import dump
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
prog = 'ncmdump' prog = 'ncmdump', add_help = False
)
parser.add_argument(
'-h', action = 'help',
help = 'show this help message and exit'
) )
parser.add_argument( parser.add_argument(
'input', metavar = 'input', nargs = '*', default = ['.'], 'input', metavar = 'input', nargs = '*', default = ['.'],
@ -33,8 +37,8 @@ group.add_argument(
help = 'overwrite file with the same name' help = 'overwrite file with the same name'
) )
group.add_argument( group.add_argument(
'-s', dest = 'skip', action = 'store_true', '-r', dest = 'rename', action = 'store_true',
help = 'skip conversion if file exist' help = 'auto rename if file name conflicts'
) )
args = parser.parse_args() args = parser.parse_args()
@ -72,39 +76,45 @@ def name_format(path, meta):
name += '.' + meta['format'] name += '.' + meta['format']
folder = args.output if args.output else os.path.dirname(path) folder = args.output if args.output else os.path.dirname(path)
save = os.path.join(folder, name) save = os.path.join(folder, name)
if not (args.cover or args.skip): save = validate_collision(save) if args.rename: save = validate_collision(save)
return save return save
if args.output: def main():
args.output = os.path.abspath(args.output) if args.output:
if not os.path.exists(args.output): args.output = os.path.abspath(args.output)
print('output does not exist') if not os.path.exists(args.output):
exit() print('output does not exist')
if not os.path.isdir(args.output): exit()
print('output is not a folder') if not os.path.isdir(args.output):
exit() print('output is not a folder')
exit()
files = [] files = []
for path in args.input: for path in args.input:
path = os.path.abspath(path) path = os.path.abspath(path)
if not os.path.exists(path): if not os.path.exists(path):
continue continue
if os.path.isdir(path): if os.path.isdir(path):
files += [os.path.join(path, name) for name in os.listdir(path) if os.path.splitext(name)[-1] == '.ncm'] files += [os.path.join(path, name) for name in os.listdir(path) if os.path.splitext(name)[-1] == '.ncm']
else: else:
files += [path] files += [path]
if sys.version[0] == '2':
files = [path.decode(sys.stdin.encoding) for path in files]
if sys.version[0] == '2': if not files:
files = [path.decode(sys.stdin.encoding) for path in files] print('empty input')
exit()
if not files: for path in files:
print('empty input') try:
exit() save = dump(path, name_format, not args.cover)
if save: print(os.path.split(save)[-1])
if args.delete: os.remove(path)
except KeyboardInterrupt:
exit()
except:
print(traceback.format_exc())
for path in files: if __name__ == '__main__':
try: main()
save = ncmdump.dump(path, name_format, args.skip)
if save: print(os.path.split(save)[-1])
if args.delete: os.remove(path)
except KeyboardInterrupt:
exit()

29
ncmdump.py → ncmdump/core.py

@ -7,7 +7,7 @@ Created on Sun Jul 15 01:05:58 2018
import binascii, struct import binascii, struct
import base64, json import base64, json
import os, traceback import os
from Crypto.Cipher import AES from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad from Crypto.Util.Padding import unpad
@ -17,7 +17,7 @@ from mutagen import mp3, flac, id3
def dump(input_path, output_path = None, skip = True): def dump(input_path, output_path = None, skip = True):
output_path = (lambda path, meta: os.path.splitext(path)[0] + '.' + meta['format']) if not output_path else output_path output_path = (lambda path, meta: os.path.splitext(path)[0] + '.' + meta['format']) if not output_path else output_path
output_path = (lambda path, meta: path) if not callable(output_path) else output_path output_path_generator = (lambda path, meta: output_path) if not callable(output_path) else output_path
core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857') core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857')
meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728') meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728')
@ -78,7 +78,7 @@ def dump(input_path, output_path = None, skip = True):
f.seek(image_space - image_size, 1) f.seek(image_space - image_size, 1)
# media data # media data
output_path = output_path(input_path, meta_data) output_path = output_path_generator(input_path, meta_data)
if skip and os.path.exists(output_path): return if skip and os.path.exists(output_path): return
data = f.read() data = f.read()
@ -128,25 +128,4 @@ def dump(input_path, output_path = None, skip = True):
audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']]) audio['artist'] = '/'.join([artist[0] for artist in meta_data['artist']])
audio.save() audio.save()
return output_path return output_path
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
files = sys.argv[1:]
else:
files = [name for name in os.listdir('.') if os.path.splitext(name)[-1] == '.ncm']
if sys.version[0] == '2':
files = [path.decode(sys.stdin.encoding) for path in files]
if not files:
print('please input file path!')
for path in files:
try:
dump(path)
print(os.path.split(path)[-1])
except Exception as e:
print(traceback.format_exc())
pass

24
setup.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
setup(
name = 'ncmdump',
version = '0.1.0',
description = 'netease cloud music copyright protection file dump',
url = 'http://github.com/nondanee/ncmdump',
author = 'nondanee',
author_email = 'iminezn5656@outlook.com',
license = 'MIT',
keywords = ('ncm', 'netease cloud music'),
packages = find_packages(),
platforms = 'any',
zip_safe = False,
python_requires = '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
install_requires = ['pycryptodome', 'mutagen'],
entry_points = {
'console_scripts': [
'ncmdump=ncmdump.app:main'
]
}
)
Loading…
Cancel
Save