FIX:(#211/#212)Split Latest Issue/Last Published (Thnx ClayM), FIX:(#215) Exception-based series would never update on a DB refresh and would get dropped, IMP:(#191) Download link available per issue (Copy icon first, then Download link is available), IMP: Added icons on issue details screen instead of textual options, IMP:(#32) 'This Week' has an indicator light when new pull-list is available, IMP: Braggin Rights section in Configuration/Information tab (WIP)

This commit is contained in:
evilhero 2013-02-17 05:31:18 -05:00
parent 5817ff18f6
commit 4225577860
19 changed files with 137 additions and 41 deletions

View File

@ -1,5 +1,6 @@
<%inherit file="base.html"/>
<%!
import os
from mylar import db
import mylar
%>
@ -9,6 +10,7 @@
<div id="subhead_menu">
<a id="menu_link_refresh" onclick="doAjaxCall('refreshArtist?ComicID=${comic['ComicID']}', $(this)),'table'" href="#" data-success="'${comic['ComicName']}' is being refreshed">Refresh Comic</a>
<a id="menu_link_delete" href="deleteArtist?ComicID=${comic['ComicID']}">Delete Comic</a>
<a id="menu_link_refresh" onclick="doAjaxCall('manualRename?comicid=${comic['ComicID']}', $(this),'table'" href="#" data-success="Renaming files.">Rename Files</a>
<a id="menu_link_refresh" onclick="doAjaxCall('forceRescan?ComicID=${comic['ComicID']}', $(this)),'table'" href="#" data-success="'${comic['ComicName']}' is being refreshed">Recheck Files</a>
%if comic['Status'] == 'Paused':
<a id="menu_link_resume" href="#" onclick="doAjaxCall('resumeArtist?ComicID=${comic['ComicID']}',$(this),true)" data-success="${comic['ComicName']} resumed">Resume Comic</a>
@ -222,7 +224,8 @@
<input type="hidden" value="Go">
<input type="checkbox" name="skipped2wanted" onclick="doAjaxCall('skipped2wanted?comicid=${comic['ComicID']}',$(this),'table')" value="1" data-success="Skipped Issues Changed to Wanted" style="float: right; vertical-align: middle; margin: 3px; margin-top: -1px;" /><label style="float: right; vertical-align: middle; margin: 3px; margin-top: -1px;">Change All Skipped to Wanted </label>
</div>
<table class="display" id="issue_table">
<table class="display" id="issue_table">
<thead>
<tr>
<th id="select" align="left"><input type="checkbox" onClick="toggle(this)" class="checkbox" /></th>
@ -230,6 +233,7 @@
<th id="issuename">Name</th>
<th id="reldate">Date</th>
<th id="status">Status</th>
<th id="options">Options</th>
</tr>
</thead>
<tbody>
@ -249,19 +253,41 @@
<td id="issuenumber">${issue['Issue_Number']}</td>
<td id="issuename">${issue['IssueName']}</td>
<td id="reldate">${issue['IssueDate']}</td>
<td id="status">${issue['Status']}
<td id="status">${issue['Status']}</td>
<td id="options">
%if issue['Status'] == 'Skipped':
[<a href="#" onclick="doAjaxCall('queueissue?ComicID=${issue['ComicID']}&IssueID=${issue['IssueID']}&ComicIssue=${issue['Issue_Number']}&ComicYear=${issue['IssueDate']}&mode=want',$(this),'table')">want</a>]
<a href="#" title="Mark issue as Wanted" onclick="doAjaxCall('queueissue?ComicID=${issue['ComicID']}&IssueID=${issue['IssueID']}&ComicIssue=${issue['Issue_Number']}&ComicYear=${issue['IssueDate']}&mode=want',$(this),'table')"><img src="interfaces/default/images/wanted_icon.png" height="25" width="25" /></a>
%elif (issue['Status'] == 'Wanted'):
[<a href="#" onclick="doAjaxCall('unqueueissue?IssueID=${issue['IssueID']}&ComicID=${issue['ComicID']}',$(this),'table')" data-success="'${issue['Issue_Number']}' has been marked as skipped">skip</a>]
<a href="#" title="Mark issue as Skipped" onclick="doAjaxCall('unqueueissue?IssueID=${issue['IssueID']}&ComicID=${issue['ComicID']}',$(this),'table')" data-success="'${issue['Issue_Number']}' has been marked as skipped"><img="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
%elif (issue['Status'] == 'Snatched'):
<a href="#" onclick="doAjaxCall('queueissue?ComicID=${issue['ComicID']}&IssueID=${issue['IssueID']}&ComicIssue=${issue['Issue_Number']}&mode=want', $(this),'table')" data-success="Retrying the same version of '${issue['ComicName']}' '${issue['Issue_Number']}'" title="Retry the same download again"><img src="interfaces/default/images/retry_icon.png" height="25" width="25" /></a>
<a href="#" title="Mark issue as Skipped" onclick="doAjaxCall('unqueueissue?IssueID=${issue['IssueID']}&ComicID=${issue['ComicID']}',$(this),'table')" data-success="'${issue['Issue_Number']}' has been marked as skipped"><img="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
%else:
[<a href="#" onclick="doAjaxCall('queueissue?ComicID=${issue['ComicID']}&IssueID=${issue['IssueID']}&ComicIssue=${issue['Issue_Number']}&mode=want', $(this),'table')" data-success="Retrying the same version of '${issue['ComicName']}' '${issue['Issue_Number']}'" title="Retry the same download again">retry</a>][<a href="#" onclick="doAjaxCall('queueissue?IssueID=${issue['IssueID']}&ComicID=${issue['ComicID']}&ComicIssue=${issue['Issue_Number']}&new=True', $(this),'table')" title="Try a new download, skipping all previously tried nzbs" data-success="Downloading new version for '${issue['ComicName']}' '${issue['Issue_Number']}'" data-success="Looking for a new version of '${issue['ComicName']}' '${issue['Issue_Number']}'">new</a>]
%if issue['inCacheDIR']:
<%
try:
with open(os.path.join(mylar.CACHE_DIR,issue['Location'])) as f:
linky = issue['Location']
except IOError as e:
linky = None
%>
%if linky:
<a href="cache/${linky}"><img src="interfaces/default/images/download_icon.png" height="25" width="25" title="Download the issue" /></a>
%endif
%else:
<a href="#" onclick="doAjaxCall('downloadLocal?IssueID=${issue['IssueID']}', $(this), 'table')" ><img src="interfaces/default/images/copy_icon.png" height="25" width="25" title="Copy issue to local cache (ready for download)" /></a>
%endif
<a href="#" onclick="doAjaxCall('queueissue?ComicID=${issue['ComicID']}&IssueID=${issue['IssueID']}&ComicIssue=${issue['Issue_Number']}&mode=want', $(this),'table')" data-success="Retrying the same version of '${issue['ComicName']}' '${issue['Issue_Number']}'" title="Retry the same download again"><img src="interfaces/default/images/retry_icon.png" height="25" width="25" /></a>
<a href="#" title="Mark issue as Skipped" onclick="doAjaxCall('unqueueissue?IssueID=${issue['IssueID']}&ComicID=${issue['ComicID']}',$(this),'table')" data-success="'${issue['Issue_Number']}' has been marked as skipped"><img="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
%endif
<a href="#" onclick="doAjaxCall('archiveissue?IssueID=${issue['IssueID']}',$(this),'table')"><img src="interfaces/default/images/archive_icon.png" height="25" width="25" title="Mark issue as Archived"></a>
</td>
</tr>
%endfor
</tbody>
</table>
</div>
</form>
</div>
</%def>

View File

@ -47,8 +47,17 @@
</div>
</fieldset>
</td>
<td>
</td>
<td>
<fieldset>
<legend>Bragging Rights</legend>
<div>
<label><strong># of Comics you're watching: </strong> ${comicinfo['COUNT_COMICS']}</br>
<label><strong># of Issues you're watching: </strong> ${comicinfo['COUNT_ISSUES']}</br>
<label><strong># of Issues you actually have: </strong> ${comicinfo['COUNT_HAVES']}</br>
<label><strong> ... total HD-space being used: </strong></br>
</div>
</fieldset>
<fieldset>
<legend>Branch history</legend>
<label>This would be a nice place to see revision history...</label>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -131,7 +131,6 @@
No
%endif
</td>
<td id="addcomic">[<a href="preSearchit?ComicName=${wresult['ComicName']}">Import</a>]
[<a href="deleteimport?ComicName=${wresult['ComicName']}">Remove</a>]
</td>
</tr>

View File

@ -12,7 +12,8 @@
<th id="publisher">Publisher</th>
<th id="name">Comic</th>
<th id="year">Year</th>
<th id="issue">Latest Issue</th>
<th id="issue">Last Issue</th>
<th id="published">Published</th>
<th id="have">Have</th>
<th id="status">Status</th>
<th id="status">Active</th>
@ -66,7 +67,8 @@
<td id="publisher">${comic['ComicPublisher']}</td>
<td id="name"><span title="${comic['ComicSortName']}"></span><a href="artistPage?ComicID=${comic['ComicID']}">${comic['ComicName']}</a></td>
<td id="year"><span title="${comic['ComicYear']}"></span>${comic['ComicYear']}</td>
<td id="issue"><span title="${comic['LatestIssue']}"></span># ${comic['LatestIssue']} (${comic['LatestDate']})</td>
<td id="issue"><span title="${comic['LatestIssue']}"></span># ${comic['LatestIssue']}</td>
<td id="published">${comic['LatestDate']}</td>
<td id="have"><span title="${percent}"></span><div class="progress-container"><div style="background-color:#a3e532; height:14px; width:${percent}%"><div class="havetracks">${havetracks}/${totaltracks}</div></div></div></td>
<td id="status">
%if 'present' in comic['ComicPublished'].lower():
@ -102,7 +104,7 @@
{
"bDestroy": true,
"aoColumnDefs": [
{ 'bSortable': false, 'aTargets': [ 4 ] }
{ 'bSortable': false, 'aTargets': [ 5 ] }
],
"oLanguage": {
"sLengthMenu":"Show _MENU_ results per page",

View File

@ -14,7 +14,7 @@
</%def>
<%def name="body()">
<div id="artistheader" class="clearfix">
<div class="clearfix">
<h1>Weekly Pull list for : ${pulldate}</h1>
</div>
@ -24,7 +24,7 @@
<thead>
<tr>
<th id="publisher">Publisher</th>
<th id="comicname">COMIC</th>
<th id="comicname">Comic</th>
<th id="comicnumber">Number</th>
<th id="status">Status</th>
</tr>
@ -76,9 +76,9 @@
$('#pull_table').dataTable (
{
"bDestroy": true,
"aoColumnDefs": [
{ 'bSortable': false, 'aTargets': [ 2,3 ] }
],
//"aoColumnDefs": [
// { 'bSortable': false, 'aTargets': [ 2,3 ] }
//],
"oLanguage": {
"sLengthMenu":"Show _MENU_ issues per page",
"sEmptyTable": "No issue information available",

View File

@ -169,6 +169,10 @@ EXTRA_SCRIPTS = None
ENABLE_PRE_SCRIPTS = 1
PRE_SCRIPTS = None
COUNT_COMICS = 0
COUNT_ISSUES = 0
COUNT_HAVES = 0
def CheckSection(sec):
""" Check if INI section exists, if not create it """
try:
@ -228,7 +232,7 @@ def initialize():
NEWZNAB, NEWZNAB_HOST, NEWZNAB_APIKEY, NEWZNAB_ENABLED, EXTRA_NEWZNABS,\
RAW, RAW_PROVIDER, RAW_USERNAME, RAW_PASSWORD, RAW_GROUPS, EXPERIMENTAL, \
PREFERRED_QUALITY, MOVE_FILES, RENAME_FILES, LOWERCASE_FILENAMES, USE_MINSIZE, MINSIZE, USE_MAXSIZE, MAXSIZE, CORRECT_METADATA, FOLDER_FORMAT, FILE_FORMAT, REPLACE_CHAR, REPLACE_SPACES, ADD_TO_CSV, CVINFO, LOG_LEVEL, POST_PROCESSING, \
COMIC_LOCATION, QUAL_ALTVERS, QUAL_SCANNER, QUAL_TYPE, QUAL_QUALITY, ENABLE_EXTRA_SCRIPTS, EXTRA_SCRIPTS, ENABLE_PRE_SCRIPTS, PRE_SCRIPTS, PULLNEW
COMIC_LOCATION, QUAL_ALTVERS, QUAL_SCANNER, QUAL_TYPE, QUAL_QUALITY, ENABLE_EXTRA_SCRIPTS, EXTRA_SCRIPTS, ENABLE_PRE_SCRIPTS, PRE_SCRIPTS, PULLNEW, COUNT_ISSUES, COUNT_HAVES, COUNT_COMICS
if __INITIALIZED__:
return False
@ -429,8 +433,10 @@ def initialize():
# Get the currently installed version - returns None, 'win32' or the git hash
# Also sets INSTALL_TYPE variable to 'win', 'git' or 'source'
CURRENT_VERSION = versioncheck.getVersion()
hash = CURRENT_VERSION[:7]
print ("hash is set to : " + str(hash))
if CURRENT_VERSION is not None:
hash = CURRENT_VERSION[:7]
else:
hash = "unknown"
if version.MYLAR_VERSION == 'master':
vers = 'M'

View File

@ -375,11 +375,12 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None):
if imported is None or imported == 'None':
pass
else:
print ("imported length is : " + str(len(imported)))
print ("imported is :" + str(imported))
if mylar.IMP_MOVE:
logger.info("Mass import - Move files")
moveit.movefiles(comicid,comlocation,ogcname)
else:
logger.info("Mass import - Moving not Enabled. Setting Archived Status for import.")
moveit.archivefiles(comicid,ogcname)
#check for existing files...
updater.forceRescan(comicid)

View File

@ -19,7 +19,7 @@ def movefiles(comicid,comlocation,ogcname,imported=None):
orig_iss = impr['impID'][orig_iss+1:]
print ("Issue :" + str(orig_iss))
#before moving check to see if Rename to Mylar structure is enabled.
if mylar.IMP_RENAME:
if mylar.IMP_RENAME and mylar.FILE_FORMAT != '':
print("Renaming files according to configuration details : " + str(mylar.FILE_FORMAT))
renameit = helpers.rename_param(comicid, impr['ComicName'], orig_iss, orig_filename)
nfilename = renameit['nfilename']
@ -43,3 +43,14 @@ def movefiles(comicid,comlocation,ogcname,imported=None):
newValue = {"Status": "Imported" }
myDB.upsert("importresults", newValue, controlValue)
return
def archivefiles(comicid,ogcname):
# if move files isn't enabled, let's set all found comics to Archive status :)
result = myDB.action("SELECT * FROM importresults WHERE ComicName=?", [ogcname])
if result is None: pass
else:
ogdir = result['Location']
origdir = os.path.join(os.path.dirname(ogdir))
updater.forceRescan(comicid,archive=origdir) #send to rescanner with archive mode turned on

View File

@ -15,7 +15,7 @@ def searchit(cm):
logger.fdebug(u'Parsing results from <a href="%s">nzbx.co</a>' % searchURL)
request = urllib2.Request(searchURL)
request.add_header(mylar.USER_AGENT)
request.add_header('User-Agent', str(mylar.USER_AGENT))
opener = urllib2.build_opener()
try:

View File

@ -345,9 +345,9 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, nzbprov, nzbpr, Is
bb = prov_nzbx.searchit(comsearch[findloop])
if nzbprov != 'nzbx':
# Add a user-agent
print ("user-agent:" + str(mylar.USER_AGENT))
#print ("user-agent:" + str(mylar.USER_AGENT))
request = urllib2.Request(findurl)
request.add_header('User Agent', str(mylar.USER_AGENT))
request.add_header('User-Agent', str(mylar.USER_AGENT))
opener = urllib2.build_opener()
try:

View File

@ -35,7 +35,16 @@ def dbUpdate():
for comic in activecomics:
comicid = comic[0]
mylar.importer.addComictoDB(comicid)
mismatch = "no"
CV_EXcomicid = myDB.action("SELECT * from exceptions WHERE ComicID=?", [comicid]).fetchone()
if CV_EXcomicid is None: pass
else:
if CV_EXcomicid['variloop'] == '99':
mismatch = "yes"
if comicid[:1] == "G":
mylar.importer.GCDimport(comicid)
else:
mylar.importer.addComictoDB(comicid,mismatch)
logger.info('Update complete')
@ -209,12 +218,15 @@ def foundsearch(ComicID, IssueID):
logger.info(u"Updating now complete for " + str(comic['ComicName']) + " issue: " + str(issue['Issue_Number']))
return
def forceRescan(ComicID):
def forceRescan(ComicID,archive=None):
myDB = db.DBConnection()
# file check to see if issue exists
rescan = myDB.action('SELECT * FROM comics WHERE ComicID=?', [ComicID]).fetchone()
logger.info(u"Now checking files for " + str(rescan['ComicName']) + " (" + str(rescan['ComicYear']) + ") in " + str(rescan['ComicLocation']) )
fc = filechecker.listFiles(dir=rescan['ComicLocation'], watchcomic=rescan['ComicName'], AlternateSearch=rescan['AlternateSearch'])
if archive is None:
fc = filechecker.listFiles(dir=rescan['ComicLocation'], watchcomic=rescan['ComicName'], AlternateSearch=rescan['AlternateSearch'])
else:
fc = filechecker.listFiles(dir=archive, watchcomic=rescan['ComicName'], AlternateSearch=rescan['AlternateSearch'])
iscnt = rescan['Total']
havefiles = 0
fccnt = int(fc['comiccount'])
@ -410,6 +422,8 @@ def forceRescan(ComicID):
#we have the # of comics, now let's update the db.
#even if we couldn't find the physical issue, check the status.
#if Archived, increase the 'Have' count.
if archive:
issStatus = "Archived"
if haveissue == "no" and issuedupe == "no":
isslocation = "None"
if old_status == "Skipped":

View File

@ -431,6 +431,17 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("artistPage?ComicID=%s" % ComicID)
unqueueissue.exposed = True
def archiveissue(self, IssueID):
myDB = db.DBConnection()
issue = myDB.action('SELECT * FROM issues WHERE IssueID=?', [IssueID]).fetchone()
logger.info(u"Marking " + issue['ComicName'] + " issue # " + issue['Issue_Number'] + " as archived...")
controlValueDict = {'IssueID': IssueID}
newValueDict = {'Status': 'Archived'}
myDB.upsert("issues", newValueDict, controlValueDict)
raise cherrypy.HTTPRedirect("artistPage?ComicID=%s" % issue['ComicID'])
archiveissue.exposed = True
def pullist(self):
myDB = db.DBConnection()
weeklyresults = []
@ -661,26 +672,32 @@ class WebInterface(object):
clearhistory.exposed = True
def downloadLocal(self, IssueID):
print ("issueid: " + str(IssueID))
#print ("issueid: " + str(IssueID))
myDB = db.DBConnection()
issueDL = myDB.action("SELECT * FROM issues WHERE IssueID=?", [IssueID]).fetchone()
comicid = issueDL['ComicID']
print ("comicid: " + str(comicid))
#print ("comicid: " + str(comicid))
comic = myDB.action("SELECT * FROM comics WHERE ComicID=?", [comicid]).fetchone()
issueLOC = comic['ComicLocation']
print ("IssueLOC: " + str(issueLOC))
#print ("IssueLOC: " + str(issueLOC))
issueFILE = issueDL['Location']
print ("IssueFILE: "+ str(issueFILE))
#print ("IssueFILE: "+ str(issueFILE))
issuePATH = os.path.join(issueLOC,issueFILE)
print ("IssuePATH: " + str(issuePATH))
#print ("IssuePATH: " + str(issuePATH))
dstPATH = os.path.join(mylar.CACHE_DIR, issueFILE)
print ("dstPATH: " + str(dstPATH))
shutil.copy2(issuePATH, dstPATH)
print ("copied to cache...")
#issueURL = urllib.quote_plus(issueFILE)
#print ("issueURL:" + str(issueURL))
filepath = urllib.quote_plus(issueFILE)
return serve_file(filepath, "application/x-download", "attachment")
#print ("dstPATH: " + str(dstPATH))
try:
shutil.copy2(issuePATH, dstPATH)
except IOError as e:
logger.error("Could not copy " + str(issuePATH) + " to " + str(dstPATH) + ". Copy to Cache terminated.")
raise cherrypy.HTTPRedirect("artistPage?ComicID=%s" % comicid)
logger.debug("sucessfully copied to cache...Enabling Download link")
controlValueDict = {'IssueID': IssueID}
newValueDict = {'inCacheDIR': 'True'}
myDB.upsert("issues", newValueDict, controlValueDict)
#print("DB updated - Download link now enabled.")
downloadLocal.exposed = True
@ -811,6 +828,7 @@ class WebInterface(object):
updater.forceRescan(comicid)
else:
print ("nothing to do if I'm not moving.")
#hit the archiver in movefiles here...
raise cherrypy.HTTPRedirect("importResults")
@ -894,6 +912,16 @@ class WebInterface(object):
# branch_history, err = mylar.versioncheck.runGit("log --oneline --pretty=format:'%h - %ar - %s' -n 4")
# br_hist = branch_history.replace("\n", "<br />\n")
myDB = db.DBConnection()
CCOMICS = myDB.action("SELECT COUNT(*) FROM comics").fetchall()
CHAVES = myDB.action("SELECT COUNT(*) FROM issues WHERE Status='Downloaded' OR Status='Archived'").fetchall()
CISSUES = myDB.action("SELECT COUNT(*) FROM issues").fetchall()
COUNT_COMICS = CCOMICS[0][0]
COUNT_HAVES = CHAVES[0][0]
COUNT_ISSUES = CISSUES[0][0]
comicinfo = { "COUNT_COMICS" : COUNT_COMICS,
"COUNT_HAVES" : COUNT_HAVES,
"COUNT_ISSUES" : COUNT_ISSUES }
config = {
"http_host" : mylar.HTTP_HOST,
@ -967,7 +995,7 @@ class WebInterface(object):
"pre_scripts" : mylar.PRE_SCRIPTS,
"log_dir" : mylar.LOG_DIR
}
return serve_template(templatename="config.html", title="Settings", config=config)
return serve_template(templatename="config.html", title="Settings", config=config, comicinfo=comicinfo)
config.exposed = True
def error_change(self, comicid, errorgcd, comicname):