Movie search
Profile Settings
This commit is contained in:
@@ -24,3 +24,11 @@ def toUnicode(original, *args):
|
||||
except UnicodeDecodeError:
|
||||
ascii_text = str(original).encode('string_escape')
|
||||
return unicode(ascii_text)
|
||||
|
||||
|
||||
def is_int(value):
|
||||
try:
|
||||
int(value)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
@@ -1,17 +1,67 @@
|
||||
from flask.globals import current_app
|
||||
from flask.helpers import json, jsonify
|
||||
from flask.helpers import json
|
||||
from libs.werkzeug.urls import url_decode
|
||||
import flask
|
||||
|
||||
import re
|
||||
|
||||
def getParams():
|
||||
return getattr(flask.request, 'args')
|
||||
|
||||
params = url_decode(getattr(flask.request, 'environ').get('QUERY_STRING', ''))
|
||||
reg = re.compile('^[a-z0-9_\.]+$')
|
||||
|
||||
current = temp = {}
|
||||
for param, value in sorted(params.iteritems()):
|
||||
|
||||
nest = re.split("([\[\]]+)", param)
|
||||
if len(nest) > 1:
|
||||
nested = []
|
||||
for key in nest:
|
||||
if reg.match(key):
|
||||
nested.append(key)
|
||||
|
||||
current = temp
|
||||
|
||||
for item in nested:
|
||||
if item is nested[-1]:
|
||||
current[item] = value
|
||||
else:
|
||||
try:
|
||||
current[item]
|
||||
except:
|
||||
current[item] = {}
|
||||
|
||||
current = current[item]
|
||||
else:
|
||||
temp[param] = value
|
||||
|
||||
return dictToList(temp)
|
||||
|
||||
def dictToList(params):
|
||||
|
||||
if type(params) is dict:
|
||||
new = {}
|
||||
for x, value in params.iteritems():
|
||||
try:
|
||||
new_value = [dictToList(value2) for value2 in value.itervalues()]
|
||||
except:
|
||||
new_value = value
|
||||
|
||||
new[x] = new_value
|
||||
else:
|
||||
new = params
|
||||
|
||||
return new
|
||||
|
||||
def getParam(attr, default = None):
|
||||
return getattr(flask.request, 'args').get(attr, default)
|
||||
|
||||
def padded_jsonify(callback, *args, **kwargs):
|
||||
content = str(callback) + '(' + json.dumps(dict(*args, **kwargs)) + ')'
|
||||
return current_app.response_class(content, mimetype = 'text/javascript')
|
||||
return getattr(current_app, 'response_class')(content, mimetype = 'text/javascript')
|
||||
|
||||
def jsonify(mimetype, *args, **kwargs):
|
||||
content = json.dumps(dict(*args, **kwargs))
|
||||
return getattr(current_app, 'response_class')(content, mimetype = mimetype)
|
||||
|
||||
def jsonified(*args, **kwargs):
|
||||
from couchpotato.environment import Env
|
||||
@@ -19,4 +69,5 @@ def jsonified(*args, **kwargs):
|
||||
if callback:
|
||||
return padded_jsonify(callback, *args, **kwargs)
|
||||
else:
|
||||
return jsonify(*args, **kwargs)
|
||||
return jsonify('text/javascript' if Env.doDebug() else 'application/json', *args, **kwargs)
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from couchpotato.core.plugins.library.main import LibraryPlugin
|
||||
|
||||
def start():
|
||||
return LibraryPlugin()
|
||||
|
||||
config = []
|
||||
@@ -0,0 +1,32 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Library
|
||||
|
||||
|
||||
class LibraryPlugin(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
addEvent('library.add', self.add)
|
||||
|
||||
def add(self, attrs = {}):
|
||||
|
||||
db = get_session();
|
||||
|
||||
l = db.query(Library).filter_by(identifier = attrs.get('identifier')).first()
|
||||
|
||||
if not l:
|
||||
l = Library(
|
||||
name = attrs.get('name'),
|
||||
year = attrs.get('year'),
|
||||
identifier = attrs.get('identifier'),
|
||||
description = attrs.get('description')
|
||||
)
|
||||
db.add(l)
|
||||
db.commit()
|
||||
|
||||
return l
|
||||
|
||||
def update(self, item):
|
||||
|
||||
pass
|
||||
@@ -0,0 +1,6 @@
|
||||
from couchpotato.core.plugins.movie.main import MoviePlugin
|
||||
|
||||
def start():
|
||||
return MoviePlugin()
|
||||
|
||||
config = []
|
||||
@@ -0,0 +1,94 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.helpers.request import getParams, jsonified
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Movie, Release, Profile
|
||||
from couchpotato.environment import Env
|
||||
from urllib import urlencode
|
||||
|
||||
|
||||
class MoviePlugin(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
addApiView('movie.search', self.search)
|
||||
addApiView('movie.list', self.list)
|
||||
addApiView('movie.add', self.add)
|
||||
|
||||
def list(self):
|
||||
|
||||
a = getParams()
|
||||
|
||||
results = get_session().query(Movie).filter(
|
||||
Movie.releases.any(
|
||||
Release.status.has(identifier = 'wanted')
|
||||
)
|
||||
).all()
|
||||
|
||||
movies = []
|
||||
for movie in results:
|
||||
temp = {
|
||||
'id': movie.id,
|
||||
'name': movie.id,
|
||||
'releases': [],
|
||||
}
|
||||
for release in movie.releases:
|
||||
temp['releases'].append({
|
||||
'status': release.status.label,
|
||||
'quality': release.quality.label
|
||||
})
|
||||
|
||||
movies.append(temp)
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
'empty': len(movies) == 0,
|
||||
'movies': movies,
|
||||
})
|
||||
|
||||
def search(self):
|
||||
|
||||
a = getParams()
|
||||
cache_key = '%s/%s' % (__name__, urlencode(a))
|
||||
movies = Env.get('cache').get(cache_key)
|
||||
|
||||
if not movies:
|
||||
results = fireEvent('provider.movie.search', q = a.get('q'))
|
||||
|
||||
# Combine movie results
|
||||
movies = []
|
||||
for r in results:
|
||||
movies += r
|
||||
|
||||
Env.get('cache').set(cache_key, movies, timeout = 10)
|
||||
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
'empty': len(movies) == 0,
|
||||
'movies': movies,
|
||||
})
|
||||
|
||||
def add(self):
|
||||
|
||||
a = getParams()
|
||||
db = get_session();
|
||||
|
||||
library = fireEvent('library.add', attrs = a)
|
||||
profile = db.query(Profile).filter_by(identifier = a.get('profile_identifier'))
|
||||
|
||||
m = db.query(Movie).filter_by(library = library).first()
|
||||
|
||||
if not m:
|
||||
m = Movie(
|
||||
library = library,
|
||||
profile = profile,
|
||||
)
|
||||
db.add(m)
|
||||
db.commit()
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
'added': True,
|
||||
'params': a,
|
||||
})
|
||||
@@ -1,6 +0,0 @@
|
||||
from couchpotato.core.plugins.movie_add.main import MovieAdd
|
||||
|
||||
def start():
|
||||
return MovieAdd()
|
||||
|
||||
config = []
|
||||
@@ -1,36 +0,0 @@
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.helpers.request import getParams, jsonified
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
|
||||
class MovieAdd(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
addApiView('movie.add.search', self.search)
|
||||
addApiView('movie.add.select', self.select)
|
||||
|
||||
def search(self):
|
||||
|
||||
a = getParams()
|
||||
|
||||
results = fireEvent('provider.movie.search', q = a.get('q'))
|
||||
|
||||
# Combine movie results
|
||||
movies = []
|
||||
for r in results:
|
||||
movies += r
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
'empty': len(movies) == 0,
|
||||
'movies': movies,
|
||||
})
|
||||
|
||||
def select(self):
|
||||
|
||||
a = getParams()
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
'added': True,
|
||||
})
|
||||
@@ -1,6 +0,0 @@
|
||||
from couchpotato.core.plugins.movie_list.main import MovieList
|
||||
|
||||
def start():
|
||||
return MovieList()
|
||||
|
||||
config = []
|
||||
@@ -1,41 +0,0 @@
|
||||
from couchpotato import get_session
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.helpers.request import getParams, jsonified
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.core.settings.model import Movie, Release
|
||||
|
||||
class MovieList(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
addApiView('movie.list', self.list)
|
||||
|
||||
def list(self):
|
||||
|
||||
a = getParams()
|
||||
|
||||
results = get_session().query(Movie).filter(
|
||||
Movie.releases.any(
|
||||
Release.status.has(identifier = 'wanted')
|
||||
)
|
||||
).all()
|
||||
|
||||
movies = []
|
||||
for movie in results:
|
||||
temp = {
|
||||
'id': movie.id,
|
||||
'name': movie.id,
|
||||
'releases': [],
|
||||
}
|
||||
for release in movie.releases:
|
||||
temp['releases'].append({
|
||||
'status': release.status.label,
|
||||
'quality': release.quality.label
|
||||
})
|
||||
|
||||
movies.append(temp)
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
'empty': len(movies) == 0,
|
||||
'movies': movies,
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
from couchpotato.core.plugins.profile.main import ProfilePlugin
|
||||
|
||||
def start():
|
||||
return ProfilePlugin()
|
||||
|
||||
config = []
|
||||
@@ -0,0 +1,28 @@
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.request import jsonified, getParams
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
|
||||
class ProfilePlugin(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
addEvent('profile.get', self.get)
|
||||
|
||||
addApiView('profile.save', self.save)
|
||||
addApiView('profile.delete', self.delete)
|
||||
|
||||
def get(self, key = ''):
|
||||
|
||||
pass
|
||||
|
||||
def save(self):
|
||||
|
||||
a = getParams()
|
||||
|
||||
return jsonified({
|
||||
'success': True,
|
||||
'a': a
|
||||
})
|
||||
|
||||
def delete(self):
|
||||
pass
|
||||
@@ -1,7 +1,7 @@
|
||||
from couchpotato.core.providers.tmdb.main import TMDB
|
||||
from couchpotato.core.providers.tmdb.main import TMDBWrapper
|
||||
|
||||
def start():
|
||||
return TMDB()
|
||||
return TMDBWrapper()
|
||||
|
||||
config = [{
|
||||
'name': 'themoviedb',
|
||||
|
||||
@@ -4,6 +4,7 @@ from couchpotato.core.helpers.encoding import simplifyString, toUnicode
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.base import Provider
|
||||
from couchpotato.environment import Env
|
||||
from libs.themoviedb import tmdb
|
||||
from urllib import quote_plus
|
||||
import copy
|
||||
import simplejson as json
|
||||
@@ -11,7 +12,7 @@ import urllib2
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
class TMDB(Provider):
|
||||
class TMDBWrapper(Provider):
|
||||
"""Api for theMovieDb"""
|
||||
|
||||
type = 'movie'
|
||||
@@ -20,6 +21,10 @@ class TMDB(Provider):
|
||||
|
||||
def __init__(self):
|
||||
addEvent('provider.movie.search', self.search)
|
||||
addEvent('provider.movie.info', self.getInfo)
|
||||
|
||||
# Use base wrapper
|
||||
tmdb.Config.api_key = self.conf('api_key')
|
||||
|
||||
def conf(self, attr):
|
||||
return Env.setting(attr, 'themoviedb')
|
||||
@@ -32,31 +37,32 @@ class TMDB(Provider):
|
||||
|
||||
log.debug('TheMovieDB - Searching for movie: %s' % q)
|
||||
|
||||
url = "%s/%s/%s/json/%s/%s" % (self.apiUrl, 'Movie.search', 'en', self.conf('api_key'), quote_plus(simplifyString(q)))
|
||||
raw = tmdb.search(simplifyString(q))
|
||||
|
||||
log.info('Searching: %s' % url)
|
||||
#url = "%s/%s/%s/json/%s/%s" % (self.apiUrl, 'Movie.search', 'en', self.conf('api_key'), quote_plus(simplifyString(q)))
|
||||
|
||||
data = urllib2.urlopen(url)
|
||||
jsn = json.load(data)
|
||||
|
||||
return self.parse(jsn, limit, alternative = alternative)
|
||||
# data = urllib2.urlopen(url)
|
||||
# jsn = json.load(data)
|
||||
|
||||
def parse(self, data, limit, alternative = True):
|
||||
if data:
|
||||
if raw:
|
||||
log.debug('TheMovieDB - Parsing RSS')
|
||||
try:
|
||||
results = []
|
||||
nr = 0
|
||||
for movie in data:
|
||||
for movie in raw:
|
||||
|
||||
year = str(movie['released'])[:4]
|
||||
for k, x in movie.iteritems():
|
||||
print k
|
||||
print x
|
||||
|
||||
year = str(movie.get('released', 'none'))[:4]
|
||||
|
||||
# Poster url
|
||||
poster = ''
|
||||
for p in movie['posters']:
|
||||
p = p['image']
|
||||
if(p['size'] == 'thumb'):
|
||||
poster = p['url']
|
||||
for p in movie.get('images'):
|
||||
if(p.get('type') == 'poster'):
|
||||
poster = p.get('thumb')
|
||||
break
|
||||
|
||||
# 1900 is the same as None
|
||||
@@ -64,16 +70,16 @@ class TMDB(Provider):
|
||||
year = None
|
||||
|
||||
movie_data = {
|
||||
'id': int(movie['id']),
|
||||
'name': toUnicode(movie['name']),
|
||||
'id': int(movie.get('id', 0)),
|
||||
'name': toUnicode(movie.get('name')),
|
||||
'poster': poster,
|
||||
'imdb': movie['imdb_id'],
|
||||
'imdb': movie.get('imdb_id'),
|
||||
'year': year,
|
||||
'tagline': 'This is the tagline of the movie',
|
||||
}
|
||||
results.append(copy.deepcopy(movie_data))
|
||||
|
||||
alternativeName = movie['alternative_name']
|
||||
alternativeName = movie.get('alternative_name')
|
||||
if alternativeName and alternative:
|
||||
if alternativeName.lower() != movie['name'].lower() and alternativeName.lower() != 'none' and alternativeName != None:
|
||||
movie_data['name'] = toUnicode(alternativeName)
|
||||
@@ -88,6 +94,10 @@ class TMDB(Provider):
|
||||
log.error('TheMovieDB - Failed to parse XML response from TheMovieDb: %s' % e)
|
||||
return False
|
||||
|
||||
return results
|
||||
|
||||
def getInfo(self):
|
||||
pass
|
||||
|
||||
def isDisabled(self):
|
||||
if self.conf('api_key') == '':
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import with_statement
|
||||
from couchpotato.api import addApiView
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.encoding import is_int
|
||||
from couchpotato.core.helpers.request import getParams, jsonified
|
||||
import ConfigParser
|
||||
import os.path
|
||||
@@ -60,7 +61,7 @@ class Settings():
|
||||
return default
|
||||
|
||||
def cleanValue(self, value):
|
||||
if(self.is_int(value)):
|
||||
if(is_int(value)):
|
||||
return int(value)
|
||||
|
||||
if str(value).lower() in self.bool:
|
||||
@@ -91,13 +92,6 @@ class Settings():
|
||||
if not self.p.has_option(section, option):
|
||||
self.p.set(section, option, value)
|
||||
|
||||
def is_int(self, value):
|
||||
try:
|
||||
int(value)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def addOptions(self, section_name, options):
|
||||
self.options[section_name] = options
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ from elixir.entity import Entity
|
||||
from elixir.fields import Field
|
||||
from elixir.options import options_defaults
|
||||
from elixir.relationships import OneToMany, ManyToOne
|
||||
from sqlalchemy.types import Integer, String, Unicode, UnicodeText, Boolean
|
||||
from sqlalchemy.types import Integer, String, Unicode, UnicodeText, Boolean, \
|
||||
Float
|
||||
|
||||
options_defaults["shortnames"] = True
|
||||
|
||||
@@ -19,13 +20,26 @@ class Movie(Entity):
|
||||
The files belonging to the movie object are global for the whole movie
|
||||
such as trailers, nfo, thumbnails"""
|
||||
|
||||
mooli_id = Field(Integer)
|
||||
library = ManyToOne('Library')
|
||||
|
||||
profile = ManyToOne('Profile')
|
||||
releases = OneToMany('Release')
|
||||
files = OneToMany('File')
|
||||
|
||||
|
||||
class Library(Entity):
|
||||
|
||||
title = Field(Unicode)
|
||||
year = Field(Integer)
|
||||
identifier = Field(Unicode)
|
||||
rating = Field(Float)
|
||||
|
||||
plot = Field(UnicodeText)
|
||||
tagline = Field(UnicodeText(255))
|
||||
|
||||
movie = OneToMany('Movie')
|
||||
|
||||
|
||||
class Release(Entity):
|
||||
"""Logically groups all files that belong to a certain release, such as
|
||||
parts of a movie, subtitles."""
|
||||
@@ -55,6 +69,7 @@ class Quality(Entity):
|
||||
releases = OneToMany('Release')
|
||||
profile_types = ManyToOne('ProfileType')
|
||||
|
||||
|
||||
class Profile(Entity):
|
||||
""""""
|
||||
|
||||
@@ -66,6 +81,7 @@ class Profile(Entity):
|
||||
movie = OneToMany('Movie')
|
||||
profile_type = OneToMany('ProfileType')
|
||||
|
||||
|
||||
class ProfileType(Entity):
|
||||
""""""
|
||||
|
||||
@@ -76,6 +92,7 @@ class ProfileType(Entity):
|
||||
type = OneToMany('Quality')
|
||||
profile = ManyToOne('Profile')
|
||||
|
||||
|
||||
class File(Entity):
|
||||
"""File that belongs to a release."""
|
||||
|
||||
@@ -114,6 +131,7 @@ class History(Entity):
|
||||
message = Field(UnicodeText())
|
||||
release = ManyToOne('Release')
|
||||
|
||||
|
||||
class RenameHistory(Entity):
|
||||
"""Remembers from where to where files have been moved."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user