FIX: undefined on filter box on startup, IMP: Added Meta-Tagging options on a series / issue basis on comic details screen, IMP: Issue Information is now available per issue and is extracted currently from the cbz file to display (if no cbz is present, the option isn't available), IMP: Failed Download handling is implemented and available in GUI - required to replace existing autoProcessComics.py and ComicRN.py scripts, IMP: Added ability to specify post-processing script instead of ComicRN.py, IMP: Added abilty to edit the issue date for a given issue by simply clicking on it - this will help to avoid dates that have incorrect or 0000-00-00, IMP: Story Arc searching is working (not adding yet), IMP: Added Archived/Ignored options to Upcoming/Wanted tab, IMP: Fixed some alignment and display issues on the Upcoming section, IMP: Added better directory handling for Updating Comic Location when it needs to get changed for all existing series (locmove in config.ini), IMP: Added better handling for unicode characters in series titles when searching / filechecking, IMP: When adding a new series with no data, Mylar would error out (now will add and just retain 0 issues), FIX: When year was fuzzied, search would still attempt to do a date-check comparison and say everything failed, IMP: Better handling of nzb names when retaining for post-processing comparisons, IMP: Future Upcoming now will use actual shipping date of issue if available in order to see if issue is available, FIX: If annuals were enabled, refreshing a series would put some issues into an Archived status because the actual counts would be off, IMP: When file checking, Alternate Naming would be searched last which resulted in matching incorrectly to the series title or other alternate naming for the given series, now will check the Alternate Naming first for a match, then drop back down to the series name itself otherwise, IMP: Improved Annual detection when integrated with a given series, IMP: Improved the checking of the future Upcoming list for issues marked as Wanted but not available yet and then auto-adding, IMP: Improved upon story arc checking for missing issues / searching for wanted, IMP: Enabling Annuals support now within Configuration GUI, bunch of other things....

This commit is contained in:
evilhero 2014-07-28 15:28:09 -04:00
parent 5696ab905c
commit 78261e8fd8
35 changed files with 2606 additions and 895 deletions

View File

@ -148,17 +148,25 @@ div#main { margin: 0; padding: 80px 0 0 0; }
.comictable td#maindetails { width: 200px; padding: 10px; }
.comictable td#middle { vertical-align: middle; }
table#artist_table { background-color: white; width: 100%; padding: 20px; }
table#series_table { background-color: white; width: 100%; padding: 20px; }
table#artist_table th#select { text-align: left; }
table#artist_table th#name { text-align: left; min-width: 200px; }
table#artist_table th#status { text-align: left; min-width: 50px; }
table#artist_table th#album { text-align: left; min-width: 300px; }
table#artist_table th#have { text-align: center; }
table#artist_table td#name { vertical-align: middle; text-align: left; min-width:200px; }
table#artist_table td#status { vertical-align: middle; text-align: left; min-width: 50px; }
table#artist_table td#album { vertical-align: middle; text-align: left; min-width: 300px; }
table#artist_table td#have { vertical-align: middle; }
table#series_table th#publisher { text-align: left; min-width: 50px; }
table#series_table th#name { text-align: left; min-width: 250px; }
table#series_table th#year { text-align: left; min-width: 25px; }
table#series_table th#issue { text-align: left; min-width: 100px; }
table#series_table th#published { vertical-align: middle; text-align: left; min-width:40px; }
table#series_table th#have { text-align: center; }
table#series_table th#status { vertical-align: middle; text-align: left; min-width: 25px; }
table#series_table th#active { vertical-align: middle; text-align: left; min-width: 20px; }
table#series_table td#publisher { text-align: left; max-width: 100px; }
table#series_table td#name { text-align: left; max-width: 250px; }
table#series_table td#year { vertical-align: middle; text-align: left; max-width: 30px; }
table#series_table td#issue { vertical-align: middle; text-align: left; max-width: 100px; }
table#series_table td#published { vertical-align: middle; text-align: left; max-width: 40px; }
table#series_table td#have { text-align: center; }
table#series_table td#status { vertical-align: middle; text-align: left; max-width: 25px; }
table#series_table td#active { vertical-align: middle; text-align: left; max-width: 20px; }
div#paddingheader { padding-top: 48px; font-size: 24px; font-weight: bold; text-align: center; }
div#paddingheadertitle { padding-top: 24px; font-size: 24px; font-weight: bold; text-align: center; }

View File

@ -112,7 +112,6 @@
<script src="js/plugins.js"></script>
<script src="interfaces/default/js/script.js"></script>
<script src="interfaces/default/js/browser.js"></script>
<!--[if lt IE 7 ]>
<script src="js/libs/dd_belatedpng.js"></script>
<script> DD_belatedPNG.fix('img, .png_bg');</script>

119
data/interfaces/default/comicdetails.html Normal file → Executable file
View File

@ -13,7 +13,10 @@
%if mylar.RENAME_FILES:
<a id="menu_link_refresh" onclick="doAjaxCall('manualRename?comicid=${comic['ComicID']}', $(this),'table')" data-success="Renaming files.">Rename Files</a>
%endif
<a id="menu_link_refresh" onclick="doAjaxCall('forceRescan?ComicID=${comic['ComicID']}', $(this)),'table'" href="#" data-success="'${comic['ComicName']}' is being rescanned">Recheck Files</a>
<a id="menu_link_refresh" onclick="doAjaxCall('forceRescan?ComicID=${comic['ComicID']}', $(this),'table')" data-success="${comic['ComicName']} is being rescanned">Recheck Files</a>
%if mylar.ENABLE_META:
<a id="menu_link_refresh" onclick="doAjaxCall('group_metatag?dirName=${comic['ComicLocation']}&ComicID=${comic['ComicID']}', $(this),'table')" data-success="(re)tagging every issue present for '${comic['ComicName']}'">Manual MetaTagging</a>
%endif
%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>
%else:
@ -295,6 +298,7 @@
<label for="Downloaded" class="checkbox inline Downloaded"><input type="checkbox" id="Downloaded" checked="checked" /> Downloaded: <b>${isCounts['Downloaded']}</b></label>
<label for="Skipped" class="checkbox inline Skipped"><input type="checkbox" id="Skipped" checked="checked" /> Skipped: <b>${isCounts['Skipped']}</b></label>
<label for="Ignored" class="checkbox inline Ignored"><input type="checkbox" id="Ignored" checked="checked" /> Ignored: <b>${isCounts['Ignored']}</b></label>
<label for="Failed" class="checkbox inline Failed"><input type="checkbox" id="Failed" checked="checked" /> Failed: <b>${isCounts['Failed']}</b></label>
</div>
</div>
@ -310,6 +314,7 @@
<option value="Downloaded">Downloaded</option>
<option value="Archived">Archived</option>
<option value="Ignored">Ignored</option>
<option value="Failed">Failed</option>
</select>
selected issues
<input type="hidden" value="Go">
@ -345,6 +350,8 @@
grade = 'A'
elif issue['Status'] == 'Ignored':
grade = 'A'
elif issue['Status'] == 'Failed':
grade = 'C'
else:
grade = 'A'
%>
@ -353,8 +360,15 @@
<td id="select"><input type="checkbox" name="${issue['IssueID']}" class="checkbox" value="${issue['IssueID']}"/></td>
<td id="int_issuenumber">${issue['Int_IssueNumber']}</td>
<td id="issuenumber">${issue['Issue_Number']}</td>
<td id="issuename">${issue['IssueName']}</td>
<td id="reldate">${issue['IssueDate']}</td>
<%
if len(issue['IssueName']) > 80:
issuename = issue['IssueName'][:80] + '...'
else:
issuename = issue['IssueName']
endif
%>
<td id="issuename">${issuename}</td>
<td class="edit" title="Publication Date (click to edit)" id="${issue['ComicID']}.${issue['IssueID']}">${issue['IssueDate']}</td>
<td id="status">${issue['Status']}
%if issue['Status'] == 'Downloaded' or issue['Status'] == 'Archived':
<%Csize = mylar.helpers.human_size(issue['ComicSize'])%>
@ -369,8 +383,9 @@
<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 src="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
%elif (issue['Status'] == 'Snatched'):
<a href="#" onclick="doAjaxCall('queueit?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 src="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
%elif (issue['Status'] == 'Downloaded'):
<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 src="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
<a href="#" title="Mark issue as Failed" onclick="doAjaxCall('unqueueissue?IssueID=${issue['IssueID']}&ComicID=${issue['ComicID']}&mode="failed"',$(this),'table')" data-success="'${issue['Issue_Number']}' has been marked as Failed"><img src="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
%elif (issue['Status'] == 'Downloaded'):
<%
if issue['Location'] is not None:
linky = os.path.join(comic['ComicLocation'],issue['Location'])
@ -379,15 +394,34 @@
else:
linky = None
%>
%if linky:
%if linky:
<a href="downloadthis?pathfile=${linky |u}"><img src="interfaces/default/images/download_icon.png" height="25" width="25" title="Download the Issue" /></a>
%if linky.endswith('.cbz'):
<a href="#login-box" onclick="return runMetaIssue('${linky}');" class="login-window"><img src="interfaces/default/images/issueinfo.png" height="25" width="25" title="View Issue Details" /></a>
<div id="login-box" class="login-popup">
<a href="#" class="close"><img src="interfaces/default/images/close_pop.png" class="btn_close" title="Close Window" alt="Close" /></a>
<fieldset>
<div id="responsethis">
<label><strong>[ NODATA ]</strong></label></br>
</div>
</fieldset>
</div>
%endif
%if mylar.ENABLE_META:
<a href="#" title="Manually meta-tag issue" onclick="doAjaxCall('manual_metatag?dirName=${comic['ComicLocation']}&issueid=${issue['IssueID']}&filename=${linky |u}&comicid=${issue['ComicID']}',$(this),'table')" data-success="${issue['Issue_Number']} successfully tagged."><img src="interfaces/default/images/comictagger.png" height="25" width="25" /></a>
%endif
%endif
<!--
<a href="#" title="Add to Reading List" onclick="doAjaxCall('addtoreadlist?IssueID=${issue['IssueID']}',$(this),'table')" data-success="${issue['Issue_Number']} added to Reading List"><img src="interfaces/default/images/glasses-icon.png" height="25" width="25" /></a>
-->
%else:
<a href="#" onclick="doAjaxCall('queueit?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="Retry the same download again" onclick="doAjaxCall('queueit?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']}'"><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 src="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>
<!--
<a href="#" onclick="doAjaxCall('archiveissue?IssueID=${issue['IssueID']}&comicid=${comic['ComicID']}',$(this),'table')"><img src="interfaces/default/images/archive_icon.png" height="25" width="25" title="Mark issue as Archived"></a>
-->
</td>
</tr>
%endfor
@ -481,7 +515,7 @@
<% amode = 'want_ann' %>
<a href="#" title="Manual Search" onclick="doAjaxCall('queueit?ComicID=${annual['ComicID']}&IssueID=${annual['IssueID']}&ComicIssue=${annual['Issue_Number']}&ComicYear=${annual['IssueDate']}&mode=${amode}&manualsearch=True',$(this),'table')" data-success="Manually searching for ${annual['ComicName']} #${annual['Issue_Number']}"><img src="interfaces/default/images/search.png" height="25" width="25" /></a>
<a href="#" title="Mark issue as Wanted" onclick="doAjaxCall('queueissue?ComicID=${annual['ComicID']}&IssueID=${annual['IssueID']}&ComicIssue=${annual['Issue_Number']}&ComicYear=${annual['IssueDate']}&mode=${amode}',$(this),'table')"><img src="interfaces/default/images/wanted_icon.png" height="25" width="25" /></a>
<a href="#" title="Mark issue as Skipped" onclick="doAjaxCall('unqueueissue?IssueID=${annual['IssueID']}&ComicID=${annual['ComicID']}',$(this),'table')" data-success="'${annual['Issue_Number']}' has been marked as skipped"><img src="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
<a href="#" title="Mark issue as Skipped" onclick="doAjaxCall('unqueueissue?IssueID=${annual['IssueID']}&ComicID=${annual['ComicID']}&ReleaseComicID=${annual['ReleaseComicID']}',$(this),'table')" data-success="'${annual['Issue_Number']}' has been marked as skipped"><img src="interfaces/default/images/skipped_icon.png" height="25" width="25" /></a>
<a href="#" title="Add to Reading List"><img src="interfaces/default/images/glasses-icon.png" height="25" width="25" /></a>
<a href="#" title="Retry" onclick="doAjaxCall('queueissue?ComicID=${annual['ComicID']}&IssueID=${annual['IssueID']}&ComicIssue=${annual['Issue_Number']}&mode=${amode}', $(this),'table')" data-success="Retrying the same version of '${annual['ComicName']}'"><img src="interfaces/default/images/retry_icon.png" height="25" width="25" /></a>
<a href="#" title="Archive" onclick="doAjaxCall('archiveissue?IssueID=${annual['IssueID']}',$(this),'table')"><img src="interfaces/default/images/archive_icon.png" height="25" width="25" title="Mark issue as Archived" /></a>
@ -521,12 +555,79 @@
<%def name="javascriptIncludes()">
<script src="js/libs/jquery.dataTables.min.js"></script>
<script src="js/libs/jquery.jeditable.js"></script>
<style>
.ui-autocomplete-loading {
background: white url('interfaces/default/images/loader_black.gif') right center no-repeat;
}
#annseries{ width: 25em; }
</style>
<script>
$(document).ready(function() {
$('.edit').editable('issue_edit', {
callback : function(value, settings) {
console.log(this);
console.log(value);
console.log(settings);
return(value);
}
});
});
</script>
<script>
$(document).ready(function() {
$('a.login-window').click(function() {
//Getting the variable's value from a link
var loginBox = $(this).attr('href');
//Fade in the Popup
$(loginBox).fadeIn(300);
//Set the center alignment padding + border see css style
var popMargTop = ($(loginBox).height() + 24) / 2;
var popMargLeft = ($(loginBox).width() + 24) / 2;
$(loginBox).css({
'margin-top' : -popMargTop,
'margin-left' : -popMargLeft
});
// Add the mask to body
$('body').append('<div id="mask"></div>');
$('#mask').fadeIn(300);
return false;
});
// When clicking on the button close or the mask layer the popup closed
$('a.close, #mask').on('click', function() {
$('#mask , .login-popup').fadeOut(300 , function() {
$('#mask').remove();
});
return false;
});
});
</script>
<script>
function runMetaIssue(filelink) {
alert(filelink);
$.ajax({
type: "GET",
url: "IssueInfo",
data: { filelocation: filelink },
success: function(response) {
var names = response
$('#responsethis').html(response);
},
error: function(data)
{
alert('ERROR'+data.responseText);
},
});
}
</script>
<script>
$(function() {

View File

@ -133,10 +133,20 @@
<input type="checkbox" name="cvapifix" value="1" ${config['cvapifix']} /> <label>Comicvine URL Fix</label>
<br/><small>*Use this if CV's URL has changed*</small>
</div>
</fieldset>
<fieldset>
<legend>Annual Handling</legend>
<div>
<small class="heading"><span style="float: left; margin-right: .3em; margin-top: 4px;" class="ui-icon ui-icon-info"></span>Series need to be Refreshed for annuals to appear</small>
</div>
<div class="row checkbox">
<input type="checkbox" name="annuals_on" value="1" ${config['annuals_on']} /><label>Enable Series-Annual Integration</label>
</div>
</br><small>Enabled: Annuals are tracked as part of the series it belongs to</small></br>
<small>Disabled: Annuals are tracked independently and will appear on your watchlist as a series</small>
</fieldset>
</td>
<td>
<fieldset>
<legend>API</legend>
@ -150,7 +160,7 @@
<input id="api_enabled" type="checkbox" onclick="initConfigCheckbox($(this));" name="api_enabled" value="1" ${config['api_enabled']} /><label>Enable API</label>
</div>
<div class="apioptions">
<div Class="row">
<div class="row">
<label>Mylar API key</label>
<input type="text" name="api_key" id="api_key" value="${config['api_key']}" size="20">
<input type="button" value="Generate" id="generate_api">
@ -167,21 +177,13 @@
<input type="checkbox" name="nzb_startup_search" value="1" ${config['nzb_startup_search']} /><label>NZB Search on startup</label>
</div>
<div class="row">
<label>Search delay</label>
<input type="text" name="search_delay" value="${config['search_delay']}" size="4" />mins
<label>Search delay</label>
<input type="text" name="search_delay" value="${config['search_delay']}" size="4" />mins
</div>
</div>
</div>
<div class="row">
<label>Download Scan Interval</label>
<input type="text" name="download_scan_interval" value="${config['download_scan_interval']}" size="4">mins
</div>
<div class="row">
<label>Library Scan Interval</label>
<label>Library Scan Interval</label>
<input type="text" name="libraryscan_interval" value="${config['libraryscan_interval']}" size="4">mins
</div>
<legend>Comic Location</legend>
@ -584,28 +586,62 @@
</div>
</fieldset>
<fieldset>
<legend>Failed Download Handling</legend>
<div class="row checkbox left clearfix">
<input type="checkbox" id="enable_failed" onclick="initConfigCheckbox($this));" name="failed_download_handling" value="1" ${config['failed_download_handling']} /><label>Enable Failed Download Handling</label>
</div>
<div class="config">
<div class="row checkbox left clearfix">
<input type="checkbox" name="failed_auto" value="1" ${config['failed_auto']} /><label>Enable Automatic-Retry for Failed Downloads</label>
</div>
</fieldset>
</td>
<td>
<fieldset>
<legend>Post-Processing</legend>
<div class="row checkbox left clearfix">
<input type="checkbox" name="post_processing" value="1" ${config['post_processing']} /><label>Enable Post-Processing<small> (not checked = NO post-processing/post-management)</small></label>
<input type="checkbox" id="post_processing" onclick="initConfigCheckbox($this));" name="post_processing" value="1" ${config['post_processing']} /><label>Enable Post-Processing<small> (not checked = NO post-processing/post-management)</small></label>
</div>
<div class="config">
<div class="row checkbox left clearfix">
<input type="checkbox" id="enable_check_folder" onclick="initConfigCheckbox($this));" name="enable_check_folder" value="1" ${config['enable_check_folder']} /><label>Enable Folder Monitoring<small></label>
</div>
<div class="config">
<div class="row">
<label>Folder location to monitor</label>
<input type="text" name="check_folder" value="${config['check_folder']}" size="30">
<small>enter in the absolute path to monitor for new issues</small>
</div>
<div class="row">
<label>Folder Monitor Scan Interval</label>
<input type="text" name="download_scan_interval" value="${config['download_scan_interval']}" size="4">mins
<small>enter in the time delay scanning the folder</small>
</div>
</div>
</div>
<div class="row checkbox left clearfix">
<input type="checkbox" name="enable_pre_scripts" value="1" ${config['enable_pre_scripts']} /><label>Use Extra Script BEFORE Post-Processing</label>
<input type="checkbox" id="enable_pre_scripts" onclick="initConfigCheckbox($this));" name="enable_pre_scripts" value="1" ${config['enable_pre_scripts']} /><label>Use Extra Script BEFORE Post-Processing</label>
</div>
<div class="row">
<div class="config">
<div class="row">
<label>Pre - Script Location</label>
<input type="text" name="pre_scripts" value="${config['pre_scripts']}" size="30">
<small>enter in the absolute path to the script</small>
</div>
</div>
<div class="row checkbox left clearfix">
<input type="checkbox" name="enable_extra_scripts" value="1" ${config['enable_extra_scripts']} /><label>Use Extra Script AFTER Post-Processing</label>
<input type="checkbox" id="enable_extra_scripts" onclick="initConfigCheckbox($this));" name="enable_extra_scripts" value="1" ${config['enable_extra_scripts']} /><label>Use Extra Script AFTER Post-Processing</label>
</div>
<div class="row">
<label>Extra Script Location</label>
<input type="text" name="extra_scripts" value="${config['extra_scripts']}" size="30">
<small>enter in the absolute path to the script</small>
<div class="config">
<div class="row">
<label>Extra Script Location</label>
<input type="text" name="extra_scripts" value="${config['extra_scripts']}" size="30">
<small>enter in the absolute path to the script</small>
</div>
</div>
</fieldset>
<fieldset>
@ -1132,8 +1168,13 @@
initConfigCheckbox("#replace_spaces");
initConfigCheckbox("#use_minsize");
initConfigCheckbox("#use_maxsize");
initConfigCheckbox("#enable_failed");
initConfigCheckbox("#enable_meta");
initConfigCheckbox("#zero_level");
initConfigCheckbox("#post_processing");
initConfigCheckbox("#enable_check_folder");
initConfigCheckbox("#enable_pre_scripts");
initConfigCheckbox("#enable_extra_scripts");
}
$(document).ready(function() {
initThisPage();

View File

@ -283,7 +283,7 @@ input,
select,
form .checkbox input,
.configtable td#middle,
#artist_table td#have,
#series_table td#have,
#album_table td#have {
vertical-align: middle;
}
@ -1065,58 +1065,54 @@ div#artistheader h2 a {
vertical-align: middle;
}
#artist_table {
#series_table {
background-color: #FFF;
padding: 20px;
width: 100%;
}
#artist_table th#select {
#series_table th#publisher {
min-width: 150px;
text-align: left;
}
#artist_table th#select input {
vertical-align: middle;
}
#artist_table #artistImg {
background: url("../images/loader_black.gif") no-repeat scroll center center #ffffff;
border: 3px solid #FFFFFF;
box-shadow: 1px 1px 2px 0 #555555;
float: left;
height: 50px;
overflow: hidden;
text-indent: -3000px;
width: 50px;
}
#artist_table th#name {
min-width: 200px;
#series_table th#name {
min-width: 275px;
text-align: left;
}
#artist_table th#album {
min-width: 300px;
#series_table th#year,
#series_table th#issue {
min-width: 25px;
text-align: left;
}
#artist_table th#status,
#artist_table th#albumart,
#artist_table th#lastupdated {
#series_table th#status,
#series_table th#active,
#series_table th#published {
min-width: 50px;
text-align: left;
}
#artist_table th#have {
#series_table th#have {
text-align: center;
}
#artist_table td#name {
min-width: 200px;
#series_table td#publisher {
min-width: 150px;
text-align: left;
vertical-align: middle;
font-size: 12px;
}
#artist_table td#status,
#artist_table td#lastupdated {
min-width: 50px;
#series_table td#name {
min-width: 275px;
text-align: left;
vertical-align: middle;
}
#artist_table td#album {
min-width: 300px;
#series_table th#year,
#series_table th#issue {
max-width: 25px;
text-align: left;
vertical-align: middle;
}
#series_table td#status,
#series_table td#active,
#series_table td#published {
max-width: 50px;
text-align: left;
vertical-align: middle;
}
@ -1771,3 +1767,121 @@ table tr td#status a {
.ie7 legend {
margin-left: -7px;
}
/* Mask for background, by default is not display */
#mask {
display: none;
background: #000;
position: fixed;
left: 0;
top: 0;
z-index: 10;
width: 100%;
height: 100%;
opacity: 0.8;
z-index: 999;
}
/* You can customize to your needs */
.login-popup {
width: 600px;
display: none;
background: #333;
padding: 5px;
border: 2px solid #ddd;
color: white;
font-size: 1.2em;
position: absolute;
top: 20%;
left: 50%;
z-index: 99999;
box-shadow: 0px 0px 20px #999;
/* CSS3 */
-moz-box-shadow: 0px 0px 20px #999;
/* Firefox */
-webkit-box-shadow: 0px 0px 20px #999;
/* Safari, Chrome */
border-radius: 3px 3px 3px 3px;
-moz-border-radius: 3px;
/* Firefox */
-webkit-border-radius: 3px;
/* Safari, Chrome */;
}
.alignleft {
float: left;
}
.alignright {
float: right;
}
img.btn_close {
Position the close button
float: right;
margin: -28px -28px 0 0;
}
fieldset {
border: none;
}
form.signin .textbox label {
display: block;
padding-bottom: 7px;
}
form.signin .textbox span {
display: block;
}
form.signin p, form.signin span {
color: #999;
font-size: 11px;
line-height: 18px;
}
form.signin .textbox input {
background: #666666;
border-bottom: 1px solid #333;
border-left: 1px solid #000;
border-right: 1px solid #333;
border-top: 1px solid #000;
color: #fff;
border-radius: 3px 3px 3px 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
font: 13px Arial, Helvetica, sans-serif;
padding: 6px 6px 4px;
width: 200px;
}
form.signin input:-moz-placeholder {
color: #bbb;
text-shadow: 0 0 2px #000;
}
form.signin input::-webkit-input-placeholder {
color: #bbb;
text-shadow: 0 0 2px #000;
}
.button {
background: -moz-linear-gradient(center top, #f3f3f3, #dddddd);
background: -webkit-gradient(linear, left top, left bottom, from(#f3f3f3), to(#dddddd));
background: -o-linear-gradient(top, #f3f3f3, #dddddd);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f3f3f3', EndColorStr='#dddddd');
border-color: #000;
border-width: 1px;
border-radius: 4px 4px 4px 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
color: #333;
cursor: pointer;
display: inline-block;
padding: 6px 6px 4px;
margin-top: 10px;
font: 12px;
width: 214px;
}
.button:hover {
background: #ddd;
}

View File

@ -50,7 +50,7 @@
%elif future['STATUS'] == 'Skipped':
<a href="searchit?name=${future['COMIC'] | u}&issue=${future['ISSUE']}&mode=pullseries"><span class="ui-icon ui-icon-plus"></span>add series</a>
<a href="queueissue?ComicName=${future['COMIC'] | u}&ComicIssue=${future['ISSUE']}&mode=pullwant"><span class="ui-icon ui-icon-plus"></span>one off</a>
<a href="add2futurewatchlist?ComicName=${future['COMIC'] | u}&Issue=${future['ISSUE']}&Publisher=${future['PUBLISHER']}&ShipDate=${future['SHIPDATE']}&FutureID=${future['FUTUREID']}"><span class="ui-icon ui-icon-plus"></span>Watch For</a>
<a href="#" onclick="doAjaxCall('add2futurewatchlist?ComicName=${future['COMIC'] |u}&Issue=${future['ISSUE']}&Publisher=${future['PUBLISHER']}}&ShipDate=${future['SHIPDATE']}&FutureID=${future['FUTUREID']}', $(this), 'table')" data-success="Adding ${future['COMIC']} Issue: ${future['ISSUE']} to Upcoming Watchlist"><span class="ui-icon ui-icon-plus"></span>Watch For</a>
%endif
</td>
%endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

0
data/interfaces/default/importresults.html Normal file → Executable file
View File

6
data/interfaces/default/index.html Normal file → Executable file
View File

@ -7,7 +7,7 @@
<%def name="body()">
<div class="table_wrapper">
<table class="display" id="artist_table">
<table class="display" id="series_table">
<thead>
<tr>
<th id="publisher">Publisher</th>
@ -17,7 +17,7 @@
<th id="published">Published</th>
<th id="have">Have</th>
<th id="status">Status</th>
<th id="status">Active</th>
<th id="active">Active</th>
</tr>
</thead>
<tbody>
@ -63,7 +63,7 @@
<script>
function initThisPage() {
$('#artist_table').dataTable(
$('#series_table').dataTable(
{
"bDestroy": true,
"aoColumnDefs": [

View File

@ -0,0 +1,38 @@
(function($){$.fn.editable=function(target,options){if('disable'==target){$(this).data('disabled.editable',true);return;}
if('enable'==target){$(this).data('disabled.editable',false);return;}
if('destroy'==target){$(this).unbind($(this).data('event.editable')).removeData('disabled.editable').removeData('event.editable');return;}
var settings=$.extend({},$.fn.editable.defaults,{target:target},options);var plugin=$.editable.types[settings.type].plugin||function(){};var submit=$.editable.types[settings.type].submit||function(){};var buttons=$.editable.types[settings.type].buttons||$.editable.types['defaults'].buttons;var content=$.editable.types[settings.type].content||$.editable.types['defaults'].content;var element=$.editable.types[settings.type].element||$.editable.types['defaults'].element;var reset=$.editable.types[settings.type].reset||$.editable.types['defaults'].reset;var callback=settings.callback||function(){};var onedit=settings.onedit||function(){};var onsubmit=settings.onsubmit||function(){};var onreset=settings.onreset||function(){};var onerror=settings.onerror||reset;if(settings.tooltip){$(this).attr('title',settings.tooltip);}
settings.autowidth='auto'==settings.width;settings.autoheight='auto'==settings.height;return this.each(function(){var self=this;var savedwidth=$(self).width();var savedheight=$(self).height();$(this).data('event.editable',settings.event);if(!$.trim($(this).html())){$(this).html(settings.placeholder);}
$(this).bind(settings.event,function(e){if(true===$(this).data('disabled.editable')){return;}
if(self.editing){return;}
if(false===onedit.apply(this,[settings,self])){return;}
e.preventDefault();e.stopPropagation();if(settings.tooltip){$(self).removeAttr('title');}
if(0==$(self).width()){settings.width=savedwidth;settings.height=savedheight;}else{if(settings.width!='none'){settings.width=settings.autowidth?$(self).width():settings.width;}
if(settings.height!='none'){settings.height=settings.autoheight?$(self).height():settings.height;}}
if($(this).html().toLowerCase().replace(/(;|")/g,'')==settings.placeholder.toLowerCase().replace(/(;|")/g,'')){$(this).html('');}
self.editing=true;self.revert=$(self).html();$(self).html('');var form=$('<form />');if(settings.cssclass){if('inherit'==settings.cssclass){form.attr('class',$(self).attr('class'));}else{form.attr('class',settings.cssclass);}}
if(settings.style){if('inherit'==settings.style){form.attr('style',$(self).attr('style'));form.css('display',$(self).css('display'));}else{form.attr('style',settings.style);}}
var input=element.apply(form,[settings,self]);var input_content;if(settings.loadurl){var t=setTimeout(function(){input.disabled=true;content.apply(form,[settings.loadtext,settings,self]);},100);var loaddata={};loaddata[settings.id]=self.id;if($.isFunction(settings.loaddata)){$.extend(loaddata,settings.loaddata.apply(self,[self.revert,settings]));}else{$.extend(loaddata,settings.loaddata);}
$.ajax({type:settings.loadtype,url:settings.loadurl,data:loaddata,async:false,success:function(result){window.clearTimeout(t);input_content=result;input.disabled=false;}});}else if(settings.data){input_content=settings.data;if($.isFunction(settings.data)){input_content=settings.data.apply(self,[self.revert,settings]);}}else{input_content=self.revert;}
content.apply(form,[input_content,settings,self]);input.attr('name',settings.name);buttons.apply(form,[settings,self]);$(self).append(form);plugin.apply(form,[settings,self]);$(':input:visible:enabled:first',form).focus();if(settings.select){input.select();}
input.keydown(function(e){if(e.keyCode==27){e.preventDefault();reset.apply(form,[settings,self]);}});var t;if('cancel'==settings.onblur){input.blur(function(e){t=setTimeout(function(){reset.apply(form,[settings,self]);},500);});}else if('submit'==settings.onblur){input.blur(function(e){t=setTimeout(function(){form.submit();},200);});}else if($.isFunction(settings.onblur)){input.blur(function(e){settings.onblur.apply(self,[input.val(),settings]);});}else{input.blur(function(e){});}
form.submit(function(e){if(t){clearTimeout(t);}
e.preventDefault();if(false!==onsubmit.apply(form,[settings,self])){if(false!==submit.apply(form,[settings,self])){if($.isFunction(settings.target)){var str=settings.target.apply(self,[input.val(),settings]);$(self).html(str);self.editing=false;callback.apply(self,[self.innerHTML,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}}else{var submitdata={};submitdata[settings.name]=input.val();submitdata[settings.id]=self.id;if($.isFunction(settings.submitdata)){$.extend(submitdata,settings.submitdata.apply(self,[self.revert,settings]));}else{$.extend(submitdata,settings.submitdata);}
if('PUT'==settings.method){submitdata['_method']='put';}
$(self).html(settings.indicator);var ajaxoptions={type:'POST',data:submitdata,dataType:'html',url:settings.target,success:function(result,status){if(ajaxoptions.dataType=='html'){$(self).html(result);}
self.editing=false;callback.apply(self,[result,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}},error:function(xhr,status,error){onerror.apply(form,[settings,self,xhr]);}};$.extend(ajaxoptions,settings.ajaxoptions);$.ajax(ajaxoptions);}}}
$(self).attr('title',settings.tooltip);return false;});});this.reset=function(form){if(this.editing){if(false!==onreset.apply(form,[settings,self])){$(self).html(self.revert);self.editing=false;if(!$.trim($(self).html())){$(self).html(settings.placeholder);}
if(settings.tooltip){$(self).attr('title',settings.tooltip);}}}};});};$.editable={types:{defaults:{element:function(settings,original){var input=$('<input type="hidden"></input>');$(this).append(input);return(input);},content:function(string,settings,original){$(':input:first',this).val(string);},reset:function(settings,original){original.reset(this);},buttons:function(settings,original){var form=this;if(settings.submit){if(settings.submit.match(/>$/)){var submit=$(settings.submit).click(function(){if(submit.attr("type")!="submit"){form.submit();}});}else{var submit=$('<button type="submit" />');submit.html(settings.submit);}
$(this).append(submit);}
if(settings.cancel){if(settings.cancel.match(/>$/)){var cancel=$(settings.cancel);}else{var cancel=$('<button type="cancel" />');cancel.html(settings.cancel);}
$(this).append(cancel);$(cancel).click(function(event){if($.isFunction($.editable.types[settings.type].reset)){var reset=$.editable.types[settings.type].reset;}else{var reset=$.editable.types['defaults'].reset;}
reset.apply(form,[settings,original]);return false;});}}},text:{element:function(settings,original){var input=$('<input />');if(settings.width!='none'){input.width(settings.width);}
if(settings.height!='none'){input.height(settings.height);}
input.attr('autocomplete','off');$(this).append(input);return(input);}},textarea:{element:function(settings,original){var textarea=$('<textarea />');if(settings.rows){textarea.attr('rows',settings.rows);}else if(settings.height!="none"){textarea.height(settings.height);}
if(settings.cols){textarea.attr('cols',settings.cols);}else if(settings.width!="none"){textarea.width(settings.width);}
$(this).append(textarea);return(textarea);}},select:{element:function(settings,original){var select=$('<select />');$(this).append(select);return(select);},content:function(data,settings,original){if(String==data.constructor){eval('var json = '+data);}else{var json=data;}
for(var key in json){if(!json.hasOwnProperty(key)){continue;}
if('selected'==key){continue;}
var option=$('<option />').val(key).append(json[key]);$('select',this).append(option);}
$('select',this).children().each(function(){if($(this).val()==json['selected']||$(this).text()==$.trim(original.revert)){$(this).attr('selected','selected');}});}}},addInputType:function(name,input){$.editable.types[name]=input;}};$.fn.editable.defaults={name:'value',id:'id',type:'text',width:'auto',height:'auto',event:'click.editable',onblur:'cancel',loadtype:'GET',loadtext:'Loading...',placeholder:'Click to edit',loaddata:{},submitdata:{},ajaxoptions:{}};})(jQuery);

View File

@ -60,11 +60,11 @@
<small>Leaving this unchecked will not move anything, but will mark the issues as Archived</small>
</div>
<div class="config">
<input type="checkbox" name="imp_rename" id="imp_rename" value="1" ${checked(mylar.IMP_RENAME)}><label>Rename Files </label>
<input type="checkbox" style="vertical-align: middle; margin: 3px; margin-top: -1px;" name="imp_rename" id="imp_rename" value="1" ${checked(mylar.IMP_RENAME)}><label>Rename Files </label>
<small>Rename files to configuration settings</small>
</div>
<br/>
<input type="button" value="Save Changes and Scan" onclick="addScanAction();doAjaxCall('comicScan',$(this),'tabs',true);return false;" data-success="Changes saved. Library will be scanned">
<input type="button" value="Save Changes and Scan" onclick="addScanAction();doAjaxCall('comicScan',$(this),'tabs',true);return false;" data-success="Changes saved. Library will be scanned" data-always="Sucessfully completed scanning library.">
<input type="button" value="Save Changes without Scanning Library" onclick="doAjaxCall('comicScan',$(this),'tabs',true);return false;" data-success="Changes Saved Successfully">
</fieldset>
</form>

View File

@ -69,18 +69,7 @@
<%def name="javascriptIncludes()">
<script src="js/libs/jquery.dataTables.min.js"></script>
<script>
function getArtistArt() {
$("table#artist_table tr td#albumart #artistImg").each(function(){
var id = $(this).children('img').attr('id');
var image = $(this).children('img');
if ( !image.hasClass('done') ) {
image.addClass('done');
getThumb(image,id,'artist');
}
});
}
function initThisPage() {
getArtistArt();
$('#manage_comic').dataTable(
{
"bDestroy": true,

View File

@ -78,7 +78,7 @@
<table class="configtable">
<tr>
<form action="searchit" method="get">
<input type="hidden" name="type" value="storyarc">
<input type="hidden" name="type" value="story_arc">
<input type="text" value="" placeholder="Search" onfocus="if(this.value==this.defaultValue) this.value='';" name="name" />
<span class="mini-icon"></span>
<input type="submit" value="Search"/>

View File

@ -1,4 +1,9 @@
<%inherit file="base.html" />
<%!
import mylar
from mylar.helpers import checked
%>
<%def name="headerIncludes()">
<div id="subhead_container">
@ -28,6 +33,16 @@
%>
<h1 class="clearfix"><img src="interfaces/default/images/icon_search.png" alt="Search results"/>${searchtext}</h1>
<div>
<form action="CreateFolders" method="GET" id="CreatetheFolders">
<fieldset>
<div class="row">
<input type="checkbox" name="createfolders" id="createfolders" value=1 ${checked(mylar.CREATE_FOLDERS)} /><label>Automatic Folder Creation</label>
</div>
<input type="submit" style="display:none" />
</fieldset>
</form>
</div>
</div>
<div class="table_wrapper">
<table class="display" id="searchresults_table">
@ -57,7 +72,7 @@
<td class="comicyear">${result['comicyear']}</a></td>
<td class="issues">${result['issues']}</td>
<td class="add" nowrap="nowrap"><a href="addComic?comicid=${result['comicid']}&comicname=${result['name'] |u}&comicyear=${result['comicyear']}&comicpublisher=${result['publisher'] |u}&comicimage=${result['comicimage']}&comicissues=${result['issues']}&imported=${imported}&ogcname=${ogcname}"><span class="ui-icon ui-icon-plus"></span> Add this Comic</a></td>
<td class="add" nowrap="nowrap"><a href="addComic?comicid=${result['comicid']}&comicname=${result['name'] |u}&comicyear=${result['comicyear']}&comicpublisher=${result['publisher'] |u}&comicimage=${result['comicimage']}&comicissues=${result['issues']}&imported=${imported}&ogcname=${ogcname}&serinfo=${serinfo}"><span class="ui-icon ui-icon-plus"></span> Add this Comic</a></td>
</tr>
%endfor
%endif
@ -71,6 +86,12 @@
</%def>
<%def name="javascriptIncludes()">
<script type="text/javascript">
$("#createfolders").click(function() {
$('#CreatetheFolders').submit();
return true;
});
</script>
<script src="js/libs/jquery.dataTables.min.js"></script>

View File

@ -21,6 +21,8 @@
<option disabled="disabled" selected="selected">Choose...</option>
<option value="Skipped">Skipped</option>
<option value="Downloaded">Downloaded</option>
<option value="Archived">Archived</option>
<option value="Ignored">Ignored</option>
</select>
<input type="hidden" value="Go">
</div>
@ -90,10 +92,10 @@
<td id="status">${upcome['Status']}</td>
</tr>
%endfor
</tbody>
%else:
<tr><td align="center" width="100%"> no upcoming data to display</td></tr>
%endif
</tbody>
</table>
</div>
</div>
@ -102,7 +104,7 @@
<div class="table_wrapper">
<table class="display_no_select" id="upcoming_table">
%if future_nodata_upcoming:
<thead>
<thead>
<tr>
<th id="comicname">Comic</th>
<th id="issuenumber">Issue</th>
@ -116,13 +118,13 @@
<td id="comicname"><a href="comicDetails?ComicID=${f_nodata['ComicID']}">${f_nodata['ComicName']}</a></td>
<td id="issuenumber">${f_nodata['IssueNumber']}</td>
<td id="reldate">${f_nodata['IssueDate']}</td>
<td id="status">${f_nodata['Status']}</td>
<td id="status">${f_nodata['Status']}</td>
</tr>
%endfor
</tbody>
%else:
<tr><td align='center" width="100%">no upcoming future data to display</td></tr>
<tr><td align="center" width="100%">no upcoming future data to display</td></tr>
%endif
</tbody>
</table>
</div>
</div>
@ -131,14 +133,14 @@
<div class="table_wrapper">
<table class="display_no_select" id="upcoming_table">
%if futureupcoming:
<thead>
<thead>
<tr>
<th id="comicname">Comic</th>
<th id="issuenumber">Issue</th>
<th id="reldate">Release Date</th>
<th id="status">Status</th>
</tr>
</thead>
</thead>
<tbody>
%for f_upcome in futureupcoming:
<tr class="gradeZ">
@ -148,10 +150,10 @@
<td id="status">${f_upcome['Status']}</td>
</tr>
%endfor
</tbody>
%else:
<tr><td align="center" width="100%">no upcoming future data to display</td></tr>
%endif
</tbody>
</table>
</div>
</div>

View File

@ -11,7 +11,7 @@
<div id="subhead_menu">
<a id="menu_link_refresh" href="manualpull">Refresh Pull-list</a>
<a id="menu_link_delete" href="pullrecreate">Recreate Pull-list</a>
<a id="menu_link_scan" class="button">Download</a>
<a id="menu_link_refresh" class="button">Download</a>
<!-- <a id="menu_link_refresh" onclick="doAjaxCall('MassWeeklyDownload?pulldate=${pulldate}, $(this)),'table'" href="#" data-success="Now Downloading Comics to : ${mylar.GRABBAG_DIR}">Download.</a> -->
</div>
</div>

543
data/js/libs/jquery.jeditable.js Executable file
View File

@ -0,0 +1,543 @@
/*
* Jeditable - jQuery in place edit plugin
*
* Copyright (c) 2006-2009 Mika Tuupola, Dylan Verheul
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* http://www.appelsiini.net/projects/jeditable
*
* Based on editable by Dylan Verheul <dylan_at_dyve.net>:
* http://www.dyve.net/jquery/?editable
*
*/
/**
* Version 1.7.1
*
* ** means there is basic unit tests for this parameter.
*
* @name Jeditable
* @type jQuery
* @param String target (POST) URL or function to send edited content to **
* @param Hash options additional options
* @param String options[method] method to use to send edited content (POST or PUT) **
* @param Function options[callback] Function to run after submitting edited content **
* @param String options[name] POST parameter name of edited content
* @param String options[id] POST parameter name of edited div id
* @param Hash options[submitdata] Extra parameters to send when submitting edited content.
* @param String options[type] text, textarea or select (or any 3rd party input type) **
* @param Integer options[rows] number of rows if using textarea **
* @param Integer options[cols] number of columns if using textarea **
* @param Mixed options[height] 'auto', 'none' or height in pixels **
* @param Mixed options[width] 'auto', 'none' or width in pixels **
* @param String options[loadurl] URL to fetch input content before editing **
* @param String options[loadtype] Request type for load url. Should be GET or POST.
* @param String options[loadtext] Text to display while loading external content.
* @param Mixed options[loaddata] Extra parameters to pass when fetching content before editing.
* @param Mixed options[data] Or content given as paramameter. String or function.**
* @param String options[indicator] indicator html to show when saving
* @param String options[tooltip] optional tooltip text via title attribute **
* @param String options[event] jQuery event such as 'click' of 'dblclick' **
* @param String options[submit] submit button value, empty means no button **
* @param String options[cancel] cancel button value, empty means no button **
* @param String options[cssclass] CSS class to apply to input form. 'inherit' to copy from parent. **
* @param String options[style] Style to apply to input form 'inherit' to copy from parent. **
* @param String options[select] true or false, when true text is highlighted ??
* @param String options[placeholder] Placeholder text or html to insert when element is empty. **
* @param String options[onblur] 'cancel', 'submit', 'ignore' or function ??
*
* @param Function options[onsubmit] function(settings, original) { ... } called before submit
* @param Function options[onreset] function(settings, original) { ... } called before reset
* @param Function options[onerror] function(settings, original, xhr) { ... } called on error
*
* @param Hash options[ajaxoptions] jQuery Ajax options. See docs.jquery.com.
*
*/
(function($) {
$.fn.editable = function(target, options) {
if ('disable' == target) {
$(this).data('disabled.editable', true);
return;
}
if ('enable' == target) {
$(this).data('disabled.editable', false);
return;
}
if ('destroy' == target) {
$(this)
.unbind($(this).data('event.editable'))
.removeData('disabled.editable')
.removeData('event.editable');
return;
}
var settings = $.extend({}, $.fn.editable.defaults, {target:target}, options);
/* setup some functions */
var plugin = $.editable.types[settings.type].plugin || function() { };
var submit = $.editable.types[settings.type].submit || function() { };
var buttons = $.editable.types[settings.type].buttons
|| $.editable.types['defaults'].buttons;
var content = $.editable.types[settings.type].content
|| $.editable.types['defaults'].content;
var element = $.editable.types[settings.type].element
|| $.editable.types['defaults'].element;
var reset = $.editable.types[settings.type].reset
|| $.editable.types['defaults'].reset;
var callback = settings.callback || function() { };
var onedit = settings.onedit || function() { };
var onsubmit = settings.onsubmit || function() { };
var onreset = settings.onreset || function() { };
var onerror = settings.onerror || reset;
/* show tooltip */
if (settings.tooltip) {
$(this).attr('title', settings.tooltip);
}
settings.autowidth = 'auto' == settings.width;
settings.autoheight = 'auto' == settings.height;
return this.each(function() {
/* save this to self because this changes when scope changes */
var self = this;
/* inlined block elements lose their width and height after first edit */
/* save them for later use as workaround */
var savedwidth = $(self).width();
var savedheight = $(self).height();
/* save so it can be later used by $.editable('destroy') */
$(this).data('event.editable', settings.event);
/* if element is empty add something clickable (if requested) */
if (!$.trim($(this).html())) {
$(this).html(settings.placeholder);
}
$(this).bind(settings.event, function(e) {
/* abort if disabled for this element */
if (true === $(this).data('disabled.editable')) {
return;
}
/* prevent throwing an exeption if edit field is clicked again */
if (self.editing) {
return;
}
/* abort if onedit hook returns false */
if (false === onedit.apply(this, [settings, self])) {
return;
}
/* prevent default action and bubbling */
e.preventDefault();
e.stopPropagation();
/* remove tooltip */
if (settings.tooltip) {
$(self).removeAttr('title');
}
/* figure out how wide and tall we are, saved width and height */
/* are workaround for http://dev.jquery.com/ticket/2190 */
if (0 == $(self).width()) {
//$(self).css('visibility', 'hidden');
settings.width = savedwidth;
settings.height = savedheight;
} else {
if (settings.width != 'none') {
settings.width =
settings.autowidth ? $(self).width() : settings.width;
}
if (settings.height != 'none') {
settings.height =
settings.autoheight ? $(self).height() : settings.height;
}
}
//$(this).css('visibility', '');
/* remove placeholder text, replace is here because of IE */
if ($(this).html().toLowerCase().replace(/(;|")/g, '') ==
settings.placeholder.toLowerCase().replace(/(;|")/g, '')) {
$(this).html('');
}
self.editing = true;
self.revert = $(self).html();
$(self).html('');
/* create the form object */
var form = $('<form />');
/* apply css or style or both */
if (settings.cssclass) {
if ('inherit' == settings.cssclass) {
form.attr('class', $(self).attr('class'));
} else {
form.attr('class', settings.cssclass);
}
}
if (settings.style) {
if ('inherit' == settings.style) {
form.attr('style', $(self).attr('style'));
/* IE needs the second line or display wont be inherited */
form.css('display', $(self).css('display'));
} else {
form.attr('style', settings.style);
}
}
/* add main input element to form and store it in input */
var input = element.apply(form, [settings, self]);
/* set input content via POST, GET, given data or existing value */
var input_content;
if (settings.loadurl) {
var t = setTimeout(function() {
input.disabled = true;
content.apply(form, [settings.loadtext, settings, self]);
}, 100);
var loaddata = {};
loaddata[settings.id] = self.id;
if ($.isFunction(settings.loaddata)) {
$.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));
} else {
$.extend(loaddata, settings.loaddata);
}
$.ajax({
type : settings.loadtype,
url : settings.loadurl,
data : loaddata,
async : false,
success: function(result) {
window.clearTimeout(t);
input_content = result;
input.disabled = false;
}
});
} else if (settings.data) {
input_content = settings.data;
if ($.isFunction(settings.data)) {
input_content = settings.data.apply(self, [self.revert, settings]);
}
} else {
input_content = self.revert;
}
content.apply(form, [input_content, settings, self]);
input.attr('name', settings.name);
/* add buttons to the form */
buttons.apply(form, [settings, self]);
/* add created form to self */
$(self).append(form);
/* attach 3rd party plugin if requested */
plugin.apply(form, [settings, self]);
/* focus to first visible form element */
$(':input:visible:enabled:first', form).focus();
/* highlight input contents when requested */
if (settings.select) {
input.select();
}
/* discard changes if pressing esc */
input.keydown(function(e) {
if (e.keyCode == 27) {
e.preventDefault();
//self.reset();
reset.apply(form, [settings, self]);
}
});
/* discard, submit or nothing with changes when clicking outside */
/* do nothing is usable when navigating with tab */
var t;
if ('cancel' == settings.onblur) {
input.blur(function(e) {
/* prevent canceling if submit was clicked */
t = setTimeout(function() {
reset.apply(form, [settings, self]);
}, 500);
});
} else if ('submit' == settings.onblur) {
input.blur(function(e) {
/* prevent double submit if submit was clicked */
t = setTimeout(function() {
form.submit();
}, 200);
});
} else if ($.isFunction(settings.onblur)) {
input.blur(function(e) {
settings.onblur.apply(self, [input.val(), settings]);
});
} else {
input.blur(function(e) {
/* TODO: maybe something here */
});
}
form.submit(function(e) {
if (t) {
clearTimeout(t);
}
/* do no submit */
e.preventDefault();
/* call before submit hook. */
/* if it returns false abort submitting */
if (false !== onsubmit.apply(form, [settings, self])) {
/* custom inputs call before submit hook. */
/* if it returns false abort submitting */
if (false !== submit.apply(form, [settings, self])) {
/* check if given target is function */
if ($.isFunction(settings.target)) {
var str = settings.target.apply(self, [input.val(), settings]);
$(self).html(str);
self.editing = false;
callback.apply(self, [self.innerHTML, settings]);
/* TODO: this is not dry */
if (!$.trim($(self).html())) {
$(self).html(settings.placeholder);
}
} else {
/* add edited content and id of edited element to POST */
var submitdata = {};
submitdata[settings.name] = input.val();
submitdata[settings.id] = self.id;
/* add extra data to be POST:ed */
if ($.isFunction(settings.submitdata)) {
$.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings]));
} else {
$.extend(submitdata, settings.submitdata);
}
/* quick and dirty PUT support */
if ('PUT' == settings.method) {
submitdata['_method'] = 'put';
}
/* show the saving indicator */
$(self).html(settings.indicator);
/* defaults for ajaxoptions */
var ajaxoptions = {
type : 'POST',
data : submitdata,
dataType: 'html',
url : settings.target,
success : function(result, status) {
if (ajaxoptions.dataType == 'html') {
$(self).html(result);
}
self.editing = false;
callback.apply(self, [result, settings]);
if (!$.trim($(self).html())) {
$(self).html(settings.placeholder);
}
},
error : function(xhr, status, error) {
onerror.apply(form, [settings, self, xhr]);
}
};
/* override with what is given in settings.ajaxoptions */
$.extend(ajaxoptions, settings.ajaxoptions);
$.ajax(ajaxoptions);
}
}
}
/* show tooltip again */
$(self).attr('title', settings.tooltip);
return false;
});
});
/* privileged methods */
this.reset = function(form) {
/* prevent calling reset twice when blurring */
if (this.editing) {
/* before reset hook, if it returns false abort reseting */
if (false !== onreset.apply(form, [settings, self])) {
$(self).html(self.revert);
self.editing = false;
if (!$.trim($(self).html())) {
$(self).html(settings.placeholder);
}
/* show tooltip again */
if (settings.tooltip) {
$(self).attr('title', settings.tooltip);
}
}
}
};
});
};
$.editable = {
types: {
defaults: {
element : function(settings, original) {
var input = $('<input type="hidden"></input>');
$(this).append(input);
return(input);
},
content : function(string, settings, original) {
$(':input:first', this).val(string);
},
reset : function(settings, original) {
original.reset(this);
},
buttons : function(settings, original) {
var form = this;
if (settings.submit) {
/* if given html string use that */
if (settings.submit.match(/>$/)) {
var submit = $(settings.submit).click(function() {
if (submit.attr("type") != "submit") {
form.submit();
}
});
/* otherwise use button with given string as text */
} else {
var submit = $('<button type="submit" />');
submit.html(settings.submit);
}
$(this).append(submit);
}
if (settings.cancel) {
/* if given html string use that */
if (settings.cancel.match(/>$/)) {
var cancel = $(settings.cancel);
/* otherwise use button with given string as text */
} else {
var cancel = $('<button type="cancel" />');
cancel.html(settings.cancel);
}
$(this).append(cancel);
$(cancel).click(function(event) {
//original.reset();
if ($.isFunction($.editable.types[settings.type].reset)) {
var reset = $.editable.types[settings.type].reset;
} else {
var reset = $.editable.types['defaults'].reset;
}
reset.apply(form, [settings, original]);
return false;
});
}
}
},
text: {
element : function(settings, original) {
var input = $('<input />');
if (settings.width != 'none') { input.width(settings.width); }
if (settings.height != 'none') { input.height(settings.height); }
/* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
//input[0].setAttribute('autocomplete','off');
input.attr('autocomplete','off');
$(this).append(input);
return(input);
}
},
textarea: {
element : function(settings, original) {
var textarea = $('<textarea />');
if (settings.rows) {
textarea.attr('rows', settings.rows);
} else if (settings.height != "none") {
textarea.height(settings.height);
}
if (settings.cols) {
textarea.attr('cols', settings.cols);
} else if (settings.width != "none") {
textarea.width(settings.width);
}
$(this).append(textarea);
return(textarea);
}
},
select: {
element : function(settings, original) {
var select = $('<select />');
$(this).append(select);
return(select);
},
content : function(data, settings, original) {
/* If it is string assume it is json. */
if (String == data.constructor) {
eval ('var json = ' + data);
} else {
/* Otherwise assume it is a hash already. */
var json = data;
}
for (var key in json) {
if (!json.hasOwnProperty(key)) {
continue;
}
if ('selected' == key) {
continue;
}
var option = $('<option />').val(key).append(json[key]);
$('select', this).append(option);
}
/* Loop option again to set selected. IE needed this... */
$('select', this).children().each(function() {
if ($(this).val() == json['selected'] ||
$(this).text() == $.trim(original.revert)) {
$(this).attr('selected', 'selected');
}
});
}
}
},
/* Add new input type */
addInputType: function(name, input) {
$.editable.types[name] = input;
}
};
// publicly accessible defaults
$.fn.editable.defaults = {
name : 'value',
id : 'id',
type : 'text',
width : 'auto',
height : 'auto',
event : 'click.editable',
onblur : 'cancel',
loadtype : 'GET',
loadtext : 'Loading...',
placeholder: 'Click to edit',
loaddata : {},
submitdata : {},
ajaxoptions: {}
};
})(jQuery);

View File

@ -46,7 +46,7 @@ class PostProcessor(object):
FOLDER_NAME = 2
FILE_NAME = 3
def __init__(self, nzb_name, nzb_folder, module=None):
def __init__(self, nzb_name, nzb_folder, module=None, queue=None):
"""
Creates a new post processor with the given file path and optionally an NZB name.
@ -72,10 +72,11 @@ class PostProcessor(object):
self.module = module + '[POST-PROCESSING]'
else:
self.module = '[POST-PROCESSING]'
if queue: self.queue = queue
#self.in_history = False
#self.release_group = None
#self.is_proper = False
self.valreturn = []
self.log = ''
def _log(self, message, level=logger.message): #level=logger.MESSAGE):
@ -109,7 +110,7 @@ class PostProcessor(object):
try:
p = subprocess.Popen(script_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=mylar.PROG_DIR)
out, err = p.communicate() #@UnusedVariable
self._log(u"Script result: "+str(out))
self._log(u"Script result: " + out)
except OSError, e:
self._log(u"Unable to run pre_script: " + str(script_cmd))
@ -134,7 +135,7 @@ class PostProcessor(object):
try:
p = subprocess.Popen(script_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=mylar.PROG_DIR)
out, err = p.communicate() #@UnusedVariable
self._log(u"Script result: "+str(out))
self._log(u"Script result: " + out)
except OSError, e:
self._log(u"Unable to run extra_script: " + str(script_cmd))
@ -327,7 +328,10 @@ class PostProcessor(object):
nzbiss = myDB.selectone("SELECT * from nzblog WHERE nzbname=?", [nzbname]).fetchone()
if nzbiss is None:
logger.error(module + ' Unable to locate downloaded file to rename. PostProcessing aborted.')
return
self._log('Unable to locate downloaded file to rename. PostProcessing aborted.')
self.valreturn.append({"self.log" : self.log,
"mode" : 'stop'})
return self.queue.put(self.valreturn)
else:
self._log("I corrected and found the nzb as : " + str(nzbname))
logger.fdebug(module + ' Auto-corrected and found the nzb as : ' + str(nzbname))
@ -683,7 +687,14 @@ class PostProcessor(object):
elif pcheck == "unrar error":
self._log("This is a corrupt archive - whether CRC errors or it's incomplete. Marking as BAD, and retrying a different copy.")
logger.error(module + ' This is a corrupt archive - whether CRC errors or it is incomplete. Marking as BAD, and retrying a different copy.')
return self.log
self.valreturn.append({"self.log": self.log,
"mode": 'fail',
"issueid": issueid,
"comicid": comicid,
"comicname": comicnzb['ComicName'],
"issuenumber": issuenzb['Issue_Number'],
"annchk": annchk})
return self.queue.put(self.valreturn)
else:
otofilename = pcheck
self._log("Sucessfully wrote metadata to .cbz - Continuing..")
@ -728,7 +739,7 @@ class PostProcessor(object):
#if it's a Manual Run, use the ml['ComicLocation'] for the exact filename.
if ml is None:
for root, dirnames, filenames in os.walk(self.nzb_folder):
for root, dirnames, filenames in os.walk(self.nzb_folder, followlinks=True):
for filename in filenames:
if filename.lower().endswith(extensions):
odir = root
@ -817,7 +828,10 @@ class PostProcessor(object):
self._log("Post-Processing ABORTED.")
logger.warn(module + ' Failed to move directory : ' + src + ' to ' + dst + ' - check directory and manually re-run')
logger.warn(module + ' Post-Processing ABORTED')
return
self.valreturn.append({"self.log" : self.log,
"mode" : 'stop'})
return self.queue.put(self.valreturn)
#tidyup old path
try:
shutil.rmtree(self.nzb_folder)
@ -826,8 +840,9 @@ class PostProcessor(object):
self._log("Post-Processing ABORTED.")
logger.warn(module + ' Failed to remove temporary directory : ' + self.nzb_folder)
logger.warn(module + ' Post-Processing ABORTED')
return
self.valreturn.append({"self.log" : self.log,
"mode" : 'stop'})
return self.queue.put(self.valreturn)
self._log("Removed temporary directory : " + str(self.nzb_folder))
logger.fdebug(module + ' Removed temporary directory : ' + self.nzb_folder)
else:
@ -848,7 +863,10 @@ class PostProcessor(object):
except (OSError, IOError):
logger.fdebug(module + ' Failed to move directory - check directories and manually re-run.')
logger.fdebug(module + ' Post-Processing ABORTED.')
return
self.valreturn.append({"self.log" : self.log,
"mode" : 'stop'})
return self.queue.put(self.valreturn)
logger.fdebug(module + ' Successfully moved to : ' + dst)
#tidyup old path
@ -921,7 +939,12 @@ class PostProcessor(object):
#manual run + not snatched torrent (or normal manual-run)
logger.info(module + ' Post-Processing completed for: ' + series + ' ' + dispiss )
self._log(u"Post Processing SUCCESSFUL! ")
return self.log
self.valreturn.append({"self.log" : self.log,
"mode" : 'stop',
"issueid" : issueid,
"comicid" : comicid})
return self.queue.put(self.valreturn)
if annchk == "no":
prline = series + '(' + issueyear + ') - issue #' + issuenumOG
@ -952,7 +975,15 @@ class PostProcessor(object):
logger.info(module + ' Post-Processing completed for: ' + series + ' ' + dispiss )
self._log(u"Post Processing SUCCESSFUL! ")
return self.log
self.valreturn.append({"self.log" : self.log,
"mode" : 'stop',
"issueid" : issueid,
"comicid" : comicid})
return self.queue.put(self.valreturn)
class FolderCheck():

View File

@ -24,6 +24,7 @@ import sqlite3
import itertools
import csv
import shutil
import Queue
import platform
import locale
from threading import Lock, Thread
@ -66,6 +67,7 @@ WRITELOCK = False
#WeeklyScheduler = None
#VersionScheduler = None
#FolderMonitorScheduler = None
QUEUE = Queue.Queue()
DATA_DIR = None
DBLOCK = False
@ -119,6 +121,7 @@ DESTINATION_DIR = None
CHMOD_DIR = None
CHMOD_FILE = None
USENET_RETENTION = None
CREATE_FOLDERS = True
ADD_COMICS = False
COMIC_DIR = None
@ -132,6 +135,7 @@ NZB_STARTUP_SEARCH = False
LIBRARYSCAN_INTERVAL = 300
DOWNLOAD_SCAN_INTERVAL = 5
CHECK_FOLDER = None
ENABLE_CHECK_FOLDER = False
INTERFACE = None
PREFERRED_QUALITY = 0
@ -179,6 +183,7 @@ SKIPPED2WANTED = False
CVINFO = False
LOG_LEVEL = None
POST_PROCESSING = 1
POST_PROCESSING_SCRIPT = None
NZB_DOWNLOADER = None #0 = sabnzbd, #1 = nzbget, #2 = blackhole
@ -276,6 +281,9 @@ ENABLE_RSS = 0
RSS_CHECKINTERVAL = 20
RSS_LASTRUN = None
FAILED_DOWNLOAD_HANDLING = 0
FAILED_AUTO = 0
ENABLE_TORRENTS = 0
MINSEEDS = 0
TORRENT_LOCAL = 0
@ -346,8 +354,8 @@ def initialize():
with INIT_LOCK:
global __INITIALIZED__, COMICVINE_API, DEFAULT_CVAPI, CVAPI_COUNT, CVAPI_TIME, CVAPI_MAX, FULL_PATH, PROG_DIR, VERBOSE, DAEMON, COMICSORT, DATA_DIR, CONFIG_FILE, CFG, CONFIG_VERSION, LOG_DIR, CACHE_DIR, MAX_LOGSIZE, LOGVERBOSE, OLDCONFIG_VERSION, OS_DETECT, OS_LANG, OS_ENCODING, \
HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, HTTPS_FORCE_ON, API_ENABLED, API_KEY, LAUNCH_BROWSER, GIT_PATH, SAFESTART, \
CURRENT_VERSION, LATEST_VERSION, CHECK_GITHUB, CHECK_GITHUB_ON_STARTUP, CHECK_GITHUB_INTERVAL, USER_AGENT, DESTINATION_DIR, \
queue, HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, HTTPS_FORCE_ON, API_ENABLED, API_KEY, LAUNCH_BROWSER, GIT_PATH, SAFESTART, \
CURRENT_VERSION, LATEST_VERSION, CHECK_GITHUB, CHECK_GITHUB_ON_STARTUP, CHECK_GITHUB_INTERVAL, USER_AGENT, DESTINATION_DIR, CREATE_FOLDERS, \
DOWNLOAD_DIR, USENET_RETENTION, SEARCH_INTERVAL, NZB_STARTUP_SEARCH, INTERFACE, AUTOWANT_ALL, AUTOWANT_UPCOMING, ZERO_LEVEL, ZERO_LEVEL_N, COMIC_COVER_LOCAL, HIGHCOUNT, \
LIBRARYSCAN, LIBRARYSCAN_INTERVAL, DOWNLOAD_SCAN_INTERVAL, NZB_DOWNLOADER, USE_SABNZBD, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_PRIORITY, SAB_DIRECTORY, USE_BLACKHOLE, BLACKHOLE_DIR, ADD_COMICS, COMIC_DIR, IMP_MOVE, IMP_RENAME, IMP_METADATA, \
USE_NZBGET, NZBGET_HOST, NZBGET_PORT, NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_PRIORITY, NZBGET_DIRECTORY, NZBSU, NZBSU_UID, NZBSU_APIKEY, DOGNZB, DOGNZB_UID, DOGNZB_APIKEY, \
@ -356,10 +364,10 @@ def initialize():
ENABLE_META, CMTAGGER_PATH, CT_TAG_CR, CT_TAG_CBL, CT_CBZ_OVERWRITE, INDIE_PUB, BIGGIE_PUB, IGNORE_HAVETOTAL, PROVIDER_ORDER, \
dbUpdateScheduler, searchScheduler, RSSScheduler, WeeklyScheduler, VersionScheduler, FolderMonitorScheduler, \
ENABLE_TORRENTS, MINSEEDS, TORRENT_LOCAL, LOCAL_WATCHDIR, TORRENT_SEEDBOX, SEEDBOX_HOST, SEEDBOX_PORT, SEEDBOX_USER, SEEDBOX_PASS, SEEDBOX_WATCHDIR, \
ENABLE_RSS, RSS_CHECKINTERVAL, RSS_LASTRUN, ENABLE_TORRENT_SEARCH, ENABLE_KAT, KAT_PROXY, ENABLE_CBT, CBT_PASSKEY, SNATCHEDTORRENT_NOTIFY, \
ENABLE_RSS, RSS_CHECKINTERVAL, RSS_LASTRUN, FAILED_DOWNLOAD_HANDLING, FAILED_AUTO, ENABLE_TORRENT_SEARCH, ENABLE_KAT, KAT_PROXY, ENABLE_CBT, CBT_PASSKEY, SNATCHEDTORRENT_NOTIFY, \
PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, NMA_ENABLED, NMA_APIKEY, NMA_PRIORITY, NMA_ONSNATCH, PUSHOVER_ENABLED, PUSHOVER_PRIORITY, PUSHOVER_APIKEY, PUSHOVER_USERKEY, PUSHOVER_ONSNATCH, BOXCAR_ENABLED, BOXCAR_ONSNATCH, BOXCAR_TOKEN, \
PUSHBULLET_ENABLED, PUSHBULLET_APIKEY, PUSHBULLET_DEVICEID, PUSHBULLET_ONSNATCH, LOCMOVE, NEWCOM_DIR, FFTONEWCOM_DIR, \
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, SEARCH_DELAY, GRABBAG_DIR, READ2FILENAME, STORYARCDIR, CVURL, CVAPIFIX, CHECK_FOLDER, \
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, POST_PROCESSING_SCRIPT, SEARCH_DELAY, GRABBAG_DIR, READ2FILENAME, STORYARCDIR, CVURL, CVAPIFIX, CHECK_FOLDER, ENABLE_CHECK_FOLDER, \
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, SYNO_FIX, CHMOD_FILE, CHMOD_DIR, ANNUALS_ON, CV_ONLY, CV_ONETIMER, WEEKFOLDER, UMASK
if __INITIALIZED__:
@ -417,6 +425,7 @@ def initialize():
CHECK_GITHUB_INTERVAL = check_setting_int(CFG, 'General', 'check_github_interval', 360)
DESTINATION_DIR = check_setting_str(CFG, 'General', 'destination_dir', '')
CREATE_FOLDERS = bool(check_setting_int(CFG, 'General', 'create_folders', 1))
CHMOD_DIR = check_setting_str(CFG, 'General', 'chmod_dir', '0777')
CHMOD_FILE = check_setting_str(CFG, 'General', 'chmod_file', '0660')
USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', '1500')
@ -432,6 +441,7 @@ def initialize():
IMP_METADATA = bool(check_setting_int(CFG, 'General', 'imp_metadata', 0))
DOWNLOAD_SCAN_INTERVAL = check_setting_int(CFG, 'General', 'download_scan_interval', 5)
CHECK_FOLDER = check_setting_str(CFG, 'General', 'check_folder', '')
ENABLE_CHECK_FOLDER = bool(check_setting_int(CFG, 'General', 'enable_check_folder', 0))
INTERFACE = check_setting_str(CFG, 'General', 'interface', 'default')
AUTOWANT_ALL = bool(check_setting_int(CFG, 'General', 'autowant_all', 0))
AUTOWANT_UPCOMING = bool(check_setting_int(CFG, 'General', 'autowant_upcoming', 1))
@ -520,6 +530,7 @@ def initialize():
ENABLE_PRE_SCRIPTS = bool(check_setting_int(CFG, 'General', 'enable_pre_scripts', 0))
PRE_SCRIPTS = check_setting_str(CFG, 'General', 'pre_scripts', '')
POST_PROCESSING = bool(check_setting_int(CFG, 'General', 'post_processing', 1))
POST_PROCESSING_SCRIPT = check_setting_str(CFG, 'General', 'post_processing_script', '')
ENABLE_META = bool(check_setting_int(CFG, 'General', 'enable_meta', 0))
CMTAGGER_PATH = check_setting_str(CFG, 'General', 'cmtagger_path', '')
@ -534,6 +545,8 @@ def initialize():
RSS_CHECKINTERVAL = check_setting_str(CFG, 'General', 'rss_checkinterval', '20')
RSS_LASTRUN = check_setting_str(CFG, 'General', 'rss_lastrun', '')
FAILED_DOWNLOAD_HANDLING = bool(check_setting_int(CFG, 'General', 'failed_download_handling', 0))
FAILED_AUTO = bool(check_setting_int(CFG, 'General', 'failed_auto', 0))
ENABLE_TORRENTS = bool(check_setting_int(CFG, 'Torrents', 'enable_torrents', 0))
MINSEEDS = check_setting_str(CFG, 'Torrents', 'minseeds', '0')
TORRENT_LOCAL = bool(check_setting_int(CFG, 'Torrents', 'torrent_local', 0))
@ -594,12 +607,13 @@ def initialize():
PR = []
#add torrents to provider counter.
if ENABLE_CBT:
PR.append('cbt')
PR_NUM +=1
if ENABLE_KAT:
PR.append('kat')
PR_NUM +=1
if ENABLE_TORRENT_SEARCH:
if ENABLE_CBT:
PR.append('cbt')
PR_NUM +=1
if ENABLE_KAT:
PR.append('kat')
PR_NUM +=1
NZBSU = bool(check_setting_int(CFG, 'NZBsu', 'nzbsu', 0))
@ -720,19 +734,20 @@ def initialize():
TMPPR_NUM +=1
if PR_NUM != TMPPR_NUM:
#print 'existing Order count does not match New Order count'
if PR_NUM > TMPPR_NUM:
#print 'New entries exist, appending to end as default ordering'
TMPPR_NUM = 0
while (TMPPR_NUM < PR_NUM):
#print 'checking entry #' + str(TMPPR_NUM) + ': ' + str(PR[TMPPR_NUM])
if not any(d.get("provider",None) == str(PR[TMPPR_NUM]) for d in PROV_ORDER):
#print 'new provider should be : ' + str(TMPPR_NUM) + ' -- ' + str(PR[TMPPR_NUM])
PROV_ORDER.append({"order_seq": TMPPR_NUM,
"provider": str(PR[TMPPR_NUM])})
# print 'existing Order count does not match New Order count'
# if PR_NUM > TMPPR_NUM:
# print 'New entries exist, appending to end as default ordering'
TMPPR_NUM = 0
while (TMPPR_NUM < PR_NUM):
#print 'checking entry #' + str(TMPPR_NUM) + ': ' + str(PR[TMPPR_NUM])
if not any(d.get("provider",None) == str(PR[TMPPR_NUM]) for d in PROV_ORDER):
new_order_seqnum = len(PROV_ORDER)
#print 'new provider should be : ' + str(new_order_seqnum) + ' -- ' + str(PR[TMPPR_NUM])
PROV_ORDER.append({"order_seq": new_order_seqnum,
"provider": str(PR[TMPPR_NUM])})
#else:
#print 'provider already exists at : ' + str(TMPPR_NUM) + ' -- ' + str(PR[TMPPR_NUM])
TMPPR_NUM +=1
#print 'provider already exists at : ' + str(new_order_seqnum) + ' -- ' + str(PR[TMPPR_NUM])
TMPPR_NUM +=1
#this isn't ready for primetime just yet...
@ -1052,6 +1067,7 @@ def config_write():
new_config['General']['check_github_interval'] = CHECK_GITHUB_INTERVAL
new_config['General']['destination_dir'] = DESTINATION_DIR
new_config['General']['create_folders'] = int(CREATE_FOLDERS)
new_config['General']['chmod_dir'] = CHMOD_DIR
new_config['General']['chmod_file'] = CHMOD_FILE
new_config['General']['usenet_retention'] = USENET_RETENTION
@ -1065,6 +1081,7 @@ def config_write():
new_config['General']['imp_move'] = int(IMP_MOVE)
new_config['General']['imp_rename'] = int(IMP_RENAME)
new_config['General']['imp_metadata'] = int(IMP_METADATA)
new_config['General']['enable_check_folder'] = int(ENABLE_CHECK_FOLDER)
new_config['General']['download_scan_interval'] = DOWNLOAD_SCAN_INTERVAL
new_config['General']['check_folder'] = CHECK_FOLDER
new_config['General']['interface'] = INTERFACE
@ -1103,6 +1120,7 @@ def config_write():
new_config['General']['enable_pre_scripts'] = int(ENABLE_PRE_SCRIPTS)
new_config['General']['pre_scripts'] = PRE_SCRIPTS
new_config['General']['post_processing'] = int(POST_PROCESSING)
new_config['General']['post_processing_script'] = POST_PROCESSING_SCRIPT
new_config['General']['weekfolder'] = int(WEEKFOLDER)
new_config['General']['locmove'] = int(LOCMOVE)
new_config['General']['newcom_dir'] = NEWCOM_DIR
@ -1118,6 +1136,8 @@ def config_write():
new_config['General']['enable_rss'] = int(ENABLE_RSS)
new_config['General']['rss_checkinterval'] = RSS_CHECKINTERVAL
new_config['General']['rss_lastrun'] = RSS_LASTRUN
new_config['General']['failed_download_handling'] = int(FAILED_DOWNLOAD_HANDLING)
new_config['General']['failed_auto'] = int(FAILED_AUTO)
# Need to unpack the providers for saving in config.ini
if PROVIDER_ORDER is None:
@ -1290,8 +1310,7 @@ def start():
SCHED.add_interval_job(versioncheck.checkGithub, minutes=CHECK_GITHUB_INTERVAL)
#run checkFolder every X minutes (basically Manual Run Post-Processing)
logger.info('Monitor folder set to : ' + str(CHECK_FOLDER))
if CHECK_FOLDER:
if ENABLE_CHECK_FOLDER:
if DOWNLOAD_SCAN_INTERVAL >0:
logger.info('Enabling folder monitor for : ' + str(CHECK_FOLDER) + ' every ' + str(DOWNLOAD_SCAN_INTERVAL) + ' minutes.')
#FolderMonitorScheduler.thread.start()
@ -1307,19 +1326,20 @@ def dbcheck():
conn=sqlite3.connect(DB_FILE)
c=conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS comics (ComicID TEXT UNIQUE, ComicName TEXT, ComicSortName TEXT, ComicYear TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, Have INTEGER, Total INTEGER, ComicImage TEXT, ComicPublisher TEXT, ComicLocation TEXT, ComicPublished TEXT, LatestIssue TEXT, LatestDate TEXT, Description TEXT, QUALalt_vers TEXT, QUALtype TEXT, QUALscanner TEXT, QUALquality TEXT, LastUpdated TEXT, AlternateSearch TEXT, UseFuzzy TEXT, ComicVersion TEXT, SortOrder INTEGER, ForceContinuing INTEGER)')
c.execute('CREATE TABLE IF NOT EXISTS issues (IssueID TEXT, ComicName TEXT, IssueName TEXT, Issue_Number TEXT, DateAdded TEXT, Status TEXT, Type TEXT, ComicID, ArtworkURL Text, ReleaseDate TEXT, Location TEXT, IssueDate TEXT, Int_IssueNumber INT, ComicSize TEXT, AltIssueNumber TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS comics (ComicID TEXT UNIQUE, ComicName TEXT, ComicSortName TEXT, ComicYear TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, Have INTEGER, Total INTEGER, ComicImage TEXT, ComicPublisher TEXT, ComicLocation TEXT, ComicPublished TEXT, LatestIssue TEXT, LatestDate TEXT, Description TEXT, QUALalt_vers TEXT, QUALtype TEXT, QUALscanner TEXT, QUALquality TEXT, LastUpdated TEXT, AlternateSearch TEXT, UseFuzzy TEXT, ComicVersion TEXT, SortOrder INTEGER, ForceContinuing INTEGER, ComicName_Filesafe TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS issues (IssueID TEXT, ComicName TEXT, IssueName TEXT, Issue_Number TEXT, DateAdded TEXT, Status TEXT, Type TEXT, ComicID, ArtworkURL Text, ReleaseDate TEXT, Location TEXT, IssueDate TEXT, Int_IssueNumber INT, ComicSize TEXT, AltIssueNumber TEXT, IssueDate_Edit TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS snatched (IssueID TEXT, ComicName TEXT, Issue_Number TEXT, Size INTEGER, DateAdded TEXT, Status TEXT, FolderName TEXT, ComicID TEXT, Provider TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS upcoming (ComicName TEXT, IssueNumber TEXT, ComicID TEXT, IssueID TEXT, IssueDate TEXT, Status TEXT, DisplayComicName TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS nzblog (IssueID TEXT, NZBName TEXT, SARC TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS nzblog (IssueID TEXT, NZBName TEXT, SARC TEXT, PROVIDER TEXT, ID TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS weekly (SHIPDATE text, PUBLISHER text, ISSUE text, COMIC VARCHAR(150), EXTRA text, STATUS text)')
# c.execute('CREATE TABLE IF NOT EXISTS sablog (nzo_id TEXT, ComicName TEXT, ComicYEAR TEXT, ComicIssue TEXT, name TEXT, nzo_complete TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS importresults (impID TEXT, ComicName TEXT, ComicYear TEXT, Status TEXT, ImportDate TEXT, ComicFilename TEXT, ComicLocation TEXT, WatchMatch TEXT, DisplayName TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS readlist (IssueID TEXT, ComicName TEXT, Issue_Number TEXT, Status TEXT, DateAdded TEXT, Location TEXT, inCacheDir TEXT, SeriesYear TEXT, ComicID TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS readinglist(StoryArcID TEXT, ComicName TEXT, IssueNumber TEXT, SeriesYear TEXT, IssueYEAR TEXT, StoryArc TEXT, TotalIssues TEXT, Status TEXT, inCacheDir TEXT, Location TEXT, IssueArcID TEXT, ReadingOrder INT, IssueID TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS annuals (IssueID TEXT, Issue_Number TEXT, IssueName TEXT, IssueDate TEXT, Status TEXT, ComicID TEXT, GCDComicID TEXT, Location TEXT, ComicSize TEXT, Int_IssueNumber INT, ComicName TEXT, ReleaseDate TEXT, ReleaseComicID TEXT, ReleaseComicName TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS annuals (IssueID TEXT, Issue_Number TEXT, IssueName TEXT, IssueDate TEXT, Status TEXT, ComicID TEXT, GCDComicID TEXT, Location TEXT, ComicSize TEXT, Int_IssueNumber INT, ComicName TEXT, ReleaseDate TEXT, ReleaseComicID TEXT, ReleaseComicName TEXT, IssueDate_Edit TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS rssdb (Title TEXT UNIQUE, Link TEXT, Pubdate TEXT, Site TEXT, Size TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS futureupcoming (ComicName TEXT, IssueNumber TEXT, ComicID TEXT, IssueID TEXT, IssueDate TEXT, Publisher TEXT, Status TEXT, DisplayComicName TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS failed (ID TEXT, Status TEXT, ComicID TEXT, IssueID TEXT, Provider TEXT, ComicName TEXT, Issue_Number TEXT, NZBName TEXT)')
conn.commit
c.close
#new
@ -1450,6 +1470,16 @@ def dbcheck():
except:
c.execute('ALTER TABLE nzblog ADD COLUMN SARC TEXT')
try:
c.execute('SELECT PROVIDER from nzblog')
except:
c.execute('ALTER TABLE nzblog ADD COLUMN PROVIDER TEXT')
try:
c.execute('SELECT ID from nzblog')
except:
c.execute('ALTER TABLE nzblog ADD COLUMN ID TEXT')
try:
c.execute('SELECT Location from annuals')
except:
@ -1516,6 +1546,20 @@ def dbcheck():
except:
c.execute('ALTER TABLE importresults ADD COLUMN DisplayName TEXT')
try:
c.execute('SELECT ComicName_Filesafe from comics')
except:
c.execute('ALTER TABLE comics ADD COLUMN ComicName_Filesafe TEXT')
try:
c.execute('SELECT IssueDate_Edit from issues')
except:
c.execute('ALTER TABLE issues ADD COLUMN IssueDate_Edit TEXT')
try:
c.execute('SELECT IssueDate_Edit from annuals')
except:
c.execute('ALTER TABLE annuals ADD COLUMN IssueDate_Edit TEXT')
#if it's prior to Wednesday, the issue counts will be inflated by one as the online db's everywhere
#prepare for the next 'new' release of a series. It's caught in updater.py, so let's just store the

View File

@ -52,7 +52,7 @@ def pulldetails(comicid,type,issueid=None,offset=1):
#this is used ONLY for CV_ONLY
PULLURL = mylar.CVURL + 'issues/?api_key=' + str(comicapi) + '&format=xml&filter=id:' + str(issueid) + '&field_list=cover_date'
elif type == 'storyarc':
PULLURL = mylar.CVURL + 'story_arc/?api_key=' + str(comicapi) + '&format=xml&filter=id:' + str(issueid) + '&field_list=cover_date'
PULLURL = mylar.CVURL + 'story_arcs/?api_key=' + str(comicapi) + '&format=xml&filter=name:' + str(issueid) + '&field_list=cover_date'
#CV API Check here.
if mylar.CVAPI_COUNT == 0 or mylar.CVAPI_COUNT >= mylar.CVAPI_MAX:
@ -71,7 +71,7 @@ def pulldetails(comicid,type,issueid=None,offset=1):
return dom
def getComic(comicid,type,issueid=None):
def getComic(comicid,type,issueid=None,arc=None):
if type == 'issue':
offset = 1
issue = {}
@ -111,6 +111,9 @@ def getComic(comicid,type,issueid=None):
elif type == 'firstissue':
dom = pulldetails(comicid,'firstissue',issueid,1)
return GetFirstIssue(issueid,dom)
elif type == 'storyarc':
dom = pulldetails(arc,'storyarc',None,1)
return GetComicInfo(issueid,dom)
def GetComicInfo(comicid,dom):
@ -333,7 +336,10 @@ def GetIssuesInfo(comicid,dom):
tempissue['StoreDate'] = subtrack.getElementsByTagName('store_date')[0].firstChild.wholeText
except:
tempissue['StoreDate'] = '0000-00-00'
tempissue['Issue_Number'] = subtrack.getElementsByTagName('issue_number')[0].firstChild.wholeText
try:
tempissue['Issue_Number'] = subtrack.getElementsByTagName('issue_number')[0].firstChild.wholeText
except:
logger.fdebug('No Issue Number available - Trade Paperbacks, Graphic Novels and Compendiums are not supported as of yet.')
issuech.append({
'Comic_ID': comicid,
'Issue_ID': tempissue['Issue_ID'],

View File

@ -129,8 +129,10 @@ def listFiles(dir,watchcomic,Publisher,AlternateSearch=None,manual=None,sarc=Non
#check if a year is present in series title (ie. spider-man 2099)
#also check if decimal present in series title (ie. batman beyond 2.0)
#- check if brackets present in series title
numberinseries = 'False'
decimalinseries = 'False'
bracketsinseries = 'False'
for i in watchcomic.split():
if ('20' in i or '19' in i):
@ -154,11 +156,29 @@ def listFiles(dir,watchcomic,Publisher,AlternateSearch=None,manual=None,sarc=Non
logger.fdebug('[FILECHECKER] std is : ' + str(std))
except:
pass
#logger.fdebug('[FILECHECKER] i : ' + str(i))
if ('(' in i):
bracketsinseries = 'True'
bracket_length_st = watchcomic.find('(')
bracket_length_en = watchcomic.find(')', bracket_length_st)
bracket_length = bracket_length_en - bracket_length_st
bracket_word = watchcomic[bracket_length_st:bracket_length_en]
logger.fdebug('[FILECHECKER] bracketinseries: ' + str(bracket_word))
logger.fdebug('[FILECHECKER] numberinseries: ' + str(numberinseries))
logger.fdebug('[FILECHECKER] decimalinseries: ' + str(decimalinseries))
logger.fdebug('[FILECHECKER] bracketinseries: ' + str(bracketsinseries))
#remove the brackets..
if bracketsinseries == 'True':
logger.fdebug('[FILECHECKER] modifying subname to accomodate brackets within series title.')
subnm_mod2 = re.findall('[^()]+', subname[bracket_length_en:])
logger.fdebug('[FILECHECKER] subnm_mod : ' + str(subnm_mod2))
subnm_mod = re.sub('[\(\)]',' ', subname[:bracket_length_en]) + str(subname[bracket_length_en+1:])
logger.fdebug('[FILECHECKER] modified subname is now : ' + str(subnm_mod))
subname = subnm_mod
subnm = re.findall('[^()]+', subname)
logger.fdebug('[FILECHECKER] subnm len : ' + str(len(subnm)))
if len(subnm) == 1:
@ -196,6 +216,26 @@ def listFiles(dir,watchcomic,Publisher,AlternateSearch=None,manual=None,sarc=Non
subname = re.sub('[\.]', '', subname)
subnm = re.findall('[^()]+', subname)
else:
if numberinseries == 'True' or decimalinseries == 'True':
#we need to remove the series from the subname and then search the remainder.
watchname = re.sub('[\:\;\!\'\/\?\+\=\_\%\.]', '', watchcomic) #remove spec chars for watchcomic match.
logger.fdebug('[FILECHECKER] watch-cleaned: ' + watchname)
subthis = re.sub('.cbr', '', subname)
subthis = re.sub('.cbz', '', subthis)
subthis = re.sub('[\:\;\!\'\/\?\+\=\_\%\.]', '', subthis)
logger.fdebug('[FILECHECKER] sub-cleaned: ' + subthis)
#we need to make sure the file is part of the correct series or else will match falsely
if watchname not in subthis:
logger.fdebug('[FILECHECKER] this is a false match. Ignoring this result.')
continue
subthis = subthis[len(watchname):] #remove watchcomic
#we need to now check the remainder of the string for digits assuming it's a possible year
logger.fdebug('[FILECHECKER] new subname: ' + str(subthis))
subname = re.sub('(.*)[\s+|_+](19\d{2}|20\d{2})(.*)', '\\1 (\\2) \\3', subthis)
subname = watchname + subname
subnm = re.findall('[^()]+', subname)
subsplit = subname.replace('_', ' ').split()
@ -320,10 +360,12 @@ def listFiles(dir,watchcomic,Publisher,AlternateSearch=None,manual=None,sarc=Non
nonocount = nonocount + subcnt + blspc
#subname = re.sub('[\_\#\,\/\:\;\.\-\!\$\%\+\'\?\@]',' ', subname)
if decimalinseries == 'True':
modwatchcomic = re.sub('[\_\#\,\/\:\;\!\$\%\'\?\@]', ' ', u_watchcomic)
modwatchcomic = re.sub('[\_\#\,\/\:\;\!\$\%\?\@]', ' ', u_watchcomic)
else:
modwatchcomic = re.sub('[\_\#\,\/\:\;\.\!\$\%\'\?\@]', ' ', u_watchcomic)
modwatchcomic = re.sub('[\-]', '', modwatchcomic) #trying this too - 2014-03-01
modwatchcomic = re.sub('[\_\#\,\/\:\;\.\!\$\%\?\@]', ' ', u_watchcomic)
if bracketsinseries == 'True':
modwatchcomic = re.sub('[\(\)]', ' ', modwatchcomic)
modwatchcomic = re.sub('[\-\']', '', modwatchcomic) #trying this too - 2014-03-01
#if leavehyphen == False:
# logger.fdebug('[FILECHECKER] ('removing hyphen for comparisons')
# modwatchcomic = re.sub('-', ' ', modwatchcomic)
@ -346,18 +388,38 @@ def listFiles(dir,watchcomic,Publisher,AlternateSearch=None,manual=None,sarc=Non
subname = re.sub('\s+', ' ', str(subname)).strip()
AS_Alt = []
AS_Tuple = []
if AlternateSearch is not None:
chkthealt = AlternateSearch.split('##')
if chkthealt == 0:
AS_Alternate = AlternateSearch
for calt in chkthealt:
AS_tupled = False
AS_Alternate = re.sub('##','',calt)
if '!!' in AS_Alternate:
# if it's !! present, it's the comicid associated with the series as an added annual.
# extract the !!, store it and then remove it so things will continue.
as_start = AS_Alternate.find('!!')
logger.fdebug('as_start: ' + str(as_start) + ' --- ' + str(AS_Alternate[as_start:]))
as_end = AS_Alternate.find('##', as_start)
if as_end == -1: as_end = len(AS_Alternate)
logger.fdebug('as_start: ' + str(as_end) + ' --- ' + str(AS_Alternate[as_start:as_end]))
AS_ComicID = AS_Alternate[as_start+2:as_end]
logger.fdebug('[FILECHECKER] Extracted comicid for given annual : ' + str(AS_ComicID))
AS_Alternate = re.sub('!!' + str(AS_ComicID), '', AS_Alternate)
AS_tupled = True
#same = encode.
u_altsearchcomic = AS_Alternate.encode('ascii', 'ignore').strip()
altsearchcomic = re.sub('[\_\#\,\/\:\;\.\!\$\%\+\'\?\@]', ' ', u_altsearchcomic)
altsearchcomic = re.sub('[\-]', ' ', altsearchcomic) #because this is a watchcomic registered, use same algorithim for watchcomic
altsearchcomic = re.sub('[\_\#\,\/\:\;\.\!\$\%\+\?\@]', ' ', u_altsearchcomic)
altsearchcomic = re.sub('[\-\']', '', altsearchcomic) #because this is a watchcomic registered, use same algorithim for watchcomic
altsearchcomic = re.sub('\&', ' and ', altsearchcomic)
altsearchcomic = re.sub('\s+', ' ', str(altsearchcomic)).strip()
if detectthe_sub == True:
altsearchcomic = re.sub("\\bthe\\b", "", altsearchcomic.lower())
altsearchcomic = re.sub('\s+', ' ', str(altsearchcomic)).strip()
if AS_tupled:
AS_Tuple.append({"ComicID": AS_ComicID,
"AS_Alternate": altsearchcomic})
AS_Alt.append(altsearchcomic)
else:
#create random characters so it will never match.
@ -365,421 +427,428 @@ def listFiles(dir,watchcomic,Publisher,AlternateSearch=None,manual=None,sarc=Non
AS_Alt.append(altsearchcomic)
#if '_' in subname:
# subname = subname.replace('_', ' ')
logger.fdebug('[FILECHECKER] AS_Alt : ' + str(AS_Alt))
logger.fdebug('[FILECHECKER] watchcomic:' + str(modwatchcomic) + ' ..comparing to found file: ' + str(subname))
if modwatchcomic.lower() in subname.lower() or any(x.lower() in subname.lower() for x in AS_Alt):#altsearchcomic.lower() in subname.lower():
comicpath = os.path.join(basedir, item)
logger.fdebug('[FILECHECKER] ' + modwatchcomic + ' - watchlist match on : ' + comicpath)
comicsize = os.path.getsize(comicpath)
#print ("Comicsize:" + str(comicsize))
comiccnt+=1
if modwatchcomic.lower() in subname.lower() or any(x.lower() in subname.lower() for x in AS_Alt):
#if the alternate search name is almost identical, it won't match up because it will hit the 'normal' first.
#not important for series' matches, but for annuals, etc it is very important.
#loop through the Alternates picking out the ones that match and then do an overall loop.
enable_annual = False
loopchk = [x for x in AS_Alt if x.lower() in subname.lower()]
if len(loopchk) > 0 and loopchk[0] != '':
logger.fdebug('[FILECHECKER] This should be an alternate: ' + str(loopchk))
if 'annual' in subname.lower():
logger.fdebug('[FILECHECKER] Annual detected - proceeding')
enable_annual = True
stann = 0
if 'annual' in subname.lower():
logger.fdebug('[FILECHECKER] Annual detected - proceeding')
jtd_len = subname.lower().find('annual')
cchk = modwatchcomic
else:
if modwatchcomic.lower() in subname.lower():
cchk = modwatchcomic
else:
cchk_ls = [x for x in AS_Alt if x.lower() in subname.lower()]
cchk = cchk_ls[0]
#print "something: " + str(cchk)
loopchk = []
if modwatchcomic.lower() in subname.lower() and enable_annual == False:
loopchk.append(modwatchcomic)
if 'annual' in subname.lower():
logger.fdebug('[FILECHECKER] Annual detected - proceeding cautiously.')
enable_annual = False
jtd_len = subname.lower().find('annual')
logger.fdebug('[FILECHECKER] Complete matching list of names to this file [' + str(len(loopchk)) + '] : ' + str(loopchk))
for loopit in loopchk:
modwatchcomic = loopit
logger.fdebug('[FILECHECKER] AS_Tuple : ' + str(AS_Tuple))
annual_comicid = None
for ATS in AS_Tuple:
logger.fdebug('[FILECHECKER] ' + str(ATS['AS_Alternate']) + ' comparing to ' + str(modwatchcomic))
if ATS['AS_Alternate'] == modwatchcomic:
logger.fdebug('[FILECHECKER] Associating ComiciD : ' + str(ATS['ComicID']))
annual_comicid = str(ATS['ComicID'])
break
comicpath = os.path.join(basedir, item)
logger.fdebug('[FILECHECKER] ' + modwatchcomic + ' - watchlist match on : ' + comicpath)
comicsize = os.path.getsize(comicpath)
#print ("Comicsize:" + str(comicsize))
comiccnt+=1
stann = 0
cchk = modwatchcomic
#else:
#if modwatchcomic.lower() in subname.lower():
# cchk = modwatchcomic
#else:
# cchk_ls = [x for x in AS_Alt if x.lower() in subname.lower()]
# cchk = cchk_ls[0]
logger.fdebug('[FILECHECKER] cchk is : ' + str(cchk))
logger.fdebug('[FILECHECKER] we should remove ' + str(nonocount) + ' characters')
findtitlepos = subname.find('-')
if charpos != 0:
logger.fdebug('[FILECHECKER] detected ' + str(len(charpos)) + ' special characters')
i=0
while (i < len(charpos)):
for i,j in enumerate(charpos):
#logger.fdebug('i,j:' + str(i) + ',' + str(j))
#logger.fdebug(str(len(subname)) + ' - subname: ' + subname)
#logger.fdebug("digitchk: " + str(subname[j:]))
if j >= len(subname):
logger.fdebug('[FILECHECKER] end reached. ignoring remainder.')
break
elif subname[j:] == '-':
if j <= len(subname) and subname[j+1].isdigit():
logger.fdebug('[FILECHECKER] negative issue detected.')
#detneg = "yes"
elif j > findtitlepos:
if subname[j:] == '#':
if subname[j+1].isdigit():
logger.fdebug('[FILECHECKER] # detected denoting issue#, ignoring.')
else:
nonocount-=1
elif '-' in watchcomic and j < len(watchcomic):
logger.fdebug('[FILECHECKER] - appears in series title, ignoring.')
else:
logger.fdebug('[FILECHECKER] special character appears outside of title - ignoring @ position: ' + str(charpos[i]))
nonocount-=1
i+=1
for i,j in enumerate(charpos):
logger.fdebug('i,j:' + str(i) + ',' + str(j))
logger.fdebug(str(len(subname)) + ' - subname: ' + subname)
logger.fdebug("digitchk: " + str(subname[j:]))
if j >= len(subname):
logger.fdebug('[FILECHECKER] ' + str(j) + ' is >= ' + str(len(subname)) + ' .End reached. ignoring remainder.')
break
elif subname[j:] == '-':
if j <= len(subname) and subname[j+1].isdigit():
logger.fdebug('[FILECHECKER] negative issue detected.')
#detneg = "yes"
elif j > findtitlepos:
if subname[j:] == '#':
if subname[j+1].isdigit():
logger.fdebug('[FILECHECKER] # detected denoting issue#, ignoring.')
else:
nonocount-=1
elif ('-' in watchcomic or '.' in watchcomic) and j < len(watchcomic):
logger.fdebug('[FILECHECKER] - appears in series title, ignoring.')
else:
logger.fdebug('[FILECHECKER] special character appears outside of title - ignoring @ position: ' + str(charpos[i]))
nonocount-=1
#remove versioning here
if volrem != None:
jtd_len = len(cchk)# + len(volrem)# + nonocount + 1 #1 is to account for space btwn comic and vol #
else:
jtd_len = len(cchk)# + nonocount
#remove versioning here
if volrem != None:
jtd_len = len(cchk)# + len(volrem)# + nonocount + 1 #1 is to account for space btwn comic and vol #
else:
jtd_len = len(cchk)# + nonocount
if sarc and mylar.READ2FILENAME:
removest = subname.find(' ') # the - gets removed above so we test for the first blank space...
if subname[:removest].isdigit():
jtd_len += removest + 1 # +1 to account for space in place of -
logger.fdebug('[FILECHECKER] adjusted jtd_len to : ' + str(removest) + ' because of story-arc reading order tags')
if sarc and mylar.READ2FILENAME:
removest = subname.find(' ') # the - gets removed above so we test for the first blank space...
if subname[:removest].isdigit():
jtd_len += removest + 1 # +1 to account for space in place of -
logger.fdebug('[FILECHECKER] adjusted jtd_len to : ' + str(removest) + ' because of story-arc reading order tags')
logger.fdebug('[FILECHECKER] nonocount [' + str(nonocount) + '] cchk [' + cchk + '] length [' + str(len(cchk)) + ']')
logger.fdebug('[FILECHECKER] nonocount [' + str(nonocount) + '] cchk [' + cchk + '] length [' + str(len(cchk)) + ']')
#if detectand:
# jtd_len = jtd_len - 2 # char substitution diff between & and 'and' = 2 chars
#if detectthe_mod == True and detectthe_sub == False:
#jtd_len = jtd_len - 3 # char subsitiution diff between 'the' and '' = 3 chars
#if detectand:
# jtd_len = jtd_len - 2 # char substitution diff between & and 'and' = 2 chars
#if detectthe_mod == True and detectthe_sub == False:
#jtd_len = jtd_len - 3 # char subsitiution diff between 'the' and '' = 3 chars
#justthedigits = item[jtd_len:]
#justthedigits = item[jtd_len:]
logger.fdebug('[FILECHECKER] final jtd_len to prune [' + str(jtd_len) + ']')
logger.fdebug('[FILECHECKER] before title removed from FILENAME [' + str(item) + ']')
logger.fdebug('[FILECHECKER] after title removed from FILENAME [' + str(item[jtd_len:]) + ']')
logger.fdebug('[FILECHECKER] creating just the digits using SUBNAME, pruning first [' + str(jtd_len) + '] chars from [' + subname + ']')
logger.fdebug('[FILECHECKER] final jtd_len to prune [' + str(jtd_len) + ']')
logger.fdebug('[FILECHECKER] before title removed from FILENAME [' + str(item) + ']')
logger.fdebug('[FILECHECKER] after title removed from FILENAME [' + str(item[jtd_len:]) + ']')
logger.fdebug('[FILECHECKER] creating just the digits using SUBNAME, pruning first [' + str(jtd_len) + '] chars from [' + subname + ']')
justthedigits_1 = subname[jtd_len:].strip()
justthedigits_1 = subname[jtd_len:].strip()
logger.fdebug('[FILECHECKER] after title removed from SUBNAME [' + justthedigits_1 + ']')
if enable_annual: justthedigits_1 = 'Annual ' + str(justthedigits_1)
logger.fdebug('[FILECHECKER] after title removed from SUBNAME [' + justthedigits_1 + ']')
#remove the title if it appears
#findtitle = justthedigits.find('-')
#if findtitle > 0 and detneg == "no":
# justthedigits = justthedigits[:findtitle]
# logger.fdebug('[FILECHECKER] ("removed title from name - is now : " + str(justthedigits))
#remove the title if it appears
#findtitle = justthedigits.find('-')
#if findtitle > 0 and detneg == "no":
# justthedigits = justthedigits[:findtitle]
# logger.fdebug('[FILECHECKER] ("removed title from name - is now : " + str(justthedigits))
justthedigits = justthedigits_1.split(' ', 1)[0]
justthedigits = justthedigits_1.split(' ', 1)[0]
digitsvalid = "false"
for jdc in list(justthedigits):
#logger.fdebug('[FILECHECKER] ('jdc:' + str(jdc))
if not jdc.isdigit():
#logger.fdebug('[FILECHECKER] ('alpha')
jdc_start = justthedigits.find(jdc)
alpha_isschk = justthedigits[jdc_start:]
#logger.fdebug('[FILECHECKER] ('alpha_isschk:' + str(alpha_isschk))
for issexcept in issue_exceptions:
if issexcept.lower() in alpha_isschk.lower() and len(alpha_isschk) <= len(issexcept):
logger.fdebug('[FILECHECKER] ALPHANUMERIC EXCEPTION : [' + justthedigits + ']')
digitsvalid = "true"
break
if digitsvalid == "true": break
try:
tmpthedigits = justthedigits_1.split(' ', 1)[1]
logger.fdebug('[FILECHECKER] If the series has a decimal, this should be a number [' + tmpthedigits + ']')
if 'cbr' in tmpthedigits.lower() or 'cbz' in tmpthedigits.lower():
tmpthedigits = tmpthedigits[:-3].strip()
logger.fdebug('[FILECHECKER] Removed extension - now we should just have a number [' + tmpthedigits + ']')
poss_alpha = tmpthedigits
if poss_alpha.isdigit():
digitsvalid = "true"
if justthedigits.lower() == 'annual':
logger.fdebug('[FILECHECKER] ANNUAL DETECTED [' + poss_alpha + ']')
justthedigits += ' ' + poss_alpha
else:
justthedigits += '.' + poss_alpha
logger.fdebug('[FILECHECKER] DECIMAL ISSUE DETECTED [' + justthedigits + ']')
else:
for issexcept in issue_exceptions:
decimalexcept = False
if '.' in issexcept:
decimalexcept = True
issexcept = issexcept[1:] #remove the '.' from comparison...
if issexcept.lower() in poss_alpha.lower() and len(poss_alpha) <= len(issexcept):
if decimalexcept:
issexcept = '.' + issexcept
justthedigits += issexcept #poss_alpha
logger.fdebug('[FILECHECKER] ALPHANUMERIC EXCEPTION. COMBINING : [' + justthedigits + ']')
digitsvalid = "true"
break
except:
tmpthedigits = None
# justthedigits = justthedigits.split(' ', 1)[0]
#if the issue has an alphanumeric (issue_exceptions, join it and push it through)
logger.fdebug('[FILECHECKER] JUSTTHEDIGITS [' + justthedigits + ']' )
if digitsvalid == "true":
pass
else:
if justthedigits.isdigit():
digitsvalid = "true"
else:
if '.' in justthedigits:
tmpdec = justthedigits.find('.')
b4dec = justthedigits[:tmpdec]
a4dec = justthedigits[tmpdec+1:]
if a4dec.isdigit() and b4dec.isdigit():
logger.fdebug('[FILECHECKER] DECIMAL ISSUE DETECTED')
digitsvalid = "true"
else:
try:
x = float(justthedigits)
#validity check
if x < 0:
logger.fdebug("I've encountered a negative issue #: " + str(justthedigits) + ". Trying to accomodate.")
digitsvalid = "false"
for jdc in list(justthedigits):
#logger.fdebug('[FILECHECKER] ('jdc:' + str(jdc))
if not jdc.isdigit():
#logger.fdebug('[FILECHECKER] ('alpha')
jdc_start = justthedigits.find(jdc)
alpha_isschk = justthedigits[jdc_start:]
#logger.fdebug('[FILECHECKER] ('alpha_isschk:' + str(alpha_isschk))
for issexcept in issue_exceptions:
if issexcept.lower() in alpha_isschk.lower() and len(alpha_isschk) <= len(issexcept):
logger.fdebug('[FILECHECKER] ALPHANUMERIC EXCEPTION : [' + justthedigits + ']')
digitsvalid = "true"
else: raise ValueError
except ValueError, e:
logger.fdebug('Probably due to an incorrect match - I cannot determine the issue number from given issue #: ' + str(justthedigits))
break
if digitsvalid == "true": break
try:
tmpthedigits = justthedigits_1.split(' ', 1)[1]
logger.fdebug('[FILECHECKER] If the series has a decimal, this should be a number [' + tmpthedigits + ']')
if 'cbr' in tmpthedigits.lower() or 'cbz' in tmpthedigits.lower():
tmpthedigits = tmpthedigits[:-3].strip()
logger.fdebug('[FILECHECKER] Removed extension - now we should just have a number [' + tmpthedigits + ']')
poss_alpha = tmpthedigits
if poss_alpha.isdigit():
digitsvalid = "true"
if justthedigits.lower() == 'annual' and 'annual' not in watchcomic.lower():
logger.fdebug('[FILECHECKER] ANNUAL DETECTED [' + poss_alpha + ']')
justthedigits += ' ' + poss_alpha
else:
justthedigits += '.' + poss_alpha
logger.fdebug('[FILECHECKER] DECIMAL ISSUE DETECTED [' + justthedigits + ']')
else:
for issexcept in issue_exceptions:
decimalexcept = False
if '.' in issexcept:
decimalexcept = True
issexcept = issexcept[1:] #remove the '.' from comparison...
if issexcept.lower() in poss_alpha.lower() and len(poss_alpha) <= len(issexcept):
if decimalexcept:
issexcept = '.' + issexcept
justthedigits += issexcept #poss_alpha
logger.fdebug('[FILECHECKER] ALPHANUMERIC EXCEPTION. COMBINING : [' + justthedigits + ']')
digitsvalid = "true"
break
except:
tmpthedigits = None
# justthedigits = justthedigits.split(' ', 1)[0]
#if the issue has an alphanumeric (issue_exceptions, join it and push it through)
logger.fdebug('[FILECHECKER] JUSTTHEDIGITS [' + justthedigits + ']' )
if digitsvalid == "true":
pass
else:
if justthedigits.isdigit():
digitsvalid = "true"
else:
if '.' in justthedigits:
tmpdec = justthedigits.find('.')
b4dec = justthedigits[:tmpdec]
a4dec = justthedigits[tmpdec+1:]
if a4dec.isdigit() and b4dec.isdigit():
logger.fdebug('[FILECHECKER] DECIMAL ISSUE DETECTED')
digitsvalid = "true"
else:
try:
x = float(justthedigits)
#validity check
if x < 0:
logger.fdebug("I've encountered a negative issue #: " + str(justthedigits) + ". Trying to accomodate.")
digitsvalid = "true"
else: raise ValueError
except ValueError, e:
logger.fdebug('Probably due to an incorrect match - I cannot determine the issue number from given issue #: ' + str(justthedigits))
# else:
# logger.fdebug('[FILECHECKER] NO DECIMALS DETECTED')
# digitsvalid = "false"
# if justthedigits.lower() == 'annual':
# logger.fdebug('[FILECHECKER] ANNUAL [' + tmpthedigits.split(' ', 1)[1] + ']')
# justthedigits += ' ' + tmpthedigits.split(' ', 1)[1]
# digitsvalid = "true"
# else:
# try:
# if tmpthedigits.isdigit(): #.split(' ', 1)[1] is not None:
# poss_alpha = tmpthedigits#.split(' ', 1)[1]
# if poss_alpha.isdigit():
# digitsvalid = "true"
# justthedigits += '.' + poss_alpha
# logger.fdebug('[FILECHECKER] DECIMAL ISSUE DETECTED [' + justthedigits + ']')
# for issexcept in issue_exceptions:
# if issexcept.lower() in poss_alpha.lower() and len(poss_alpha) <= len(issexcept):
# justthedigits += poss_alpha
# logger.fdebug('[FILECHECKER] ALPHANUMERIC EXCEPTION. COMBINING : [' + justthedigits + ']')
# digitsvalid = "true"
# break
# except:
# pass
logger.fdebug('[FILECHECKER] final justthedigits [' + justthedigits + ']')
if digitsvalid == "false":
logger.fdebug('[FILECHECKER] Issue number not properly detected...ignoring.')
comiccnt -=1 # remove the entry from the list count as it was incorrrectly tallied.
continue
logger.fdebug('[FILECHECKER] final justthedigits [' + justthedigits + ']')
if digitsvalid == "false":
logger.fdebug('[FILECHECKER] Issue number not properly detected...ignoring.')
comiccnt -=1 # remove the entry from the list count as it was incorrrectly tallied.
continue
if manual is not None:
#this is needed for Manual Run to determine matches
#without this Batman will match on Batman Incorporated, and Batman and Robin, etc..
if manual is not None:
#this is needed for Manual Run to determine matches
#without this Batman will match on Batman Incorporated, and Batman and Robin, etc..
# in case it matches on an Alternate Search pattern, set modwatchcomic to the cchk value
modwatchcomic = cchk
logger.fdebug('[FILECHECKER] cchk = ' + cchk.lower())
logger.fdebug('[FILECHECKER] modwatchcomic = ' + modwatchcomic.lower())
logger.fdebug('[FILECHECKER] subname = ' + subname.lower())
comyear = manual['SeriesYear']
issuetotal = manual['Total']
comicvolume = manual['ComicVersion']
logger.fdebug('[FILECHECKER] SeriesYear: ' + str(comyear))
logger.fdebug('[FILECHECKER] IssueTotal: ' + str(issuetotal))
logger.fdebug('[FILECHECKER] Comic Volume: ' + str(comicvolume))
logger.fdebug('[FILECHECKER] volume detected: ' + str(volrem))
# in case it matches on an Alternate Search pattern, set modwatchcomic to the cchk value
modwatchcomic = cchk
logger.fdebug('[FILECHECKER] cchk = ' + cchk.lower())
logger.fdebug('[FILECHECKER] modwatchcomic = ' + modwatchcomic.lower())
logger.fdebug('[FILECHECKER] subname = ' + subname.lower())
comyear = manual['SeriesYear']
issuetotal = manual['Total']
comicvolume = manual['ComicVersion']
logger.fdebug('[FILECHECKER] SeriesYear: ' + str(comyear))
logger.fdebug('[FILECHECKER] IssueTotal: ' + str(issuetotal))
logger.fdebug('[FILECHECKER] Comic Volume: ' + str(comicvolume))
logger.fdebug('[FILECHECKER] volume detected: ' + str(volrem))
if comicvolume:
ComVersChk = re.sub("[^0-9]", "", comicvolume)
if ComVersChk == '' or ComVersChk == '1':
ComVersChk = 0
else:
ComVersChk = 0
if comicvolume:
ComVersChk = re.sub("[^0-9]", "", comicvolume)
if ComVersChk == '' or ComVersChk == '1':
ComVersChk = 0
else:
ComVersChk = 0
# even if it's a V1, we need to pull the date for the given issue ID and get the publication year
# for the issue. Because even if it's a V1, if there are additional Volumes then it's possible that
# it will take the incorrect series. (ie. Detective Comics (1937) & Detective Comics (2011).
# If issue #28 (2013) is found, it exists in both series, and because DC 1937 is a V1, it will bypass
# the year check which will result in the incorrect series being picked (1937)
# even if it's a V1, we need to pull the date for the given issue ID and get the publication year
# for the issue. Because even if it's a V1, if there are additional Volumes then it's possible that
# it will take the incorrect series. (ie. Detective Comics (1937) & Detective Comics (2011).
# If issue #28 (2013) is found, it exists in both series, and because DC 1937 is a V1, it will bypass
# the year check which will result in the incorrect series being picked (1937)
#set the issue/year threshold here.
# 2013 - (24issues/12) = 2011.
#minyear = int(comyear) - (int(issuetotal) / 12)
#set the issue/year threshold here.
# 2013 - (24issues/12) = 2011.
#minyear = int(comyear) - (int(issuetotal) / 12)
maxyear = manual['LatestDate'][:4] # yyyy-mm-dd
maxyear = manual['LatestDate'][:4] # yyyy-mm-dd
#subnm defined at being of module.
len_sm = len(subnm)
#subnm defined at being of module.
len_sm = len(subnm)
#print ("there are " + str(lenm) + " words.")
cnt = 0
yearmatch = "none"
vers4year = "no"
vers4vol = "no"
#print ("there are " + str(lenm) + " words.")
cnt = 0
yearmatch = "none"
vers4year = "no"
vers4vol = "no"
for ct in subsplit:
if ct.lower().startswith('v') and ct[1:].isdigit():
logger.fdebug('[FILECHECKER] possible versioning..checking')
#we hit a versioning # - account for it
if ct[1:].isdigit():
if len(ct[1:]) == 4: #v2013
logger.fdebug('[FILECHECKER] Version detected as ' + str(ct))
vers4year = "yes" #re.sub("[^0-9]", " ", str(ct)) #remove the v
for ct in subsplit:
if ct.lower().startswith('v') and ct[1:].isdigit():
logger.fdebug('[FILECHECKER] possible versioning..checking')
#we hit a versioning # - account for it
if ct[1:].isdigit():
if len(ct[1:]) == 4: #v2013
logger.fdebug('[FILECHECKER] Version detected as ' + str(ct))
vers4year = "yes" #re.sub("[^0-9]", " ", str(ct)) #remove the v
break
else:
if len(ct) < 4:
logger.fdebug('[FILECHECKER] Version detected as ' + str(ct))
vers4vol = str(ct)
break
logger.fdebug('[FILECHECKER] false version detection..ignoring.')
versionmatch = "false"
if vers4year is not "no" or vers4vol is not "no":
if comicvolume: #is not "None" and comicvolume is not None:
D_ComicVersion = re.sub("[^0-9]", "", comicvolume)
if D_ComicVersion == '':
D_ComicVersion = 0
else:
D_ComicVersion = 0
F_ComicVersion = re.sub("[^0-9]", "", volrem)
S_ComicVersion = str(comyear)
logger.fdebug('[FILECHECKER] FCVersion: ' + str(F_ComicVersion))
logger.fdebug('[FILECHECKER] DCVersion: ' + str(D_ComicVersion))
logger.fdebug('[FILECHECKER] SCVersion: ' + str(S_ComicVersion))
#if annualize == "true" and int(ComicYear) == int(F_ComicVersion):
# logger.fdebug('[FILECHECKER] ("We matched on versions for annuals " + str(volrem))
if int(F_ComicVersion) == int(D_ComicVersion) or int(F_ComicVersion) == int(S_ComicVersion):
logger.fdebug('[FILECHECKER] We matched on versions...' + str(volrem))
versionmatch = "true"
else:
logger.fdebug('[FILECHECKER] Versions wrong. Ignoring possible match.')
result_comyear = None
while (cnt < len_sm):
if subnm[cnt] is None: break
if subnm[cnt] == ' ':
pass
else:
logger.fdebug('[FILECHECKER] ' + str(cnt) + ' Bracket Word: ' + str(subnm[cnt]))
#if ComVersChk == 0:
# logger.fdebug('[FILECHECKER] Series version detected as V1 (only series in existance with that title). Bypassing year check')
# yearmatch = "true"
# break
if subnm[cnt][:-2] == '19' or subnm[cnt][:-2] == '20':
logger.fdebug('[FILECHECKER] year detected: ' + str(subnm[cnt]))
result_comyear = subnm[cnt]
if int(result_comyear) <= int(maxyear) and int(result_comyear) >= int(comyear):
logger.fdebug('[FILECHECKER] ' + str(result_comyear) + ' is within the series range of ' + str(comyear) + '-' + str(maxyear))
#still possible for incorrect match if multiple reboots of series end/start in same year
yearmatch = "true"
break
else:
if len(ct) < 4:
logger.fdebug('[FILECHECKER] Version detected as ' + str(ct))
vers4vol = str(ct)
break
logger.fdebug('[FILECHECKER] false version detection..ignoring.')
versionmatch = "false"
if vers4year is not "no" or vers4vol is not "no":
if comicvolume: #is not "None" and comicvolume is not None:
D_ComicVersion = re.sub("[^0-9]", "", comicvolume)
if D_ComicVersion == '':
D_ComicVersion = 0
else:
D_ComicVersion = 0
F_ComicVersion = re.sub("[^0-9]", "", volrem)
S_ComicVersion = str(comyear)
logger.fdebug('[FILECHECKER] FCVersion: ' + str(F_ComicVersion))
logger.fdebug('[FILECHECKER] DCVersion: ' + str(D_ComicVersion))
logger.fdebug('[FILECHECKER] SCVersion: ' + str(S_ComicVersion))
#if annualize == "true" and int(ComicYear) == int(F_ComicVersion):
# logger.fdebug('[FILECHECKER] ("We matched on versions for annuals " + str(volrem))
if int(F_ComicVersion) == int(D_ComicVersion) or int(F_ComicVersion) == int(S_ComicVersion):
logger.fdebug('[FILECHECKER] We matched on versions...' + str(volrem))
versionmatch = "true"
else:
logger.fdebug('[FILECHECKER] Versions wrong. Ignoring possible match.')
result_comyear = None
while (cnt < len_sm):
if subnm[cnt] is None: break
if subnm[cnt] == ' ':
pass
else:
logger.fdebug('[FILECHECKER] ' + str(cnt) + ' Bracket Word: ' + str(subnm[cnt]))
#if ComVersChk == 0:
# logger.fdebug('[FILECHECKER] Series version detected as V1 (only series in existance with that title). Bypassing year check')
# yearmatch = "true"
# break
if subnm[cnt][:-2] == '19' or subnm[cnt][:-2] == '20':
logger.fdebug('[FILECHECKER] year detected: ' + str(subnm[cnt]))
result_comyear = subnm[cnt]
if int(result_comyear) <= int(maxyear):
logger.fdebug('[FILECHECKER] ' + str(result_comyear) + ' is within the series range of ' + str(comyear) + '-' + str(maxyear))
#still possible for incorrect match if multiple reboots of series end/start in same year
yearmatch = "true"
break
logger.fdebug('[FILECHECKER] ' + str(result_comyear) + ' - not right - year not within series range of ' + str(comyear) + '-' + str(maxyear))
yearmatch = "false"
break
cnt+=1
if versionmatch == "false":
if yearmatch == "false":
logger.fdebug('[FILECHECKER] Failed to match on both version and issue year.')
continue
else:
logger.fdebug('[FILECHECKER] ' + str(result_comyear) + ' - not right - year not within series range of ' + str(comyear) + '-' + str(maxyear))
yearmatch = "false"
logger.fdebug('[FILECHECKER] Matched on versions, not on year - continuing.')
else:
if yearmatch == "false":
logger.fdebug('[FILECHECKER] Matched on version, but not on year - continuing.')
else:
logger.fdebug('[FILECHECKER] Matched on both version, and issue year - continuing.')
if yearmatch == "none":
if ComVersChk == 0:
logger.fdebug('[FILECHECKER] Series version detected as V1 (only series in existance with that title). Bypassing year check.')
yearmatch = "true"
else:
continue
if 'annual' in subname.lower():
subname = re.sub('annual', '', subname.lower())
subname = re.sub('\s+', ' ', subname)
#if the sub has an annual, let's remove it from the modwatch as well
modwatchcomic = re.sub('annual', '', modwatchcomic.lower())
#tmpitem = item[:jtd_len]
# if it's an alphanumeric with a space, rejoin, so we can remove it cleanly just below this.
substring_removal = None
poss_alpha = subname.split(' ')[-1:]
logger.fdebug('[FILECHECKER] poss_alpha: ' + str(poss_alpha))
logger.fdebug('[FILECHECKER] lenalpha: ' + str(len(''.join(poss_alpha))))
for issexcept in issue_exceptions:
if issexcept.lower()in str(poss_alpha).lower() and len(''.join(poss_alpha)) <= len(issexcept):
#get the last 2 words so that we can remove them cleanly
substring_removal = ' '.join(subname.split(' ')[-2:])
substring_join = ''.join(subname.split(' ')[-2:])
logger.fdebug('[FILECHECKER] substring_removal: ' + str(substring_removal))
logger.fdebug('[FILECHECKER] substring_join: ' + str(substring_join))
break
cnt+=1
if versionmatch == "false":
if yearmatch == "false":
logger.fdebug('[FILECHECKER] Failed to match on both version and issue year.')
continue
else:
logger.fdebug('[FILECHECKER] Matched on versions, not on year - continuing.')
else:
if yearmatch == "false":
logger.fdebug('[FILECHECKER] Matched on version, but not on year - continuing.')
else:
logger.fdebug('[FILECHECKER] Matched on both version, and issue year - continuing.')
if yearmatch == "none":
if ComVersChk == 0:
logger.fdebug('[FILECHECKER] Series version detected as V1 (only series in existance with that title). Bypassing year check.')
yearmatch = "true"
if substring_removal is not None:
sub_removed = subname.replace('_', ' ').replace(substring_removal, substring_join)
else:
sub_removed = subname.replace('_', ' ')
logger.fdebug('[FILECHECKER] sub_removed: ' + str(sub_removed))
split_sub = sub_removed.rsplit(' ',1)[0].split(' ') #removes last word (assuming it's the issue#)
split_mod = modwatchcomic.replace('_', ' ').split() #batman
logger.fdebug('[FILECHECKER] split_sub: ' + str(split_sub))
logger.fdebug('[FILECHECKER] split_mod: ' + str(split_mod))
x = len(split_sub)-1
scnt = 0
if x > len(split_mod)-1:
logger.fdebug('[FILECHECKER] number of words do not match...aborting.')
else:
while ( x > -1 ):
logger.fdebug(str(split_sub[x]) + ' comparing to ' + str(split_mod[x]))
if str(split_sub[x]).lower() == str(split_mod[x]).lower():
scnt+=1
logger.fdebug('[FILECHECKER] word match exact. ' + str(scnt) + '/' + str(len(split_mod)))
x-=1
wordcnt = int(scnt)
logger.fdebug('[FILECHECKER] scnt:' + str(scnt))
totalcnt = int(len(split_mod))
logger.fdebug('[FILECHECKER] split_mod length:' + str(totalcnt))
try:
spercent = (wordcnt/totalcnt) * 100
except ZeroDivisionError:
spercent = 0
logger.fdebug('[FILECHECKER] we got ' + str(spercent) + ' percent.')
if int(spercent) >= 80:
logger.fdebug('[FILECHECKER] this should be considered an exact match.Justthedigits:' + justthedigits)
else:
logger.fdebug('[FILECHECKER] failure - not an exact match.')
continue
if 'annual' in subname.lower():
subname = re.sub('annual', '', subname.lower())
subname = re.sub('\s+', ' ', subname)
#if the sub has an annual, let's remove it from the modwatch as well
modwatchcomic = re.sub('annual', '', modwatchcomic.lower())
#tmpitem = item[:jtd_len]
# if it's an alphanumeric with a space, rejoin, so we can remove it cleanly just below this.
substring_removal = None
poss_alpha = subname.split(' ')[-1:]
logger.fdebug('[FILECHECKER] poss_alpha: ' + str(poss_alpha))
logger.fdebug('[FILECHECKER] lenalpha: ' + str(len(''.join(poss_alpha))))
for issexcept in issue_exceptions:
if issexcept.lower()in str(poss_alpha).lower() and len(''.join(poss_alpha)) <= len(issexcept):
#get the last 2 words so that we can remove them cleanly
substring_removal = ' '.join(subname.split(' ')[-2:])
substring_join = ''.join(subname.split(' ')[-2:])
logger.fdebug('[FILECHECKER] substring_removal: ' + str(substring_removal))
logger.fdebug('[FILECHECKER] substring_join: ' + str(substring_join))
break
if substring_removal is not None:
sub_removed = subname.replace('_', ' ').replace(substring_removal, substring_join)
if manual:
#print item
#print comicpath
#print comicsize
#print result_comyear
#print justthedigits
comiclist.append({
'ComicFilename': item,
'ComicLocation': comicpath,
'ComicSize': comicsize,
'ComicYear': result_comyear,
'JusttheDigits': justthedigits
})
#print('appended.')
# watchmatch['comiclist'] = comiclist
# break
else:
sub_removed = subname.replace('_', ' ')
logger.fdebug('[FILECHECKER] sub_removed: ' + str(sub_removed))
split_sub = sub_removed.rsplit(' ',1)[0].split(' ') #removes last word (assuming it's the issue#)
split_mod = modwatchcomic.replace('_', ' ').split() #batman
logger.fdebug('[FILECHECKER] split_sub: ' + str(split_sub))
logger.fdebug('[FILECHECKER] split_mod: ' + str(split_mod))
x = len(split_sub)-1
scnt = 0
if x > len(split_mod)-1:
logger.fdebug('[FILECHECKER] number of words do not match...aborting.')
else:
while ( x > -1 ):
logger.fdebug(str(split_sub[x]) + ' comparing to ' + str(split_mod[x]))
if str(split_sub[x]).lower() == str(split_mod[x]).lower():
scnt+=1
logger.fdebug('[FILECHECKER] word match exact. ' + str(scnt) + '/' + str(len(split_mod)))
x-=1
wordcnt = int(scnt)
logger.fdebug('[FILECHECKER] scnt:' + str(scnt))
totalcnt = int(len(split_mod))
logger.fdebug('[FILECHECKER] split_mod length:' + str(totalcnt))
try:
spercent = (wordcnt/totalcnt) * 100
except ZeroDivisionError:
spercent = 0
logger.fdebug('[FILECHECKER] we got ' + str(spercent) + ' percent.')
if int(spercent) >= 80:
logger.fdebug('[FILECHECKER] this should be considered an exact match.Justthedigits:' + justthedigits)
else:
logger.fdebug('[FILECHECKER] failure - not an exact match.')
continue
if manual:
#print item
#print comicpath
#print comicsize
#print result_comyear
#print justthedigits
comiclist.append({
'ComicFilename': item,
'ComicLocation': comicpath,
'ComicSize': comicsize,
'ComicYear': result_comyear,
'JusttheDigits': justthedigits
})
#print('appended.')
# watchmatch['comiclist'] = comiclist
# break
else:
if moddir is not None:
item = os.path.join(moddir, item)
comiclist.append({
'ComicFilename': item,
'ComicLocation': comicpath,
'ComicSize': comicsize,
'JusttheDigits': justthedigits
})
#crcvalue = crc(comicpath)
#logger.fdebug('[FILECHECKER] CRC is calculated as ' + str(crcvalue) + ' for : ' + item)
watchmatch['comiclist'] = comiclist
if moddir is not None:
item = os.path.join(moddir, item)
comiclist.append({
'ComicFilename': item,
'ComicLocation': comicpath,
'ComicSize': comicsize,
'JusttheDigits': justthedigits,
'AnnualComicID': annual_comicid
})
#crcvalue = crc(comicpath)
#logger.fdebug('[FILECHECKER] CRC is calculated as ' + str(crcvalue) + ' for : ' + item)
watchmatch['comiclist'] = comiclist
break
else:
#directory found - ignoring
pass

View File

@ -616,6 +616,8 @@ def fullmonth(monthno):
#simple numerical to worded month conversion....
basmonths = {'1':'January','2':'February','3':'March','4':'April','5':'May','6':'June','7':'July','8':'August','9':'September','10':'October','11':'November','12':'December'}
monthconv = None
for numbs in basmonths:
if numbs in str(int(monthno)):
monthconv = basmonths[numbs]
@ -628,23 +630,21 @@ def updateComicLocation():
if mylar.NEWCOM_DIR is not None:
logger.info('Performing a one-time mass update to Comic Location')
#create the root dir if it doesn't exist
if os.path.isdir(mylar.NEWCOM_DIR):
logger.info('Directory (' + mylar.NEWCOM_DIR + ') already exists! Continuing...')
else:
logger.info('Directory does not exist!')
try:
os.makedirs(mylar.NEWCOM_DIR)
logger.info('Directory successfully created at: ' + mylar.NEWCOM_DIR)
except OSError:
logger.error('Could not create comicdir : ' + mylar.NEWCOM_DIR)
return
mylar.filechecker.validateAndCreateDirectory(mylar.NEWCOM_DIR, create=True)
dirlist = myDB.select("SELECT * FROM comics")
comloc = []
if dirlist is not None:
for dl in dirlist:
comversion = dl['ComicVersion']
u_comicnm = dl['ComicName']
# let's remove the non-standard characters here that will break filenaming / searching.
comicname_folder = filesafe(u_comicnm)
publisher = re.sub('!','',dl['ComicPublisher']) # thanks Boom!
year = dl['ComicYear']
comversion = dl['ComicVersion']
if comversion is None:
comversion = 'None'
#if comversion is None, remove it so it doesn't populate with 'None'
@ -655,54 +655,61 @@ def updateComicLocation():
else:
folderformat = mylar.FOLDER_FORMAT
#remove all 'bad' characters from the Series Name in order to create directories.
u_comicnm = dl['ComicName']
u_comicname = u_comicnm.encode('ascii', 'ignore').strip()
if ':' in u_comicname or '/' in u_comicname or ',' in u_comicname or '?' in u_comicname:
comicdir = u_comicname
if ':' in comicdir:
comicdir = comicdir.replace(':','')
if '/' in comicdir:
comicdir = comicdir.replace('/','-')
if ',' in comicdir:
comicdir = comicdir.replace(',','')
if '?' in comicdir:
comicdir = comicdir.replace('?','')
else: comicdir = u_comicname
#do work to generate folder path
values = {'$Series': comicdir,
'$Publisher': re.sub('!','',dl['ComicPublisher']),
'$Year': dl['ComicYear'],
'$series': dl['ComicName'].lower(),
'$publisher': re.sub('!','',dl['ComicPublisher']).lower(),
'$VolumeY': 'V' + str(dl['ComicYear']),
'$VolumeN': comversion
values = {'$Series': comicname_folder,
'$Publisher': publisher,
'$Year': year,
'$series': comicname_folder.lower(),
'$publisher': publisher.lower(),
'$VolumeY': 'V' + str(year),
'$VolumeN': comversion,
'$Annual': 'Annual'
}
if mylar.FFTONEWCOM_DIR:
#if this is enabled (1) it will apply the Folder_Format to all the new dirs
if mylar.FOLDER_FORMAT == '':
comlocation = re.sub(mylar.DESTINATION_DIR, mylar.NEWCOM_DIR, comicdir)
comlocation = re.sub(mylar.DESTINATION_DIR, mylar.NEWCOM_DIR, dl['ComicLocation']).strip()
else:
first = replace_all(folderformat, values)
if mylar.REPLACE_SPACES:
#mylar.REPLACE_CHAR ...determines what to replace spaces with underscore or dot
first = first.replace(' ', mylar.REPLACE_CHAR)
comlocation = os.path.join(mylar.NEWCOM_DIR,first)
comlocation = os.path.join(mylar.NEWCOM_DIR,first).strip()
else:
comlocation = re.sub(mylar.DESTINATION_DIR, mylar.NEWCOM_DIR, comicdir)
comlocation = re.sub(mylar.DESTINATION_DIR, mylar.NEWCOM_DIR, dl['ComicLocation']).strip()
ctrlVal = {"ComicID": dl['ComicID']}
newVal = {"ComicLocation": comlocation}
myDB.upsert("Comics", newVal, ctrlVal)
logger.fdebug('updated ' + dl['ComicName'] + ' to : ' + comlocation)
comloc.append({"comlocation": comlocation,
"origlocation": dl['ComicLocation'],
"comicid": dl['ComicID']})
if len(comloc) > 0:
#give the information about what we're doing.
if mylar.FFTONEWCOM_DIR:
logger.info('FFTONEWCOM_DIR is enabled. Applying the existing folder format to ALL directories regardless of existing location paths')
else:
logger.info('FFTONEWCOM_DIR is not enabled. I will keep existing subdirectory paths, and will only change the actual Comic Location in the path.')
logger.fdebug(' (ie. /mnt/Comics/Marvel/Hush-(2012) to /mnt/mynewLocation/Marvel/Hush-(2012) ')
#do the deed.
for cl in comloc:
ctrlVal = {"ComicID": cl['comicid']}
newVal = {"ComicLocation": cl['comlocation']}
# myDB.upsert("Comics", newVal, ctrlVal)
logger.fdebug('Updated : ' + cl['origlocation'] + ' .: TO :. ' + cl['comlocation'])
logger.info('Updated ' + str(len(comloc)) + ' series to a new Comic Location as specified in the config.ini')
else:
logger.fdebug('Failed in updating the Comic Locations. Check Folder Format string and/or log the issue.')
else:
logger.info('There are no series in your watchlist to Update the locations. Not updating anything at this time.')
#set the value to 0 here so we don't keep on doing this...
mylar.LOCMOVE = 0
mylar.config_write()
else:
logger.info('No new ComicLocation path specified - not updating.')
logger.info('No new ComicLocation path specified - not updating. Set NEWCOMD_DIR in config.ini')
#raise cherrypy.HTTPRedirect("config")
return
@ -918,12 +925,16 @@ def renamefile_readingorder(readorder):
def latestdate_fix():
import db, logger
datefix = []
cnupdate = []
myDB = db.DBConnection()
comiclist = myDB.select('SELECT * FROM comics')
if comiclist is None:
logger.fdebug('No Series in watchlist to correct latest date')
return
for cl in comiclist:
if cl['ComicName_Filesafe'] is None:
cnupdate.append({"comicid": cl['ComicID'],
"comicname_filesafe": filesafe(cl['ComicName'])})
latestdate = cl['LatestDate']
#logger.fdebug("latestdate: " + str(latestdate))
if latestdate[8:] == '':
@ -945,10 +956,18 @@ def latestdate_fix():
#now we fix.
if len(datefix) > 0:
logger.info('Preparing to correct/fix ' + str(len(datefix)) + ' series that have incorrect values given for the Latest Date field.')
for df in datefix:
newCtrl = {"ComicID": df['comicid']}
newVal = {"LatestDate": df['latestdate']}
myDB.upsert("comics", newVal, newCtrl)
if len(cnupdate) > 0:
logger.info('Preparing to update ' + str(len(cnupdate)) + ' series on your watchlist for use with non-ascii characters')
for cn in cnupdate:
newCtrl = {"ComicID": cn['comicid']}
newVal = {"ComicName_Filesafe": cn['comicname_filesafe']}
myDB.upsert("comics", newVal, newCtrl)
return
def checkFolder():
@ -1120,6 +1139,258 @@ def cvapi_check(web=None):
line = str(mylar.CVAPI_COUNT) + ' hits / ' + str(mins) + ' minutes'
return line
def filesafe(comic):
import unicodedata
u_comic = unicodedata.normalize('NFKD', comic).encode('ASCII', 'ignore').strip()
comicname_filesafe = re.sub('[\:\'\,\?\!\\\]', '', u_comic)
comicname_filesafe = re.sub('[\/]','-', comicname_filesafe)
return comicname_filesafe
def IssueDetails(filelocation, IssueID=None):
import zipfile, logger, shutil
from xml.dom.minidom import parseString
dstlocation = os.path.join(mylar.CACHE_DIR, 'temp.zip')
issuedetails = []
if filelocation.endswith('.cbz'):
logger.info('CBZ file detected. Checking for .xml within file')
shutil.copy( filelocation, dstlocation )
else:
logger.info('filename is not a cbz : ' + filelocation)
return
cover = "notfound"
issuetag = None
modtime = os.path.getmtime(dstlocation)
logger.info('file modtime set to : ' + str(modtime))
with zipfile.ZipFile(dstlocation, 'r') as inzipfile:
for infile in inzipfile.namelist():
if infile == 'ComicInfo.xml':
logger.info('Extracting ComicInfo.xml to display.')
dst = os.path.join(mylar.CACHE_DIR, 'ComicInfo.xml')
data = inzipfile.read(infile)
print str(data)
issuetag = 'xml'
elif '000.jpg' in infile or '000.png' in infile or '00.jpg' in infile:
logger.info('Extracting primary image ' + infile + ' as coverfile for display.')
local_file = open(os.path.join(mylar.CACHE_DIR,'temp.jpg'), "wb")
local_file.write(inzipfile.read(infile))
local_file.close
cover = "found"
elif ('001.jpg' in infile or '001.png' in infile) and cover == "notfound":
logger.info('Extracting primary image ' + infile + ' as coverfile for display.')
local_file = open(os.path.join(mylar.CACHE_DIR,'temp.jpg'), "wb")
local_file.write(inzipfile.read(infile))
local_file.close
cover = "found"
ComicImage = os.path.join('cache', 'temp.jpg?'+str(modtime))
IssueImage = replacetheslash(ComicImage)
if issuetag is None:
import subprocess
from subprocess import CalledProcessError, check_output
unzip_cmd = "/usr/bin/unzip"
try:
#unzip -z will extract the zip comment field.
data = subprocess.check_output( [ unzip_cmd, '-z', dstlocation ] )
# return data is encoded in bytes, not unicode. Need to figure out how to run check_output returning utf-8
issuetag = 'comment'
except CalledProcessError as e:
logger.warn('Unable to extract comment field from zipfile.')
print 'data:' + str(data)
if issuetag == 'xml':
#import easy to use xml parser called minidom:
dom = parseString(data)
results = dom.getElementsByTagName('ComicInfo')
for result in results:
try:
issue_title = result.getElementsByTagName('Title')[0].firstChild.wholeText
except:
issue_title = "None"
try:
series_title = result.getElementsByTagName('Series')[0].firstChild.wholeText
except:
series_title = "None"
try:
issue_number = result.getElementsByTagName('Number')[0].firstChild.wholeText
except:
issue_number = "None"
try:
summary = result.getElementsByTagName('Summary')[0].firstChild.wholeText
except:
summary = "None"
if '*List' in summary:
summary_cut = summary.find('*List')
summary = summary[:summary_cut]
try:
notes = result.getElementsByTagName('Notes')[0].firstChild.wholeText #IssueID is in here
except:
notes = "None"
try:
year = result.getElementsByTagName('Year')[0].firstChild.wholeText
except:
year = "None"
try:
month = result.getElementsByTagName('Month')[0].firstChild.wholeText
except:
month = "None"
try:
day = result.getElementsByTagName('Day')[0].firstChild.wholeText
except:
day = "None"
try:
writer = result.getElementsByTagName('Writer')[0].firstChild.wholeText
except:
writer = "None"
try:
penciller = result.getElementsByTagName('Penciller')[0].firstChild.wholeText
except:
penciller = "None"
try:
inker = result.getElementsByTagName('Inker')[0].firstChild.wholeText
except:
inker = "None"
try:
colorist = result.getElementsByTagName('Colorist')[0].firstChild.wholeText
except:
colorist = "None"
try:
letterer = result.getElementsByTagName('Letterer')[0].firstChild.wholeText
except:
letterer = "None"
try:
cover_artist = result.getElementsByTagName('CoverArtist')[0].firstChild.wholeText
except:
cover_artist = "None"
try:
editor = result.getElementsByTagName('Editor')[0].firstChild.wholeText
except:
editor = "None"
try:
publisher = result.getElementsByTagName('Publisher')[0].firstChild.wholeText
except:
publisher = "None"
try:
webpage = result.getElementsByTagName('Web')[0].firstChild.wholeText
except:
webpage = "None"
try:
pagecount = result.getElementsByTagName('PageCount')[0].firstChild.wholeText
except:
pagecount = 0
logger.info("number of pages I counted: " + str(pagecount))
i = 0
while (i < int(pagecount)):
pageinfo = result.getElementsByTagName('Page')[i].attributes
attrib = pageinfo.getNamedItem('Image')
logger.info('Frontcover validated as being image #: ' + str(attrib.value))
att = pageinfo.getNamedItem('Type')
logger.info('pageinfo: ' + str(pageinfo))
if att.value == 'FrontCover':
logger.info('FrontCover detected. Extracting.')
break
i+=1
else:
stripline = 'Archive: ' + dstlocation
data = re.sub(stripline, '', data.encode("utf-8"))
import ast
ast_data = ast.literal_eval(str(data))
lastmodified = ast_data['lastModified']
print lastmodified
dt = ast_data['ComicBookInfo/1.0']
publisher = dt['publisher']
year = dt['publicationYear']
month = dt['publicationMonth']
try:
day = dt['publicationDay']
except:
day = None
issue_title = dt['title']
series_title = dt['series']
issue_number = dt['issue']
summary = dt['comments']
editor = "None"
colorist = "None"
artist = "None"
writer = "None"
letterer = "None"
cover_artist = "None"
penciller = "None"
inker = "None"
for cl in dt['credits']:
if cl['role'] == 'Editor':
if editor == "None": editor = cl['person']
else: editor += ', ' + cl['person']
elif cl['role'] == 'Colorist':
if colorist == "None": colorist = cl['person']
else: colorist += ', ' + cl['person']
elif cl['role'] == 'Artist':
if artist == "None": artist = cl['person']
else: artist += ', ' + cl['person']
elif cl['role'] == 'Writer':
if writer == "None": writer = cl['person']
else: writer += ', ' + cl['person']
elif cl['role'] == 'Letterer':
if letterer == "None": letterer = cl['person']
else: letterer += ', ' + cl['person']
elif cl['role'] == 'Cover':
if cover_artist == "None": cover_artist = cl['person']
else: cover_artist += ', ' + cl['person']
elif cl['role'] == 'Penciller':
if penciller == "None": penciller = cl['person']
else: penciller += ', ' + cl['person']
elif cl['role'] == 'Inker':
if inker == "None": inker = cl['person']
else: inker += ', ' + cl['person']
try:
notes = dt['notes']
except:
notes = "None"
try:
webpage = dt['web']
except:
webpage = "None"
try:
pagecount = dt['pagecount']
except:
pagecount = "None"
issuedetails.append({"title": issue_title,
"series": series_title,
"issue_number": issue_number,
"summary": summary,
"notes": notes,
"year": year,
"month": month,
"day": day,
"writer": writer,
"penciller": penciller,
"inker": inker,
"colorist": colorist,
"letterer": letterer,
"cover_artist": cover_artist,
"editor": editor,
"publisher": publisher,
"webpage": webpage,
"pagecount": pagecount,
"IssueImage": IssueImage})
return issuedetails
from threading import Thread
class ThreadWithReturnValue(Thread):
@ -1129,10 +1400,9 @@ class ThreadWithReturnValue(Thread):
self._return = None
def run(self):
if self._Thread__target is not None:
self._return = self._Thread__target(*self._Thread__args,
**self._Thread__kwargs)
self._return = self._Thread__target(*self._Thread__args, **self._Thread__kwargs)
def join(self):
Thread.join(self)
return self._return

View File

@ -22,6 +22,7 @@ import re
import urllib
import urllib2
import shutil
import imghdr
import sqlite3
import cherrypy
@ -43,7 +44,7 @@ def is_exists(comicid):
return False
def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,calledfrom=None,annload=None,chkwant=None,issuechk=None,issuetype=None):
def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,calledfrom=None,annload=None,chkwant=None,issuechk=None,issuetype=None,latestissueinfo=None):
# Putting this here to get around the circular import. Will try to use this to update images at later date.
# from mylar import cache
@ -66,6 +67,11 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
return 'Exists'
newValueDict = {"Status": "Loading"}
comlocation = dbcomic['ComicLocation']
if not latestissueinfo:
latestissueinfo = []
latestissueinfo.append({"latestiss": dbcomic['LatestIssue'],
"latestdate": dbcomic['LatestDate']})
filechecker.validateAndCreateDirectory(comlocation, True)
oldcomversion = dbcomic['ComicVersion'] #store the comicversion and chk if it exists before hammering.
myDB.upsert("comics", newValueDict, controlValueDict)
@ -195,7 +201,7 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
#sresults = mb.findComic(annComicName, mode, issue=annissues, limityear=annualval['AnnualYear'])
#print "annualyear: " + str(annualval['AnnualYear'])
logger.fdebug('[IMPORTER-ANNUAL] - Annual Year:' + str(annualyear))
sresults, explicit = mb.findComic(annComicName, mode, issue=None)#,explicit=True)
sresults, explicit = mb.findComic(annComicName, mode, issue=None, explicit='all')#,explicit=True)
type='comic'
@ -290,28 +296,12 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
#comic book location on machine
# setup default location here
if comlocation is None:
# let's remove the non-standard characters here.
u_comicnm = comic['ComicName']
u_comicname = u_comicnm.encode('ascii', 'ignore').strip()
dirbad = [':',',','/','?','!','\''] #in u_comicname or '/' in u_comicname or ',' in u_comicname or '?' in u_comicname:
comicdir = u_comicname
for dbd in dirbad:
if dbd in u_comicname:
if dbd == '/': repthechar = '-'
else: repthechar = ''
comicdir = comicdir.replace(dbd,repthechar)
# if ':' in comicdir:
# comicdir = comicdir.replace(dbd,'')
# if '/' in comicdir:
# comicdir = comicdir.replace('/','-')
# if ',' in comicdir:
# comicdir = comicdir.replace(',','')
# if '?' in comicdir:
# comicdir = comicdir.replace('?','')
# if '!' in comicdir:
# comicdir = comicdir.replace('!','')
u_comicnm = comic['ComicName']
# let's remove the non-standard characters here that will break filenaming / searching.
comicname_filesafe = helpers.filesafe(u_comicnm)
if comlocation is None:
comicdir = comicname_filesafe
series = comicdir
publisher = re.sub('!','',comic['ComicPublisher']) # thanks Boom!
year = SeriesYear
@ -408,6 +398,11 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
with open(coverfile, 'wb') as the_file:
the_file.write(com_image)
try:
logger.info('Image header check: ' + imghdr.what(coverfile))
except:
logger.info('image is corrupted.')
raise Exception
logger.info('Successfully retrieved cover for ' + comic['ComicName'])
except Exception, e:
@ -459,6 +454,7 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
controlValueDict = {"ComicID": comicid}
newValueDict = {"ComicName": comic['ComicName'],
"ComicSortName": sortname,
"ComicName_Filesafe": comicname_filesafe,
"ComicYear": SeriesYear,
"ComicImage": ComicImage,
"Total": comicIssues,
@ -489,7 +485,7 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
#move to own function so can call independently to only refresh issue data
#issued is from cv.getComic, comic['ComicName'] & comicid would both be already known to do independent call.
issuedata = updateissuedata(comicid, comic['ComicName'], issued, comicIssues, calledfrom, SeriesYear=SeriesYear)
issuedata = updateissuedata(comicid, comic['ComicName'], issued, comicIssues, calledfrom, SeriesYear=SeriesYear, latestissueinfo=latestissueinfo)
if issuedata is None:
logger.warn('Unable to complete Refreshing / Adding issue data - this WILL create future problems if not addressed.')
return
@ -520,8 +516,8 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
latestdate = issuedata['LatestDate']
lastpubdate = issuedata['LastPubDate']
#move the files...if imported is not empty (meaning it's not from the mass importer.)
if imported is None or imported == 'None':
#move the files...if imported is not empty & not futurecheck (meaning it's not from the mass importer.)
if imported is None or imported == 'None' or imported == 'futurecheck':
pass
else:
if mylar.IMP_MOVE:
@ -547,7 +543,11 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
logger.fdebug('latestissue status: ' + chkstats['Status'])
if chkstats['Status'] == 'Skipped' or chkstats['Status'] == 'Wanted' or chkstats['Status'] == 'Snatched':
logger.info('Checking this week pullist for new issues of ' + comic['ComicName'])
updater.newpullcheck(comic['ComicName'], comicid, issue=latestiss)
if comic['ComicName'] != comicname_filesafe:
cn_pull = comicname_filesafe
else:
cn_pull = comic['ComicName']
updater.newpullcheck(cn_pull, comicid, issue=latestiss)
#here we grab issues that have been marked as wanted above...
@ -583,7 +583,9 @@ def addComictoDB(comicid,mismatch=None,pullupd=None,imported=None,ogcname=None,c
logger.info('Finished grabbing what I could.')
if imported == 'futurecheck':
logger.info('Returning to Future-Check module to complete the add & remove entry.')
return
if calledfrom == 'addbyid':
logger.info('Sucessfully added ' + comic['ComicName'] + ' (' + str(SeriesYear) + ') by directly using the ComicVine ID')
@ -994,7 +996,7 @@ def manualAnnual(manual_comicid, comicname, comicyear, comicid):
logger.info('Attempting to integrate ' + sr['ComicName'] + ' (' + str(issueid) + ') to the existing series of ' + comicname + '(' + str(comicyear) + ')')
if len(sr) is None or len(sr) == 0:
logger.fdebug('Could not find any information on the series indicated : ' + str(manual_comicid))
pass
return
else:
n = 0
noissues = sr['ComicIssues']
@ -1034,10 +1036,11 @@ def manualAnnual(manual_comicid, comicname, comicyear, comicid):
#"M_ComicID": manual_comicid}
myDB.upsert("annuals", newVals, newCtrl)
n+=1
logger.info('Successfully integrated ' + str(n) + ' issues of ' + sr['ComicName'] + ' to the series: ' + comicname)
return
def updateissuedata(comicid, comicname=None, issued=None, comicIssues=None, calledfrom=None, issuechk=None, issuetype=None, SeriesYear=None):
def updateissuedata(comicid, comicname=None, issued=None, comicIssues=None, calledfrom=None, issuechk=None, issuetype=None, SeriesYear=None, latestissueinfo=None):
weeklyissue_check = []
logger.fdebug('issuedata call references...')
logger.fdebug('comicid:' + str(comicid))
@ -1045,6 +1048,7 @@ def updateissuedata(comicid, comicname=None, issued=None, comicIssues=None, call
logger.fdebug('comicissues:' + str(comicIssues))
logger.fdebug('calledfrom: ' + str(calledfrom))
logger.fdebug('issuechk: ' + str(issuechk))
logger.fdebug('latestissueinfo: ' + str(latestissueinfo))
logger.fdebug('issuetype: ' + str(issuetype))
#to facilitate independent calls to updateissuedata ONLY, account for data not available and get it.
#chkType comes from the weeklypulllist - either 'annual' or not to distinguish annuals vs. issues
@ -1222,38 +1226,60 @@ def updateissuedata(comicid, comicname=None, issued=None, comicIssues=None, call
n+=1
if len(issuedata) > 1 and not calledfrom == 'dbupdate':
logger.fdebug('initiating issue updating - info & status')
issue_collection(issuedata,nostatus='False')
else:
logger.fdebug('initiating issue updating - just the info')
issue_collection(issuedata,nostatus='True')
styear = str(SeriesYear)
if firstdate[5:7] == '00':
stmonth = "?"
else:
stmonth = helpers.fullmonth(firstdate[5:7])
ltyear = re.sub('/s','', latestdate[:4])
if latestdate[5:7] == '00':
ltmonth = "?"
else:
ltmonth = helpers.fullmonth(latestdate[5:7])
#try to determine if it's an 'actively' published comic from above dates
#threshold is if it's within a month (<55 days) let's assume it's recent.
c_date = datetime.date(int(latestdate[:4]),int(latestdate[5:7]),1)
n_date = datetime.date.today()
recentchk = (n_date - c_date).days
#print ("recentchk: " + str(recentchk))
if recentchk <= 55:
if calledfrom == 'futurecheck' and len(issuedata) == 0:
logger.fdebug('This is a NEW series with no issue data - skipping issue updating for now, and assigning generic information so things don\'t break')
latestdate = latestissueinfo[0]['latestdate'] # if it's from futurecheck, issuechk holds the latestdate for the given issue
latestiss = latestissueinfo[0]['latestiss']
lastpubdate = 'Present'
publishfigure = str(SeriesYear) + ' - ' + str(lastpubdate)
else:
lastpubdate = str(ltmonth) + ' ' + str(ltyear)
if len(issuedata) > 1 and not calledfrom == 'dbupdate':
logger.fdebug('initiating issue updating - info & status')
issue_collection(issuedata,nostatus='False')
else:
logger.fdebug('initiating issue updating - just the info')
issue_collection(issuedata,nostatus='True')
styear = str(SeriesYear)
if firstdate[5:7] == '00':
stmonth = "?"
else:
stmonth = helpers.fullmonth(firstdate[5:7])
ltyear = re.sub('/s','', latestdate[:4])
if latestdate[5:7] == '00':
ltmonth = "?"
else:
ltmonth = helpers.fullmonth(latestdate[5:7])
#try to determine if it's an 'actively' published comic from above dates
#threshold is if it's within a month (<55 days) let's assume it's recent.
try:
c_date = datetime.date(int(latestdate[:4]),int(latestdate[5:7]),1)
except:
logger.error('Cannot determine Latest Date for given series. This is most likely due to an issue having a date of : 0000-00-00')
latestdate = str(SeriesYear) + '-01-01'
logger.error('Setting Latest Date to be ' + str(latestdate) + '. You should inform CV that the issue data is stale.')
c_date = datetime.date(int(latestdate[:4]),int(latestdate[5:7]),1)
n_date = datetime.date.today()
recentchk = (n_date - c_date).days
if recentchk <= 55:
lastpubdate = 'Present'
else:
lastpubdate = str(ltmonth) + ' ' + str(ltyear)
publishfigure = str(stmonth) + ' ' + str(styear) + ' - ' + str(lastpubdate)
if stmonth == '?' and styear == '?' and lastpubdate =='0000' and comicIssues == '0':
logger.info('No available issue data - I believe this is a NEW series.')
latestdate = latestissueinfo[0]['latestdate']
latestiss = latestissueinfo[0]['latestiss']
lastpubdate = 'Present'
publishfigure = str(SeriesYear) + ' - ' + str(lastpubdate)
publishfigure = str(stmonth) + ' ' + str(styear) + ' - ' + str(lastpubdate)
controlValueStat = {"ComicID": comicid}

View File

@ -96,9 +96,10 @@ def libraryScan(dir=None, append=False, ComicID=None, ComicName=None, cron=None)
import_comicids = {}
for watch in watchlist:
#use the comicname_filesafe to start
watchdisplaycomic = re.sub('[\_\#\,\/\:\;\!\$\%\&\+\'\?\@]', ' ', watch['ComicName']).encode('utf-8').strip()
# let's clean up the name, just in case for comparison purposes...
watchcomic = re.sub('[\_\#\,\/\:\;\.\-\!\$\%\&\+\'\?\@]', ' ', watch['ComicName']).encode('utf-8').strip()
watchcomic = re.sub('[\_\#\,\/\:\;\.\-\!\$\%\&\+\'\?\@]', ' ', watch['ComicName_Filesafe']).encode('utf-8').strip()
#watchcomic = re.sub('\s+', ' ', str(watchcomic)).strip()
if ' the ' in watchcomic.lower():
@ -153,6 +154,10 @@ def libraryScan(dir=None, append=False, ComicID=None, ComicName=None, cron=None)
d_filename = re.sub('[\_\#\,\/\;\!\$\%\&\?\@]', ' ', comfilename)
d_filename = re.sub('[\:\-\+\']', '#', d_filename)
#strip extraspaces
d_filename = re.sub('\s+', ' ', d_filename)
cfilename = re.sub('\s+', ' ', cfilename)
#versioning - remove it
subsplit = cfilename.replace('_', ' ').split()
volno = None
@ -315,14 +320,13 @@ def libraryScan(dir=None, append=False, ComicID=None, ComicName=None, cron=None)
logger.fdebug("adjusted comic and issue: " + str(comic_iss))
#remove 'the' from here for proper comparisons.
if ' the ' in comic_iss.lower():
comic_iss = comic_iss[-4:]
comic_iss = re.sub('\\bthe\\b','', comic_iss).strip()
splitit = comic_iss.split(None)
logger.fdebug("adjusting from: " + str(comic_iss_b4) + " to: " + str(comic_iss))
#here we cycle through the Watchlist looking for a match.
while (cm_cn < watchcnt):
#setup the watchlist
comname = ComicName[cm_cn]
print ("watch_comic:" + comname)
comyear = ComicYear[cm_cn]
compub = ComicPublisher[cm_cn]
comtotal = ComicTotal[cm_cn]

View File

@ -15,6 +15,7 @@
from __future__ import with_statement
import re
import time
import threading
import urllib, urllib2
@ -27,16 +28,20 @@ from mylar.helpers import multikeysort, replace_all, cleanName, cvapi_check
mb_lock = threading.Lock()
def pullsearch(comicapi,comicquery,offset,explicit):
def pullsearch(comicapi,comicquery,offset,explicit,type):
u_comicquery = urllib.quote(comicquery.encode('utf-8').strip())
u_comicquery = u_comicquery.replace(" ", "%20")
if explicit == 'all' or explicit == 'loose':
PULLURL = mylar.CVURL + 'search?api_key=' + str(comicapi) + '&resources=volume&query=' + u_comicquery + '&field_list=id,name,start_year,site_detail_url,count_of_issues,image,publisher,description&format=xml&page=' + str(offset)
PULLURL = mylar.CVURL + 'search?api_key=' + str(comicapi) + '&resources=' + str(type) + '&query=' + u_comicquery + '&field_list=id,name,start_year,site_detail_url,count_of_issues,image,publisher,description&format=xml&page=' + str(offset)
else:
# 02/22/2014 use the volume filter label to get the right results.
PULLURL = mylar.CVURL + 'volumes?api_key=' + str(comicapi) + '&filter=name:' + u_comicquery + '&field_list=id,name,start_year,site_detail_url,count_of_issues,image,publisher,description&format=xml&offset=' + str(offset) # 2012/22/02 - CVAPI flipped back to offset instead of page
# add the 's' to the end of type to pluralize the caption (it's needed)
if type == 'story_arc':
logger.info('redefining.')
u_comicquery = re.sub("%20AND%20", "%20", u_comicquery)
PULLURL = mylar.CVURL + str(type) + 's?api_key=' + str(comicapi) + '&filter=name:' + u_comicquery + '&field_list=id,name,start_year,site_detail_url,count_of_issues,image,publisher,description&format=xml&offset=' + str(offset) # 2012/22/02 - CVAPI flipped back to offset instead of page
#all these imports are standard on most modern python implementations
#CV API Check here.
@ -59,7 +64,7 @@ def pullsearch(comicapi,comicquery,offset,explicit):
dom = parseString(data)
return dom
def findComic(name, mode, issue, limityear=None, explicit=None):
def findComic(name, mode, issue, limityear=None, explicit=None, type=None):
#with mb_lock:
comiclist = []
@ -77,7 +82,7 @@ def findComic(name, mode, issue, limityear=None, explicit=None):
if explicit is None:
#logger.fdebug('explicit is None. Setting to Default mode of ALL search words.')
comicquery=name.replace(" ", " AND ")
#comicquery=name.replace(" ", " AND ")
explicit = 'all'
#OR
@ -99,8 +104,11 @@ def findComic(name, mode, issue, limityear=None, explicit=None):
else:
comicapi = mylar.COMICVINE_API
if type is None:
type = 'volume'
#let's find out how many results we get from the query...
searched = pullsearch(comicapi,comicquery,0,explicit)
searched = pullsearch(comicapi,comicquery,0,explicit,type)
if searched is None: return False
totalResults = searched.getElementsByTagName('number_of_total_results')[0].firstChild.wholeText
logger.fdebug("there are " + str(totalResults) + " search results...")
@ -118,8 +126,8 @@ def findComic(name, mode, issue, limityear=None, explicit=None):
#explicit uses offset
offsetcount = countResults
searched = pullsearch(comicapi,comicquery,offsetcount,explicit)
comicResults = searched.getElementsByTagName('volume')
searched = pullsearch(comicapi,comicquery,offsetcount,explicit,type)
comicResults = searched.getElementsByTagName(type) #('volume')
body = ''
n = 0
if not comicResults:

View File

@ -16,13 +16,12 @@
from __future__ import division
import mylar
from mylar import logger, db, updater, helpers, parseit, findcomicfeed, notifiers, rsscheck
from mylar import logger, db, updater, helpers, parseit, findcomicfeed, notifiers, rsscheck, Failed
import lib.feedparser as feedparser
import urllib
import os, errno
import string
import sqlite3 as lite
import sys
import getopt
import re
@ -34,7 +33,11 @@ import email.utils
import datetime
from wsgiref.handlers import format_date_time
def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, IssueID, AlternateSearch=None, UseFuzzy=None, ComicVersion=None, SARC=None, IssueArcID=None, mode=None, rsscheck=None, ComicID=None, manualsearch=None):
def search_init(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDate, StoreDate, IssueID, AlternateSearch=None, UseFuzzy=None, ComicVersion=None, SARC=None, IssueArcID=None, mode=None, rsscheck=None, ComicID=None, manualsearch=None, filesafe=None):
if filesafe:
if filesafe != ComicName:
logger.info('[SEARCH] altering ComicName to search-safe Name : ' + filesafe)
ComicName = filesafe
if ComicYear == None: ComicYear = '2014'
else: ComicYear = str(ComicYear)[:4]
if Publisher == 'IDW Publishing': Publisher = 'IDW'
@ -597,46 +600,51 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
except:
logger.fdebug('invalid date found. Unable to continue - skipping result.')
continue
#use store date instead of publication date for comparisons since publication date is usually +2 months
if StoreDate is None or StoreDate == '0000-00-00':
if IssueDate is None or IssueDate == '0000-00-00':
logger.fdebug('Invalid store date & issue date detected - you probably should refresh the series or wait for CV to correct the data')
if UseFuzzy == "1":
logger.fdebug('Year has been fuzzied for this series, ignoring store date comparison entirely.')
else:
#use store date instead of publication date for comparisons since publication date is usually +2 months
if StoreDate is None or StoreDate == '0000-00-00':
if IssueDate is None or IssueDate == '0000-00-00':
logger.fdebug('Invalid store date & issue date detected - you probably should refresh the series or wait for CV to correct the data')
continue
else:
stdate = IssueDate
else:
stdate = StoreDate
#logger.fdebug('Posting date of : ' + str(pubdate))
# convert it to a tuple
dateconv = email.utils.parsedate_tz(pubdate)
#logger.fdebug('dateconv of : ' + str(dateconv))
# convert it to a numeric time, then subtract the timezone difference (+/- GMT)
if dateconv[-1] is not None:
postdate_int = time.mktime(dateconv[:len(dateconv)-1]) - dateconv[-1]
else:
postdate_int = time.mktime(dateconv[:len(dateconv)-1])
#logger.fdebug('postdate_int of : ' + str(postdate_int))
#logger.fdebug('Issue date of : ' + str(stdate))
#convert it to a Thu, 06 Feb 2014 00:00:00 format
issue_convert = datetime.datetime.strptime(stdate.rstrip(), '%Y-%m-%d')
#logger.fdebug('issue_convert:' + str(issue_convert))
#issconv = issue_convert.strftime('%a, %d %b %Y %H:%M:%S')
# to get past different locale's os-dependent dates, let's convert it to a generic datetime format
stamp = time.mktime(issue_convert.timetuple())
#logger.fdebug('stamp: ' + str(stamp))
issconv = format_date_time(stamp)
#logger.fdebug('issue date is :' + str(issconv))
#convert it to a tuple
econv = email.utils.parsedate_tz(issconv)
#logger.fdebug('econv:' + str(econv))
#convert it to a numeric and drop the GMT/Timezone
issuedate_int = time.mktime(econv[:len(econv)-1])
#logger.fdebug('issuedate_int:' + str(issuedate_int))
if postdate_int < issuedate_int:
logger.fdebug(str(pubdate) + ' is before store date of ' + str(stdate) + '. Ignoring search result as this is not the right issue.')
continue
else:
stdate = IssueDate
else:
stdate = StoreDate
#logger.fdebug('Posting date of : ' + str(pubdate))
# convert it to a tuple
dateconv = email.utils.parsedate_tz(pubdate)
#logger.fdebug('dateconv of : ' + str(dateconv))
# convert it to a numeric time, then subtract the timezone difference (+/- GMT)
if dateconv[-1] is not None:
postdate_int = time.mktime(dateconv[:len(dateconv)-1]) - dateconv[-1]
else:
postdate_int = time.mktime(dateconv[:len(dateconv)-1])
#logger.fdebug('postdate_int of : ' + str(postdate_int))
#logger.fdebug('Issue date of : ' + str(stdate))
#convert it to a Thu, 06 Feb 2014 00:00:00 format
issue_convert = datetime.datetime.strptime(stdate.rstrip(), '%Y-%m-%d')
#logger.fdebug('issue_convert:' + str(issue_convert))
#issconv = issue_convert.strftime('%a, %d %b %Y %H:%M:%S')
# to get past different locale's os-dependent dates, let's convert it to a generic datetime format
stamp = time.mktime(issue_convert.timetuple())
#logger.fdebug('stamp: ' + str(stamp))
issconv = format_date_time(stamp)
#logger.fdebug('issue date is :' + str(issconv))
#convert it to a tuple
econv = email.utils.parsedate_tz(issconv)
#logger.fdebug('econv:' + str(econv))
#convert it to a numeric and drop the GMT/Timezone
issuedate_int = time.mktime(econv[:len(econv)-1])
#logger.fdebug('issuedate_int:' + str(issuedate_int))
if postdate_int < issuedate_int:
logger.fdebug(str(pubdate) + ' is before store date of ' + str(stdate) + '. Ignoring search result as this is not the right issue.')
continue
else:
logger.fdebug(str(pubdate) + ' is after store date of ' + str(stdate))
logger.fdebug(str(pubdate) + ' is after store date of ' + str(stdate))
# -- end size constaints.
@ -1094,6 +1102,10 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
#issue comparison now as well
if int(intIss) == int(comintIss):
comicinfo = []
comicinfo.append({"ComicName": ComicName,
"IssueNumber": IssueNumber,
"comyear": comyear})
#check if nzb is in do not download list ;)
if nzbprov == 'experimental':
#id is located after the /download/ portion
@ -1113,13 +1125,29 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
nzbtempid = path_parts[2]
nzbid = re.sub('.torrent', '', nzbtempid).rstrip()
elif nzbprov == 'nzb.su':
pass
url_parts = urlparse.urlparse(entry['link'])
path_parts = url_parts[2].rpartition('/')
nzbid = re.sub('.nzb&amp','', path_parts[2]).strip()
elif nzbprov == 'dognzb':
pass
url_parts = urlparse.urlparse(entry['link'])
path_parts = url_parts[2].rpartition('/')
nzbid = path_parts[0].rsplit('/',1)[1]
elif nzbprov == 'newznab':
#if in format of http://newznab/getnzb/<id>.nzb&i=1&r=apikey
nzbid = os.path.splitext(entry['link'])[0].rsplit('/', 1)[1]
nzbname = nzbname_create(nzbprov, info=comicinfo, title=entry['title'])
if mylar.FAILED_DOWNLOAD_HANDLING:
if nzbid is not None:
call_the_fail = Failed.FailedProcessor(nzb_name=nzbname, id=nzbid, issueid=IssueID, comicid=ComicID, prov=tmpprov)
check_the_fail = call_the_fail.failed_check()
if check_the_fail == 'Failed':
logger.fdebug('[FAILED_DOWNLOAD_CHECKER] [' + str(tmpprov) + '] Marked as a bad download : ' + str(nzbid))
continue
elif check_the_fail == 'Good':
logger.fdebug('[FAILED_DOWNLOAD_CHECKER] This is not in the failed downloads list. Will continue with the download.')
logger.fdebug('issues match!')
logger.info(u"Found " + ComicName + " (" + str(comyear) + ") issue: " + str(IssueNumber) + " using " + str(tmpprov) )
## -- inherit issue. Comic year is non-standard. nzb year is the year
@ -1131,7 +1159,6 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
linkit = os.path.splitext(entry['link'])[1]
if mylar.USE_SABNZBD:
linkit = linkit.replace("&", "%26")
logger.fdebug('new linkit:' + linkit)
linkapi = str(linkstart) + str(linkit)
else:
# this should work for every other provider
@ -1147,27 +1174,16 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
if mylar.USE_BLACKHOLE and nzbprov != 'CBT' and nzbprov != 'KAT':
logger.fdebug("using blackhole directory at : " + str(mylar.BLACKHOLE_DIR))
if os.path.exists(mylar.BLACKHOLE_DIR):
#pretty this biatch up.
BComicName = re.sub('[\:\,\/\?]', '', str(ComicName))
Bl_ComicName = re.sub('[\&]', 'and', str(BComicName))
filenamenzb = str(re.sub(" ", ".", str(Bl_ComicName))) + "." + str(IssueNumber) + ".(" + str(comyear) + ").nzb"
# Add a user-agent
request = urllib2.Request(linkapi) #(str(mylar.BLACKHOLE_DIR) + str(filenamenzb))
request.add_header('User-Agent', str(mylar.USER_AGENT))
try:
opener = helpers.urlretrieve(urllib2.urlopen(request), str(mylar.BLACKHOLE_DIR) + str(filenamenzb))
opener = helpers.urlretrieve(urllib2.urlopen(request), str(mylar.BLACKHOLE_DIR) + str(nzbname) + '.nzb')
except Exception, e:
logger.warn('Error fetching data from %s: %s' % (nzbprov, e))
return
logger.fdebug("filename saved to your blackhole as : " + str(filenamenzb))
logger.info(u"Successfully sent .nzb to your Blackhole directory : " + str(mylar.BLACKHOLE_DIR) + str(filenamenzb) )
extensions = ('.cbr', '.cbz')
if filenamenzb.lower().endswith(extensions):
fd, ext = os.path.splitext(filenamenzb)
logger.fdebug("Removed extension from nzb: " + ext)
nzbname = re.sub(str(ext), '', str(filenamenzb))
logger.fdebug("nzb name to be used for post-processing is : " + str(nzbname))
logger.fdebug("filename saved to your blackhole as : " + str(nzbname) + '.nzb')
logger.info(u"Successfully sent .nzb to your Blackhole directory : " + str(mylar.BLACKHOLE_DIR) + str(filenamenzb) + '.nzb')
sent_to = "your Blackhole Directory"
#end blackhole
elif nzbprov == 'CBT' or nzbprov == 'KAT':
@ -1177,13 +1193,6 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
logger.fdebug("Torrent Provider:" + nzbprov)
foundc = "yes"
#let's change all space to decimals for simplicity
nzbname = re.sub(" ", ".", str(entry['title']))
#gotta replace & or escape it
nzbname = re.sub("\&", 'and', str(nzbname))
nzbname = re.sub('[\,\:\?]', '', str(nzbname))
if nzbname.lower().endswith('.torrent'):
nzbname = re.sub('.torrent', '', nzbname)
rcheck = rsscheck.torsend2client(ComicName, IssueNumber, comyear, entry['link'], nzbprov)
if rcheck == "fail":
logger.error("Unable to send torrent - check logs and settings.")
@ -1208,27 +1217,8 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
if e.errno != errno.EEXIST:
raise
logger.fdebug("link to retrieve via api:" + str(helpers.apiremove(linkapi,'$')))
#let's change all space to decimals for simplicity
nzbname = re.sub('\s+',' ', entry['title']) #make sure we remove the extra spaces.
logger.fdebug('[SEARCHER] entry[title]: ' + entry['title'])
logger.fdebug('[SEARCHER] nzbname (\s): ' + nzbname)
nzbname = re.sub(' ', '.', nzbname)
logger.fdebug('[SEARCHER] nzbname (space to .): ' + nzbname)
#gotta replace & or escape it
nzbname = re.sub("\&", 'and', nzbname)
nzbname = re.sub('[\,\:\?]', '', nzbname)
extensions = ('.cbr', '.cbz')
logger.fdebug('[SEARCHER] end nzbname: ' + nzbname)
if nzbname.lower().endswith(extensions):
fd, ext = os.path.splitext(nzbname)
logger.fdebug("Removed extension from nzb: " + ext)
nzbname = re.sub(str(ext), '', str(nzbname))
logger.fdebug("nzbname used for post-processing:" + str(nzbname))
# #test nzb.get
#test nzb.get
if mylar.USE_NZBGET:
from xmlrpclib import ServerProxy
if mylar.NZBGET_HOST[:4] == 'http':
@ -1271,8 +1261,12 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
if mylar.SAB_CATEGORY:
tmpapi = tmpapi + "&cat=" + str(mylar.SAB_CATEGORY)
logger.fdebug("...attaching category: " + str(helpers.apiremove(tmpapi,'&')))
if mylar.RENAME_FILES or mylar.POST_PROCESSING:
tmpapi = tmpapi + "&script=ComicRN.py"
if mylar.POST_PROCESSING: #or mylar.RENAME_FILES:
if mylar.POST_PROCESSING_SCRIPT:
#this is relative to the SABnzbd script directory (ie. no path)
tmpapi = tmpapi + "&script=" + mylar.POST_PROCESSING_SCRIPT
else:
tmpapi = tmpapi + "&script=ComicRN.py"
logger.fdebug("...attaching rename script: " + str(helpers.apiremove(tmpapi,'&')))
#final build of send-to-SAB
tmpapi = tmpapi + "&apikey=" + str(mylar.SAB_APIKEY)
@ -1333,7 +1327,8 @@ def NZB_SEARCH(ComicName, IssueNumber, ComicYear, SeriesYear, Publisher, IssueDa
if foundc == "yes":
foundcomic.append("yes")
logger.fdebug("Found matching comic...preparing to send to Updater with IssueID: " + str(IssueID) + " and nzbname: " + str(nzbname))
updater.nzblog(IssueID, nzbname, ComicName, SARC, IssueArcID)
if '[RSS]' in tmpprov : tmpprov = tmpprov[:-4].strip()
updater.nzblog(IssueID, nzbname, ComicName, SARC, IssueArcID, nzbid, tmpprov)
prov_count == 0
#break
return foundc
@ -1409,7 +1404,7 @@ def searchforissue(issueid=None, new=False, rsscheck=None):
ComicYear = str(result['IssueDate'])[:4]
mode = result['mode']
if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.ENABLE_KAT or mylar.ENABLE_CBT) and (mylar.USE_SABNZBD or mylar.USE_NZBGET or mylar.ENABLE_TORRENTS or mylar.USE_BLACKHOLE):
foundNZB, prov = search_init(comic['ComicName'], result['Issue_Number'], str(ComicYear), comic['ComicYear'], Publisher, IssueDate, StoreDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, rsscheck=rsscheck, ComicID=result['ComicID'])
foundNZB, prov = search_init(comic['ComicName'], result['Issue_Number'], str(ComicYear), comic['ComicYear'], Publisher, IssueDate, StoreDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, rsscheck=rsscheck, ComicID=result['ComicID'], filesafe=comic['ComicName_Filesafe'])
if foundNZB == "yes":
#print ("found!")
updater.foundsearch(result['ComicID'], result['IssueID'], mode=mode, provider=prov)
@ -1448,7 +1443,7 @@ def searchforissue(issueid=None, new=False, rsscheck=None):
foundNZB = "none"
if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.ENABLE_KAT or mylar.ENABLE_CBT) and (mylar.USE_SABNZBD or mylar.USE_NZBGET or mylar.ENABLE_TORRENTS or mylar.USE_BLACKHOLE):
foundNZB, prov = search_init(comic['ComicName'], result['Issue_Number'], str(IssueYear), comic['ComicYear'], Publisher, IssueDate, StoreDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, rsscheck=rsscheck, ComicID=result['ComicID'])
foundNZB, prov = search_init(comic['ComicName'], result['Issue_Number'], str(IssueYear), comic['ComicYear'], Publisher, IssueDate, StoreDate, result['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, rsscheck=rsscheck, ComicID=result['ComicID'], filesafe=comic['ComicName_Filesafe'])
if foundNZB == "yes":
logger.fdebug("I found " + comic['ComicName'] + ' #:' + str(result['Issue_Number']))
updater.foundsearch(ComicID=result['ComicID'], IssueID=result['IssueID'], mode=mode, provider=prov)
@ -1481,7 +1476,7 @@ def searchIssueIDList(issuelist):
else:
IssueYear = str(issue['IssueDate'])[:4]
if (mylar.NZBSU or mylar.DOGNZB or mylar.EXPERIMENTAL or mylar.NEWZNAB or mylar.ENABLE_CBT or mylar.ENABLE_KAT) and (mylar.USE_SABNZBD or mylar.USE_NZBGET or mylar.ENABLE_TORRENTS or mylar.USE_BLACKHOLE):
foundNZB, prov = search_init(comic['ComicName'], issue['Issue_Number'], str(IssueYear), comic['ComicYear'], Publisher, issue['IssueDate'], issue['ReleaseDate'], issue['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, ComicID=issue['ComicID'])
foundNZB, prov = search_init(comic['ComicName'], issue['Issue_Number'], str(IssueYear), comic['ComicYear'], Publisher, issue['IssueDate'], issue['ReleaseDate'], issue['IssueID'], AlternateSearch, UseFuzzy, ComicVersion, SARC=None, IssueArcID=None, mode=mode, ComicID=issue['ComicID'], filesafe=comic['ComicName_Filesafe'])
if foundNZB == "yes":
#print ("found!")
updater.foundsearch(ComicID=issue['ComicID'], IssueID=issue['IssueID'], mode=mode, provider=prov)
@ -1533,3 +1528,50 @@ def provider_sequence(nzbprovider, torprovider, newznab_hosts):
logger.fdebug('sequence is now to start with ' + pr_order[1] + ' at spot #' + str(pr_order[0]))
return prov_order,newznab_info
def nzbname_create(provider, title=None, info=None):
#the nzbname here is used when post-processing
# it searches nzblog which contains the nzbname to pull out the IssueID and start the post-processing
# it is also used to keep the hashinfo for the nzbname in case it fails downloading, it will get put into the failed db for future exclusions
if mylar.USE_BLACKHOLE and provider != 'CBT' and provider != 'KAT':
if os.path.exists(mylar.BLACKHOLE_DIR):
#load in the required info to generate the nzb names when required (blackhole only)
ComicName = info[0]['ComicName']
IssueNumber = info[0]['IssueNumber']
comyear = info[0]['comyear']
#pretty this biatch up.
BComicName = re.sub('[\:\,\/\?]', '', str(ComicName))
Bl_ComicName = re.sub('[\&]', 'and', str(BComicName))
nzbname = str(re.sub(" ", ".", str(Bl_ComicName))) + "." + str(IssueNumber) + ".(" + str(comyear) + ")"
logger.fdebug("nzb name to be used for post-processing is : " + str(nzbname))
elif provider == 'CBT' or provider == 'KAT':
#let's change all space to decimals for simplicity
nzbname = re.sub(" ", ".", title)
#gotta replace & or escape it
nzbname = re.sub("\&", 'and', str(nzbname))
nzbname = re.sub('[\,\:\?]', '', str(nzbname))
if nzbname.lower().endswith('.torrent'):
nzbname = re.sub('.torrent', '', nzbname)
else:
# let's change all space to decimals for simplicity
nzbname = re.sub('\s+',' ', title) #make sure we remove the extra spaces.
logger.fdebug('[SEARCHER] entry[title]: ' + title)
logger.fdebug('[SEARCHER] nzbname (\s): ' + nzbname)
nzbname = re.sub(' ', '.', nzbname)
logger.fdebug('[SEARCHER] nzbname (space to .): ' + nzbname)
#gotta replace & or escape it
nzbname = re.sub("\&", 'and', nzbname)
nzbname = re.sub('[\,\:\?]', '', nzbname)
extensions = ('.cbr', '.cbz')
logger.fdebug('[SEARCHER] end nzbname: ' + nzbname)
nzbname = re.sub('.cbr', '', nzbname).strip()
nzbname = re.sub('.cbz', '', nzbname).strip()
logger.fdebug("nzbname used for post-processing:" + str(nzbname))
return nzbname

View File

@ -281,13 +281,42 @@ def populate(link,publisher,shipdate):
if exinfo == '&': exinfo = 'N/A'
comic = tempName[:stissue].strip()
if 'for \$1' in comic:
exinfo = 'for $1'
comic = comic.replace('for \$1\:', '').lstrip()
issuedate = shipdate
if 'on sale' in str(titlet).lower():
onsale_start = str(titlet).lower().find('on sale') + 8
onsale_end = str(titlet).lower().find('<br>',onsale_start)
thedate = str(titlet)[onsale_start:onsale_end]
m = None
basemonths = {'january':'1','jan':'1','february':'2','feb':'2','march':'3','mar':'3','april':'4','apr':'4','may':'5','june':'6','july':'7','august':'8','aug':'8','september':'9','sept':'9','october':'10','oct':'10','november':'11','nov':'11','december':'12','dec':'12'}
for month in basemonths:
if month in thedate.lower():
m = basemonths[month]
monthname = month
break
if m is not None:
theday = len(month) + 1 # account for space between month & day
thedaystart = thedate[theday:(theday+2)].strip() # day numeric won't exceed 2
if len(str(thedaystart)) == 1:
thedaystart = '0' + str(thedaystart)
if len(str(m)) == 1:
m = '0' + str(m)
thedate = shipdate[-4:] + '-' + str(m) + '-' + str(thedaystart)
logger.info('[' + comic + '] On sale :' + str(thedate))
exinfo += ' [' + str(thedate) + ']'
issuedate = thedate
if issue1:
upcome.append({
'Shipdate': shipdate,
'Shipdate': issuedate,
'Publisher': publisher.upper(),
'Issue': re.sub('#', '',issue1).lstrip(),
'Comic': comic.upper(),
@ -298,7 +327,7 @@ def populate(link,publisher,shipdate):
#print ('extra info: ' + exinfo)
if issue2:
upcome.append({
'Shipdate': shipdate,
'Shipdate': issuedate,
'Publisher': publisher.upper(),
'Issue': re.sub('#', '', issue2).lstrip(),
'Comic': comic.upper(),
@ -309,7 +338,7 @@ def populate(link,publisher,shipdate):
#print ('extra info: ' + exinfo)
else:
upcome.append({
'Shipdate': shipdate,
'Shipdate': issuedate,
'Publisher': publisher.upper(),
'Issue': re.sub('#', '', issue).lstrip(),
'Comic': comic.upper(),

View File

@ -113,44 +113,55 @@ def dbUpdate(ComicIDList=None):
fndissue = []
for issue in issues:
for issuenew in issues_new:
#logger.fdebug(str(issue['Issue_Number']) + ' - issuenew:' + str(issuenew['IssueID']) + ' : ' + str(issuenew['Status']))
#logger.fdebug(str(issue['Issue_Number']) + ' - issue:' + str(issue['IssueID']) + ' : ' + str(issue['Status']))
if issuenew['IssueID'] == issue['IssueID'] and issuenew['Status'] != issue['Status']:
ctrlVAL = {"IssueID": issue['IssueID']}
#if the status is None and the original status is either Downloaded / Archived, keep status & stats
if issuenew['Status'] == None and (issue['Status'] == 'Downloaded' or issue['Status'] == 'Archived'):
newVAL = {"Location": issue['Location'],
"ComicSize": issue['ComicSize'],
"Status": issue['Status']}
#if the status is now Downloaded/Snatched, keep status & stats (downloaded only)
elif issuenew['Status'] == 'Downloaded' or issue['Status'] == 'Snatched':
newVAL = {"Location": issue['Location'],
"ComicSize": issue['ComicSize']}
if issuenew['Status'] == 'Downloaded':
newVAL['Status'] = issuenew['Status']
logger.fdebug(str(issue['Issue_Number']) + ' - issuenew:' + str(issuenew['IssueID']) + ' : ' + str(issuenew['Status']))
logger.fdebug(str(issue['Issue_Number']) + ' - issue:' + str(issue['IssueID']) + ' : ' + str(issue['Status']))
try:
if issuenew['IssueID'] == issue['IssueID'] and (issuenew['Status'] != issue['Status'] or issue['IssueDate_Edit'] is not None):
ctrlVAL = {"IssueID": issue['IssueID']}
#if the status is None and the original status is either Downloaded / Archived, keep status & stats
if issuenew['Status'] == None and (issue['Status'] == 'Downloaded' or issue['Status'] == 'Archived'):
newVAL = {"Location": issue['Location'],
"ComicSize": issue['ComicSize'],
"Status": issue['Status']}
#if the status is now Downloaded/Snatched, keep status & stats (downloaded only)
elif issuenew['Status'] == 'Downloaded' or issue['Status'] == 'Snatched':
newVAL = {"Location": issue['Location'],
"ComicSize": issue['ComicSize']}
if issuenew['Status'] == 'Downloaded':
newVAL['Status'] = issuenew['Status']
else:
newVAL['Status'] = issue['Status']
elif issue['Status'] == 'Archived':
newVAL = {"Status": issue['Status'],
"Location": issue['Location'],
"ComicSize": issue['ComicSize']}
else:
newVAL['Status'] = issue['Status']
#change the status to the previous status
newVAL = {"Status": issue['Status']}
elif issue['Status'] == 'Archived':
newVAL = {"Status": issue['Status'],
"Location": issue['Location'],
"ComicSize": issue['ComicSize']}
else:
#change the status to the previous status
newVAL = {"Status": issue['Status']}
if newVAL['Status'] == None:
newVAL = {"Status": "Skipped"}
if newVAL['Status'] == None:
newVAL = {"Status": "Skipped"}
if issue['IssueDate_Edit']:
logger.info('[#' + str(issue['Issue_Number']) + '] detected manually edited Issue Date.')
logger.info('new value : ' + str(issue['IssueDate']) + ' ... cv value : ' + str(issuenew['IssueDate']))
newVAL['IssueDate'] = issue['IssueDate']
newVAL['IssueDate_Edit'] = issue['IssueDate_Edit']
if any(d['IssueID'] == str(issue['IssueID']) for d in ann_list):
#logger.fdebug("annual detected for " + str(issue['IssueID']) + " #: " + str(issue['Issue_Number']))
myDB.upsert("Annuals", newVAL, ctrlVAL)
else:
#logger.fdebug('#' + str(issue['Issue_Number']) + ' writing issuedata: ' + str(newVAL))
myDB.upsert("Issues", newVAL, ctrlVAL)
fndissue.append({"IssueID": issue['IssueID']})
icount+=1
break
except:
logger.warn('Something is out of whack somewhere with the series.')
#if it's an annual (ie. deadpool-2011 ) on a refresh will throw index errors for some reason.
if any(d['IssueID'] == str(issue['IssueID']) for d in ann_list):
#logger.fdebug("annual detected for " + str(issue['IssueID']) + " #: " + str(issue['Issue_Number']))
myDB.upsert("Annuals", newVAL, ctrlVAL)
else:
#logger.fdebug('#' + str(issue['Issue_Number']) + ' writing issuedata: ' + str(newVAL))
myDB.upsert("Issues", newVAL, ctrlVAL)
fndissue.append({"IssueID": issue['IssueID']})
icount+=1
break
logger.info("In the process of converting the data to CV, I changed the status of " + str(icount) + " issues.")
issues_new = myDB.select('SELECT * FROM issues WHERE ComicID=? AND Status is NULL', [ComicID])
@ -410,7 +421,7 @@ def no_searchresults(ComicID):
"LatestIssue": "Error"}
myDB.upsert("comics", newValue, controlValue)
def nzblog(IssueID, NZBName, ComicName, SARC=None, IssueArcID=None):
def nzblog(IssueID, NZBName, ComicName, SARC=None, IssueArcID=None, id=None, prov=None):
myDB = db.DBConnection()
newValue = {"NZBName": NZBName}
@ -428,12 +439,17 @@ def nzblog(IssueID, NZBName, ComicName, SARC=None, IssueArcID=None):
IssueID = 'S' + str(IssueArcID)
newValue['SARC'] = SARC
controlValue = {"IssueID": IssueID}
#print controlValue
#newValue['NZBName'] = NZBName
#print newValue
controlValue = {"IssueID": IssueID,
"Provider": prov}
if id:
logger.info('setting the nzbid for this download grabbed by ' + prov + ' in the nzblog to : ' + str(id))
newValue["ID"] = id
myDB.upsert("nzblog", newValue, controlValue)
def foundsearch(ComicID, IssueID, mode=None, down=None, provider=None, SARC=None, IssueArcID=None, module=None):
# When doing a Force Search (Wanted tab), the resulting search calls this to update.
@ -563,9 +579,22 @@ def forceRescan(ComicID,archive=None,module=None):
myDB = db.DBConnection()
# file check to see if issue exists
rescan = myDB.selectone('SELECT * FROM comics WHERE ComicID=?', [ComicID]).fetchone()
if rescan['AlternateSearch'] is not None:
altnames = rescan['AlternateSearch'] + '##'
else:
altnames = ''
annscan = myDB.select('SELECT * FROM annuals WHERE ComicID=?', [ComicID])
if annscan is None:
pass
else:
for ascan in annscan:
logger.info('ReleaseComicName: ' + ascan['ReleaseComicName'])
if ascan['ReleaseComicName'] not in altnames:
altnames += ascan['ReleaseComicName'] + '!!' + ascan['ReleaseComicID'] + '##'
altnames = altnames[:-2]
logger.info(module + ' Now checking files for ' + rescan['ComicName'] + ' (' + str(rescan['ComicYear']) + ') in ' + rescan['ComicLocation'] )
if archive is None:
fc = filechecker.listFiles(dir=rescan['ComicLocation'], watchcomic=rescan['ComicName'], Publisher=rescan['ComicPublisher'], AlternateSearch=rescan['AlternateSearch'])
fc = filechecker.listFiles(dir=rescan['ComicLocation'], watchcomic=rescan['ComicName'], Publisher=rescan['ComicPublisher'], AlternateSearch=altnames) #rescan['AlternateSearch'])
else:
fc = filechecker.listFiles(dir=archive, watchcomic=rescan['ComicName'], Publisher=rescan['ComicPublisher'], AlternateSearch=rescan['AlternateSearch'])
iscnt = rescan['Total']
@ -747,9 +776,15 @@ def forceRescan(ComicID,archive=None,module=None):
if haveissue == "yes" or issuedupe == "yes": break
n+=1
else:
if tmpfc['AnnualComicID']:
ANNComicID = tmpfc['AnnualComicID']
logger.fdebug(module + ' Forcing ComicID to ' + str(ANNComicID) + ' in case of duplicate numbering across volumes.')
reannuals = myDB.select('SELECT * FROM annuals WHERE ComicID=? AND ReleaseComicID=?', [ComicID, ANNComicID])
else:
reannuals = myDB.select('SELECT * FROM annuals WHERE ComicID=?', [ComicID])
# annual inclusion here.
#logger.fdebug("checking " + str(temploc))
reannuals = myDB.select('SELECT * FROM annuals WHERE ComicID=?', [ComicID])
fcnew = shlex.split(str(temploc))
fcn = len(fcnew)
n = 0
@ -786,8 +821,8 @@ def forceRescan(ComicID,archive=None,module=None):
if int(fcdigit) == int_iss:
logger.fdebug(module + ' Annual match - issue : ' + str(int_iss))
for d in annualdupechk:
if int(d['fcdigit']) == int(fcdigit):
logger.fdebug(module + ' Duplicate annual issue detected - not counting this: ' + str(tmpfc['ComicFilename']))
if int(d['fcdigit']) == int(fcdigit) and d['anncomicid'] == ANNComicID:
logger.fdebug(module + ' Duplicate annual issue detected for Annual ComicID of ' + str(ANNComicID) + ' - not counting this: ' + str(tmpfc['ComicFilename']))
issuedupe = "yes"
break
if issuedupe == "no":
@ -800,7 +835,8 @@ def forceRescan(ComicID,archive=None,module=None):
logger.fdebug(module + ' .......filesize: ' + str(tmpfc['ComicSize']))
# to avoid duplicate issues which screws up the count...let's store the filename issues then
# compare earlier...
annualdupechk.append({'fcdigit': int(fcdigit)})
annualdupechk.append({'fcdigit': int(fcdigit),
'anncomicid': ANNComicID})
break
som+=1
if haveissue == "yes": break

View File

@ -33,7 +33,7 @@ import shutil
import mylar
from mylar import logger, db, importer, mb, search, filechecker, helpers, updater, parseit, weeklypull, PostProcessor, version, librarysync, moveit #,rsscheck
from mylar import logger, db, importer, mb, search, filechecker, helpers, updater, parseit, weeklypull, PostProcessor, version, librarysync, moveit, Failed #,rsscheck
#from mylar.helpers import checked, radio, today
import lib.simplejson as simplejson
@ -119,10 +119,11 @@ class WebInterface(object):
isCounts[3] = 0 #3 archived
isCounts[4] = 0 #4 downloaded
isCounts[5] = 0 #5 ignored
#isCounts[6] = 0 #6 read
isCounts[6] = 0 #6 failed
#isCounts[7] = 0 #7 read
for curResult in issues:
baseissues = {'skipped':1,'wanted':2,'archived':3,'downloaded':4,'ignored':5}
baseissues = {'skipped':1,'wanted':2,'archived':3,'downloaded':4,'ignored':5,'failed':6}
for seas in baseissues:
if curResult['Status'] is None:
continue
@ -136,7 +137,8 @@ class WebInterface(object):
"Wanted" : str(isCounts[2]),
"Archived" : str(isCounts[3]),
"Downloaded" : str(isCounts[4]),
"Ignored" : str(isCounts[5])
"Ignored" : str(isCounts[5]),
"Failed" : str(isCounts[6])
}
usethefuzzy = comic['UseFuzzy']
skipped2wanted = "0"
@ -173,7 +175,7 @@ class WebInterface(object):
return serve_template(templatename="comicdetails.html", title=comic['ComicName'], comic=comic, issues=issues, comicConfig=comicConfig, isCounts=isCounts, series=series, annuals=annuals, annualinfo=aName)
comicDetails.exposed = True
def searchit(self, name, issue=None, mode=None, type=None, explicit=None):
def searchit(self, name, issue=None, mode=None, type=None, explicit=None, serinfo=None):
if type is None: type = 'comic' # let's default this to comic search only for the time being (will add story arc, characters, etc later)
else: logger.fdebug(str(type) + " mode enabled.")
#mode dictates type of search:
@ -195,15 +197,15 @@ class WebInterface(object):
searchresults, explicit = mb.findComic(name, mode, issue=None, explicit=explicit)
elif type == 'comic' and mode == 'want':
searchresults, explicit = mb.findComic(name, mode, issue)
elif type == 'storyarc':
searchresults, explicit = mb.findComic(name, mode, issue=None, storyarc='yes')
elif type == 'story_arc':
searchresults, explicit = mb.findComic(name, mode=None, issue=None, explicit='explicit', type='story_arc')
searchresults = sorted(searchresults, key=itemgetter('comicyear','issues'), reverse=True)
#print ("Results: " + str(searchresults))
return serve_template(templatename="searchresults.html", title='Search Results for: "' + name + '"', searchresults=searchresults, type=type, imported=None, ogcname=None, name=name, explicit=explicit)
return serve_template(templatename="searchresults.html", title='Search Results for: "' + name + '"', searchresults=searchresults, type=type, imported=None, ogcname=None, name=name, explicit=explicit, serinfo=serinfo)
searchit.exposed = True
def addComic(self, comicid, comicname=None, comicyear=None, comicimage=None, comicissues=None, comicpublisher=None, imported=None, ogcname=None):
def addComic(self, comicid, comicname=None, comicyear=None, comicimage=None, comicissues=None, comicpublisher=None, imported=None, ogcname=None, serinfo=None):
myDB = db.DBConnection()
if imported == "confirm":
# if it's coming from the importer and it's just for confirmation, record the right selection and break.
@ -224,6 +226,17 @@ class WebInterface(object):
myDB.upsert("importresults", newValue, controlValue)
self.importResults()
return
elif imported == 'futurecheck':
print 'serinfo:' + str(serinfo)
logger.info('selected comicid of : ' + str(comicid) + ' [ ' + comicname + ' (' + str(comicyear) + ') ]')
ser = []
ser.append({"comicname": comicname,
"comicyear": comicyear,
"comicissues": comicissues,
"comicpublisher": comicpublisher,
"IssueDate": serinfo[0]['IssueDate'],
"IssueNumber": serinfo[0]['IssueNumber']})
self.future_check_add(comicid, ser)
sresults = []
cresults = []
mismatch = "no"
@ -410,19 +423,64 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("comicDetails?ComicID=%s" % gcomicid)
GCDaddComic.exposed = True
def post_process(self, nzb_name, nzb_folder):
logger.info(u"Starting postprocessing for : " + str(nzb_name) )
PostProcess = PostProcessor.PostProcessor(nzb_name, nzb_folder)
if nzb_name == 'Manual Run' or nzb_name == 'Manual+Run':
threading.Thread(target=PostProcess.Process).start()
raise cherrypy.HTTPRedirect("home")
else:
result = helpers.ThreadWithReturnValue(target=PostProcess.Process)
result.start()
#result = PostProcess.Process()
return result.join()
#log2screen = threading.Thread(target=PostProcessor.PostProcess, args=[nzb_name,nzb_folder]).start()
#return serve_template(templatename="postprocess.html", title="postprocess")
def post_process(self, nzb_name, nzb_folder, failed=False):
import Queue
logger.info('Starting postprocessing for : ' + nzb_name)
if failed == '0':
failed = False
elif failed == '1':
failed = True
queue = Queue.Queue()
if not failed:
PostProcess = PostProcessor.PostProcessor(nzb_name, nzb_folder, queue=queue)
if nzb_name == 'Manual Run' or nzb_name == 'Manual+Run':
threading.Thread(target=PostProcess.Process).start()
raise cherrypy.HTTPRedirect("home")
else:
thread_ = threading.Thread(target=PostProcess.Process, name="Post-Processing")
thread_.start()
thread_.join()
chk = queue.get()
while True:
if chk[0]['mode'] == 'fail':
yield chk[0]['self.log']
logger.info('Initiating Failed Download handling')
if chk[0]['annchk'] == 'no': mode = 'want'
else: mode = 'want_ann'
failed = True
break
elif chk[0]['mode'] == 'stop':
yield chk[0]['self.log']
break
else:
logger.error('mode is unsupported: ' + chk[0]['mode'])
yield chk[0]['self.log']
break
if failed:
if mylar.FAILED_DOWNLOAD_HANDLING:
#drop the if-else continuation so we can drop down to this from the above if statement.
logger.info('Initiating Failed Download handling for this download.')
FailProcess = Failed.FailedProcessor(nzb_name=nzb_name, nzb_folder=nzb_folder, queue=queue)
thread_ = threading.Thread(target=FailProcess.Process, name="FAILED Post-Processing")
thread_.start()
thread_.join()
failchk = queue.get()
if failchk[0]['mode'] == 'retry':
yield chk[0]['self.log']
logger.info('Attempting to return to search module with ' + str(failchk[0]['issueid']))
if failchk[0]['annchk'] == 'no': mode = 'want'
else: mode = 'want_ann'
self.queueit(mode=mode, ComicName=failchk[0]['comicname'], ComicIssue=failchk[0]['issuenumber'], ComicID=failchk[0]['comicid'], IssueID=failchk[0]['issueid'], manualsearch=True)
elif failchk[0]['mode'] == 'stop':
yield chk[0]['self.log']
else:
logger.error('mode is unsupported: ' + failchk[0]['mode'])
yield chk[0]['self.log']
else:
logger.warn('Failed Download Handling is not enabled. Leaving Failed Download as-is.')
post_process.exposed = True
def pauseArtist(self, ComicID):
@ -462,7 +520,7 @@ class WebInterface(object):
if ComicID is None:
myDB.action('DROP table nzblog')
logger.fdebug("Deleted nzblog table.")
myDB.action('CREATE TABLE IF NOT EXISTS nzblog (IssueID TEXT, NZBName TEXT, SARC TEXT)')
myDB.action('CREATE TABLE IF NOT EXISTS nzblog (IssueID TEXT, NZBName TEXT, SARC TEXT, PROVIDER TEXT, ID TEXT)')
logger.fdebug("Re-created nzblog table.")
raise cherrypy.HTTPRedirect("history")
wipenzblog.exposed = True
@ -619,13 +677,43 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("comicDetails?ComicID=%s" % ComicID)
refreshArtist.exposed=True
def editIssue(self, ComicID):
def issue_edit(self, id, value):
print 'here'
print 'id: ' + str(id)
print 'value: ' + str(value)
comicid = id[:id.find('.')]
print 'comicid:' + str(comicid)
issueid = id[id.find('.')+1:]
print 'issueid:' + str(issueid)
myDB = db.DBConnection()
comic = myDB.selectone('SELECT * from comics WHERE ComicID=?', [ComicID]).fetchone()
title = 'Now Editing ' + comic['ComicName']
return serve_template(templatename="editcomic.html", title=title, comic=comic)
#raise cherrypy.HTTPRedirect("comicDetails?ComicID=%s" & ComicID)
editIssue.exposed=True
comicchk = myDB.selectone('SELECT ComicYear FROM comics WHERE ComicID=?', [comicid]).fetchone()
issuechk = myDB.selectone('SELECT * FROM issues WHERE IssueID=?', [issueid]).fetchone()
if issuechk is None:
logger.error('Cannot edit this for some reason - something is wrong.')
return
oldissuedate = issuechk['IssueDate']
seriesyear = comicchk['ComicYear']
#check if the new date is in the correct format of yyyy-mm-dd
try:
valid_date = time.strptime(value, '%Y-%m-%d')
except ValueError:
logger.error('invalid date provided. Rejecting edit.')
return oldissuedate
#if the new issue year is less than the series year - reject it.
if value[:4] < seriesyear:
logger.error('Series year of ' + str(seriesyear) + ' is less than new issue date of ' + str(value[:4]))
return oldissuedate
newVal = {"IssueDate" : value,
"IssueDate_Edit" : oldissuedate}
ctrlVal = {"IssueID": issueid}
myDB.upsert("issues", newVal, ctrlVal)
logger.info('updated issueinfo')
return value
issue_edit.exposed=True
def force_rss(self):
logger.info('attempting to run RSS Check Forcibly')
@ -662,7 +750,7 @@ class WebInterface(object):
else:
newaction = action
for IssueID in args:
#print ("issueID: " + str(IssueID) + "... " + str(newaction))
print ("issueID: " + str(IssueID) + "... " + str(newaction))
if IssueID is None or 'issue_table' in IssueID or 'history_table' in IssueID:
continue
else:
@ -686,12 +774,17 @@ class WebInterface(object):
issuestoArchive.append(IssueID)
elif action == 'Wanted' or action == 'Retry':
if action == 'Retry': newaction = 'Wanted'
logger.info(u"Marking %s %s as %s" % (mi['ComicName'], mi['Issue_Number'], newaction))
logger.info(u"Marking %s %s as %s" % (comicname, mi['Issue_Number'], newaction))
issuesToAdd.append(IssueID)
elif action == 'Skipped':
logger.info(u"Marking " + str(IssueID) + " as Skipped")
elif action == 'Clear':
myDB.action("DELETE FROM snatched WHERE IssueID=?", [IssueID])
elif action == 'Failed' and mylar.FAILED_DOWNLOAD_HANDLING:
logger.info('Marking [' + comicname + '] : ' + str(IssueID) + ' as Failed. Sending to failed download handler.')
failedcomicid = mi['ComicID']
failedissueid = IssueID
break
controlValueDict = {"IssueID": IssueID}
newValueDict = {"Status": newaction}
if annchk == 'yes':
@ -699,6 +792,8 @@ class WebInterface(object):
else:
myDB.upsert("issues", newValueDict, controlValueDict)
logger.fdebug("updated...to " + str(newaction))
if action == 'Failed' and mylar.FAILED_DOWNLOAD_HANDLING:
self.failed_handling(failedcomicid, failedissueid)
if len(issuestoArchive) > 0:
updater.forceRescan(mi['ComicID'])
if len(issuesToAdd) > 0:
@ -763,8 +858,8 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("pullist")
#return
elif mode == 'want' or mode == 'want_ann' or manualsearch:
cdname = myDB.selectone("SELECT ComicName from comics where ComicID=?", [ComicID]).fetchone()
ComicName = cdname['ComicName']
cdname = myDB.selectone("SELECT ComicName, ComicName_Filesafe from comics where ComicID=?", [ComicID]).fetchone()
ComicName = cdname['ComicName_Filesafe']
controlValueDict = {"IssueID": IssueID}
newStatus = {"Status": "Wanted"}
if mode == 'want':
@ -804,7 +899,7 @@ class WebInterface(object):
Publisher = miy['ComicPublisher']
UseAFuzzy = miy['UseFuzzy']
ComicVersion = miy['ComicVersion']
foundcom, prov = search.search_init(ComicName, ComicIssue, ComicYear, SeriesYear, Publisher, issues['IssueDate'], storedate, IssueID, AlternateSearch, UseAFuzzy, ComicVersion, mode=mode, ComicID=ComicID, manualsearch=manualsearch)
foundcom, prov = search.search_init(ComicName, ComicIssue, ComicYear, SeriesYear, Publisher, issues['IssueDate'], storedate, IssueID, AlternateSearch, UseAFuzzy, ComicVersion, mode=mode, ComicID=ComicID, manualsearch=manualsearch, filesafe=miy['ComicName_Filesafe'])
if foundcom == "yes":
# file check to see if issue exists and update 'have' count
if IssueID is not None:
@ -819,24 +914,40 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect(redirect)
queueissue.exposed = True
def unqueueissue(self, IssueID, ComicID, ComicName=None, Issue=None, FutureID=None):
def unqueueissue(self, IssueID, ComicID, ComicName=None, Issue=None, FutureID=None, mode=None, ReleaseComicID=None):
myDB = db.DBConnection()
if ComicName is None:
issue = myDB.selectone('SELECT * FROM issues WHERE IssueID=?', [IssueID]).fetchone()
if ReleaseComicID is None: #ReleaseComicID is used for annuals.
issue = myDB.selectone('SELECT * FROM issues WHERE IssueID=?', [IssueID]).fetchone()
else:
issue = None
annchk = 'no'
if issue is None:
if mylar.ANNUALS_ON:
issann = myDB.selectone('SELECT * FROM annuals WHERE IssueID=?', [IssueID]).fetchone()
comicname = issann['ReleaseComicName']
issue = issann['Issue_Number']
if ReleaseComicID is None:
issann = myDB.selectone('SELECT * FROM annuals WHERE IssueID=?', [IssueID]).fetchone()
else:
issann = myDB.selectone('SELECT * FROM annuals WHERE IssueID=? AND ReleaseComicID=?', [IssueID, ReleaseComicID]).fetchone()
ComicName = issann['ReleaseComicName']
IssueNumber = issann['Issue_Number']
annchk = 'yes'
comicid = issann['ComicID']
ComicID = issann['ComicID']
ReleaseComicID = issann['ReleaseComicID']
else:
comicname = issue['ComicName']
issue = issue['Issue_Number']
logger.info(u"Marking " + comicname + " issue # " + str(issue) + " as Skipped...")
ComicName = issue['ComicName']
IssueNumber = issue['Issue_Number']
controlValueDict = {"IssueID": IssueID}
newValueDict = {"Status": "Skipped"}
if mode == 'failed' and mylar.FAILED_DOWNLOAD_HANDLING:
logger.info(u"Marking " + ComicName + " issue # " + str(IssueNumber) + " as Failed...")
newValueDict = {"Status": "Failed"}
myDB.upsert("failed", newValueDict, controlValueDict)
yield cherrypy.HTTPRedirect("comicDetails?ComicID=%s" % ComicID)
self.failed_handling(ComicID=ComicID, IssueID=IssueID)
else:
logger.info(u"Marking " + ComicName + " issue # " + str(IssueNumber) + " as Skipped...")
newValueDict = {"Status": "Skipped"}
if annchk == 'yes':
myDB.upsert("annuals", newValueDict, controlValueDict)
else:
@ -868,11 +979,34 @@ class WebInterface(object):
unqueueissue.exposed = True
def archiveissue(self, IssueID):
def failed_handling(self, ComicID, IssueID):
import Queue
queue = Queue.Queue()
FailProcess = Failed.FailedProcessor(issueid=IssueID, comicid=ComicID, queue=queue)
thread_ = threading.Thread(target=FailProcess.Process, name="FAILED Post-Processing")
thread_.start()
thread_.join()
failchk = queue.get()
if failchk[0]['mode'] == 'retry':
logger.info('Attempting to return to search module with ' + str(failchk[0]['issueid']))
if failchk[0]['annchk'] == 'no': mode = 'want'
else: mode = 'want_ann'
self.queueit(mode=mode, ComicName=failchk[0]['comicname'], ComicIssue=failchk[0]['issuenumber'], ComicID=failchk[0]['comicid'], IssueID=failchk[0]['issueid'], manualsearch=True)
elif failchk[0]['mode'] == 'stop':
pass
else:
logger.error('mode is unsupported: ' + failchk[0]['mode'])
failed_handling.exposed = True
def archiveissue(self, IssueID, comicid):
print 'marking issue : ' + str(IssueID)
myDB = db.DBConnection()
issue = myDB.selectone('SELECT * FROM issues WHERE IssueID=?', [IssueID]).fetchone()
annchk = 'no'
if issue is None:
print 'issue is none'
if mylar.ANNUALS_ON:
issann = myDB.selectone('SELECT * FROM annuals WHERE IssueID=?', [IssueID]).fetchone()
comicname = issann['ReleaseComicName']
@ -880,9 +1014,11 @@ class WebInterface(object):
annchk = 'yes'
comicid = issann['ComicID']
else:
print 'issue not none'
comicname = issue['ComicName']
print comicname
issue = issue['Issue_Number']
comicid = issue['ComicID']
print issue
logger.info(u"Marking " + comicname + " issue # " + str(issue) + " as archived...")
controlValueDict = {'IssueID': IssueID}
newValueDict = {'Status': 'Archived'}
@ -1014,12 +1150,14 @@ class WebInterface(object):
if chkfuture is not None:
logger.info('Already on Future Upcoming list - not adding at this time.')
return
logger.info('Adding ' + ComicName + ' # ' + str(Issue) + ' to future upcoming watchlist')
newCtrl = {"ComicName": ComicName,
"IssueNumber": Issue,
logger.info('Adding ' + ComicName + ' # ' + str(Issue) + ' [' + Publisher + '] to future upcoming watchlist')
newCtrl = {"ComicName": ComicName,
"IssueNumber": Issue,
"Publisher": Publisher}
newVal = {"Status": "Wanted",
"IssueDate": ShipDate}
myDB.upsert("futureupcoming", newVal, newCtrl)
fCtrl = {"FutureID": FutureID}
@ -1055,18 +1193,24 @@ class WebInterface(object):
"IssueNumber": cf['IssueNumber'], #this should be all #1's as the sql above limits the hits.
"Publisher": cf['Publisher'],
"Status": cf['Status']})
print 'cflist: ' + str(cflist)
#now we load in
logger.info('I will be looking to see if any information has been released for ' + str(len(cflist)) + ' series that are NEW series')
#limit the search to just the 'current year' since if it's anything but a #1, it should have associated data already.
#limittheyear = []
#limittheyear.append(cf['IssueDate'][-4:])
for ser in cflist:
logger.info('looking for new data for ' + ser['ComicName'] + '[#' + str(ser['IssueNumber']) + '] (' + str(ser['IssueDate'][-4:]) + ')')
searchresults, explicit = mb.findComic(ser['ComicName'], mode='pullseries', issue=ser['IssueNumber'], limityear=ser['IssueDate'][-4:], explicit='explicit')
theissdate = ser['IssueDate'][-4:]
if not theissdate.startswith('20'):
theissdate = ser['IssueDate'][:4]
logger.info('looking for new data for ' + ser['ComicName'] + '[#' + str(ser['IssueNumber']) + '] (' + str(theissdate) + ')')
searchresults, explicit = mb.findComic(ser['ComicName'], mode='pullseries', issue=ser['IssueNumber'], limityear=theissdate, explicit='all')
print searchresults
if len(searchresults) > 1:
logger.info('publisher: ' + str(ser['Publisher']))
logger.info('More than one result returned - this may have to be a manual add')
return serve_template(templatename="searchresults.html", title='New Series Results for: "' + ser['ComicName'] + '"',searchresults=searchresults, type='series', imported='futurecheck', ogcname=ser['ComicName'], name=ser['ComicName'], explicit='all', serinfo=ser) #imported=comicstoIMP, ogcname=ogcname)
#call secondary module here to complete the selected add.
else:
for sr in searchresults:
#we should probably load all additional issues for the series on the futureupcoming list that are marked as Wanted and then
@ -1086,15 +1230,36 @@ class WebInterface(object):
logger.info('Marking ' + str(len(chkthewanted)) + ' additional issues as Wanted from ' + ser['ComicName'] + ' series as requested')
chktheadd = importer.addComictoDB(sr['comicid'], "no", chkwant=chkthewanted)
if chktheadd != 'Exists':
logger.info('Sucessfully imported ' + ser['ComicName'] + ' (' + str(ser['IssueDate'][-4:]) + ')')
myDB.action('DELETE from futureupcoming WHERE ComicName=?', [ser['ComicName']])
logger.info('Removed ' + ser['ComicName'] + ' (' + str(ser['IssueDate'][-4:]) + ') from the future upcoming list as it is now added.')
self.future_check_add(sr['comicid'], ser, chkthewanted, theissdate)
future_check.exposed = True
def future_check_add(self, comicid, serinfo, chkthewanted=None, theissdate=None):
#In order to not error out when adding series with absolutely NO issue data, we need to 'fakeup' some values
#latestdate = the 'On sale' date from the futurepull-list OR the Shipping date if not available.
#latestiss = the IssueNumber for the first issue (this should always be #1, but might change at some point)
ser = serinfo
if theissdate is None:
theissdate = ser['IssueDate'][-4:]
if not theissdate.startswith('20'):
theissdate = ser['IssueDate'][:4]
latestissueinfo = []
latestissueinfo.append({"latestdate": ser['IssueDate'],
"latestiss": ser['IssueNumber']})
logger.fdebug('sending latestissueinfo from future as : ' + str(latestissueinfo))
chktheadd = importer.addComictoDB(comicid, "no", chkwant=chkthewanted, latestissueinfo=latestissueinfo, calledfrom="futurecheck")
if chktheadd != 'Exists':
logger.info('Sucessfully imported ' + ser['ComicName'] + ' (' + str(theissdate) + ')')
myDB = db.DBConnection()
myDB.action('DELETE from futureupcoming WHERE ComicName=?', [ser['ComicName']])
logger.info('Removed ' + ser['ComicName'] + ' (' + str(theissdate) + ') from the future upcoming list as it is now added.')
raise cherrypy.HTTPRedirect("home")
future_check.exposed = True
future_check_add.exposed = True
def filterpull(self):
myDB = db.DBConnection()
@ -1133,46 +1298,65 @@ class WebInterface(object):
upcoming = []
upcoming_count = 0
futureupcoming_count = 0
try:
pull_date = myDB.selectone("SELECT SHIPDATE from weekly").fetchone()
logger.fdebug(u"Weekly pull list present - retrieving pull-list date.")
if (pull_date is None):
pulldate = '00000000'
else:
pulldate = pull_date['SHIPDATE']
except (sqlite3.OperationalError, TypeError),msg:
logger.info(u"Error Retrieving weekly pull list - attempting to adjust")
pulldate = '00000000'
for upc in upcomingdata:
if len(upc['IssueDate']) <= 7 :
#if it's less than or equal 7, then it's a future-pull so let's check the date and display
#tmpdate = datetime.datetime.com
tmpdatethis = upc['IssueDate']
if tmpdatethis[:2] == '20':
tmpdate = tmpdatethis #in correct format of yyyymm
tmpdate = tmpdatethis + '01' #in correct format of yyyymm
else:
findst = tmpdatethis.find('-') #find the '-'
tmpdate = tmpdatethis[findst+1:] + tmpdatethis[:findst] #rebuild in format of yyyymm
timenow = datetime.datetime.now().strftime('%Y%m')
#logger.fdebug('comparing pubdate of: ' + str(tmpdate) + ' to now date of: ' + str(timenow))
if int(tmpdate) >= int(timenow):
if upc['Status'] == 'Wanted':
futureupcoming_count +=1
futureupcoming.append({"ComicName": upc['ComicName'],
"IssueNumber": upc['IssueNumber'],
"IssueDate": upc['IssueDate'],
"ComicID": upc['ComicID'],
"IssueID": upc['IssueID'],
"Status": upc['Status'],
"DisplayComicName": upc['DisplayComicName']})
tmpdate = tmpdatethis[findst+1:] + tmpdatethis[:findst] + '01' #rebuild in format of yyyymm
#timenow = datetime.datetime.now().strftime('%Y%m')
else:
#if it's greater than 7 it's a full date, and shouldn't be displayed ;)
timenow = datetime.datetime.now().strftime('%Y%m%d') #convert to yyyymmdd
#if it's greater than 7 it's a full date.
tmpdate = re.sub("[^0-9]", "", upc['IssueDate']) #convert date to numerics only (should be in yyyymmdd)
#logger.fdebug('comparing pubdate of: ' + str(tmpdate) + ' to now date of: ' + str(timenow))
timenow = datetime.datetime.now().strftime('%Y%m%d') #convert to yyyymmdd
#logger.fdebug('comparing pubdate of: ' + str(tmpdate) + ' to now date of: ' + str(timenow))
pulldate = re.sub("[^0-9]", "", pulldate) #convert pulldate to numerics only (should be in yyyymmdd)
if int(tmpdate) >= int(timenow) and int(tmpdate) == int(pulldate): #int(pulldate) <= int(timenow):
if upc['Status'] == 'Wanted':
upcoming_count +=1
upcoming.append({"ComicName": upc['ComicName'],
"IssueNumber": upc['IssueNumber'],
"IssueDate": upc['IssueDate'],
"ComicID": upc['ComicID'],
"IssueID": upc['IssueID'],
"Status": upc['Status'],
"DisplayComicName": upc['DisplayComicName']})
elif int(tmpdate) >= int(timenow):
if len(upc['IssueDate']) <= 7:
issuedate = tmpdate[:4] + '-' + tmpdate[4:6] + '-00'
else:
issuedate = upc['IssueDate']
if upc['Status'] == 'Wanted':
futureupcoming_count +=1
futureupcoming.append({"ComicName": upc['ComicName'],
"IssueNumber": upc['IssueNumber'],
"IssueDate": issuedate,
"ComicID": upc['ComicID'],
"IssueID": upc['IssueID'],
"Status": upc['Status'],
"DisplayComicName": upc['DisplayComicName']})
futureupcoming = sorted(futureupcoming, key=itemgetter('IssueDate','ComicName','IssueNumber'), reverse=True)
if int(tmpdate) >= int(timenow):
if upc['Status'] == 'Wanted':
upcoming_count +=1
upcoming.append({"ComicName": upc['ComicName'],
"IssueNumber": upc['IssueNumber'],
"IssueDate": upc['IssueDate'],
"ComicID": upc['ComicID'],
"IssueID": upc['IssueID'],
"Status": upc['Status'],
"DisplayComicName": upc['DisplayComicName']})
issues = myDB.select("SELECT * from issues WHERE Status='Wanted'")
isscnt = myDB.select("SELECT COUNT(*) FROM issues WHERE Status='Wanted'")
@ -1594,9 +1778,11 @@ class WebInterface(object):
GCDissue = int(GCDissue) / 1000
if '.' not in str(GCDissue): GCDissue = str(GCDissue) + ".00"
logger.fdebug("issue converted to " + str(GCDissue))
isschk = myDB.selectone("SELECT * FROM issues WHERE ComicName=? AND Issue_Number=? AND ComicID=?", [comic['ComicName'], str(GCDissue), comic['ComicID']]).fetchone()
isschk = myDB.selectone("SELECT * FROM issues WHERE Issue_Number=? AND ComicID=?", [str(GCDissue), comic['ComicID']]).fetchone()
else:
isschk = myDB.selectone("SELECT * FROM issues WHERE ComicName=? AND Issue_Number=? AND ComicID=?", [comic['ComicName'], arc['IssueNumber'], comic['ComicID']]).fetchone()
issue_int = helpers.issuedigits(arc['IssueNumber'])
logger.info('int_issue = ' + str(issue_int))
isschk = myDB.selectone("SELECT * FROM issues WHERE Int_IssueNumber=? AND ComicID=?", [issue_int, comic['ComicID']]).fetchone()
if isschk is None:
logger.fdebug("we matched on name, but issue " + str(arc['IssueNumber']) + " doesn't exist for " + comic['ComicName'])
else:
@ -1823,7 +2009,7 @@ class WebInterface(object):
logger.fdebug("You don't have any issues from " + StoryArcName + ". Aborting Mass Copy.")
return
else:
dst = os.path.join(mylar.CACHE, StoryArcName)
dst = os.path.join(mylar.CACHE_DIR, StoryArcName)
for files in copylist:
copyloc = files['Location']
@ -2218,9 +2404,9 @@ class WebInterface(object):
mode='series'
if yearRANGE is None:
sresults, explicit = mb.findComic(displaycomic, mode, issue=numissues, explicit='all') #ComicName, mode, issue=numissues)
sresults, explicit = mb.findComic(ogcname, mode, issue=numissues, explicit='all') #ComicName, mode, issue=numissues)
else:
sresults, explicit = mb.findComic(displaycomic, mode, issue=numissues, limityear=yearRANGE, explicit='all') #ComicName, mode, issue=numissues, limityear=yearRANGE)
sresults, explicit = mb.findComic(ogcname, mode, issue=numissues, limityear=yearRANGE, explicit='all') #ComicName, mode, issue=numissues, limityear=yearRANGE)
type='comic'
if len(sresults) == 1:
@ -2230,7 +2416,7 @@ class WebInterface(object):
# #need to move the files here.
elif len(sresults) == 0 or len(sresults) is None:
implog = implog + "no results, removing the year from the agenda and re-querying.\n"
sresults, explicit = mb.findComic(displaycomic, mode, issue=numissues, explicit='all') #ComicName, mode, issue=numissues)
sresults, explicit = mb.findComic(ogcname, mode, issue=numissues, explicit='all') #ComicName, mode, issue=numissues)
if len(sresults) == 1:
sr = sresults[0]
implog = implog + "only one result...automagik-mode enabled for " + displaycomic + " :: " + str(sr['comicid']) + "\n"
@ -2252,7 +2438,7 @@ class WebInterface(object):
cresults = self.addComic(comicid=sr['comicid'],comicname=sr['name'],comicyear=sr['comicyear'],comicpublisher=sr['publisher'],comicimage=sr['comicimage'],comicissues=sr['issues'],imported='yes',ogcname=ogcname) #imported=comicstoIMP,ogcname=ogcname)
return serve_template(templatename="searchfix.html", title="Error Check", comicname=sr['name'], comicid=sr['comicid'], comicyear=sr['comicyear'], comicimage=sr['comicimage'], comicissues=sr['issues'], cresults=cresults, imported='yes', ogcname=str(ogcname))
else:
return serve_template(templatename="searchresults.html", title='Import Results for: "' + displaycomic + '"',searchresults=sresults, type=type, imported='yes', ogcname=ogcname, explicit=explicit) #imported=comicstoIMP, ogcname=ogcname)
return serve_template(templatename="searchresults.html", title='Import Results for: "' + displaycomic + '"',searchresults=sresults, type=type, imported='yes', ogcname=ogcname, name=ogcname, explicit=explicit) #imported=comicstoIMP, ogcname=ogcname)
preSearchit.exposed = True
def pretty_git(self, br_history):
@ -2332,6 +2518,9 @@ class WebInterface(object):
"launch_browser" : helpers.checked(mylar.LAUNCH_BROWSER),
"logverbose" : helpers.checked(mylar.LOGVERBOSE),
"max_logsize" : mylar.MAX_LOGSIZE,
"annuals_on" : helpers.checked(mylar.ANNUALS_ON),
"enable_check_folder" : helpers.checked(mylar.ENABLE_CHECK_FOLDER),
"check_folder" : mylar.CHECK_FOLDER,
"download_scan_interval" : mylar.DOWNLOAD_SCAN_INTERVAL,
"nzb_search_interval" : mylar.SEARCH_INTERVAL,
"nzb_startup_search" : helpers.checked(mylar.NZB_STARTUP_SEARCH),
@ -2389,6 +2578,7 @@ class WebInterface(object):
"cbt_passkey" : mylar.CBT_PASSKEY,
"snatchedtorrent_notify" : mylar.SNATCHEDTORRENT_NOTIFY,
"destination_dir" : mylar.DESTINATION_DIR,
"create_folders" : helpers.checked(mylar.CREATE_FOLDERS),
"chmod_dir" : mylar.CHMOD_DIR,
"chmod_file" : mylar.CHMOD_FILE,
"replace_spaces" : helpers.checked(mylar.REPLACE_SPACES),
@ -2443,6 +2633,8 @@ class WebInterface(object):
"ct_tag_cr" : helpers.checked(mylar.CT_TAG_CR),
"ct_tag_cbl" : helpers.checked(mylar.CT_TAG_CBL),
"ct_cbz_overwrite" : helpers.checked(mylar.CT_CBZ_OVERWRITE),
"failed_download_handling" : helpers.checked(mylar.FAILED_DOWNLOAD_HANDLING),
"failed_auto" : helpers.checked(mylar.FAILED_AUTO),
"branch" : version.MYLAR_VERSION,
"br_type" : mylar.INSTALL_TYPE,
"br_version" : mylar.versioncheck.getVersion(),
@ -2491,13 +2683,13 @@ class WebInterface(object):
b = urllib.unquote_plus(comicname)
cname = b.encode('utf-8')
print ('comicid to be attached : ' + str(manual_comicid))
print ('comicname : ' + str(cname))
print ('comicyear : ' + str(comicyear))
print ('comicid : ' + str(comicid))
logger.fdebug('comicid to be attached : ' + str(manual_comicid))
logger.fdebug('comicname : ' + str(cname))
logger.fdebug('comicyear : ' + str(comicyear))
logger.fdebug('comicid : ' + str(comicid))
issueid = manual_comicid
logger.fdebug(str(issueid) + ' added to series list as an Annual')
threading.Thread(target=importer.manualAnnual, args=[manual_comicid, comicname, comicyear, comicid]).start()
logger.fdebug('I will be adding ' + str(issueid) + ' to the Annual list for this series.')
threading.Thread(target=importer.manualAnnual, args=[manual_comicid, cname, comicyear, comicid]).start()
raise cherrypy.HTTPRedirect("comicDetails?ComicID=%s" % comicid)
manual_annual_add.exposed = True
@ -2619,17 +2811,17 @@ class WebInterface(object):
readOptions.exposed = True
def configUpdate(self, comicvine_api=None, http_host='0.0.0.0', http_username=None, http_port=8090, http_password=None, api_enabled=0, api_key=None, launch_browser=0, logverbose=0, max_logsize=None, download_scan_interval=None, nzb_search_interval=None, nzb_startup_search=0, libraryscan_interval=None,
def configUpdate(self, comicvine_api=None, http_host='0.0.0.0', http_username=None, http_port=8090, http_password=None, api_enabled=0, api_key=None, launch_browser=0, logverbose=0, annuals_on=0, max_logsize=None, download_scan_interval=None, nzb_search_interval=None, nzb_startup_search=0, libraryscan_interval=None,
nzb_downloader=0, sab_host=None, sab_username=None, sab_apikey=None, sab_password=None, sab_category=None, sab_priority=None, sab_directory=None, log_dir=None, log_level=0, blackhole_dir=None,
nzbget_host=None, nzbget_port=None, nzbget_username=None, nzbget_password=None, nzbget_category=None, nzbget_priority=None, nzbget_directory=None,
usenet_retention=None, nzbsu=0, nzbsu_uid=None, nzbsu_apikey=None, dognzb=0, dognzb_uid=None, dognzb_apikey=None, newznab=0, newznab_host=None, newznab_name=None, newznab_apikey=None, newznab_uid=None, newznab_enabled=0,
raw=0, raw_provider=None, raw_username=None, raw_password=None, raw_groups=None, experimental=0,
enable_meta=0, cmtagger_path=None, ct_tag_cr=0, ct_tag_cbl=0, ct_cbz_overwrite=0, enable_rss=0, rss_checkinterval=None, enable_torrent_search=0, enable_kat=0, enable_cbt=0, cbt_passkey=None, snatchedtorrent_notify=0,
raw=0, raw_provider=None, raw_username=None, raw_password=None, raw_groups=None, experimental=0, check_folder=None, enable_check_folder=0,
enable_meta=0, cmtagger_path=None, ct_tag_cr=0, ct_tag_cbl=0, ct_cbz_overwrite=0, enable_rss=0, rss_checkinterval=None, failed_download_handling=0, failed_auto=0, enable_torrent_search=0, enable_kat=0, enable_cbt=0, cbt_passkey=None, snatchedtorrent_notify=0,
enable_torrents=0, minseeds=0, torrent_local=0, local_watchdir=None, torrent_seedbox=0, seedbox_watchdir=None, seedbox_user=None, seedbox_pass=None, seedbox_host=None, seedbox_port=None,
prowl_enabled=0, prowl_onsnatch=0, prowl_keys=None, prowl_priority=None, nma_enabled=0, nma_apikey=None, nma_priority=0, nma_onsnatch=0, pushover_enabled=0, pushover_onsnatch=0, pushover_apikey=None, pushover_userkey=None, pushover_priority=None, boxcar_enabled=0, boxcar_onsnatch=0, boxcar_token=None,
pushbullet_enabled=0, pushbullet_apikey=None, pushbullet_deviceid=None, pushbullet_onsnatch=0,
preferred_quality=0, move_files=0, rename_files=0, add_to_csv=1, cvinfo=0, lowercase_filenames=0, folder_format=None, file_format=None, enable_extra_scripts=0, extra_scripts=None, enable_pre_scripts=0, pre_scripts=None, post_processing=0, syno_fix=0, search_delay=None, chmod_dir=0777, chmod_file=0660, cvapifix=0,
tsab=None, destination_dir=None, replace_spaces=0, replace_char=None, use_minsize=0, minsize=None, use_maxsize=0, maxsize=None, autowant_all=0, autowant_upcoming=0, comic_cover_local=0, zero_level=0, zero_level_n=None, interface=None, **kwargs):
tsab=None, destination_dir=None, create_folders=1, replace_spaces=0, replace_char=None, use_minsize=0, minsize=None, use_maxsize=0, maxsize=None, autowant_all=0, autowant_upcoming=0, comic_cover_local=0, zero_level=0, zero_level_n=None, interface=None, **kwargs):
mylar.COMICVINE_API = comicvine_api
mylar.HTTP_HOST = http_host
mylar.HTTP_PORT = http_port
@ -2639,7 +2831,10 @@ class WebInterface(object):
mylar.API_KEY = api_key
mylar.LAUNCH_BROWSER = launch_browser
mylar.LOGVERBOSE = logverbose
mylar.ANNUALS_ON = int(annuals_on)
mylar.MAX_LOGSIZE = max_logsize
mylar.ENABLE_CHECK_FOLDER = enable_check_folder
mylar.CHECK_FOLDER = check_folder
mylar.DOWNLOAD_SCAN_INTERVAL = download_scan_interval
mylar.SEARCH_INTERVAL = nzb_search_interval
mylar.NZB_STARTUP_SEARCH = nzb_startup_search
@ -2739,6 +2934,7 @@ class WebInterface(object):
mylar.FOLDER_FORMAT = folder_format
mylar.FILE_FORMAT = file_format
mylar.DESTINATION_DIR = destination_dir
mylar.CREATE_FOLDERS = create_folders
mylar.AUTOWANT_ALL = autowant_all
mylar.AUTOWANT_UPCOMING = autowant_upcoming
mylar.COMIC_COVER_LOCAL = comic_cover_local
@ -2753,6 +2949,8 @@ class WebInterface(object):
mylar.CT_TAG_CR = ct_tag_cr
mylar.CT_TAG_CBL = ct_tag_cbl
mylar.CT_CBZ_OVERWRITE = ct_cbz_overwrite
mylar.FAILED_DOWNLOAD_HANDLING = failed_download_handling
mylar.FAILED_AUTO = failed_auto
mylar.LOG_DIR = log_dir
mylar.LOG_LEVEL = log_level
mylar.CHMOD_DIR = chmod_dir
@ -2983,3 +3181,78 @@ class WebInterface(object):
return serve_download(pathfile)
downloadthis.exposed = True
def IssueInfo(self, filelocation):
issuedetails = helpers.IssueDetails(filelocation)
print str(issuedetails)
issueinfo = '<table width="500"><tr><td>'
issueinfo += '<img style="float: left; padding-right: 10px" src=' + issuedetails[0]['IssueImage'] + ' height="400" width="263">'
issueinfo += '<h1><center><b>' + issuedetails[0]['series'] + '</br>[#' + issuedetails[0]['issue_number'] + ']</b></center></h1>'
issueinfo += '<center>"' + issuedetails[0]['title'] + '"</center></br>'
issueinfo += '</br><p class="alignleft">' + str(issuedetails[0]['pagecount']) + ' pages</p>'
if issuedetails[0]['day'] is None:
issueinfo += '<p class="alignright">(' + str(issuedetails[0]['year']) + '-' + str(issuedetails[0]['month']) + ')</p></br>'
else:
issueinfo += '<p class="alignright">(' + str(issuedetails[0]['year']) + '-' + str(issuedetails[0]['month']) + '-' + str(issuedetails[0]['day']) + ')</p></br>'
if not issuedetails[0]['writer'] == 'None':
issueinfo += 'Writer: ' + issuedetails[0]['writer'] + '</br>'
if not issuedetails[0]['penciller'] == 'None':
issueinfo += 'Penciller: ' + issuedetails[0]['penciller'] + '</br>'
if not issuedetails[0]['inker'] == 'None':
issueinfo += 'Inker: ' + issuedetails[0]['inker'] + '</br>'
if not issuedetails[0]['colorist'] == 'None':
issueinfo += 'Colorist: ' + issuedetails[0]['colorist'] + '</br>'
if not issuedetails[0]['letterer'] == 'None':
issueinfo += 'Letterer: ' + issuedetails[0]['letterer'] + '</br>'
if not issuedetails[0]['editor'] == 'None':
issueinfo += 'Editor: ' + issuedetails[0]['editor'] + '</br>'
issueinfo += '</td></tr>'
#issueinfo += '<img src="interfaces/default/images/rename.png" height="25" width="25"></td></tr>'
issueinfo += '<tr><td>Summary: ' + issuedetails[0]['summary'] + '</br></td></tr>'
issueinfo += '<tr><td><center>' + os.path.split(filelocation)[1] + '</center>'
issueinfo += '</td></tr></table>'
return issueinfo
#import json
#json_dump = json.dumps(issuedetails)
#json_dump = json_dump.replace("\\","\\\\")
#print 'json_dump:' + str(json_dump)
#return json_dump
IssueInfo.exposed = True
def manual_metatag(self, dirName, issueid, filename, comicid):
module = '[MANUAL META-TAGGING]'
try:
import cmtagmylar
metaresponse = cmtagmylar.run(dirName, issueid=issueid, filename=filename)
except ImportError:
logger.warn(module + ' comictaggerlib not found on system. Ensure the ENTIRE lib directory is located within mylar/lib/comictaggerlib/ directory.')
metaresponse = "fail"
if metaresponse == "fail":
logger.fdebug(module + ' Unable to write metadata successfully - check mylar.log file.')
elif metaresponse == "unrar error":
logger.error(module + ' This is a corrupt archive - whether CRC errors or it is incomplete. Marking as BAD, and retrying a different copy.')
#launch failed download handling here.
else:
logger.info(module + ' Sucessfully wrote metadata to .cbz (' + os.path.split(metaresponse)[1] + ') - Continuing..')
updater.forceRescan(comicid)
manual_metatag.exposed = True
def group_metatag(self, dirName, ComicID):
myDB = db.DBConnection()
groupinfo = myDB.select('SELECT * FROM issues WHERE ComicID=? and Location is not NULL', [ComicID])
if groupinfo is None:
logger.warn('No issues physically exist within the series directory for me to (re)-tag.')
return
for ginfo in groupinfo:
self.manual_metatag(dirName, ginfo['IssueID'], os.path.join(dirName, ginfo['Location']))
logger.info('Finished doing a complete series (re)tagging of metadata.')
group_metatag.exposed = True
def CreateFolders(self, createfolders=None):
print 'createfolders is ' + str(createfolders)
if createfolders:
mylar.CREATE_FOLDERS = int(createfolders)
mylar.config_write()
CreateFolders.exposed = True

View File

@ -97,10 +97,10 @@ def pullit(forcecheck=None):
# this checks for the following lists
# first need to only look for checkit variables
checkit=['COMICS',
'COMIC & GRAPHIC NOVELS',
'IDW PUBLISHING',
'MAGAZINES',
'MERCHANDISE']
#'COMIC & GRAPHIC NOVELS',
#if COMICS is found, determine which publisher
checkit2=['DC',
@ -174,32 +174,41 @@ def pullit(forcecheck=None):
mylar.PULLNEW = 'yes'
for yesyes in checkit:
if yesyes in i:
logger.info('yesyes found: ' + yesyes)
if format(str(yesyes)) == 'COMICS':
logger.info('yesyes = comics: ' + format(str(yesyes)))
for chkchk in checkit2:
flagged = "no"
logger.info('chkchk is : ' + chkchk)
if chkchk in i:
logger.info('chkchk found in i: ' + chkchk)
bl = i.split()
blchk = str(bl[0]) + " " + str(bl[1])
if chkchk in blchk:
pub = format(str(chkchk)) + " COMICS"
#print (pub)
logger.info("chkchk: " + str(pub))
break
else:
if i.find("COMICS") < 1 and "GRAPHIC NOVELS" in i:
logger.info('chkchk not in i - i.findcomics: ' + str(i.find("COMICS")) + ' length: ' + str(len(i.strip())))
if all( [i.find("COMICS") < 1, len(i.strip()) == 6 ] ) or ("GRAPHIC NOVELS" in i):
# if i.find("COMICS") < 1 and (len(i.strip()) == 6 or "& GRAPHIC NOVELS" in i):
pub = "COMICS"
#print (pub)
logger.info("i.find comics & len =6 : " + pub)
break
elif i.find("COMICS") > 12:
#print ("comics word found in comic title")
logger.info("comics word found in comic title")
flagged = "yes"
break
else:
if i.find("COMIC") < 1 and "GRAPHIC NOVELS" in i:
logger.info('yesyes not found: ' + yesyes + ' i.findcomics: ' + str(i.find("COMICS")) + ' length: ' + str(len(i.strip())))
if all( [i.find("COMICS") < 1, len(i.strip()) == 6 ] ) or ("GRAPHIC NOVELS" in i):
# if i.find("COMIC") < 1 and (len(i.strip()) == 6 or "& GRAPHIC NOVELS" in i):
logger.info("format string not comics & i.find < 1: " + pub)
pub = "COMICS"
break
else:
pub = format(str(yesyes))
#print (pub)
logger.info("format string not comics & i.find > 1: " + pub)
break
if flagged == "no":
break
@ -231,7 +240,8 @@ def pullit(forcecheck=None):
while (n < comicend + 1):
comicnm = comicnm + " " + issname[n]
n+=1
#print ("Comicname: " + str(comicnm) )
comcnm = re.sub('1 FOR \$1','', comicnm).strip()
logger.info("Comicname: " + str(comicnm) )
#get remainder
comicrm = issname[comicend +2]
if '$' in comicrm:
@ -242,10 +252,10 @@ def pullit(forcecheck=None):
break
comicrm = str(comicrm) + " " + str(issname[n])
n+=1
#print ("Comic Extra info: " + str(comicrm) )
#print ("ship: " + str(shipdate))
#print ("pub: " + str(pub))
#print ("issue: " + str(issue))
logger.info("Comic Extra info: " + str(comicrm) )
logger.info("ship: " + str(shipdate))
logger.info("pub: " + str(pub))
logger.info("issue: " + str(issue))
#--let's make sure we don't wipe out decimal issues ;)
# if '.' in issue:
# issue_decimal = re.compile(r'[^\d.]+')
@ -446,7 +456,7 @@ def pullitcheck(comic1off_name=None,comic1off_id=None,forcecheck=None, futurepul
w = 1
else:
#let's read in the comic.watchlist from the db here
cur.execute("SELECT ComicID, ComicName, ComicYear, ComicPublisher, ComicPublished, LatestDate, ForceContinuing, AlternateSearch, LatestIssue from comics")
cur.execute("SELECT ComicID, ComicName_Filesafe, ComicYear, ComicPublisher, ComicPublished, LatestDate, ForceContinuing, AlternateSearch, LatestIssue from comics")
while True:
watchd = cur.fetchone()
#print ("watchd: " + str(watchd))

View File

@ -22,7 +22,7 @@ class AuthURLOpener(urllib.FancyURLopener):
return urllib.FancyURLopener.open(self, url)
def processIssue(dirName, nzbName=None):
def processIssue(dirName, nzbName=None, failed=False):
config = ConfigParser.ConfigParser()
configFilename = os.path.join(os.path.dirname(sys.argv[0]), "autoProcessComics.cfg")
@ -59,6 +59,8 @@ def processIssue(dirName, nzbName=None):
params['nzb_folder'] = dirName
if nzbName != None:
params['nzb_name'] = nzbName
params['failed'] = failed
myOpener = AuthURLOpener(username, password)

View File

@ -26,7 +26,12 @@ if os.environ.has_key('NZBOP_SCRIPTDIR') and not os.environ['NZBOP_VERSION'][0:5
POSTPROCESS_NONE=95
#Start script
result = autoProcessComics.processIssue(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'])
if os.environ['NZBPP_TOTALSTATUS'] == 'FAILURE' or os.environ['NZBPP_TOTALSTATUS'] == 'WARNING':
failit = 1
else:
failit = 0
result = autoProcessComics.processIssue(os.environ['NZBPP_DIRECTORY'], os.environ['NZBPP_NZBNAME'], failed=failit)
elif len(sys.argv) == NZBGET_NO_OF_ARGUMENTS:

View File

@ -17,6 +17,6 @@ if len(sys.argv) < 2:
print "No folder supplied - is this being called from SABnzbd or NZBGet?"
sys.exit()
elif len(sys.argv) >= 3:
sys.exit(autoProcessComics.processIssue(sys.argv[1], sys.argv[3]))
sys.exit(autoProcessComics.processIssue(sys.argv[1], sys.argv[3], sys.argv[7])
else:
sys.exit(autoProcessComics.processIssue(sys.argv[1]))