# -*- coding: cp949 -*- import cmd, os, sys import codeshift import util import id3tag_manip from maniadb_core import maniadb_core from interface import * class maniadb_shell(cmd.Cmd): def emptyline(self): pass def do_load(self, str): try: loaded_num = self.core.load(str.split()) print u'%d file(s) loaded.' % loaded_num except Exception as e: util.trace_error(u'Error while loading:', e) def do_unload(self, str): try: nums = self.__parse_param(str) unloaded_num = self.core.unload(nums) print u'%d file(s) unloaded.' % unloaded_num except Exception as e: util.trace_error(u'Error while unloading:', e) def do_clear(self, str): try: self.core.clear_list() except Exception as e: util.trace_error(u'Error while clearing:', e) def do_list(self, str): try: if str == u'': nums = [x for x in xrange(1, self.core.list_size()+1)] else: nums = self.__parse_param(str) totnum = self.core.list_size() for num in nums: str = u'[%d/%d] ' % (num, totnum) if self.core.is_tagged(num) == True: str += u'*' str += util.fit_string(self.core.get_file_name(num), 60, u' ... ') print str except Exception as e: util.trace_error(u'Error while listing:', e) def do_det(self, str): try: num = int(str) file_name = self.core.get_file_name(num) file_info = id3tag_manip.mp3info(file_name) print u'Detailed information of #%d' % num print u'=' * 50 print u'태그버전: ', file_info[u'tag_ver'] print u'경로: ', file_info[u'path'] print u'곡명: ', file_info[u'song'] print u'아티스트: ', file_info[u'artist'] print u'앨범명: ', file_info[u'album'] print u'발매일: ', file_info[u'release_date'] print u'시간: ', file_info[u'time'] print u'VBR: ', file_info[u'vbr'] print u'Bitrate: ', file_info[u'bit_rate'], u'kbps' print u'용량: ', '%.2f' % (float(file_info[u'size_bytes'])/float(1024*1024)), u'MiB' print u'디스크: ', file_info[u'disc_num'] print u'트랙: ', file_info[u'track_num'] print u'레이블: ', file_info[u'publisher'] print u'' except Exception as e: util.trace_error(u'Error while detailed info:', e) def do_retr(self, str): try: nums = self.__parse_param(str) tot_num = self.core.list_size() for num in nums: print u'[%d / %d]' % (num, tot_num) if self.__retrieve(num) == False: print u'Retrieval canceled at %d' % num return False except Exception as e: util.trace_error(u'Error while retrieving:', e) def do_retrall(self, str): try: tot_num = self.core.list_size() for num in xrange(1, self.core.list_size()+1): if self.core.is_tagged(num) == True: print u'Number %d is already tagged.' % num continue print u'[%d / %d]' % (num, tot_num) if self.__retrieve(num) == False: print u'Retrieval canceled at %d' % num return False except Exception as e: util.trace_error(u'Error while retrieving all:', e) def do_nresp(self, str): try: if str == u'': print self.nresp else: self.nresp = int(str) print u'Set number of responses to', self.nresp except Exception as e: util.trace_error(u'Error while setting nresp:', e) def do_exp(self, str): try: if str == '': print >> sys.stderr, u'파일 이름을 입력해야 합니다.' return False all_files = self.core.get_all_files() with open(str, u'w') as f: for one in all_files: f.write(codeshift.uni2loc(one+u'\n')) print u'%d item(s) exported to %s' % (len(all_files), str) except Exception as e: util.trace_error(u'Error while exporting all list:', e) def do_expunt(self, str): try: if str == '': print >> sys.stderr, u'파일 이름을 입력해야 합니다.' return False untagged_files = self.core.get_untagged_files() with open(str, u'w') as f: for untagged in untagged_files: f.write(codeshift.uni2loc(untagged+u'\n')) print u'%d untagged item(s) exported to %s' % (len(untagged_files), str) except Exception as e: util.trace_error(u'Error while exporting untagged:', e) def do_exptag(self, str): try: if str == '': print >> sys.stderr, u'파일 이름을 입력해야 합니다.' return False tagged_files = self.core.get_tagged_files() with open(str, u'w') as f: for tagged in tagged_files: f.write(codeshift.uni2loc(tagged+u'\n')) print u'%d tagged item(s) exported to %s' % (len(tagged_files), str) except Exception as e: util.trace_error(u'Error while exporting tagged:', e) def do_exit(self, str): print u'Exiting...' sys.exit(0) def do_tag(self, str): try: nums = self.__parse_param(str) for num in nums: self.core.set_tagged(num, True) except Exception as e: util.trace_error(u'Error while tag command:', e) def do_unt(self, str): try: nums = self.__parse_param(str) for num in nums: self.core.set_tagged(num, False) except Exception as e: util.trace_error(u'Error while tag command:', e) def do_EOF(self, str): return True # return True: Ok to go to next item # return False: Stop right now def __retrieve(self, num): song_info = None # song_info song_selnum = -1 # chosen item number album_info = None # album_info # get the item of num file_name = self.core.get_file_name(num) while True: # cli interface: keyword input from user kwdiface = keyword_interface() if kwdiface.show_menu(file_name) != 0: print u'Canceled.' return False # send a query and parse the result song_info = self.core.song_query(kwdiface.keyword_song, kwdiface.keyword_artist, self.nresp) # cli interface: choose right one from responses itmiface = itemselection_interface() # itemselection interface response. # 0: success, 1: back to keyword search, 2: exit to shell response = itmiface.show_menu(song_info[u'item']) if response == 0: song_selnum = itmiface.selnum break elif response == 1: continue elif response == 2: return False else: raise Exception(u'Wrong response code at itemselection_interface') # querying album information chosen_item = song_info[u'item'][song_selnum-1] album_link = chosen_item[u'album'][u'link'] album_id = album_link[album_link.find(u'a=')+2:] # album info print u'Querying album id %s information...' % album_id album_info = self.core.album_query(album_id) # update mp3 tag self.core.update(num, song_info, song_selnum, album_info) print u'성공적으로 태그를 수정했습니다.\n' return True def __parse_param(self, str): fin_list = [] for t in str.split(): # convert t to unicode form ut = codeshift.loc2uni(t) # hyphen position hypos = ut.find(u'-') # we couldn't find hyphen: if hypos == -1: if ut.isnumeric(): intn = int(ut) if 0 < intn and intn <= self.core.list_size(): fin_list.append(intn) else: raise Exception(ut+u': Number exceeded the limit') else: raise Exception(ut+u' is not a valid numeric form.') # we've found hyphen, else: # hyphen is the first character - if hypos == 0: endstr = ut[1:] # thoroughly check the number form if endstr.isnumeric(): endint = int(endstr) if 0 < endint and endint <= self.core.list_size(): # valid number form is converted to a series of numbers from 1 to endint for x in xrange(1, endint+1): fin_list.append(x) else: raise Exception(ut+u': Ending number exceeded the limit') else: raise Exception(ut+u' is not a valid numeric form.') # hyphen is the last character - elif hypos == len(ut)-1: stastr = ut[:hypos] # thoroughly check the number form if stastr.isnumeric(): staint = int(stastr) if 0 < staint and staint <= self.core.list_size(): # valid number form is converted to a series of numbers from staint to the last of the list for x in xrange(staint, self.core.list_size()+1): fin_list.append(x) else: raise Exception(ut+u': Starting number exceeded the limit') else: raise Exception(ut+u' is not a valid numeric form.') # hyphen is the middle character else: stastr, endstr = ut.split(u'-') if stastr.isnumeric() and endstr.isnumeric(): staint, endint = int(stastr), int(endstr) # check integer numbers are all valid if staint > 0 and endint > 0 and staint <= endint and endint <= self.core.list_size(): for x in xrange(staint, endint+1): fin_list.append(x) else: raise Exception(ut+u': Starting number or ending number exceeded the limit') else: raise Exception(ut+u' is not a valid numeric form.') # sort numbers and remove duplication, if any fin_list = list(set(fin_list)) fin_list.sort() return fin_list def help_EOF(self): pass def help_det(self): print u'=== det (detailed info) 명령어 도움말 ===\n' print u'하나의 인자를 받습니다. 인자는 파일 목록의 번호입니다.' print u'목록 번호의 파일을 읽어 세부 정보를 출력합니다.' print u'예: det 3' def help_exp(self): print u'=== exp (export all) 명령어 도움말 ===\n' print u'하나의 인자를 받습니다. 인자는 파일 이름입니다.' print u'지정된 파일에 현재 파일 목록을 기록합니다.' print u'예: exp list.txt' def help_expunt(self): print u'=== expunt (exprt untagged) 명령어 도움말 ===\n' print u'하나의 인자를 받습니다. 인자는 파일 이름입니다.' print u'지정된 파일에 본 프로그램이 현재 변경하지 않은 파일의 목록을 기록합니다.' print u'예: expunt untagged.txt' def help_load(self): print u'=== load 명령어 도움말 ===\n' print u'한 개 이상의 파일 이름을 인자로 받을 수 있습니다.' print u'인자로 직접 MP3 파일 이름을 전달할 수 있고, 파일의 목록을 전달할 수도 있습니다.' print u'파일의 목록은 한 줄에 하나씩 MP3 파일을 적은 텍스트 파일입니다.' print u'파일 목록은 파일 이름 앞에 \'@\'기호를 앞에 붙여서 구분합니다.' print u'예: load a.mp3 b.mp3 @othrs.txt' print u' [othrs.txt 내용]' print u' c.mp3' print u' d.mp3' print u' e.mp3' print u'' print u' * 로드되는 파일 목록: a~e.mp3' def help_retr(self): print u'=== retr (retrieve) 명령어 도움말 ===\n' print u'maniadb.com에 mp3 태그 정보를 검색합니다.' print u'파일 목록 번호를 인자로 받습니다. 각 번호는 공백으로 구분합니다.' print u'중복된 번호는 한 번만 처리되며 \'-\'기호를 이용하여 연속된 번호를 입력할 수 있습니다' print u'단, 시작 번호와 끝 번호, 그리고 \'-\'기호 사이에는 공백이 없어야 합니다.' print u'\'-\'기호를 쓸 때 시작번호나 끝 번호 중 하나를 생략할 수 있는데,\n이 때 생략된 번호는 각 목록의 처음과 마지막 번호로 간주합니다.' print u'예: retr 1 2 5-8 (목록 번호 1, 2, 5, 6, 7, 8번의 태그 정보를 검색합니다.)' print u' retr -4 (목록 번호 1, 2, 3, 4번의 태그 정보를 검색합니다.)' print u' retr 11- (목록 번호 11번부터 마지막 번호까지 검색합니다.)' def help_tag(self): print u'=== tag (set tagged) 명령어 도움말 ===\n' print u'목록 번호의 MP3 파일의 태그를 현재 프로그램에서 수정한 것으로 처리합니다.' print u'파일 목록의 번호를 인자로 받습니다. \'-\'기호를 이용하여 연속된 번호를 입력할 수 있습니다' print u'태그는 수정한 것으로 처리되지만, 실제로 내용이 변경된 것은 아닙니다.' print u'예: tag 1 7 22 (1, 7, 22번 MP3 파일에 대해 태그를 수정한 것으로 처리.)' print u' tag 1-20 (1~20번 MP3 파일에 대해 태그를 수정한 것으로 처리.)' print u' tag -5 (1~5번 파일에 대해 처리.)' print u' tag 10- (10~마지막 번호까지 처리.)' def help_unt(self): print u'=== unt (set untagged) 명령어 도움말 ===\n' print u'목록 번호의 MP3 파일의 태그를 현재 프로그램에서 아직 수정하지 않은 것으로 처리합니다.' print u'파일 목록의 번호를 인자로 받습니다. \'-\'기호를 이용하여 연속된 번호를 입력할 수 있습니다' print u'태그는 수정하지 않은 것으로 처리되지만, 실제로 내용이 변경된 것은 아닙니다.' print u'예: unt 1 7 22 (1, 7, 22번 MP3 파일에 대해 태그를 수정하지 않은 것으로 처리.)' print u' unt 1-20 (1~20번 MP3 파일에 대해 태그를 수정하지 않은 것으로 처리.)' print u' unt -5 (1~5번 파일에 대해 처리.)' print u' unt 10- (10~마지막 번호까지 처리.)' def help_clear(self): print u'=== clear 명령어 도움말 ===\n' print u'목록을 초기화합니다. 목록 내용이 모두 지워집니다. 인자를 필요로 하지 않습니다.' print u'예: clear' def help_exit(self): print u'=== help_exit 명령어 도움말 ===\n' print u'프로그램을 종료합니다. 인자를 필요로 하지 않습니다.' print u'예: exit' def help_exptag(self): print u'=== exptag (export tagged) 명령어 도움말 ===\n' print u'현재 프로그램이 태그를 수정한 파일만을 목록으로 만듭니다.' print u'파일 이름 하나를 인자로 받습니다. 해당 파일에 한 줄에 하나씩 목록의 파일 경로를 적습니다.' print u'예: exptag tagged.txt' def help_nresp(self): print u'=== nresp (number of responses) 명령어 도움말 ===\n' print u'검색 쿼리를 보낼 때 최대 몇 개까지 응답을 받을 수 있을지 결정합니다.' print u'기본값은 10이며 Maniadb OpenAPI v0.3에 따르면 최대 200까지 가능합니다.' print u'인자 없이 입력하면 현재 설정값을 출력하고, 인자를 입력하면 설정값을 입력된 값으로 변경합니다.' print u'예: nresp (현재 설정값 출력)' print u' nresp 50 (최대 50개까지 검색 응답을 받을 수 있도록 조정)' def help_retrall(self): print u'=== retrall (retrieve all) 명령어 도움말 ===\n' print u'모든 파일 목록에 대해 태그 검색을 수행합니다. 인자를 필요로 하지 않습니다.' print u'예: retrall' def help_unload(self): print u'=== unload 명령어 도움말 ===\n' print u'load 명령과 반대로 목록에서 내용을 삭제합니다.' print u'인자로 목록 번호를 받습니다. \'-\'기호를 이용하여 연속된 번호를 입력할 수 있습니다' print u'실제로 파일이 디스크에서 삭제되지는 않습니다.' print u'예: unload 3 (3번을 목록에서 삭제)' print u' unload 11-20 (11~20번을 목록에서 삭제)' print u' unload 7 9 11 20-22 (7, 9, 11, 20, 21, 22번을 목록에서 삭제)' def help_list(self): print u'=== list 명령어 도움말 ===\n' print u'현재 파일 목록을 출력합니다.' print u'인자를 입력하지 않을 경우 모든 파일 목록을 출력합니다.' print u'인자로 목록 번호를 전달할 수 있습니다. \'-\'기호를 이용하여 연속된 번호를 입력할 수 있습니다' print u'현재 프로그램에 의해 태그가 수정된 파일은 파일 경로 앞에 \'*\' 가 붙습니다.' print u'예: list -10 (1~10번을 출력)' print u' list 100- (100번부터 마지막까지 출력)' print u' list 5 8 11 16-30 (5, 8, 11, 16~30번을 출력)' core = maniadb_core() nresp = 10 def help(): print u'A Simple Tag Retreival Agent, powered by maniadb.com\n' print u'사용법: python maniadb_shell.py arguments...\n' print u'arguments' print u'\t파일 목록. 파일 목록은 하나씩 인자로 전달해도 되고, 텍스트 파일 안에 한 줄에 하나씩 입력해도 된다.' print u'\t텍스트 파일을 인자로 줄 때 \'@\' 기호룰 붙인다.' def main(argv): if len(argv) == 2 and argv[1] == u'-h': help() return 0 else: try: shell = maniadb_shell() if len(argv) > 1: shell.core.load(argv[1:]) shell.doc_header = codeshift.uni2loc(u'명령어의 목록입니다. (자세한 사항은 \'help <명령어>\'을 입력)') shell.nohelp = codeshift.uni2loc(u'명령어 \'%s\'에 대한 도움말이 없습니다.') shell.prompt = codeshift.uni2loc(u'maniadb>') shell.cmdloop(codeshift.uni2loc(u'=== A Simple Tag Retreival Agent, powered by maniadb.com ===')) except KeyboardInterrupt: print u'Exiting...' return 0 if __name__ == '__main__': sys.exit(main(sys.argv))