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
- [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
```
$ pip install pycryptodome mutagen
```
## Usage
### Specify files
## Install
```
$ python ncmdump.py [file ...]
$ pip install git+https://github.com/nondanee/ncmdump.git
```
### Traverse working directory
```
$ python ncmdump.py
```
### More options
```
$ python app.py -h
usage: ncmdump [-h] [-f format] [-o output] [-d] [-c | -s] [input [input ...]]
## Usage
### Execute
```sh
$ ncmdump -h # equivalent to "python ncmdump/app.py -h"
usage: ncmdump [-h] [-f format] [-o output] [-d] [-c | -r] [input [input ...]]
positional arguments:
input ncm file or folder path
input ncm file or folder path
optional arguments:
-h, --help show this help message and exit
-f format customize naming format
-o output customize saving folder
-d delete source after conversion
-c overwrite file with the same name
-s skip conversion if file exist
-h show this help message and exit
-f format customize naming format
-o output customize saving folder
-d delete source after conversion
-c overwrite file with the same name
-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
"""
import argparse, os, sys, re
import ncmdump
import argparse, os, sys, traceback, re
from .core import dump
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(
'input', metavar = 'input', nargs = '*', default = ['.'],
@ -33,8 +37,8 @@ group.add_argument(
help = 'overwrite file with the same name'
)
group.add_argument(
'-s', dest = 'skip', action = 'store_true',
help = 'skip conversion if file exist'
'-r', dest = 'rename', action = 'store_true',
help = 'auto rename if file name conflicts'
)
args = parser.parse_args()
@ -72,39 +76,45 @@ def name_format(path, meta):
name += '.' + meta['format']
folder = args.output if args.output else os.path.dirname(path)
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
if args.output:
args.output = os.path.abspath(args.output)
if not os.path.exists(args.output):
print('output does not exist')
exit()
if not os.path.isdir(args.output):
print('output is not a folder')
exit()
def main():
if args.output:
args.output = os.path.abspath(args.output)
if not os.path.exists(args.output):
print('output does not exist')
exit()
if not os.path.isdir(args.output):
print('output is not a folder')
exit()
files = []
for path in args.input:
path = os.path.abspath(path)
if not os.path.exists(path):
continue
if os.path.isdir(path):
files += [os.path.join(path, name) for name in os.listdir(path) if os.path.splitext(name)[-1] == '.ncm']
else:
files += [path]
files = []
for path in args.input:
path = os.path.abspath(path)
if not os.path.exists(path):
continue
if os.path.isdir(path):
files += [os.path.join(path, name) for name in os.listdir(path) if os.path.splitext(name)[-1] == '.ncm']
else:
files += [path]
if sys.version[0] == '2':
files = [path.decode(sys.stdin.encoding) for path in files]
if sys.version[0] == '2':
files = [path.decode(sys.stdin.encoding) for path in files]
if not files:
print('empty input')
exit()
if not files:
print('empty input')
exit()
for path in files:
try:
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:
try:
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()
if __name__ == '__main__':
main()

29
ncmdump.py → ncmdump/core.py

@ -7,7 +7,7 @@ Created on Sun Jul 15 01:05:58 2018
import binascii, struct
import base64, json
import os, traceback
import os
from Crypto.Cipher import AES
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):
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')
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)
# 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
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.save()
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
return output_path

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