26 changed files with 1027 additions and 795 deletions
@ -0,0 +1,25 @@ |
|||||
|
from migrate.changeset.schema import create_column |
||||
|
from sqlalchemy.schema import MetaData, Column, Table, Index |
||||
|
from sqlalchemy.types import Integer |
||||
|
|
||||
|
meta = MetaData() |
||||
|
|
||||
|
|
||||
|
def upgrade(migrate_engine): |
||||
|
meta.bind = migrate_engine |
||||
|
|
||||
|
# Change release, add last_edit and index |
||||
|
last_edit_column = Column('last_edit', Integer) |
||||
|
release = Table('release', meta, last_edit_column) |
||||
|
|
||||
|
create_column(last_edit_column, release) |
||||
|
Index('ix_release_last_edit', release.c.last_edit).create() |
||||
|
|
||||
|
# Change movie last_edit |
||||
|
last_edit_column = Column('last_edit', Integer) |
||||
|
movie = Table('movie', meta, last_edit_column) |
||||
|
Index('ix_movie_last_edit', movie.c.last_edit).create() |
||||
|
|
||||
|
|
||||
|
def downgrade(migrate_engine): |
||||
|
pass |
@ -0,0 +1,48 @@ |
|||||
|
from .main import Pushalot |
||||
|
|
||||
|
def start(): |
||||
|
return Pushalot() |
||||
|
|
||||
|
config = [{ |
||||
|
'name': 'pushalot', |
||||
|
'groups': [ |
||||
|
{ |
||||
|
'tab': 'notifications', |
||||
|
'list': 'notification_providers', |
||||
|
'name': 'pushalot', |
||||
|
'description': 'for Windows Phone and Windows 8', |
||||
|
'options': [ |
||||
|
{ |
||||
|
'name': 'enabled', |
||||
|
'default': 0, |
||||
|
'type': 'enabler', |
||||
|
}, |
||||
|
{ |
||||
|
'name': 'auth_token', |
||||
|
'label': 'Auth Token', |
||||
|
}, |
||||
|
{ |
||||
|
'name': 'silent', |
||||
|
'label': 'Silent', |
||||
|
'default': 0, |
||||
|
'type': 'bool', |
||||
|
'description': 'Don\'t send Toast notifications. Only update Live Tile', |
||||
|
}, |
||||
|
{ |
||||
|
'name': 'important', |
||||
|
'label': 'High Priority', |
||||
|
'default': 0, |
||||
|
'type': 'bool', |
||||
|
'description': 'Send message with High priority.', |
||||
|
}, |
||||
|
{ |
||||
|
'name': 'on_snatch', |
||||
|
'default': 0, |
||||
|
'type': 'bool', |
||||
|
'advanced': True, |
||||
|
'description': 'Also send message when movie is snatched.', |
||||
|
}, |
||||
|
], |
||||
|
} |
||||
|
], |
||||
|
}] |
@ -0,0 +1,37 @@ |
|||||
|
from couchpotato.core.helpers.encoding import toUnicode |
||||
|
from couchpotato.core.logger import CPLog |
||||
|
from couchpotato.core.notifications.base import Notification |
||||
|
import traceback |
||||
|
|
||||
|
log = CPLog(__name__) |
||||
|
|
||||
|
class Pushalot(Notification): |
||||
|
|
||||
|
urls = { |
||||
|
'api': 'https://pushalot.com/api/sendmessage' |
||||
|
} |
||||
|
|
||||
|
def notify(self, message = '', data = {}, listener = None): |
||||
|
if self.isDisabled(): return |
||||
|
|
||||
|
data = { |
||||
|
'AuthorizationToken': self.conf('auth_token'), |
||||
|
'Title': self.default_title, |
||||
|
'Body': toUnicode(message), |
||||
|
'LinkTitle': toUnicode("CouchPotato"), |
||||
|
'link': toUnicode("https://couchpota.to/"), |
||||
|
'IsImportant': self.conf('important'), |
||||
|
'IsSilent': self.conf('silent'), |
||||
|
} |
||||
|
|
||||
|
headers = { |
||||
|
'Content-type': 'application/x-www-form-urlencoded' |
||||
|
} |
||||
|
|
||||
|
try: |
||||
|
self.urlopen(self.urls['api'], headers = headers, params = data, multipart = True, show_error = False) |
||||
|
return True |
||||
|
except: |
||||
|
log.error('PushAlot failed: %s', traceback.format_exc()) |
||||
|
|
||||
|
return False |
@ -0,0 +1,699 @@ |
|||||
|
var MovieAction = new Class({ |
||||
|
|
||||
|
class_name: 'action icon', |
||||
|
|
||||
|
initialize: function(movie){ |
||||
|
var self = this; |
||||
|
self.movie = movie; |
||||
|
|
||||
|
self.create(); |
||||
|
if(self.el) |
||||
|
self.el.addClass(self.class_name) |
||||
|
}, |
||||
|
|
||||
|
create: function(){}, |
||||
|
|
||||
|
disable: function(){ |
||||
|
this.el.addClass('disable') |
||||
|
}, |
||||
|
|
||||
|
enable: function(){ |
||||
|
this.el.removeClass('disable') |
||||
|
}, |
||||
|
|
||||
|
createMask: function(){ |
||||
|
var self = this; |
||||
|
self.mask = new Element('div.mask', { |
||||
|
'styles': { |
||||
|
'z-index': '1' |
||||
|
} |
||||
|
}).inject(self.movie, 'top').fade('hide'); |
||||
|
//self.positionMask();
|
||||
|
}, |
||||
|
|
||||
|
positionMask: function(){ |
||||
|
var self = this, |
||||
|
movie = $(self.movie), |
||||
|
s = movie.getSize() |
||||
|
|
||||
|
return; |
||||
|
|
||||
|
return self.mask.setStyles({ |
||||
|
'width': s.x, |
||||
|
'height': s.y |
||||
|
}).position({ |
||||
|
'relativeTo': movie |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
toElement: function(){ |
||||
|
return this.el || null |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
var MA = {}; |
||||
|
|
||||
|
MA.IMDB = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
id: null, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.id = self.movie.get('identifier'); |
||||
|
|
||||
|
self.el = new Element('a.imdb', { |
||||
|
'title': 'Go to the IMDB page of ' + self.movie.getTitle(), |
||||
|
'href': 'http://www.imdb.com/title/'+self.id+'/', |
||||
|
'target': '_blank' |
||||
|
}); |
||||
|
|
||||
|
if(!self.id) self.disable(); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
MA.Release = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el = new Element('a.releases.icon.download', { |
||||
|
'title': 'Show the releases that are available for ' + self.movie.getTitle(), |
||||
|
'events': { |
||||
|
'click': self.show.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
if(self.movie.data.releases.length == 0){ |
||||
|
self.el.hide() |
||||
|
} |
||||
|
else { |
||||
|
|
||||
|
var buttons_done = false; |
||||
|
|
||||
|
self.movie.data.releases.sortBy('-info.score').each(function(release){ |
||||
|
if(buttons_done) return; |
||||
|
|
||||
|
var status = Status.get(release.status_id); |
||||
|
|
||||
|
if((self.next_release && (status.identifier == 'ignored' || status.identifier == 'failed')) || (!self.next_release && status.identifier == 'available')){ |
||||
|
self.hide_on_click = false; |
||||
|
self.show(); |
||||
|
buttons_done = true; |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
show: function(e){ |
||||
|
var self = this; |
||||
|
if(e) |
||||
|
(e).preventDefault(); |
||||
|
|
||||
|
if(!self.options_container){ |
||||
|
self.options_container = new Element('div.options').adopt( |
||||
|
self.release_container = new Element('div.releases.table').adopt( |
||||
|
self.trynext_container = new Element('div.buttons.try_container') |
||||
|
) |
||||
|
).inject(self.movie, 'top'); |
||||
|
|
||||
|
// Header
|
||||
|
new Element('div.item.head').adopt( |
||||
|
new Element('span.name', {'text': 'Release name'}), |
||||
|
new Element('span.status', {'text': 'Status'}), |
||||
|
new Element('span.quality', {'text': 'Quality'}), |
||||
|
new Element('span.size', {'text': 'Size'}), |
||||
|
new Element('span.age', {'text': 'Age'}), |
||||
|
new Element('span.score', {'text': 'Score'}), |
||||
|
new Element('span.provider', {'text': 'Provider'}) |
||||
|
).inject(self.release_container) |
||||
|
|
||||
|
self.movie.data.releases.sortBy('-info.score').each(function(release){ |
||||
|
|
||||
|
var status = Status.get(release.status_id), |
||||
|
quality = Quality.getProfile(release.quality_id) || {}, |
||||
|
info = release.info, |
||||
|
provider = self.get(release, 'provider') + (release.info['provider_extra'] ? self.get(release, 'provider_extra') : ''); |
||||
|
release.status = status; |
||||
|
|
||||
|
var release_name = self.get(release, 'name'); |
||||
|
if(release.files && release.files.length > 0){ |
||||
|
try { |
||||
|
var movie_file = release.files.filter(function(file){ |
||||
|
var type = File.Type.get(file.type_id); |
||||
|
return type && type.identifier == 'movie' |
||||
|
}).pick(); |
||||
|
release_name = movie_file.path.split(Api.getOption('path_sep')).getLast(); |
||||
|
} |
||||
|
catch(e){} |
||||
|
} |
||||
|
|
||||
|
// Create release
|
||||
|
new Element('div', { |
||||
|
'class': 'item '+status.identifier, |
||||
|
'id': 'release_'+release.id |
||||
|
}).adopt( |
||||
|
new Element('span.name', {'text': release_name, 'title': release_name}), |
||||
|
new Element('span.status', {'text': status.identifier, 'class': 'release_status '+status.identifier}), |
||||
|
new Element('span.quality', {'text': quality.get('label') || 'n/a'}), |
||||
|
new Element('span.size', {'text': release.info['size'] ? Math.floor(self.get(release, 'size')) : 'n/a'}), |
||||
|
new Element('span.age', {'text': self.get(release, 'age')}), |
||||
|
new Element('span.score', {'text': self.get(release, 'score')}), |
||||
|
new Element('span.provider', { 'text': provider, 'title': provider }), |
||||
|
release.info['detail_url'] ? new Element('a.info.icon', { |
||||
|
'href': release.info['detail_url'], |
||||
|
'target': '_blank' |
||||
|
}) : null, |
||||
|
new Element('a.download.icon', { |
||||
|
'events': { |
||||
|
'click': function(e){ |
||||
|
(e).preventDefault(); |
||||
|
if(!this.hasClass('completed')) |
||||
|
self.download(release); |
||||
|
} |
||||
|
} |
||||
|
}), |
||||
|
new Element('a.delete.icon', { |
||||
|
'events': { |
||||
|
'click': function(e){ |
||||
|
(e).preventDefault(); |
||||
|
self.ignore(release); |
||||
|
this.getParent('.item').toggleClass('ignored') |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
).inject(self.release_container) |
||||
|
|
||||
|
if(status.identifier == 'ignored' || status.identifier == 'failed' || status.identifier == 'snatched'){ |
||||
|
if(!self.last_release || (self.last_release && self.last_release.status.identifier != 'snatched' && status.identifier == 'snatched')) |
||||
|
self.last_release = release; |
||||
|
} |
||||
|
else if(!self.next_release && status.identifier == 'available'){ |
||||
|
self.next_release = release; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
if(self.last_release){ |
||||
|
self.release_container.getElement('#release_'+self.last_release.id).addClass('last_release'); |
||||
|
} |
||||
|
|
||||
|
if(self.next_release){ |
||||
|
self.release_container.getElement('#release_'+self.next_release.id).addClass('next_release'); |
||||
|
} |
||||
|
|
||||
|
if(self.next_release || self.last_release){ |
||||
|
|
||||
|
self.trynext_container.adopt( |
||||
|
new Element('span.or', { |
||||
|
'text': 'This movie is snatched, if anything went wrong, download' |
||||
|
}), |
||||
|
self.last_release ? new Element('a.button.orange', { |
||||
|
'text': 'the same release again', |
||||
|
'events': { |
||||
|
'click': self.trySameRelease.bind(self) |
||||
|
} |
||||
|
}) : null, |
||||
|
self.next_release && self.last_release ? new Element('span.or', { |
||||
|
'text': ',' |
||||
|
}) : null, |
||||
|
self.next_release ? [new Element('a.button.green', { |
||||
|
'text': self.last_release ? 'another release' : 'the best release', |
||||
|
'events': { |
||||
|
'click': self.tryNextRelease.bind(self) |
||||
|
} |
||||
|
}), |
||||
|
new Element('span.or', { |
||||
|
'text': 'or pick one below' |
||||
|
})] : null |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
self.movie.slide('in', self.options_container); |
||||
|
}, |
||||
|
|
||||
|
get: function(release, type){ |
||||
|
return release.info[type] || 'n/a' |
||||
|
}, |
||||
|
|
||||
|
download: function(release){ |
||||
|
var self = this; |
||||
|
|
||||
|
var release_el = self.release_container.getElement('#release_'+release.id), |
||||
|
icon = release_el.getElement('.download.icon'); |
||||
|
|
||||
|
icon.addClass('spinner'); |
||||
|
|
||||
|
Api.request('release.download', { |
||||
|
'data': { |
||||
|
'id': release.id |
||||
|
}, |
||||
|
'onComplete': function(json){ |
||||
|
icon.removeClass('spinner') |
||||
|
if(json.success) |
||||
|
icon.addClass('completed'); |
||||
|
else |
||||
|
icon.addClass('attention').set('title', 'Something went wrong when downloading, please check logs.'); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
ignore: function(release){ |
||||
|
var self = this; |
||||
|
|
||||
|
Api.request('release.ignore', { |
||||
|
'data': { |
||||
|
'id': release.id |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
tryNextRelease: function(movie_id){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.last_release) |
||||
|
self.ignore(self.last_release); |
||||
|
|
||||
|
if(self.next_release) |
||||
|
self.download(self.next_release); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
trySameRelease: function(movie_id){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.last_release) |
||||
|
self.download(self.last_release); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
MA.Trailer = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
id: null, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el = new Element('a.trailer', { |
||||
|
'title': 'Watch the trailer of ' + self.movie.getTitle(), |
||||
|
'events': { |
||||
|
'click': self.watch.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
watch: function(offset){ |
||||
|
var self = this; |
||||
|
|
||||
|
var data_url = 'http://gdata.youtube.com/feeds/videos?vq="{title}" {year} trailer&max-results=1&alt=json-in-script&orderby=relevance&sortorder=descending&format=5&fmt=18' |
||||
|
var url = data_url.substitute({ |
||||
|
'title': encodeURI(self.movie.getTitle()), |
||||
|
'year': self.movie.get('year'), |
||||
|
'offset': offset || 1 |
||||
|
}), |
||||
|
size = $(self.movie).getSize(), |
||||
|
height = (size.x/16)*9, |
||||
|
id = 'trailer-'+randomString(); |
||||
|
|
||||
|
self.player_container = new Element('div[id='+id+']'); |
||||
|
self.container = new Element('div.hide.trailer_container') |
||||
|
.adopt(self.player_container) |
||||
|
.inject($(self.movie), 'top'); |
||||
|
|
||||
|
self.container.setStyle('height', 0); |
||||
|
self.container.removeClass('hide'); |
||||
|
|
||||
|
self.close_button = new Element('a.hide.hide_trailer', { |
||||
|
'text': 'Hide trailer', |
||||
|
'events': { |
||||
|
'click': self.stop.bind(self) |
||||
|
} |
||||
|
}).inject(self.movie); |
||||
|
|
||||
|
self.container.setStyle('height', height); |
||||
|
$(self.movie).setStyle('height', height); |
||||
|
|
||||
|
new Request.JSONP({ |
||||
|
'url': url, |
||||
|
'onComplete': function(json){ |
||||
|
var video_url = json.feed.entry[0].id.$t.split('/'), |
||||
|
video_id = video_url[video_url.length-1]; |
||||
|
|
||||
|
self.player = new YT.Player(id, { |
||||
|
'height': height, |
||||
|
'width': size.x, |
||||
|
'videoId': video_id, |
||||
|
'playerVars': { |
||||
|
'autoplay': 1, |
||||
|
'showsearch': 0, |
||||
|
'wmode': 'transparent', |
||||
|
'iv_load_policy': 3 |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
self.close_button.removeClass('hide'); |
||||
|
|
||||
|
var quality_set = false; |
||||
|
var change_quality = function(state){ |
||||
|
if(!quality_set && (state.data == 1 || state.data || 2)){ |
||||
|
try { |
||||
|
self.player.setPlaybackQuality('hd720'); |
||||
|
quality_set = true; |
||||
|
} |
||||
|
catch(e){ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
self.player.addEventListener('onStateChange', change_quality); |
||||
|
|
||||
|
} |
||||
|
}).send() |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
stop: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.player.stopVideo(); |
||||
|
self.container.addClass('hide'); |
||||
|
self.close_button.addClass('hide'); |
||||
|
$(self.movie).setStyle('height', null); |
||||
|
|
||||
|
setTimeout(function(){ |
||||
|
self.container.destroy() |
||||
|
self.close_button.destroy(); |
||||
|
}, 1800) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
}); |
||||
|
|
||||
|
MA.Edit = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el = new Element('a.edit', { |
||||
|
'title': 'Change movie information, like title and quality.', |
||||
|
'events': { |
||||
|
'click': self.editMovie.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
editMovie: function(e){ |
||||
|
var self = this; |
||||
|
(e).preventDefault(); |
||||
|
|
||||
|
if(!self.options_container){ |
||||
|
self.options_container = new Element('div.options').adopt( |
||||
|
new Element('div.form').adopt( |
||||
|
self.title_select = new Element('select', { |
||||
|
'name': 'title' |
||||
|
}), |
||||
|
self.profile_select = new Element('select', { |
||||
|
'name': 'profile' |
||||
|
}), |
||||
|
new Element('a.button.edit', { |
||||
|
'text': 'Save & Search', |
||||
|
'events': { |
||||
|
'click': self.save.bind(self) |
||||
|
} |
||||
|
}) |
||||
|
) |
||||
|
).inject(self.movie, 'top'); |
||||
|
|
||||
|
Array.each(self.movie.data.library.titles, function(alt){ |
||||
|
new Element('option', { |
||||
|
'text': alt.title |
||||
|
}).inject(self.title_select); |
||||
|
|
||||
|
if(alt['default']) |
||||
|
self.title_select.set('value', alt.title); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
Quality.getActiveProfiles().each(function(profile){ |
||||
|
|
||||
|
var profile_id = profile.id ? profile.id : profile.data.id; |
||||
|
|
||||
|
new Element('option', { |
||||
|
'value': profile_id, |
||||
|
'text': profile.label ? profile.label : profile.data.label |
||||
|
}).inject(self.profile_select); |
||||
|
|
||||
|
if(self.movie.profile && self.movie.profile.data && self.movie.profile.data.id == profile_id) |
||||
|
self.profile_select.set('value', profile_id); |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
self.movie.slide('in', self.options_container); |
||||
|
}, |
||||
|
|
||||
|
save: function(e){ |
||||
|
(e).preventDefault(); |
||||
|
var self = this; |
||||
|
|
||||
|
Api.request('movie.edit', { |
||||
|
'data': { |
||||
|
'id': self.movie.get('id'), |
||||
|
'default_title': self.title_select.get('value'), |
||||
|
'profile_id': self.profile_select.get('value') |
||||
|
}, |
||||
|
'useSpinner': true, |
||||
|
'spinnerTarget': $(self.movie), |
||||
|
'onComplete': function(){ |
||||
|
self.movie.quality.set('text', self.profile_select.getSelected()[0].get('text')); |
||||
|
self.movie.title.set('text', self.title_select.getSelected()[0].get('text')); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
self.movie.slide('out'); |
||||
|
} |
||||
|
|
||||
|
}) |
||||
|
|
||||
|
MA.Refresh = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el = new Element('a.refresh', { |
||||
|
'title': 'Refresh the movie info and do a forced search', |
||||
|
'events': { |
||||
|
'click': self.doRefresh.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
doRefresh: function(e){ |
||||
|
var self = this; |
||||
|
(e).preventDefault(); |
||||
|
|
||||
|
Api.request('movie.refresh', { |
||||
|
'data': { |
||||
|
'id': self.movie.get('id') |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
MA.Readd = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var movie_done = Status.get(self.movie.data.status_id).identifier == 'done'; |
||||
|
if(!movie_done) |
||||
|
var snatched = self.movie.data.releases.filter(function(release){ |
||||
|
return release.status && (release.status.identifier == 'snatched' || release.status.identifier == 'downloaded' || release.status.identifier == 'done'); |
||||
|
}).length; |
||||
|
|
||||
|
if(movie_done || snatched && snatched > 0) |
||||
|
self.el = new Element('a.readd', { |
||||
|
'title': 'Readd the movie and mark all previous snatched/downloaded as ignored', |
||||
|
'events': { |
||||
|
'click': self.doReadd.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
doReadd: function(e){ |
||||
|
var self = this; |
||||
|
(e).preventDefault(); |
||||
|
|
||||
|
Api.request('movie.add', { |
||||
|
'data': { |
||||
|
'identifier': self.movie.get('identifier'), |
||||
|
'ignore_previous': 1 |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
MA.Delete = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
|
||||
|
Implements: [Chain], |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el = new Element('a.delete', { |
||||
|
'title': 'Remove the movie from this CP list', |
||||
|
'events': { |
||||
|
'click': self.showConfirm.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
showConfirm: function(e){ |
||||
|
var self = this; |
||||
|
(e).preventDefault(); |
||||
|
|
||||
|
if(!self.delete_container){ |
||||
|
self.delete_container = new Element('div.buttons.delete_container').adopt( |
||||
|
new Element('a.cancel', { |
||||
|
'text': 'Cancel', |
||||
|
'events': { |
||||
|
'click': self.hideConfirm.bind(self) |
||||
|
} |
||||
|
}), |
||||
|
new Element('span.or', { |
||||
|
'text': 'or' |
||||
|
}), |
||||
|
new Element('a.button.delete', { |
||||
|
'text': 'Delete ' + self.movie.title.get('text'), |
||||
|
'events': { |
||||
|
'click': self.del.bind(self) |
||||
|
} |
||||
|
}) |
||||
|
).inject(self.movie, 'top'); |
||||
|
} |
||||
|
|
||||
|
self.movie.slide('in', self.delete_container); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
hideConfirm: function(e){ |
||||
|
var self = this; |
||||
|
(e).preventDefault(); |
||||
|
|
||||
|
self.movie.slide('out'); |
||||
|
}, |
||||
|
|
||||
|
del: function(e){ |
||||
|
(e).preventDefault(); |
||||
|
var self = this; |
||||
|
|
||||
|
var movie = $(self.movie); |
||||
|
|
||||
|
self.chain( |
||||
|
function(){ |
||||
|
self.callChain(); |
||||
|
}, |
||||
|
function(){ |
||||
|
Api.request('movie.delete', { |
||||
|
'data': { |
||||
|
'id': self.movie.get('id'), |
||||
|
'delete_from': self.movie.list.options.identifier |
||||
|
}, |
||||
|
'onComplete': function(){ |
||||
|
movie.set('tween', { |
||||
|
'duration': 300, |
||||
|
'onComplete': function(){ |
||||
|
self.movie.destroy() |
||||
|
} |
||||
|
}); |
||||
|
movie.tween('height', 0); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
self.callChain(); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
MA.Files = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el = new Element('a.directory', { |
||||
|
'title': 'Available files', |
||||
|
'events': { |
||||
|
'click': self.showFiles.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
showFiles: function(e){ |
||||
|
var self = this; |
||||
|
(e).preventDefault(); |
||||
|
|
||||
|
if(!self.options_container){ |
||||
|
self.options_container = new Element('div.options').adopt( |
||||
|
self.files_container = new Element('div.files.table') |
||||
|
).inject(self.movie, 'top'); |
||||
|
|
||||
|
// Header
|
||||
|
new Element('div.item.head').adopt( |
||||
|
new Element('span.name', {'text': 'File'}), |
||||
|
new Element('span.type', {'text': 'Type'}), |
||||
|
new Element('span.is_available', {'text': 'Available'}) |
||||
|
).inject(self.files_container) |
||||
|
|
||||
|
Array.each(self.movie.data.releases, function(release){ |
||||
|
|
||||
|
var rel = new Element('div.release').inject(self.files_container); |
||||
|
|
||||
|
Array.each(release.files, function(file){ |
||||
|
new Element('div.file.item').adopt( |
||||
|
new Element('span.name', {'text': file.path}), |
||||
|
new Element('span.type', {'text': File.Type.get(file.type_id).name}), |
||||
|
new Element('span.available', {'text': file.available}) |
||||
|
).inject(rel) |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
self.movie.slide('in', self.options_container); |
||||
|
}, |
||||
|
|
||||
|
}); |
After Width: | Height: | Size: 778 B |
@ -0,0 +1,5 @@ |
|||||
|
# COPY THIS FILE TO /etc/default/couchpotato |
||||
|
# OPTIONS: APP_PATH, RUN_AS, DAEMON_PATH, CP_PID_FILE |
||||
|
|
||||
|
APP_PATH= |
||||
|
RUN_AS=root |
Loading…
Reference in new issue