Got basic tag save via CLI working
git-svn-id: http://comictagger.googlecode.com/svn/trunk@59 6c5673fe-1810-88d6-992b-cd32ca31540c
This commit is contained in:
parent
f45e7b887f
commit
fb6d6a42b9
@ -561,5 +561,5 @@ class ComicArchive:
|
||||
metadata.publicationYear = fnp.year
|
||||
|
||||
metadata.isEmpty = False
|
||||
|
||||
|
||||
return metadata
|
||||
|
@ -36,7 +36,7 @@ from genericmetadata import GenericMetadata
|
||||
|
||||
class ComicVineTalker(QObject):
|
||||
|
||||
def __init__(self, api_key):
|
||||
def __init__(self, api_key=""):
|
||||
QObject.__init__(self)
|
||||
|
||||
# key that is registered to comictagger
|
||||
@ -142,7 +142,6 @@ class ComicVineTalker(QObject):
|
||||
|
||||
|
||||
volume_url = "http://api.comicvine.com/volume/" + str(series_id) + "/?api_key=" + self.api_key + "&format=json"
|
||||
#print "search_url = : ", volume_url
|
||||
|
||||
resp = urllib2.urlopen(volume_url)
|
||||
content = resp.read()
|
||||
|
@ -97,6 +97,59 @@ class GenericMetadata:
|
||||
self.tags = list()
|
||||
self.pages = list()
|
||||
|
||||
def overlay( self, new_md ):
|
||||
# Overlay a metadata object on this one
|
||||
# that is, when the new object has non-None
|
||||
# values, over-write them to this one
|
||||
|
||||
def assign( cur, new ):
|
||||
if new is not None:
|
||||
setattr(self, cur, new)
|
||||
|
||||
if not new_md.isEmpty:
|
||||
self.isEmpty = False
|
||||
|
||||
assign( 'series', new_md.series )
|
||||
assign( "issueNumber", new_md.issueNumber )
|
||||
assign( "issueCount", new_md.issueCount )
|
||||
assign( "title", new_md.title )
|
||||
assign( "publisher", new_md.publisher )
|
||||
assign( "publicationMonth", new_md.publicationMonth )
|
||||
assign( "publicationYear", new_md.publicationYear )
|
||||
assign( "volumeNumber", new_md.volumeNumber )
|
||||
assign( "volumeCount", new_md.volumeCount )
|
||||
assign( "genre", new_md.genre )
|
||||
assign( "language", new_md.language )
|
||||
assign( "country", new_md.country )
|
||||
assign( "alternateSeries", new_md.criticalRating )
|
||||
assign( "alt. series", new_md.alternateSeries )
|
||||
assign( "alternateNumber", new_md.alternateNumber )
|
||||
assign( "alternateCount", new_md.alternateCount )
|
||||
assign( "imprint", new_md.imprint )
|
||||
assign( "web", new_md.webLink )
|
||||
assign( "format", new_md.format )
|
||||
assign( "manga", new_md.manga )
|
||||
assign( "blackAndWhite", new_md.blackAndWhite )
|
||||
assign( "maturityRating", new_md.maturityRating )
|
||||
assign( "scanInfo", new_md.scanInfo )
|
||||
assign( "scanInfo", new_md.scanInfo )
|
||||
assign( "scanInfo", new_md.scanInfo )
|
||||
assign( "characters", new_md.characters )
|
||||
assign( "teams", new_md.teams )
|
||||
assign( "locations", new_md.locations )
|
||||
assign( "comments", new_md.comments )
|
||||
assign( "notes", new_md.notes )
|
||||
|
||||
# TODO
|
||||
# not sure if the tags, credits, and pages should broken down, or treated
|
||||
# as whole lists.... For now, go the easy route, where any overlay
|
||||
# value wipes out the whole list
|
||||
|
||||
assign( "tags", new_md.tags )
|
||||
assign( "credits", new_md.credits )
|
||||
assign( "pages", new_md.pages )
|
||||
|
||||
|
||||
def addCredit( self, person, role, primary = False ):
|
||||
|
||||
credit = dict()
|
||||
@ -114,7 +167,7 @@ class GenericMetadata:
|
||||
return "No metadata"
|
||||
|
||||
def add( tag, val ):
|
||||
if val is not None and str(val) != "":
|
||||
if val is not None and u"{0}".format(val) != "":
|
||||
vals.append( (tag, val) )
|
||||
|
||||
add( "series", self.series )
|
||||
@ -148,10 +201,10 @@ class GenericMetadata:
|
||||
add( "comments", self.comments )
|
||||
add( "notes", self.notes )
|
||||
add( "tags", utils.listToString( self.tags ) )
|
||||
|
||||
for c in self.credits:
|
||||
add( "credit", c['role']+": "+c['person'] )
|
||||
|
||||
|
||||
# find the longest field name
|
||||
flen = 0
|
||||
for i in vals:
|
||||
@ -160,7 +213,8 @@ class GenericMetadata:
|
||||
|
||||
#format the data nicely
|
||||
outstr = ""
|
||||
fmt_str = u"{0: <" + str(flen) + "}: {1}\n"
|
||||
for i in vals:
|
||||
outstr += ("{0: <" + str(flen) + "}: {1}\n").format( i[0], i[1] )
|
||||
outstr += fmt_str.format( i[0], i[1] )
|
||||
|
||||
return outstr
|
||||
|
14
options.py
14
options.py
@ -56,7 +56,7 @@ If no options are given, {0} will run in windowed mode
|
||||
year
|
||||
-o, --online Search online and attempt to identify file using
|
||||
existing metadata and images in archive. May be used
|
||||
in conjuntion with -p and -m
|
||||
in conjuntion with -f and -m
|
||||
-m, --metadata=LIST Explicity define some tags to be used as a list
|
||||
....TBD........
|
||||
....TBD........
|
||||
@ -72,11 +72,11 @@ If no options are given, {0} will run in windowed mode
|
||||
self.no_gui = False
|
||||
self.filename = None
|
||||
self.verbose = False
|
||||
self.md_settings = None
|
||||
self.metadata = None
|
||||
self.print_tags = False
|
||||
self.delete_tags = False
|
||||
self.search_online = False
|
||||
self.dryrun = True # keep this true for now!
|
||||
self.dryrun = False
|
||||
self.save_tags = False
|
||||
self.parse_filename = False
|
||||
self.rename_file = False
|
||||
@ -87,10 +87,12 @@ If no options are given, {0} will run in windowed mode
|
||||
print( msg )
|
||||
print self.help_text.format(appname)
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
def parseMetadataFromString( self, mdstr ):
|
||||
print "TBD!!!!!!!!!!!!!!!!!!!!!"
|
||||
return None
|
||||
|
||||
def parseCmdLineArgs(self):
|
||||
|
||||
|
||||
# mac no likey this from .app bundle
|
||||
if platform.system() == "Darwin" and getattr(sys, 'frozen', None):
|
||||
@ -121,7 +123,7 @@ If no options are given, {0} will run in windowed mode
|
||||
if o in ("-n", "--dryrun"):
|
||||
self.dryrun = True
|
||||
if o in ("-m", "--metadata"):
|
||||
self.md_settings = a
|
||||
self.metadata = self.parseMetadataFromString(a)
|
||||
if o in ("-s", "--save"):
|
||||
self.save_tags = True
|
||||
if o in ("-r", "--rename"):
|
||||
|
142
tagger.py
142
tagger.py
@ -33,6 +33,8 @@ from taggerwindow import TaggerWindow
|
||||
from options import Options, MetaDataStyle
|
||||
from comicarchive import ComicArchive
|
||||
from issueidentifier import IssueIdentifier
|
||||
from genericmetadata import GenericMetadata
|
||||
from comicvinetalker import ComicVineTalker
|
||||
|
||||
import utils
|
||||
|
||||
@ -49,6 +51,11 @@ def cli_mode( opts, settings ):
|
||||
if not ca.seemsToBeAComicArchive():
|
||||
print "Sorry, but "+ opts.filename + " is not a comic archive!"
|
||||
return
|
||||
|
||||
if not ca.isWritable() and ( opts.delete_tags or opts.save_tags or opts.rename_file ):
|
||||
print "This archive is not writable."
|
||||
return
|
||||
|
||||
|
||||
cix = False
|
||||
cbi = False
|
||||
@ -81,61 +88,128 @@ def cli_mode( opts, settings ):
|
||||
if opts.data_style is None or opts.data_style == MetaDataStyle.CIX:
|
||||
if cix:
|
||||
print "------ComicRack tags--------"
|
||||
print ca.readCIX()
|
||||
print u"{0}".format(ca.readCIX())
|
||||
if opts.data_style is None or opts.data_style == MetaDataStyle.CBI:
|
||||
if cbi:
|
||||
print "------ComicBookLover tags--------"
|
||||
print ca.readCBI()
|
||||
print u"{0}".format(ca.readCBI())
|
||||
|
||||
|
||||
elif opts.delete_tags:
|
||||
if not ca.isWritable():
|
||||
print "This archive is not writable."
|
||||
return
|
||||
|
||||
elif opts.delete_tags:
|
||||
if opts.data_style == MetaDataStyle.CIX:
|
||||
if cix:
|
||||
ca.removeCIX()
|
||||
print "Removed ComicRack tags."
|
||||
if not opts.dryrun:
|
||||
ca.removeCIX()
|
||||
print "Removed ComicRack tags."
|
||||
else:
|
||||
print "dry-run. ComicRack tags not removed"
|
||||
else:
|
||||
print "This archive doesn't have ComicRack tags."
|
||||
|
||||
if opts.data_style == MetaDataStyle.CBI:
|
||||
if cbi:
|
||||
ca.removeCBI()
|
||||
print "Removed ComicBookLover tags."
|
||||
if not opts.dryrun:
|
||||
ca.removeCBI()
|
||||
print "Removed ComicBookLover tags."
|
||||
else:
|
||||
print "dry-run. ComicBookLover tags not removed"
|
||||
else:
|
||||
print "This archive doesn't have ComicBookLover tags."
|
||||
|
||||
#elif opt.rename:
|
||||
# print "Gonna rename file"
|
||||
|
||||
elif opts.save_tags:
|
||||
if opts.data_style == MetaDataStyle.CIX:
|
||||
print "Gonna save ComicRack tags"
|
||||
if opts.data_style == MetaDataStyle.CBI:
|
||||
print "Gonna save ComicBookLover tags"
|
||||
|
||||
"""
|
||||
ii = IssueIdentifier( ca, settings.cv_api_key )
|
||||
matches = ii.search()
|
||||
|
||||
# OK we're gonna do a save of some new data
|
||||
md = GenericMetadata()
|
||||
|
||||
if len(matches) == 1:
|
||||
# First read in existing data, if it's there
|
||||
if opts.data_style == MetaDataStyle.CIX and cix:
|
||||
md = ca.readCIX()
|
||||
elif opts.data_style == MetaDataStyle.CBI and cbi:
|
||||
md = ca.readCBI()
|
||||
|
||||
# now, overlay the new data onto the old, in order
|
||||
|
||||
if opts.parse_filename:
|
||||
md.overlay( ca.metadataFromFilename() )
|
||||
|
||||
if opts.metadata is not None:
|
||||
md.overlay( opts.metadata )
|
||||
|
||||
|
||||
# finally, search online
|
||||
if opts.search_online:
|
||||
|
||||
ii = IssueIdentifier( ca, "" )
|
||||
|
||||
if md is None or md.isEmpty:
|
||||
print "No metadata given to search online with!"
|
||||
return
|
||||
|
||||
def myoutput( text ):
|
||||
if opts.verbose:
|
||||
IssueIdentifier.defaultWriteOutput( text )
|
||||
|
||||
# use our overlayed MD struct to search
|
||||
ii.setAdditionalMetadata( md )
|
||||
ii.onlyUseAdditionalMetaData = True
|
||||
ii.setOutputFunction( myoutput )
|
||||
matches = ii.search()
|
||||
|
||||
result = ii.search_result
|
||||
|
||||
found_match = False
|
||||
choices = False
|
||||
low_confidence = False
|
||||
|
||||
if result == ii.ResultNoMatches:
|
||||
pass
|
||||
elif result == ii.ResultFoundMatchButBadCoverScore:
|
||||
low_confidence = False
|
||||
found_match = True
|
||||
elif result == ii.ResultFoundMatchButNotFirstPage :
|
||||
found_match = True
|
||||
elif result == ii.ResultMultipleMatchesWithBadImageScores:
|
||||
low_confidence = False
|
||||
choices = True
|
||||
elif result == ii.ResultOneGoodMatch:
|
||||
found_match = True
|
||||
elif result == ii.ResultMultipleGoodMatches:
|
||||
choices = True
|
||||
|
||||
if choices:
|
||||
print "Online search: Multiple matches. Save aborted"
|
||||
return
|
||||
if low_confidence:
|
||||
print "Online search: Low confidence match. Save aborted"
|
||||
return
|
||||
if not found_match:
|
||||
print "Online search: No match found. Save aborted"
|
||||
return
|
||||
|
||||
# we got here, so we have a single match
|
||||
|
||||
# now get the particular issue data
|
||||
metadata = comicVine.fetchIssueData( match[0]['series'], match[0]['issue_number'] )
|
||||
|
||||
# write out the new data
|
||||
ca.writeMetadata( metadata, opts.data_style )
|
||||
|
||||
elif len(matches) == 0:
|
||||
pass
|
||||
cv_md = ComicVineTalker().fetchIssueData( matches[0]['volume_id'], matches[0]['issue_number'] )
|
||||
|
||||
md.overlay( cv_md )
|
||||
# ok, done building our metadata. time to save
|
||||
|
||||
elif len(matches) == 0:
|
||||
# print match options, with CV issue ID's
|
||||
pass
|
||||
"""
|
||||
#HACK
|
||||
opts.dryrun = True
|
||||
#HACK
|
||||
|
||||
if not opts.dryrun:
|
||||
# write out the new data
|
||||
ca.writeMetadata( md, opts.data_style )
|
||||
else:
|
||||
print "dry-run option was set, so nothing was written, but here is the final set of tags:"
|
||||
print u"{0}".format(md)
|
||||
|
||||
elif opt.rename_file:
|
||||
print "File renaming TBD"
|
||||
|
||||
|
||||
|
||||
#-----------------------------
|
||||
|
||||
def main():
|
||||
|
16
todo.txt
16
todo.txt
@ -2,8 +2,14 @@
|
||||
Features
|
||||
----------------
|
||||
CLI
|
||||
rename
|
||||
save
|
||||
save log
|
||||
abort flag
|
||||
explicit metadata settings option format
|
||||
just series, issue, year??
|
||||
multiple files?
|
||||
verbose settings for identifier
|
||||
interactive for choices option?
|
||||
--- or defer choices to end, by keeping special log of those files
|
||||
|
||||
Settings/Preferences Dialog
|
||||
Remove API Key
|
||||
@ -34,13 +40,11 @@ Bugs
|
||||
SERIOUS BUG: rebuilding zips!
|
||||
http://stackoverflow.com/questions/11578443/trigger-io-errno-18-cross-device-link
|
||||
|
||||
Test ComicRack android
|
||||
|
||||
OSX:
|
||||
toolbar
|
||||
weird unrar complaints
|
||||
Page browser sizing
|
||||
Override curson is not beachball
|
||||
Override cursor is not beachball
|
||||
|
||||
Other settings possibilities:
|
||||
Last tag style
|
||||
@ -50,6 +54,8 @@ Other settings possibilities:
|
||||
Filename parsing:
|
||||
Rework how series name is separated from issue
|
||||
|
||||
Test ComicRack android
|
||||
|
||||
Form type validation Ints vs strings for month, year. etc
|
||||
|
||||
Check all HTTP responses for errors
|
||||
|
Loading…
Reference in New Issue
Block a user