Skip to content
This repository has been archived by the owner on Jan 7, 2023. It is now read-only.

Commit

Permalink
Add kolsys' Plex Plugin Updater
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Amorin committed May 15, 2016
1 parent 7b15b5b commit 475c45d
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 8 deletions.
6 changes: 4 additions & 2 deletions Contents/Code/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# if platform.system() == 'Darwin':
# from mock_framework import *
from DumbTools import DumbKeyboard
from updater import Updater

PREFIX = '/video/sonarr'
NAME = 'Sonarr'
Expand Down Expand Up @@ -65,6 +66,7 @@ def main_menu():
summary=L('unmet_desc'),
thumb=R('exclamation-triangle.png')))
oc.add(PrefsObject(title=L('settings'), thumb=R('cogs.png')))
Updater(PREFIX + '/updater', oc)
return oc


Expand Down Expand Up @@ -655,12 +657,12 @@ def monitor_badge(is_monitored):


def success_message():
return MessageContainer(L('success'), L('success'))
return MessageContainer(L('Success'), L('Success'))


def error_message(exception):
Log.Exception('Error!')
return MessageContainer(L('error'), exception.message)
return MessageContainer(L('Error'), exception.message)


def timestamp(time=Datetime.UTCNow()):
Expand Down
4 changes: 4 additions & 0 deletions Contents/Code/mock_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ def ParseDate(date):
def Delta(**kwargs):
return Datetime

@staticmethod
def UTCNow(**kwargs):
return datetime.utcnow()


class Resource(object):
@staticmethod
Expand Down
154 changes: 154 additions & 0 deletions Contents/Code/updater.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# -*- coding: utf-8 -*-
#
# Plex Plugin Updater
# $Id$
#
# Universal plugin updater module for Plex Server Channels that
# implement automatic plugins updates from remote config.
# Support Github API by default
#
# https://github.com/kolsys/plex-channel-updater
#
# Copyright (c) 2014, KOL
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the <organization> nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

KEY_PLIST_VERSION = 'CFBundleVersion'
KEY_PLIST_URL = 'PlexPluginVersionUrl'

KEY_DATA_VERSION = 'tag_name'
KEY_DATA_DESC = 'body'
KEY_DATA_ZIPBALL = 'zipball_url'

CHECK_INTERVAL = CACHE_1HOUR * 12


class Updater:
info = None
update = None

def __init__(self, prefix, oc):

if self.InitBundleInfo() and self.IsUpdateAvailable():
Route.Connect(prefix, self.DoUpdate)
oc.add(DirectoryObject(
key=Callback(self.DoUpdate),
title=u'%s' % F(
'Update available: %s',
self.update['version']
),
summary=u'%s\n%s' % (L(
'Install latest version of the channel.'
), self.update['info']),
))

def NormalizeVersion(self, version):
if version[:1] == 'v':
version = version[1:]
return version

def ParseVersion(self, version):

try:
return tuple(map(int, (version.split('.'))))
except:
# String comparison by default
return version

def IsUpdateAvailable(self):
try:
info = JSON.ObjectFromURL(
self.info['url'],
cacheTime=CHECK_INTERVAL,
timeout=5
)
version = self.NormalizeVersion(info[KEY_DATA_VERSION])
dist_url = info[KEY_DATA_ZIPBALL]

except:
return False

if self.ParseVersion(version) > self.ParseVersion(
self.info['version']
):
self.update = {
'version': version,
'url': dist_url,
'info': info[KEY_DATA_DESC] if KEY_DATA_DESC in info else '',
}

return bool(self.update)

def InitBundleInfo(self):
try:
plist = Plist.ObjectFromString(Core.storage.load(
Core.storage.abs_path(
Core.storage.join_path(
Core.bundle_path,
'Contents',
'Info.plist'
)
)
))
self.info = {
'version': plist[KEY_PLIST_VERSION],
'url': plist[KEY_PLIST_URL],
}
except:
pass

return bool(self.info)

def DoUpdate(self):
try:
zip_data = Archive.ZipFromURL(self.update['url'])
bundle_path = Core.storage.abs_path(Core.bundle_path)

for name in zip_data.Names():
data = zip_data[name]
parts = name.split('/')
shifted = Core.storage.join_path(*parts[1:])
full = Core.storage.join_path(bundle_path, shifted)

if '/.' in name:
continue

if name.endswith('/'):
Core.storage.ensure_dirs(full)
else:
Core.storage.save(full, data)
del zip_data

return ObjectContainer(
header=u'%s' % L('Success'),
message=u'%s' % F(
'Channel updated to version %s',
self.update['version']
)
)
except Exception as e:
return ObjectContainer(
header=u'%s' % L('Error'),
message=u'%s' % e
)
4 changes: 3 additions & 1 deletion Contents/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.plexapp.plugins.sonarr</string>
<string>com.github.jamorin.sonarr</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>PlexFrameworkVersion</key>
<string>2</string>
<key>PlexPluginCodePolicy</key>
Expand Down
13 changes: 8 additions & 5 deletions Contents/Strings/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@
"calendar": "Calendar",
"calendar_desc": "This week's upcoming episodes",
"change": "Change",
"Channel updated to version %s": "Channel updated to version %s",
"confirm": "Confirm",
"cutoff": "Cutoff",
"days_ago": "day(s) ago",
"delete": "Delete",
"deleted": "Deleted",
"error": "Error",
"Error": "Error",
"failed": "Failed",
"grabbed": "Grabbed",
"history": "History",
"history_desc": "Recently downloaded episodes",
"hours_ago": "hour(s) ago",
"imported": "Imported",
"Install latest version of the channel.": "Install latest version of the channel.",
"list": "List",
"manual_search": "Manual Search",
"minutes_ago": "minute(s) ago",
"missing": "Missing",
"missing_desc": "List wanted or missing episodes",
"monitored": "Monitored",
"quality": "Quality",
"queue": "Queue",
Expand All @@ -31,15 +35,14 @@
"season": "Season",
"settings": "Settings",
"status": "Status",
"success": "Success",
"Success": "Success",
"title": "Title",
"toggle": "Toggle",
"today": "Today",
"tomorrow": "Tomorrow",
"unknown": "Unknown",
"unmet": "Cutoff Unmet",
"unmet_desc": "Episodes with cutoff unmet",
"yesterday": "Yesterday",
"missing": "Missing",
"missing_desc": "List wanted or missing episodes"
"Update available: %s": "Update available: %s",
"yesterday": "Yesterday"
}

0 comments on commit 475c45d

Please sign in to comment.