mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-08-19 12:59:42 -07:00
commit
2296a9fbb3
11 changed files with 207 additions and 10 deletions
|
@ -5,6 +5,7 @@ contrib
|
||||||
init-scripts
|
init-scripts
|
||||||
package
|
package
|
||||||
pylintrc
|
pylintrc
|
||||||
|
snap
|
||||||
*.md
|
*.md
|
||||||
!CHANGELOG*.md
|
!CHANGELOG*.md
|
||||||
start.bat
|
start.bat
|
||||||
|
|
94
.github/workflows/publish-snap.yml
vendored
Normal file
94
.github/workflows/publish-snap.yml
vendored
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
name: Publish Snap
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master, beta, nightly]
|
||||||
|
tags: [v*]
|
||||||
|
pull_request: ~
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-snap:
|
||||||
|
name: Build Snap Package (${{ matrix.architecture }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
architecture:
|
||||||
|
- i386
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
- armhf
|
||||||
|
- ppc64le
|
||||||
|
#- s390x # broken at the moment
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
id: prepare
|
||||||
|
run: |
|
||||||
|
git fetch --prune --unshallow --tags
|
||||||
|
if [[ $GITHUB_REF == refs/tags/*-beta || $GITHUB_REF == refs/heads/beta ]]; then
|
||||||
|
echo ::set-output name=RELEASE::beta
|
||||||
|
elif [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
|
||||||
|
echo ::set-output name=RELEASE::stable
|
||||||
|
else
|
||||||
|
echo ::set-output name=RELEASE::edge
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Set Up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
|
||||||
|
- name: Build Snap Package
|
||||||
|
uses: diddlesnaps/snapcraft-multiarch-action@v1
|
||||||
|
id: build
|
||||||
|
with:
|
||||||
|
architecture: ${{ matrix.architecture }}
|
||||||
|
|
||||||
|
- name: Upload Snap Package
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Tautulli-snap-package-${{ matrix.architecture }}
|
||||||
|
path: ${{ steps.build.outputs.snap }}
|
||||||
|
|
||||||
|
- name: Review Snap Package
|
||||||
|
uses: diddlesnaps/snapcraft-review-tools-action@v1
|
||||||
|
with:
|
||||||
|
snap: ${{ steps.build.outputs.snap }}
|
||||||
|
|
||||||
|
- name: Publish Snap Package
|
||||||
|
uses: snapcore/action-publish@v1
|
||||||
|
if: >
|
||||||
|
github.event_name != 'pull_request' &&
|
||||||
|
(startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/nightly')
|
||||||
|
with:
|
||||||
|
store_login: ${{ secrets.SNAP_LOGIN }}
|
||||||
|
snap: ${{ steps.build.outputs.snap }}
|
||||||
|
release: ${{ steps.prepare.outputs.RELEASE }}
|
||||||
|
|
||||||
|
discord:
|
||||||
|
name: Discord Notification
|
||||||
|
needs: build-snap
|
||||||
|
if: always() && github.event_name != 'pull_request'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Get Build Job Status
|
||||||
|
uses: technote-space/workflow-conclusion-action@v1
|
||||||
|
|
||||||
|
- name: Combine Job Status
|
||||||
|
id: status
|
||||||
|
run: |
|
||||||
|
failures=(neutral, skipped, timed_out, action_required)
|
||||||
|
if [[ ${array[@]} =~ $WORKFLOW_CONCLUSION ]]; then
|
||||||
|
echo ::set-output name=status::failure
|
||||||
|
else
|
||||||
|
echo ::set-output name=status::$WORKFLOW_CONCLUSION
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Post Status to Discord
|
||||||
|
uses: sarisia/actions-status-discord@v1
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
status: ${{ steps.status.outputs.status }}
|
||||||
|
title: ${{ github.workflow }}
|
||||||
|
nofail: true
|
13
.gitignore
vendored
13
.gitignore
vendored
|
@ -81,3 +81,16 @@ _ReSharper*/
|
||||||
#Ignore files generated by pyinstaller
|
#Ignore files generated by pyinstaller
|
||||||
/build
|
/build
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
|
#snapcraft specifics
|
||||||
|
/parts/
|
||||||
|
/stage/
|
||||||
|
/prime/
|
||||||
|
|
||||||
|
*.snap
|
||||||
|
|
||||||
|
.snapcraft
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
*_source.tar.bz2
|
||||||
|
snap/.snapcraft
|
|
@ -124,6 +124,8 @@ def main():
|
||||||
|
|
||||||
if helpers.bool_true(os.getenv('TAUTULLI_DOCKER', False)):
|
if helpers.bool_true(os.getenv('TAUTULLI_DOCKER', False)):
|
||||||
plexpy.DOCKER = True
|
plexpy.DOCKER = True
|
||||||
|
if helpers.bool_true(os.getenv('TAUTULLI_SNAP', False)):
|
||||||
|
plexpy.SNAP = True
|
||||||
|
|
||||||
if args.dev:
|
if args.dev:
|
||||||
plexpy.DEV = True
|
plexpy.DEV = True
|
||||||
|
|
|
@ -59,6 +59,8 @@
|
||||||
% endif
|
% endif
|
||||||
% if plexpy.INSTALL_TYPE == 'docker':
|
% if plexpy.INSTALL_TYPE == 'docker':
|
||||||
Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>
|
Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>
|
||||||
|
% elif plexpy.INSTALL_TYPE == 'snap':
|
||||||
|
Update your Snap package or <a href="#" id="updateDismiss">Dismiss</a>
|
||||||
% elif plexpy.INSTALL_TYPE in ('windows', 'macos'):
|
% elif plexpy.INSTALL_TYPE in ('windows', 'macos'):
|
||||||
<a href="${anon_url('https://github.com/%s/%s/releases/tag/%s' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.LATEST_RELEASE))}" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>
|
<a href="${anon_url('https://github.com/%s/%s/releases/tag/%s' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.LATEST_RELEASE))}" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>
|
||||||
% else:
|
% else:
|
||||||
|
@ -337,6 +339,8 @@ ${next.modalIncludes()}
|
||||||
}
|
}
|
||||||
if (result.install_type === 'docker') {
|
if (result.install_type === 'docker') {
|
||||||
msg += 'Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>';
|
msg += 'Update your Docker container or <a href="#" id="updateDismiss">Dismiss</a>';
|
||||||
|
} else if (result.install_type === 'snap') {
|
||||||
|
msg += 'Update your Snap package or <a href="#" id="updateDismiss">Dismiss</a>';
|
||||||
} else if (result.install_type === 'windows' || result.install_type === 'macos') {
|
} else if (result.install_type === 'windows' || result.install_type === 'macos') {
|
||||||
msg += '<a href="' + result.release_url + '" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>'
|
msg += '<a href="' + result.release_url + '" target="_blank" rel="noreferrer">Download</a> and install the latest version or <a href="#" id="updateDismiss">Dismiss</a>'
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -220,7 +220,7 @@
|
||||||
<p class="help-block">Check for Tautulli updates periodically.</p>
|
<p class="help-block">Check for Tautulli updates periodically.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="git_update_options">
|
<div id="git_update_options">
|
||||||
% if not plexpy.FROZEN:
|
% if not plexpy.SNAP and not plexpy.FROZEN:
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="plexpy_auto_update" name="plexpy_auto_update" value="1" ${config['plexpy_auto_update']} ${docker_setting}> Update Automatically ${docker_msg | n}
|
<input type="checkbox" id="plexpy_auto_update" name="plexpy_auto_update" value="1" ${config['plexpy_auto_update']} ${docker_setting}> Update Automatically ${docker_msg | n}
|
||||||
|
|
|
@ -98,6 +98,7 @@ CREATEPID = False
|
||||||
PIDFILE = None
|
PIDFILE = None
|
||||||
NOFORK = False
|
NOFORK = False
|
||||||
DOCKER = False
|
DOCKER = False
|
||||||
|
SNAP = False
|
||||||
FROZEN = False
|
FROZEN = False
|
||||||
|
|
||||||
SCHED = None
|
SCHED = None
|
||||||
|
@ -194,6 +195,8 @@ def initialize(config_file):
|
||||||
|
|
||||||
if DOCKER:
|
if DOCKER:
|
||||||
build = '[Docker] '
|
build = '[Docker] '
|
||||||
|
elif SNAP:
|
||||||
|
build = '[Snap] '
|
||||||
elif FROZEN:
|
elif FROZEN:
|
||||||
build = '[Bundle] '
|
build = '[Bundle] '
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -257,7 +257,7 @@ def import_tautulli_config(config=None, backup=False):
|
||||||
# Remove keys that should not be imported
|
# Remove keys that should not be imported
|
||||||
for key in _DO_NOT_IMPORT_KEYS:
|
for key in _DO_NOT_IMPORT_KEYS:
|
||||||
delattr(imported_config, key)
|
delattr(imported_config, key)
|
||||||
if plexpy.DOCKER:
|
if plexpy.DOCKER or plexpy.SNAP:
|
||||||
for key in _DO_NOT_IMPORT_KEYS_DOCKER:
|
for key in _DO_NOT_IMPORT_KEYS_DOCKER:
|
||||||
delattr(imported_config, key)
|
delattr(imported_config, key)
|
||||||
|
|
||||||
|
@ -540,3 +540,9 @@ class Config(object):
|
||||||
self.JWT_UPDATE_SECRET = True
|
self.JWT_UPDATE_SECRET = True
|
||||||
|
|
||||||
self.CONFIG_VERSION = 16
|
self.CONFIG_VERSION = 16
|
||||||
|
|
||||||
|
if self.CONFIG_VERSION == 16:
|
||||||
|
if plexpy.SNAP:
|
||||||
|
self.PLEXPY_AUTO_UPDATE = 0
|
||||||
|
|
||||||
|
self.CONFIG_VERSION = 17
|
||||||
|
|
|
@ -133,7 +133,13 @@ def get_version():
|
||||||
return cur_commit_hash, remote_name, branch_name
|
return cur_commit_hash, remote_name, branch_name
|
||||||
|
|
||||||
else:
|
else:
|
||||||
plexpy.INSTALL_TYPE = 'docker' if plexpy.DOCKER else 'source'
|
if plexpy.DOCKER:
|
||||||
|
plexpy.INSTALL_TYPE = 'docker'
|
||||||
|
elif plexpy.SNAP:
|
||||||
|
plexpy.INSTALL_TYPE = 'snap'
|
||||||
|
else:
|
||||||
|
plexpy.INSTALL_TYPE = 'source'
|
||||||
|
|
||||||
current_version, current_branch = get_version_from_file()
|
current_version, current_branch = get_version_from_file()
|
||||||
return current_version, 'origin', current_branch
|
return current_version, 'origin', current_branch
|
||||||
|
|
||||||
|
@ -162,10 +168,13 @@ def check_update(scheduler=False, notify=False, use_cache=False):
|
||||||
|
|
||||||
if not plexpy.CURRENT_VERSION:
|
if not plexpy.CURRENT_VERSION:
|
||||||
plexpy.UPDATE_AVAILABLE = None
|
plexpy.UPDATE_AVAILABLE = None
|
||||||
elif plexpy.COMMITS_BEHIND > 0 and (plexpy.common.BRANCH in ('master', 'beta') or plexpy.FROZEN) and \
|
elif plexpy.COMMITS_BEHIND > 0 and \
|
||||||
|
(plexpy.common.BRANCH in ('master', 'beta') or plexpy.SNAP or plexpy.FROZEN) and \
|
||||||
plexpy.common.RELEASE != plexpy.LATEST_RELEASE:
|
plexpy.common.RELEASE != plexpy.LATEST_RELEASE:
|
||||||
plexpy.UPDATE_AVAILABLE = 'release'
|
plexpy.UPDATE_AVAILABLE = 'release'
|
||||||
elif plexpy.COMMITS_BEHIND > 0 and plexpy.CURRENT_VERSION != plexpy.LATEST_VERSION and not plexpy.FROZEN:
|
elif plexpy.COMMITS_BEHIND > 0 and \
|
||||||
|
not plexpy.SNAP and not plexpy.FROZEN and \
|
||||||
|
plexpy.CURRENT_VERSION != plexpy.LATEST_VERSION:
|
||||||
plexpy.UPDATE_AVAILABLE = 'commit'
|
plexpy.UPDATE_AVAILABLE = 'commit'
|
||||||
else:
|
else:
|
||||||
plexpy.UPDATE_AVAILABLE = False
|
plexpy.UPDATE_AVAILABLE = False
|
||||||
|
@ -265,7 +274,8 @@ def check_github(scheduler=False, notify=False, use_cache=False):
|
||||||
'plexpy_update_commit': plexpy.LATEST_VERSION,
|
'plexpy_update_commit': plexpy.LATEST_VERSION,
|
||||||
'plexpy_update_behind': plexpy.COMMITS_BEHIND})
|
'plexpy_update_behind': plexpy.COMMITS_BEHIND})
|
||||||
|
|
||||||
if scheduler and plexpy.CONFIG.PLEXPY_AUTO_UPDATE and not plexpy.DOCKER and not plexpy.FROZEN:
|
if scheduler and plexpy.CONFIG.PLEXPY_AUTO_UPDATE and \
|
||||||
|
not plexpy.DOCKER and not plexpy.SNAP and not plexpy.FROZEN:
|
||||||
logger.info('Running automatic update.')
|
logger.info('Running automatic update.')
|
||||||
plexpy.shutdown(restart=True, update=True)
|
plexpy.shutdown(restart=True, update=True)
|
||||||
|
|
||||||
|
@ -279,7 +289,7 @@ def update():
|
||||||
if not plexpy.UPDATE_AVAILABLE:
|
if not plexpy.UPDATE_AVAILABLE:
|
||||||
return
|
return
|
||||||
|
|
||||||
if plexpy.INSTALL_TYPE in ('docker', 'windows', 'macos'):
|
if plexpy.INSTALL_TYPE in ('docker', 'snap', 'windows', 'macos'):
|
||||||
return
|
return
|
||||||
|
|
||||||
elif plexpy.INSTALL_TYPE == 'git':
|
elif plexpy.INSTALL_TYPE == 'git':
|
||||||
|
|
|
@ -4309,7 +4309,7 @@ class WebInterface(object):
|
||||||
plexpy.CONFIG.GIT_REPO,
|
plexpy.CONFIG.GIT_REPO,
|
||||||
plexpy.CURRENT_VERSION,
|
plexpy.CURRENT_VERSION,
|
||||||
plexpy.LATEST_VERSION))
|
plexpy.LATEST_VERSION))
|
||||||
}
|
}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
update = {'result': 'success',
|
update = {'result': 'success',
|
||||||
|
@ -4317,7 +4317,7 @@ class WebInterface(object):
|
||||||
'message': 'Tautulli is up to date.'
|
'message': 'Tautulli is up to date.'
|
||||||
}
|
}
|
||||||
|
|
||||||
if plexpy.DOCKER or plexpy.FROZEN:
|
if plexpy.DOCKER or plexpy.SNAP or plexpy.FROZEN:
|
||||||
update['install_type'] = plexpy.INSTALL_TYPE
|
update['install_type'] = plexpy.INSTALL_TYPE
|
||||||
|
|
||||||
return update
|
return update
|
||||||
|
@ -4351,7 +4351,7 @@ class WebInterface(object):
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@requireAuth(member_of("admin"))
|
@requireAuth(member_of("admin"))
|
||||||
def update(self, **kwargs):
|
def update(self, **kwargs):
|
||||||
if plexpy.DOCKER:
|
if plexpy.DOCKER or plexpy.SNAP:
|
||||||
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "home")
|
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "home")
|
||||||
|
|
||||||
# Show changelog after updating
|
# Show changelog after updating
|
||||||
|
|
64
snap/snapcraft.yaml
Normal file
64
snap/snapcraft.yaml
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
name: tautulli
|
||||||
|
adopt-info: tautulli
|
||||||
|
summary: A Python based monitoring and tracking tool for Plex Media Server.
|
||||||
|
description: >
|
||||||
|
Tautulli is a 3rd party application that you can run alongside your Plex Media Server to monitor activity and track various statistics.
|
||||||
|
Most importantly, these statistics include what has been watched, who watched it, when and where they watched it, and how it was watched.
|
||||||
|
The only thing missing is "why they watched it", but who am I to question your 42 plays of Frozen.
|
||||||
|
All statistics are presented in a nice and clean interface with many tables and graphs, which makes it easy to brag about your server to everyone else.
|
||||||
|
|
||||||
|
base: core18
|
||||||
|
confinement: strict
|
||||||
|
|
||||||
|
parts:
|
||||||
|
tautulli:
|
||||||
|
plugin: dump
|
||||||
|
source: .
|
||||||
|
stage-packages:
|
||||||
|
- python3
|
||||||
|
- python3-setuptools
|
||||||
|
- python3-openssl
|
||||||
|
build-packages:
|
||||||
|
- git
|
||||||
|
override-pull: |
|
||||||
|
snapcraftctl pull
|
||||||
|
TAG_FULL=$(git describe --tag)
|
||||||
|
TAG=$(echo $TAG_FULL | grep -oP '(v\d+\.\d+\.\d+(?>-beta)?)')
|
||||||
|
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||||
|
COMMIT=$(git rev-parse HEAD)
|
||||||
|
if [ "$TAG" = "$TAG_FULL" ]; then
|
||||||
|
VERSION=$TAG
|
||||||
|
else
|
||||||
|
VERSION=$(echo $COMMIT | head -c 7)
|
||||||
|
fi
|
||||||
|
if [ ! "$VERSION" = "$TAG" ] || [ ! "$VERSION" = "${VERSION%-beta}" ]; then
|
||||||
|
GRADE=devel
|
||||||
|
else
|
||||||
|
GRADE=stable
|
||||||
|
fi
|
||||||
|
if [ "$VERSION" = "$TAG" ] && [ ! "$VERSION" = "${VERSION%-beta}" ]; then
|
||||||
|
BRANCH=beta
|
||||||
|
elif [ "$VERSION" = "$TAG" ]; then
|
||||||
|
BRANCH=master
|
||||||
|
fi
|
||||||
|
echo $BRANCH > branch.txt
|
||||||
|
echo $COMMIT > version.txt
|
||||||
|
snapcraftctl set-version "$VERSION"
|
||||||
|
snapcraftctl set-grade "$GRADE"
|
||||||
|
|
||||||
|
apps:
|
||||||
|
tautulli:
|
||||||
|
command: >
|
||||||
|
usr/bin/python3 $SNAP/Tautulli.py
|
||||||
|
--datadir $SNAP_USER_COMMON/Tautulli
|
||||||
|
--config $SNAP_USER_COMMON/Tautulli/config.ini
|
||||||
|
--quiet
|
||||||
|
--nolaunch
|
||||||
|
daemon: simple
|
||||||
|
restart-condition: on-abnormal
|
||||||
|
restart-delay: 5s
|
||||||
|
plugs:
|
||||||
|
- network
|
||||||
|
- network-bind
|
||||||
|
environment:
|
||||||
|
TAUTULLI_SNAP: "True"
|
Loading…
Add table
Add a link
Reference in a new issue