Scheduler

NZBmatrix, newznab
Scores
This commit is contained in:
Ruud committed 2011-04-17 23:36:23 +02:00
1 parent 9524306739
commit 7837adec1d
38 files changed
+856 -219

No files matched your search

+74
View File
@@ -1 +1,75 @@
from uuid import uuid4
def start():
pass
config = [{
'name': 'core',
'groups': [
{
'tab': 'general',
'name': 'basics',
'description': 'Needs restart before changes take effect.',
'options': [
{
'name': 'username',
'default': '',
},
{
'name': 'password',
'default': '',
'type': 'password',
},
{
'name': 'host',
'advanced': True,
'default': '0.0.0.0',
'label': 'IP',
'description': 'Host that I should listen to. "0.0.0.0" listens to all ips.',
},
{
'name': 'port',
'default': 5000,
'type': 'int',
'description': 'The port I should listen to.',
},
{
'name': 'launch_browser',
'default': 1,
'type': 'bool',
'label': 'Launch Browser',
'description': 'Launch the browser when I start.',
},
],
},
{
'tab': 'general',
'name': 'advanced',
'description': "For those who know what the're doing",
'advanced': True,
'options': [
{
'name': 'api_key',
'default': uuid4().hex,
'readonly': 1,
'label': 'Api Key',
'description': "This is top-secret! Don't share this!",
},
{
'name': 'debug',
'default': 0,
'type': 'bool',
'label': 'Debug',
'description': 'Enable debugging.',
},
{
'name': 'url_base',
'default': '',
'label': 'Url Base',
'description': 'When using mod_proxy use this to append the url with this.',
},
],
},
],
}]
@@ -1,6 +0,0 @@
from .main import ClientScript
def start():
return ClientScript()
config = []
@@ -1,56 +0,0 @@
from couchpotato.core.event import addEvent
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
log = CPLog(__name__)
class ClientScript(Plugin):
urls = {
'style': {},
'script': {},
}
html = {
'style': '<link rel="stylesheet" href="%s" type="text/css">',
'script': '<script type="text/javascript" src="%s"></script>',
}
def __init__(self):
addEvent('register_style', self.registerStyle)
addEvent('register_script', self.registerScript)
addEvent('clientscript.get_styles', self.getStyles)
addEvent('clientscript.get_scripts', self.getScripts)
def getStyles(self, *args, **kwargs):
return self.get('style', *args, **kwargs)
def getScripts(self, *args, **kwargs):
return self.get('script', *args, **kwargs)
def get(self, type, as_html = False, location = 'head'):
data = '' if as_html else []
try:
return self.urls[type][location]
except Exception, e:
log.error(e)
return data
def registerStyle(self, path, position = 'head'):
self.register(path, 'style', position)
def registerScript(self, path, position = 'head'):
self.register(path, 'script', position)
def register(self, file, type, location):
if not self.urls[type].get(location):
self.urls[type][location] = []
filePath = file
self.urls[type][location].append(filePath)
+1 -1
View File
@@ -37,4 +37,4 @@ class Plugin():
return not self.isEnabled()
def isEnabled(self):
return self.conf('enabled', True)
return self.conf('enabled')
+9
View File
@@ -27,6 +27,7 @@ class QualityPlugin(Plugin):
def __init__(self):
addEvent('quality.all', self.all)
addEvent('quality.single', self.single)
addEvent('app.load', self.fill)
path = self.registerStatic(__file__)
@@ -46,6 +47,14 @@ class QualityPlugin(Plugin):
return temp
def single(self, identifier = ''):
db = get_session()
quality = db.query(Quality).filter_by(identifier = identifier).first()
return dict(self.getQuality(quality.identifier), **quality.to_dict())
def getQuality(self, identifier):
for q in self.qualities:
+9
View File
@@ -1,3 +1,4 @@
from couchpotato.core.event import addEvent, fireEvent
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
@@ -8,3 +9,11 @@ class Renamer(Plugin):
def __init__(self):
pass
addEvent('renamer.scan', self.scan)
addEvent('app.load', self.scan)
fireEvent('schedule.interval', 'renamer.scan', self.scan, minutes = self.conf('run_every'))
def scan(self):
print 'scan'
@@ -0,0 +1,6 @@
from .main import Score
def start():
return Score()
config = []
+22
View File
@@ -0,0 +1,22 @@
from couchpotato.core.event import addEvent
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.core.plugins.score.scores import nameScore, nameRatioScore
log = CPLog(__name__)
class Score(Plugin):
def __init__(self):
addEvent('score.calculate', self.calculate)
def calculate(self, nzb, movie):
''' Calculate the score of a NZB, used for sorting later '''
score = nameScore(nzb['name'], movie['library']['year'])
for movie_title in movie['library']['titles']:
score += nameRatioScore(nzb['name'], movie_title['title'])
return score
+51
View File
@@ -0,0 +1,51 @@
from couchpotato.core.helpers.encoding import simplifyString
from couchpotato.environment import Env
import re
name_scores = [
'proper:2', 'repack:2',
'unrated:1',
'x264:1',
'DTS:4', 'AC3:2',
'720p:10', '1080p:10', 'bluray:10', 'dvd:1', 'dvdrip:1', 'brrip:1', 'bdrip:1',
'metis:1', 'diamond:1', 'wiki:1', 'CBGB:1',
'german:-10', 'french:-10', 'spanish:-10', 'swesub:-20', 'danish:-10'
]
def nameScore(name, year):
''' Calculate score for words in the NZB name '''
score = 0
name = name.lower()
#give points for the cool stuff
for value in name_scores:
v = value.split(':')
add = int(v.pop())
if v.pop() in name:
score = score + add
#points if the year is correct
if str(year) in name:
score = score + 1
# Contains preferred word
nzb_words = re.split('\W+', simplifyString(name))
preferred_words = Env.setting('preferred_words', section = 'searcher').split(',')
for word in preferred_words:
if word.strip() and word.strip().lower() in nzb_words:
score = score + 100
return score
def nameRatioScore(nzb_name, movie_name):
nzb_words = re.split('\W+', simplifyString(nzb_name))
movie_words = re.split('\W+', simplifyString(movie_name))
# Replace .,-_ with space
left_over = len(nzb_words) - len(movie_words)
if 2 <= left_over <= 6:
return 4
else:
return 0
@@ -0,0 +1,78 @@
from .main import Searcher
import random
def start():
return Searcher()
config = [{
'name': 'searcher',
'groups': [
{
'tab': 'searcher',
'name': 'searcher',
'label': 'Search',
'description': 'Options for the searchers',
'options': [
{
'name': 'required_words',
'label': 'Required words',
'default': '',
},
{
'name': 'ignored_words',
'label': 'Ignored words',
'default': '',
},
],
}, {
'tab': 'searcher',
'name': 'searcher',
'label': 'Cronjob',
'advanced': True,
'description': 'Cron settings for the searcher see: <a href="http://packages.python.org/APScheduler/cronschedule.html">APScheduler</a> for details.',
'options': [
{
'name': 'cron_day',
'label': 'Day',
'advanced': True,
'default': '*',
'type': 'string',
'description': '<strong>*</strong>: Every day, <strong>*/2</strong>: Every 2 days, <strong>1</strong>: Every first of the month.',
},
{
'name': 'cron_hour',
'label': 'Hour',
'advanced': True,
'default': random.randint(0, 23),
'type': 'string',
'description': '<strong>*</strong>: Every hour, <strong>*/8</strong>: Every 8 hours, <strong>3</strong>: At 3, midnight.',
},
{
'name': 'cron_minute',
'label': 'Minute',
'advanced': True,
'default': random.randint(0, 59),
'type': 'string',
'description': "Just keep it random, so the providers don't get DDOSed by every CP user on a 'full' hour."
},
],
},
],
}, {
'name': 'nzb',
'groups': [
{
'tab': 'searcher',
'name': 'nzb',
'label': 'NZB',
'options': [
{
'name': 'retention',
'default': 350,
'type': 'int',
'unit': 'days'
},
],
},
],
}]
+156
View File
@@ -0,0 +1,156 @@
from couchpotato import get_session
from couchpotato.core.event import addEvent, fireEvent
from couchpotato.core.helpers.encoding import simplifyString
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.core.settings.model import Movie
from couchpotato.environment import Env
import re
log = CPLog(__name__)
class Searcher(Plugin):
def __init__(self):
addEvent('searcher.all', self.all)
addEvent('searcher.single', self.single)
addEvent('searcher.correct_movie', self.correctMovie)
# Schedule cronjob
fireEvent('schedule.cron', 'searcher.all', self.all, day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute'))
def all(self):
db = get_session()
movies = db.query(Movie).filter(
Movie.status.has(identifier = 'active')
).all()
for movie in movies:
self.single(movie.to_dict(deep = {
'profile': {'types': {'quality': {}}},
'releases': {'status': {}, 'quality': {}},
'library': {'titles': {}, 'files':{}},
'files': {}
}))
def single(self, movie):
for type in movie['profile']['types']:
results = fireEvent('provider.yarr.search', movie, type['quality'], merge = True)
sorted_results = sorted(results, key = lambda k: k['score'], reverse = True)
for nzb in sorted_results:
print nzb['name']
def correctMovie(self, nzb = {}, movie = {}, quality = {}, **kwargs):
imdb_results = kwargs.get('imdb_results', False)
single_category = kwargs.get('single_category', False)
retention = Env.setting('retention', section = 'nzb')
if retention < nzb.get('age', 0):
log.info('Wrong: Outside retention, age = %s, needs = %s: %s' % (nzb['age'], retention, nzb['name']))
return False
nzb_words = re.split('\W+', simplifyString(nzb['name']))
required_words = self.conf('required_words').split(',')
if self.conf('required_words') and not list(set(nzb_words) & set(required_words)):
log.info("NZB doesn't contain any of the required words.")
return False
ignored_words = self.conf('ignored_words').split(',')
blacklisted = list(set(nzb_words) & set(ignored_words))
if self.conf('ignored_words') and blacklisted:
log.info("NZB '%s' contains the following blacklisted words: %s" % (nzb['name'], ", ".join(blacklisted)))
return False
#qualities = fireEvent('quality.all', single = True)
preferred_quality = fireEvent('quality.single', identifier = quality['identifier'], single = True)
# Contains lower quality string
if self.containsOtherQuality(nzb['name'], preferred_quality, single_category):
log.info('Wrong: %s, looking for %s' % (nzb['name'], quality['label']))
return False
"""
# File to small
minSize = q.minimumSize(qualityType)
if minSize > item.size:
log.info('"%s" is too small to be %s. %sMB instead of the minimal of %sMB.' % (item.name, type['label'], item.size, minSize))
return False
# File to large
maxSize = q.maximumSize(qualityType)
if maxSize < item.size:
log.info('"%s" is too large to be %s. %sMB instead of the maximum of %sMB.' % (item.name, type['label'], item.size, maxSize))
return False
"""
if imdb_results:
return True
# Check if nzb contains imdb link
if self.checkIMDB([nzb['description']], movie['library']['identifier']):
return True
for movie_title in movie['library']['titles']:
movie_words = re.split('\W+', simplifyString(movie_title['title']))
if self.correctName(nzb['name'], movie_title['title']):
# if no IMDB link, at least check year range 1
if len(movie_words) > 2 and self.correctYear([nzb['name']], movie['library']['year'], 1):
return True
# if no IMDB link, at least check year
if len(movie_words) == 2 and self.correctYear([nzb['name']], movie['library']['year'], 0):
return True
return False
def containsOtherQuality(self, name, preferred_quality = {}, single_category = False):
nzb_words = re.split('\W+', simplifyString(name))
qualities = fireEvent('quality.all', single = True)
found = {}
for quality in qualities:
# Main in words
if quality['identifier'] in nzb_words:
found[quality['identifier']] = True
# Alt in words
if list(set(nzb_words) & set(quality['alternative'])):
found[quality['identifier']] = True
# Allow other qualities
for allowed in preferred_quality.get('allow'):
if found.get(allowed):
del found[allowed]
if (len(found) == 0 and single_category):
return False
return not (found.get(preferred_quality['identifier']) and len(found) == 1)
def checkIMDB(self, haystack, imdbId):
for string in haystack:
if 'imdb.com/title/' + imdbId in string:
return True
return False
def correctYear(self, haystack, year, range):
for string in haystack:
if str(year) in string or str(int(year) + range) in string or str(int(year) - range) in string: # 1 year of is fine too
return True
return False
+1 -1
View File
@@ -13,7 +13,7 @@ config = [{
{
'name': 'show_wizard',
'label': 'Run the wizard',
'default': True,
'default': 1,
'type': 'bool',
},
],
@@ -193,7 +193,7 @@ var Spotlight = new Class({
'position': 'absolute',
'background-color': 'rgba('+self.options.fillColor.join(',')+', '+self.options.fillOpacity+')',
'display': 'block',
'z-index': 2,
'z-index': 999,
'top': self.top[nr],
'left': self.left[nr],
'height': self.height[nr],
@@ -276,7 +276,7 @@ var Spotlight = new Class({
var self = this;
var soften = self.options.soften;
var edge = new Element('div', {
var edge = new Element('div.edge', {
'styles': Object.merge({
'position': 'absolute',
'width': soften,
@@ -6,13 +6,22 @@ var WizardBase = new Class({
var self = this;
self.steps = steps;
self.start();
self.spotlight = new Spotlight([], {
'fillColor': [0,0,0],
'soften': 0
});
window.addEvent('resize', self.spotlight.create.bind(self.spotlight))
},
start: function(){
var self = this;
var els = $(document.body).getElements("[name='core[username]'], [name='core[password]'], [name='core[launch_browser]']").getParent('.ctrlHolder')
p(els, self.spotlight.setElements(els))
self.spotlight.create();
},