diff --git a/.dockerignore b/.dockerignore
index 87b5c14b..8f266283 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -5,6 +5,7 @@ contrib
init-scripts
package
pylintrc
+snap
*.md
!CHANGELOG*.md
start.bat
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 44e3f7c6..79319ae1 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,3 @@
github: JonnyWong16
patreon: Tautulli
-custom: ["https://bit.ly/2InPp15"]
\ No newline at end of file
+custom: ["https://bit.ly/2InPp15", "https://bit.ly/2WTq83m"]
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/BUG-REPORT.yml b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml
new file mode 100644
index 00000000..34f617df
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml
@@ -0,0 +1,103 @@
+name: Bug Report
+description: Please do not use bug reports for support issues.
+labels: ['status:awaiting-triage', 'type:bug']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **THIS IS NOT THE PLACE TO ASK FOR SUPPORT!** Please use [Discord](https://tautulli.com/discord) for support issues.
+ - type: textarea
+ id: description
+ attributes:
+ label: Describe the Bug
+ description: A clear and concise description of the bug.
+ validations:
+ required: true
+ - type: textarea
+ id: steps
+ attributes:
+ label: Steps to Reproduce
+ description: List each action required in order to reproduce the issue.
+ placeholder: |
+ 1. Go to '...'
+ 2. Click on '...'
+ 3. Scroll down to '...'
+ 4. See error
+ - type: textarea
+ id: expected
+ attributes:
+ label: Expected Behavior
+ description: A clear and concise description of what you expected to happen.
+ - type: textarea
+ id: screenshots
+ attributes:
+ label: Screenshots
+ description: Provide screenshots to help explain your problem.
+ - type: textarea
+ id: relevant
+ attributes:
+ label: Relevant Settings
+ description: Include all settings/configuration that are relevant to your issue. For example, Plex Media Server, newsletter, or notification settings.
+ placeholder: |
+ - eg. Plex Media Server IP address/port/checkboxes/proxy/etc.
+ - eg. Notification agent configuration/triggers/conditions/text/delay/grouping/etc.
+ - eg. Newsletter agent configuration/checkboxes/template/etc.
+ - Other settings
+ - type: input
+ id: version
+ attributes:
+ label: Tautulli Version
+ description: Check Tautulli Settings > Help & Info page.
+ placeholder: eg. v2.7.5
+ validations:
+ required: true
+ - type: input
+ id: branch
+ attributes:
+ label: Git Branch
+ description: Check Tautulli Settings > Help & Info page.
+ placeholder: eg. master
+ validations:
+ required: true
+ - type: input
+ id: hash
+ attributes:
+ label: Git Commit Hash
+ description: Check Tautulli Settings > Help & Info page.
+ placeholder: eg. 2cc5bf812fe05e0666aeaeb37ed550c59816fb4c
+ validations:
+ required: true
+ - type: input
+ id: platform
+ attributes:
+ label: Platform and Version
+ description: Check Tautulli Settings > Help & Info page.
+ placeholder: eg. Windows 10
+ validations:
+ required: true
+ - type: input
+ id: python
+ attributes:
+ label: Python Version
+ description: Check Tautulli Settings > Help & Info page.
+ placeholder: eg. 3.8.10
+ validations:
+ required: true
+ - type: input
+ id: browser
+ attributes:
+ label: Browser and Version
+ placeholder: eg. Chrome 88
+ validations:
+ required: true
+ - type: input
+ id: logs
+ attributes:
+ label: Link to Logs
+ description: Include a link to your **FULL** logs (not just a few lines) on [Gist](http://gist.github.com).
+ validations:
+ required: true
+ - type: markdown
+ attributes:
+ value: |
+ Make sure to close your issue when it's solved! If you found the solution yourself please comment so that others benefit from it.
diff --git a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
new file mode 100644
index 00000000..70e2ab33
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
@@ -0,0 +1,31 @@
+name: Feature Request
+description: Suggest a new feature for Tautulli.
+labels: ['status:awaiting-triage', 'type:enhancement']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to help improve Tautulli!
+ - type: textarea
+ id: problem
+ attributes:
+ label: Is your feature request related to a problem?
+ description: If so, please provide clear and concise description of the problem.
+ placeholder: eg. I'm always frustrated when '...'
+ - type: textarea
+ id: feature
+ attributes:
+ label: What is your feature request?
+ description: A clear and concise description of the feature.
+ validations:
+ required: true
+ - type: textarea
+ id: workaround
+ attributes:
+ label: Are there any workarounds?
+ description: A clear and concise description of any alternative solutions or features you've considered.
+ - type: textarea
+ id: additional
+ attributes:
+ label: Additional Context
+ description: Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000..16aef760
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Tautulli Wiki
+ url: https://github.com/Tautulli/Tautulli/wiki
+ about: Please check the wiki to see if your question has already been answered.
+ - name: Discord
+ url: https://tautulli.com/discord
+ about: Please use Discord to ask for support.
diff --git a/.github/codeql-config.yml b/.github/codeql-config.yml
new file mode 100644
index 00000000..574f9b33
--- /dev/null
+++ b/.github/codeql-config.yml
@@ -0,0 +1,4 @@
+name: CodeQL Config
+
+paths-ignore:
+ - lib
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..1028cc5a
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,15 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ target-branch: "nightly"
+ open-pull-requests-limit: 20
+
+ - package-ecosystem: "pip"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ target-branch: "nightly"
+ open-pull-requests-limit: 20
diff --git a/.github/label-actions.yml b/.github/label-actions.yml
new file mode 100644
index 00000000..ae236e9a
--- /dev/null
+++ b/.github/label-actions.yml
@@ -0,0 +1,48 @@
+# Configuration for Label Actions - https://github.com/dessant/label-actions
+
+added:
+ comment: >
+ This feature has been added and will be available in the next release of Tautulli.
+ This issue will be automatically closed once the update is available.
+
+fixed:
+ comment: >
+ This bug has been fixed and will be available in the next release of Tautulli.
+ This issue will be automatically closed once the update is available.
+
+invalid:duplicate:
+ comment: >
+ :wave: @{issue-author}, this appears to be a duplicate of a pre-existing issue.
+ close: true
+ lock: true
+ unlabel: 'status:awaiting-triage'
+
+-invalid:duplicate:
+ reopen: true
+ unlock: true
+
+invalid:support:
+ comment: >
+ :wave: @{issue-author}, we use the issue tracker exclusively for bug reports.
+ However, this issue appears to be a support request. Please use our
+ [Discord Server](https://tautulli.com/discord) to get help with Tautulli. Thanks.
+ close: true
+ lock: true
+ lock-reason: 'off-topic'
+ unlabel: 'status:awaiting-triage'
+
+-invalid:support:
+ reopen: true
+ unlock: true
+
+invalid:template-incomplete:
+ issues:
+ comment: >
+ :wave: @{issue-author}, please edit your issue to complete the template with
+ all the required info. Your issue will be automatically closed in 5 days if
+ the template is not completed. Thanks.
+ prs:
+ comment: >
+ :wave: @{issue-author}, please edit your PR to complete the template with
+ all the required info. Your PR will be automatically closed in 5 days if
+ the template is not completed. Thanks.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..63ab24be
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,26 @@
+## Description
+
+Please include a summary of the changes.
+
+### Screenshot
+
+Include screenshots if the changes are UI-related.
+
+### Issues Fixed or Closed
+
+- Fixes #(issue)
+
+## Type of Change
+
+Please delete options that are not relevant.
+
+- [ ] Bug fix (non-breaking change which fixes an issue)
+- [ ] New feature (non-breaking change which adds functionality)
+- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
+
+## Checklist
+
+- [ ] My code follows the style guidelines of this project
+- [ ] I have performed a self-review of my own code
+- [ ] I have commented my code, particularly in hard-to-understand areas
+- [ ] I have added or updated the docstring for new or existing methods
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 00000000..e9c8e05d
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,38 @@
+name: CodeQL
+
+on:
+ push:
+ branches: [nightly]
+ pull_request:
+ branches: [nightly]
+ schedule:
+ - cron: '05 10 * * 1'
+
+jobs:
+ codeql-analysis:
+ name: CodeQL Analysis
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: ['javascript', 'python']
+
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ config-file: ./.github/codeql-config.yml
+ languages: ${{ matrix.language }}
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/issues-stale.yml b/.github/workflows/issues-stale.yml
new file mode 100644
index 00000000..b805e266
--- /dev/null
+++ b/.github/workflows/issues-stale.yml
@@ -0,0 +1,48 @@
+name: Stale Issues / PRs
+
+on:
+ schedule:
+ - cron: '00 19 * * *'
+
+jobs:
+ stale:
+ name: Check Issues / PRs
+ runs-on: ubuntu-latest
+ steps:
+ - name: Stale
+ uses: actions/stale@v9
+ with:
+ stale-issue-message: >
+ This issue is stale because it has been open for 30 days with no activity.
+ Remove the stale label or comment, otherwise this will be closed in 5 days.
+ close-issue-message: >
+ This issue was closed because it has been stalled for 5 days with no activity.
+ stale-issue-label: 'stale'
+ exempt-issue-labels: 'added,fixed,type:enhancement,status:awaiting-triage,status:in-progress'
+ stale-pr-message: >
+ This PR is stale because it has been open for 30 days with no activity.
+ Remove the stale label or comment, otherwise this will be closed in 5 days.
+ close-pr-message: >
+ This PR was closed because it has been stalled for 5 days with no activity.
+ stale-pr-label: 'stale'
+ exempt-pr-labels: 'status:in-progress,status:in-review,dependencies'
+ days-before-stale: 30
+ days-before-close: 5
+
+ - name: Invalid Template
+ uses: actions/stale@v9
+ with:
+ stale-issue-message: >
+ Invalid issues template.
+ close-issue-message: >
+ This issue was closed because the the template was not completed after 5 days.
+ stale-issue-label: 'invalid:template-incomplete'
+ stale-pr-message: >
+ Invalid PR template.
+ close-pr-message: >
+ This PR was closed because the the template was not completed after 5 days.
+ stale-pr-label: 'invalid:template-incomplete'
+ exempt-pr-labels: 'status:in-progress,status:in-review,dependencies'
+ only-labels: 'invalid:template-incomplete'
+ days-before-stale: 0
+ days-before-close: 5
diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml
new file mode 100644
index 00000000..a60987f5
--- /dev/null
+++ b/.github/workflows/issues.yml
@@ -0,0 +1,15 @@
+name: Issues
+
+on:
+ issues:
+ types: [labeled, unlabeled]
+
+jobs:
+ label:
+ name: Label Issues
+ runs-on: ubuntu-latest
+ steps:
+ - name: Label Issues
+ uses: dessant/label-actions@v4
+ with:
+ github-token: ${{ github.token }}
diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml
index 3fd2f79e..62c3f86c 100644
--- a/.github/workflows/publish-docker.yml
+++ b/.github/workflows/publish-docker.yml
@@ -1,48 +1,52 @@
name: Publish Docker
+
on:
+ workflow_dispatch: ~
push:
- branches: [master, beta, nightly, python3]
+ branches: [master, beta, nightly]
tags: [v*]
+
jobs:
- build:
+ build-docker:
+ name: Build Docker Image
runs-on: ubuntu-latest
+ if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
steps:
- name: Checkout Code
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Prepare
id: prepare
run: |
if [[ $GITHUB_REF == refs/tags/* ]]; then
- echo ::set-output name=tag::${GITHUB_REF#refs/tags/}
+ echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
elif [[ $GITHUB_REF == refs/heads/master ]]; then
- echo ::set-output name=tag::latest
+ echo "tag=latest" >> $GITHUB_OUTPUT
else
- echo ::set-output name=tag::${GITHUB_REF#refs/heads/}
+ echo "tag=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
fi
- if [[ $GITHUB_REF == refs/tags/* ]]; then
- echo ::set-output name=branch::master
+ if [[ $GITHUB_REF == refs/tags/*-beta ]]; then
+ echo "branch=beta" >> $GITHUB_OUTPUT
+ elif [[ $GITHUB_REF == refs/tags/* ]]; then
+ echo "branch=master" >> $GITHUB_OUTPUT
else
- echo ::set-output name=branch::${GITHUB_REF#refs/heads/}
+ echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
fi
- echo ::set-output name=commit::${GITHUB_SHA}
- echo ::set-output name=build_date::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- echo ::set-output name=docker_platforms::linux/amd64,linux/arm64/v8,linux/arm/v7,linux/arm/v6
- echo ::set-output name=docker_image::${{ secrets.DOCKER_REPO }}/tautulli
+ echo "commit=${GITHUB_SHA}" >> $GITHUB_OUTPUT
+ echo "docker_platforms=linux/amd64,linux/arm64/v8,linux/arm/v7,linux/arm/v6" >> $GITHUB_OUTPUT
+ echo "docker_image=${{ secrets.DOCKER_REPO }}/tautulli" >> $GITHUB_OUTPUT
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v1
- with:
- platforms: all
+ - name: Set Up QEMU
+ uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
id: buildx
- uses: docker/setup-buildx-action@v1
with:
version: latest
- name: Cache Docker Layers
- uses: actions/cache@v2
+ uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
@@ -50,22 +54,28 @@ jobs:
${{ runner.os }}-buildx-
- name: Login to DockerHub
- uses: docker/login-action@v1
+ uses: docker/login-action@v3
if: success()
with:
username: ${{ secrets.DOCKER_USERNAME }}
- password: ${{ secrets.DOCKER_PASSWORD }}
+ password: ${{ secrets.DOCKER_TOKEN }}
- name: Login to GitHub Container Registry
- uses: docker/login-action@v1
+ uses: docker/login-action@v3
if: success()
with:
registry: ghcr.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
+ - name: Extract Docker Metadata
+ id: metadata
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ steps.prepare.outputs.docker_image }}
+
- name: Docker Build and Push
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v6
if: success()
with:
context: .
@@ -76,18 +86,23 @@ jobs:
TAG=${{ steps.prepare.outputs.tag }}
BRANCH=${{ steps.prepare.outputs.branch }}
COMMIT=${{ steps.prepare.outputs.commit }}
- BUILD_DATE=${{ steps.prepare.outputs.build_date }}
tags: |
${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.tag }}
ghcr.io/${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.tag }}
+ labels: ${{ steps.metadata.outputs.labels }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
+ discord:
+ name: Discord Notification
+ needs: build-docker
+ if: always() && !contains(github.event.head_commit.message, '[skip ci]')
+ runs-on: ubuntu-latest
+ steps:
- name: Post Status to Discord
uses: sarisia/actions-status-discord@v1
- if: always()
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
- status: ${{ job.status }}
+ status: ${{ needs.build-docker.result == 'success' && 'success' || contains(needs.*.result, 'failure') && 'failure' || 'cancelled' }}
title: ${{ github.workflow }}
nofail: true
diff --git a/.github/workflows/publish-installers.yml b/.github/workflows/publish-installers.yml
new file mode 100644
index 00000000..b4a66960
--- /dev/null
+++ b/.github/workflows/publish-installers.yml
@@ -0,0 +1,178 @@
+name: Publish Installers
+
+on:
+ workflow_dispatch: ~
+ push:
+ branches: [master, beta, nightly]
+ tags: [v*]
+
+env:
+ PYTHON_VERSION: '3.11'
+
+jobs:
+ build-installer:
+ name: Build ${{ matrix.os_upper }} Installer
+ runs-on: ${{ matrix.os }}-${{ matrix.os_version }}
+ if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - os: 'windows'
+ os_upper: 'Windows'
+ os_version: 'latest'
+ arch: 'x64'
+ ext: 'exe'
+ - os: 'macos'
+ os_upper: 'MacOS'
+ os_version: '14'
+ arch: 'universal'
+ ext: 'pkg'
+
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Set Release Version
+ id: get_version
+ shell: bash
+ run: |
+ if [[ $GITHUB_REF == refs/tags/* ]]; then
+ echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
+ VERSION_NSIS=${GITHUB_REF#refs/tags/v}.1
+ echo "VERSION_NSIS=${VERSION_NSIS/%-beta.1/.0}" >> $GITHUB_OUTPUT
+ echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
+ echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
+ else
+ echo "VERSION=0.0.0" >> $GITHUB_ENV
+ echo "VERSION_NSIS=0.0.0.0" >> $GITHUB_OUTPUT
+ echo "VERSION=0.0.0" >> $GITHUB_OUTPUT
+ echo "RELEASE_VERSION=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
+ fi
+ if [[ $GITHUB_REF == refs/tags/*-beta ]]; then
+ echo "beta" > branch.txt
+ elif [[ $GITHUB_REF == refs/tags/* ]]; then
+ echo "master" > branch.txt
+ else
+ echo ${GITHUB_REF#refs/heads/} > branch.txt
+ fi
+ echo $GITHUB_SHA > version.txt
+
+ - name: Set Up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+ cache: pip
+ cache-dependency-path: '**/requirements*.txt'
+
+ - name: Install Dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r package/requirements-package.txt --no-binary cffi
+
+ - name: Build Package
+ run: |
+ pyinstaller -y ./package/Tautulli-${{ matrix.os }}.spec
+
+ - name: Create Windows Installer
+ uses: joncloud/makensis-action@v4.1
+ if: matrix.os == 'windows'
+ with:
+ script-file: ./package/Tautulli.nsi
+ arguments: >
+ /DVERSION=${{ steps.get_version.outputs.VERSION_NSIS }}
+ /DINSTALLER_NAME=..\Tautulli-${{ matrix.os }}-${{ steps.get_version.outputs.RELEASE_VERSION }}-${{ matrix.arch }}.${{ matrix.ext }}
+ additional-plugin-paths: package/nsis-plugins
+
+ - name: Create MacOS Installer
+ if: matrix.os == 'macos'
+ run: |
+ sudo pkgbuild \
+ --install-location /Applications \
+ --version ${{ steps.get_version.outputs.VERSION }} \
+ --component ./dist/Tautulli.app \
+ --scripts ./package/macos-scripts \
+ Tautulli-${{ matrix.os }}-${{ steps.get_version.outputs.RELEASE_VERSION }}-${{ matrix.arch }}.${{ matrix.ext }}
+
+ - name: Upload Installer
+ uses: actions/upload-artifact@v4
+ with:
+ name: Tautulli-${{ matrix.os }}-installer
+ path: Tautulli-${{ matrix.os }}-${{ steps.get_version.outputs.RELEASE_VERSION }}-${{ matrix.arch }}.${{ matrix.ext }}
+
+ virus-total:
+ name: VirusTotal Scan
+ needs: build-installer
+ if: needs.build-installer.result == 'success' && !contains(github.event.head_commit.message, '[skip ci]')
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download Installers
+ if: needs.build-installer.result == 'success'
+ uses: actions/download-artifact@v4
+
+ - name: Upload to VirusTotal
+ uses: crazy-max/ghaction-virustotal@v4
+ with:
+ vt_api_key: ${{ secrets.VT_API_KEY }}
+ files: |
+ Tautulli-windows-installer/Tautulli-windows-*-x64.exe
+ Tautulli-macos-installer/Tautulli-macos-*-universal.pkg
+
+ release:
+ name: Release Installers
+ needs: build-installer
+ if: always() && startsWith(github.ref, 'refs/tags/') && !contains(github.event.head_commit.message, '[skip ci]')
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Set Release Version
+ id: get_version
+ run: |
+ echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
+
+ - name: Download Installers
+ if: needs.build-installer.result == 'success'
+ uses: actions/download-artifact@v4
+
+ - name: Get Changelog
+ id: get_changelog
+ run: |
+ CHANGELOG="$( sed -n '/^## /{p; :loop n; p; /^## /q; b loop}' CHANGELOG.md \
+ | sed '$d' | sed '$d' | sed '$d' )"
+ EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
+ echo "CHANGELOG<<$EOF" >> $GITHUB_OUTPUT
+ echo "$CHANGELOG" >> $GITHUB_OUTPUT
+ echo "$EOF" >> $GITHUB_OUTPUT
+
+ - name: Create Release
+ uses: softprops/action-gh-release@v2
+ id: create_release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GHACTIONS_TOKEN }}
+ with:
+ tag_name: ${{ steps.get_version.outputs.RELEASE_VERSION }}
+ name: Tautulli ${{ steps.get_version.outputs.RELEASE_VERSION }}
+ body: |
+ ## Changelog
+
+ ##${{ steps.get_changelog.outputs.CHANGELOG }}
+ prerelease: ${{ endsWith(steps.get_version.outputs.RELEASE_VERSION, '-beta') }}
+ files: |
+ Tautulli-windows-installer/Tautulli-windows-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.exe
+ Tautulli-macos-installer/Tautulli-macos-${{ steps.get_version.outputs.RELEASE_VERSION }}-universal.pkg
+
+ discord:
+ name: Discord Notification
+ needs: [build-installer, release]
+ if: always() && !contains(github.event.head_commit.message, '[skip ci]')
+ runs-on: ubuntu-latest
+ steps:
+ - name: Post Status to Discord
+ uses: sarisia/actions-status-discord@v1
+ with:
+ webhook: ${{ secrets.DISCORD_WEBHOOK }}
+ status: ${{ needs.build-installer.result == 'success' && 'success' || contains(needs.*.result, 'failure') && 'failure' || 'cancelled' }}
+ title: ${{ github.workflow }}
+ nofail: true
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
deleted file mode 100644
index d3383b8c..00000000
--- a/.github/workflows/publish-release.yml
+++ /dev/null
@@ -1,204 +0,0 @@
-name: Publish Release
-on:
- push:
- branches: [master, beta, nightly, python3]
- tags: [v*]
-
-jobs:
- build-windows:
- runs-on: windows-latest
- steps:
- - name: Checkout Code
- uses: actions/checkout@v2
-
- - name: Set Release Version
- id: get_version
- shell: bash
- run: |
- if [[ $GITHUB_REF == refs/tags/* ]]; then
- VERSION_NSIS=${GITHUB_REF#refs/tags/v}.1
- echo ::set-output name=VERSION_NSIS::${VERSION_NSIS/%-beta.1/.0}
- echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}
- echo ::set-output name=RELEASE_VERSION::${GITHUB_REF#refs/tags/}
- else
- echo ::set-output name=VERSION_NSIS::0.0.0.0
- echo ::set-output name=VERSION::0.0.0
- echo ::set-output name=RELEASE_VERSION::${GITHUB_SHA::7}
- fi
- echo $GITHUB_SHA > version.txt
-
- - name: Set Up Python
- uses: actions/setup-python@v2
- with:
- python-version: 3.8
-
- - name: Cache Dependencies
- id: cache_dependencies
- uses: actions/cache@v2
- with:
- path: ~\AppData\Local\pip\Cache
- key: ${{ runner.os }}-pip-${{ hashFiles('package/requirements-windows.txt') }}
- restore-keys: ${{ runner.os }}-pip-
-
- - name: Install Dependencies
- run: |
- python -m pip install --upgrade pip
- pip install -r package/requirements-windows.txt
-
- - name: Build Package
- run: |
- pyinstaller -y ./package/Tautulli-windows.spec
-
- - name: Create Installer
- uses: joncloud/makensis-action@v1.2
- with:
- script-file: ./package/Tautulli.nsi
- arguments: /DVERSION=${{ steps.get_version.outputs.VERSION_NSIS }} /DINSTALLER_NAME=..\Tautulli-windows-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.exe
- include-more-plugins: true
- include-custom-plugins-path: package/nsis-plugins
-
- - name: Upload Installer
- uses: actions/upload-artifact@v2
- with:
- name: Tautulli-windows-installer
- path: Tautulli-windows-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.exe
-
- - name: Post Status to Discord
- uses: sarisia/actions-status-discord@v1
- if: always()
- with:
- webhook: ${{ secrets.DISCORD_WEBHOOK }}
- status: ${{ job.status }}
- title: Build Windows Installer
- nofail: true
-
- build-macos:
- runs-on: macos-latest
- steps:
- - name: Checkout Code
- uses: actions/checkout@v2
-
- - name: Set Release Version
- id: get_version
- shell: bash
- run: |
- if [[ $GITHUB_REF == refs/tags/* ]]; then
- echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}
- echo ::set-output name=RELEASE_VERSION::${GITHUB_REF#refs/tags/}
- else
- echo "VERSION=0.0.0" >> $GITHUB_ENV
- echo ::set-output name=VERSION::0.0.0
- echo ::set-output name=RELEASE_VERSION::${GITHUB_SHA::7}
- fi
- echo $GITHUB_SHA > version.txt
-
- - name: Set Up Python
- uses: actions/setup-python@v2
- with:
- python-version: 3.8
-
- - name: Cache Dependencies
- id: cache_dependencies
- uses: actions/cache@v2
- with:
- path: ~/Library/Caches/pip
- key: ${{ runner.os }}-pip-${{ hashFiles('package/requirements-macos.txt') }}
- restore-keys: ${{ runner.os }}-pip-
-
- - name: Install Dependencies
- run: |
- python -m pip install --upgrade pip
- pip install -r package/requirements-macos.txt
-
- - name: Build Package
- run: |
- pyinstaller -y ./package/Tautulli-macos.spec
-
- - name: Create Installer
- run: |
- sudo pkgbuild --install-location /Applications --version ${{ steps.get_version.outputs.VERSION }} --component ./dist/Tautulli.app --scripts ./package/macos-scripts Tautulli-macos-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.pkg
-
- - name: Upload Installer
- uses: actions/upload-artifact@v2
- with:
- name: Tautulli-macos-installer
- path: Tautulli-macos-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.pkg
-
- - name: Post Status to Discord
- uses: sarisia/actions-status-discord@v1
- if: always()
- with:
- webhook: ${{ secrets.DISCORD_WEBHOOK }}
- status: ${{ job.status }}
- title: Build MacOS Installer
- nofail: true
-
- release:
- needs: [build-windows, build-macos]
- if: startsWith(github.ref, 'refs/tags/') && always()
- runs-on: ubuntu-latest
- steps:
- - name: Get Build Job Status
- uses: technote-space/workflow-conclusion-action@v1
-
- - name: Checkout Code
- uses: actions/checkout@v2
-
- - name: Set Release Version
- id: get_version
- run: |
- echo ::set-output name=RELEASE_VERSION::${GITHUB_REF#refs/tags/}
-
- - name: Download Windows Installer
- if: env.WORKFLOW_CONCLUSION == 'success'
- uses: actions/download-artifact@v2
- with:
- name: Tautulli-windows-installer
-
- - name: Download MacOS Installer
- if: env.WORKFLOW_CONCLUSION == 'success'
- uses: actions/download-artifact@v2
- with:
- name: Tautulli-macos-installer
-
- - name: Get Changelog
- id: get_changelog
- run: echo ::set-output name=CHANGELOG::"$( sed -n '/^## /{p; :loop n; p; /^## /q; b loop}' CHANGELOG.md | sed '$d' | sed '$d' | sed '$d' | sed ':a;N;$!ba;s/\n/%0A/g' )"
-
- - name: Create Release
- id: create_release
- uses: actions/create-release@v1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- with:
- tag_name: ${{ steps.get_version.outputs.RELEASE_VERSION }}
- release_name: Tautulli ${{ steps.get_version.outputs.RELEASE_VERSION }}
- body: |
- ## Changelog
-
- ##${{ steps.get_changelog.outputs.CHANGELOG }}
- draft: false
- prerelease: ${{ endsWith(steps.get_version.outputs.RELEASE_VERSION, '-beta') }}
-
- - name: Upload Windows Installer
- if: env.WORKFLOW_CONCLUSION == 'success'
- uses: actions/upload-release-asset@v1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- with:
- upload_url: ${{ steps.create_release.outputs.upload_url }}
- asset_path: ./Tautulli-windows-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.exe
- asset_name: Tautulli-windows-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.exe
- asset_content_type: application/vnd.microsoft.portable-executable
-
- - name: Upload MacOS Installer
- if: env.WORKFLOW_CONCLUSION == 'success'
- uses: actions/upload-release-asset@v1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- with:
- upload_url: ${{ steps.create_release.outputs.upload_url }}
- asset_path: ./Tautulli-macos-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.pkg
- asset_name: Tautulli-macos-${{ steps.get_version.outputs.RELEASE_VERSION }}-x64.pkg
- asset_content_type: application/vnd.apple.installer+xml
diff --git a/.github/workflows/publish-snap.yml b/.github/workflows/publish-snap.yml
new file mode 100644
index 00000000..b3898a38
--- /dev/null
+++ b/.github/workflows/publish-snap.yml
@@ -0,0 +1,78 @@
+name: Publish Snap
+
+on:
+ workflow_dispatch: ~
+ push:
+ branches: [master, beta, nightly]
+ tags: [v*]
+
+jobs:
+ build-snap:
+ name: Build Snap Package (${{ matrix.architecture }})
+ runs-on: ubuntu-latest
+ if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
+ strategy:
+ fail-fast: false
+ matrix:
+ architecture:
+ - amd64
+ - arm64
+ - armhf
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Prepare
+ id: prepare
+ run: |
+ git fetch --prune --unshallow --tags
+ if [[ $GITHUB_REF == refs/tags/*-beta || $GITHUB_REF == refs/heads/beta ]]; then
+ echo "RELEASE=beta" >> $GITHUB_OUTPUT
+ elif [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
+ echo "RELEASE=stable" >> $GITHUB_OUTPUT
+ else
+ echo "RELEASE=edge" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Set Up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Build Snap Package
+ uses: diddlesnaps/snapcraft-multiarch-action@master
+ id: build
+ with:
+ architecture: ${{ matrix.architecture }}
+
+ - name: Upload Snap Package
+ uses: actions/upload-artifact@v4
+ with:
+ name: Tautulli-snap-package-${{ matrix.architecture }}
+ path: ${{ steps.build.outputs.snap }}
+
+ - name: Review Snap Package
+ uses: diddlesnaps/snapcraft-review-tools-action@master
+ with:
+ snap: ${{ steps.build.outputs.snap }}
+
+ - name: Publish Snap Package
+ uses: snapcore/action-publish@v1
+ if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/nightly'
+ env:
+ SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_LOGIN }}
+ with:
+ snap: ${{ steps.build.outputs.snap }}
+ release: ${{ steps.prepare.outputs.RELEASE }}
+
+ discord:
+ name: Discord Notification
+ needs: build-snap
+ if: always() && !contains(github.event.head_commit.message, '[skip ci]')
+ runs-on: ubuntu-latest
+ steps:
+ - name: Post Status to Discord
+ uses: sarisia/actions-status-discord@v1
+ with:
+ webhook: ${{ secrets.DISCORD_WEBHOOK }}
+ status: ${{ needs.build-snap.result == 'success' && 'success' || contains(needs.*.result, 'failure') && 'failure' || 'cancelled' }}
+ title: ${{ github.workflow }}
+ nofail: true
diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml
new file mode 100644
index 00000000..ac550fe2
--- /dev/null
+++ b/.github/workflows/pull-requests.yml
@@ -0,0 +1,27 @@
+name: Pull Requests
+
+on:
+ pull_request_target:
+ types: [opened, synchronize, edited, reopened]
+
+jobs:
+ check-branch:
+ name: Check Pull Request
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v4
+
+ - name: Comment on Pull Request
+ uses: mshick/add-pr-comment@v2
+ if: github.base_ref != 'nightly'
+ with:
+ message: Pull requests must be made to the `nightly` branch. Thanks.
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Fail Workflow
+ if: github.base_ref != 'nightly'
+ run: |
+ echo Base: "$GITHUB_BASE_REF"
+ echo Head: "$GITHUB_HEAD_REF"
+ exit 1
diff --git a/.github/workflows/submit-winget.yml b/.github/workflows/submit-winget.yml
new file mode 100644
index 00000000..efa6cee7
--- /dev/null
+++ b/.github/workflows/submit-winget.yml
@@ -0,0 +1,44 @@
+name: Submit winget
+
+on:
+ workflow_dispatch: ~
+ release:
+ types: [published]
+
+jobs:
+ winget:
+ name: Submit Winget Package
+ runs-on: windows-latest
+ if: ${{ !github.event.release.prerelease }}
+ steps:
+ - name: Sync Winget Fork
+ run: gh repo sync ${{ secrets.WINGET_USERNAME }}/winget-pkgs -b master
+ env:
+ GH_TOKEN: ${{ secrets.WINGET_TOKEN }}
+
+ - name: Submit package to Windows Package Manager Community Repository
+ run: |
+ $wingetPackage = "Tautulli.Tautulli"
+ $gitToken = "${{ secrets.WINGET_TOKEN }}"
+
+ $github = Invoke-RestMethod -uri "https://api.github.com/repos/Tautulli/Tautulli/releases/latest"
+ $installerUrl = $github | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match "Tautulli-windows-.*-x64.exe" | Select -ExpandProperty browser_download_url
+ $version = "$($github.tag_name.Trim('v')).1"
+
+ # getting latest wingetcreate file
+ iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
+ .\wingetcreate.exe update $wingetPackage -s -v $version -u $installerUrl -t $gitToken
+
+ virus-total:
+ name: VirusTotal Scan
+ runs-on: ubuntu-latest
+ steps:
+ - name: Upload to VirusTotal
+ uses: crazy-max/ghaction-virustotal@v4
+ with:
+ vt_api_key: ${{ secrets.VT_API_KEY }}
+ github_token: ${{ secrets.GHACTIONS_TOKEN }}
+ update_release_body: true
+ files: |
+ .exe$
+ .pkg$
diff --git a/.gitignore b/.gitignore
index e55fd0af..1e54132b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Compiled source #
###################
+__pycache__
*.pyc
*.py~
*.pyproj
@@ -14,6 +15,13 @@
*.ini
release.lock
version.lock
+lib/*.dist-info
+lib/*.egg-info
+lib/*.pth
+lib/*/*.pyd
+lib/_distutils_hack
+lib/pkg_resources
+lib/setuptools
logs/*
backups/*
cache/*
@@ -22,6 +30,7 @@ newsletters/*
*.mmdb
version.txt
branch.txt
+.TEST
# HTTPS Cert/Key #
##################
@@ -44,6 +53,9 @@ Thumbs.db
#Ignore files generated by PyCharm
*.idea/*
+#Ignore files generated by VSCode
+*.vscode/*
+
#Ignore files generated by vi
*.swp
@@ -64,7 +76,6 @@ Thumbs.db
*.bak
*.cache
*.ilk
-*.log
[Bb]in
[Dd]ebug*/
*.lib
@@ -81,3 +92,12 @@ _ReSharper*/
#Ignore files generated by pyinstaller
/build
/dist
+
+#snapcraft specifics
+/parts/
+/stage/
+/prime/
+*.snap
+.snapcraft
+*_source.tar.bz2
+snap/.snapcraft
\ No newline at end of file
diff --git a/API.md b/API.md
index 009a9024..827c7c6b 100644
--- a/API.md
+++ b/API.md
@@ -1,3 +1,3 @@
# API Reference
-Tautulli API documentation has been moved to the [wiki page](https://github.com/Tautulli/Tautulli-Wiki/wiki/Tautulli-API-Reference).
\ No newline at end of file
+Tautulli API documentation has been moved to the [wiki page](https://github.com/Tautulli/Tautulli/wiki/Tautulli-API-Reference).
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ea9b5e1..b349b355 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,850 @@
# Changelog
+## v2.15.3 (2025-08-03)
+
+* Exporter:
+ * New: Added hearingImpaired for subtitles and visualImpaired for audio attributes to exporter fields.
+* Graphs:
+ * Fix: Remove duplicate "Total" entry in graph tooltips. (Thanks @zdimension) (#2534)
+* UI:
+ * Fix: Failing to retrieve collections / playlists with over 1000 items.
+ * Fix: Scrollbar not showing on macosx and webkit browsers. (#2221)
+ * Fix: Incorrect rounding of minutes in global stats play duration.
+ * Fix: Disable browser autocomplete for notification agent and newsletter agent configurations. (#2557)
+* API:
+ * New: Added ability to return svg files using pms_image_proxy API command.
+* Other:
+ * New: Added ability to set config values using environment variables. (Thanks @komuw) (#2309, #2543)
+
+
+## v2.15.2 (2025-04-12)
+
+* Activity:
+ * New: Added link to library by clicking media type icon.
+ * New: Added stream count to tab title on homepage. (#2517)
+* History:
+ * Fix: Check stream watched status before stream stopped status. (#2506)
+* Notifications:
+ * Fix: ntfy notifications failing to send if provider link is blank.
+ * Fix: Check Pushover notification attachment is under 5MB limit. (#2396)
+ * Fix: Track URLs redirecting to the correct media page. (#2513)
+ * New: Added audio profile notification parameters.
+ * New: Added PATCH method for Webhook notifications.
+* Graphs:
+ * New: Added Total line to daily streams graph. (Thanks @zdimension) (#2497)
+* UI:
+ * Fix: Do not redirect API requests to the login page. (#2490)
+ * Change: Swap source and stream columns in stream info modal.
+* Other:
+ * Fix: Various typos. (Thanks @luzpaz) (#2520)
+ * Fix: CherryPy CORS response header not being set correctly. (#2279)
+
+
+## v2.15.1 (2025-01-11)
+
+* Activity:
+ * Fix: Detection of HDR transcodes. (Thanks @cdecker08) (#2412, #2466)
+* Newsletters:
+ * Fix: Disable basic authentication for /newsletter and /image endpoints. (#2472)
+* Exporter:
+ * New: Added logos to season and episode exports.
+* Other:
+ * Fix: Docker container https health check.
+
+
+## v2.15.0 (2024-11-24)
+
+* Notes:
+ * Support for Python 3.8 has been dropped. The minimum Python version is now 3.9.
+* Notifications:
+ * New: Allow Telegram blockquote and tg-emoji HTML tags. (Thanks @MythodeaLoL) (#2427)
+ * New: Added Plex slug and Plex Watch URL notification parameters. (#2420)
+ * Change: Update OneSignal API calls to use the new API endpoint for Tautulli Remote App notifications.
+* Newsletters:
+ * Fix: Dumping custom dates in raw newsletter json.
+* History:
+ * Fix: Unable to fix match for artists. (#2429)
+* Exporter:
+ * New: Added movie and episode hasVoiceActivity attribute to exporter fields.
+ * New: Added subtitle canAutoSync attribute to exporter fields.
+ * New: Added logos to the exporter fields.
+* UI:
+ * New: Add friendly name to the top bar of config modals. (Thanks @peagravel) (#2432)
+* API:
+ * New: Added plex slugs to metadata in the get_metadata API command.
+* Other:
+ * Fix: Tautulli failing to start with Python 3.13. (#2426)
+
+
+## v2.14.6 (2024-10-12)
+
+* Newsletters:
+ * Fix: Allow formatting newsletter date parameters.
+ * Change: Support apscheduler compatible cron expressions.
+* UI:
+ * Fix: Round runtime before converting to human duration.
+ * Fix: Make recently added/watched rows touch scrollable.
+* Other:
+ * Fix: Auto-updater not running.
+
+
+## v2.14.5 (2024-09-20)
+
+* Activity:
+ * Fix: Display of 2k resolution on activity card.
+* Notifications:
+ * Fix: ntfy notifications with special characters failing to send.
+* Other:
+ * Fix: Memory leak with database closing. (#2404)
+
+
+## v2.14.4 (2024-08-10)
+
+* Notifications:
+ * Fix: Update Slack notification info card.
+ * New: Added ntfy notification agent. (Thanks @nwithan8) (#2356, #2000)
+* UI:
+ * Fix: macOS platform capitalization.
+* Other:
+ * Fix: Remove deprecated getdefaultlocale. (Thanks @teodorstelian) (#2364, #2345)
+
+
+## v2.14.3 (2024-06-19)
+
+* Graphs:
+ * Fix: History table not loading when clicking on the graphs in some instances.
+* UI:
+ * Fix: Scheduled tasks table not loading when certain tasks are disabled.
+ * Removed: Unnecessary Remote Server checkbox from the settings page.
+* Other:
+ * Fix: Webserver not restarting after the setup wizard.
+ * Fix: Workaround webserver crashing in some instances.
+
+
+## v2.14.2 (2024-05-18)
+
+* History:
+ * Fix: Live TV activity not logging to history.
+ * Fix: Incorrect grouping of live TV history.
+* Notifications:
+ * Fix: Pushover configuration settings refreshing after entering a token.
+ * Fix: Plex remote access down notifications not triggering.
+ * Fix: Deleting all images from Cloudinary only deleting 1000 images.
+ * New: Added platform version and product version notification parameters. (#2244)
+ * New: Added LAN streams and WAN streams notification parameters. (#2276)
+ * New: Added Dolby Vision notification parameters. (#2240)
+ * New: Added live TV channel notification parameters.
+ * Change: Improved Tautulli Remote App notification encryption method.
+ * Note: Requires Tautulli Remote App version 3.2.4.
+* Exporter:
+ * New: Added slug attribute to exporter fields.
+ * New: Added track genres to exporter fields.
+ * New: Added playlist source URI to exporter fields.
+ * New: Added artProvider and thumbProvider to exporter fields.
+* UI:
+ * Fix: Mask deleted usernames in the logs.
+ * Fix: Live TV watch stats not showing on the media info page.
+ * Fix: Users without access to Plex server not showing as inactive.
+ * Removed: Deprecated synced item pages.
+ * Removed: Anonymous redirect settings. Links now use browser no-referrer policy instead.
+* API:
+ * New: Added Dolby Vision info to the get_metadata API command.
+ * New: Added before and after parameters to the get_home_stats API command. (#2231)
+* Packages:
+ * New: Universal binary for macOS for Apple silicon.
+ * New: Bump Snap package to core22.
+* Other:
+ * Change: Login cookie expires changed to max-age.
+ * Change: Improved key generation for login password. It is recommended to reenter your HTTP Password in the settings after upgrading.
+ * Removed: Python 2 compatibility code. (#2098, #2226) (Thanks @zdimension)
+
+
+## v2.13.4 (2023-12-07)
+
+* UI:
+ * Fix: Tautulli configuration settings page not loading when system language is None.
+ * Fix: Login cookie expiring too quickly.
+
+
+## v2.13.3 (2023-12-03)
+
+* Notifications:
+ * New: Added duration_time notification parameter.
+ * New: Added file_size_bytes notification parameter.
+ * New: Added time formats notification text modifiers.
+ * New: Added support for thetvdb_url for movies.
+* UI:
+ * Fix: Activity card overflowing due to screen scaling. (#2033)
+ * Fix: Stream duration on activity card not being updated on track changes in some cases. (#2206)
+
+
+## v2.13.2 (2023-10-26)
+
+* History:
+ * New: Added quarter values icons for history watch status. (#2179, #2156) (Thanks @herby2212)
+* Graphs:
+ * New: Added concurrent streams per day graph. (#2046) (Thanks @herby2212)
+* Exporter:
+ * New: Added metadata directory to exporter fields.
+ * Removed: Banner exporter fields for tv shows.
+* UI:
+ * New: Added last triggered time to notification agents and newsletter agent lists.
+* Other:
+ * New: Added X-Plex-Language header override to config file.
+
+
+## v2.13.1 (2023-08-25)
+
+* Notes:
+ * Support for Python 3.7 has been dropped. The minimum Python version is now 3.8.
+* Other:
+ * Fix: Tautulli failing to start on some systems.
+
+
+## v2.13.0 (2023-08-25)
+
+* Notes:
+ * Support for Python 3.7 has been dropped. The minimum Python version is now 3.8.
+* Notifications:
+ * Fix: Improved watched notification trigger description. (#2104)
+ * New: Added notification image option for iOS Tautulli Remote app.
+* Exporter:
+ * New: Added track chapter export fields.
+ * New: Added on-demand subtitle export fields.
+
+
+## v2.12.5 (2023-07-13)
+
+* Activity:
+ * New: Added d3d11va to list of hardware decoders.
+* History:
+ * Fix: Incorrect grouping of play history.
+ * New: Added button in settings to regroup play history.
+* Notifications:
+ * Fix: Incorrect concurrent streams notifications by IP addresss for IPv6 addresses (#2096) (Thanks @pooley182)
+* UI:
+ * Fix: Occasional UI crashing on Python 3.11.
+ * New: Added multiselect user filters to History and Graphs pages. (#2090) (Thanks @zdimension)
+* API:
+ * New: Added regroup_history API command.
+ * Change: Updated graph API commands to accept a comma separated list of user IDs.
+
+
+## v2.12.4 (2023-05-23)
+
+* History:
+ * Fix: Set view offset equal to duration if a stream is stopped within the last 10 sec.
+* Other:
+ * Fix: Database import may fail for some older databases.
+ * Fix: Double-quoted strings for newer versions of SQLite. (#2015, #2057)
+* API:
+ * Change: Return the ID for async API calls (export_metadata, notify, notify_newsletter).
+
+
+## v2.12.3 (2023-04-14)
+
+* Activity:
+ * Fix: Incorrect subtitle decision shown when subtitles are transcoded.
+* History:
+ * Fix: Incorrect order when sorting by the duration column in the history tables.
+* Notifications:
+ * Fix: Logging error when running scripts that use PlexAPI.
+* UI:
+ * Fix: Calculate file sizes setting causing the media info table to fail to load.
+ * Fix: Incorrect artwork and thumbnail shown for Live TV on the Most Active Libraries statistics card.
+* API:
+ * Change: Renamed duration to play_duration in the get_history API response. (Note: duration kept for backwards compatibility.)
+
+
+## v2.12.2 (2023-03-16)
+
+* Other:
+ * Fix: Tautulli not starting on FreeBSD jails.
+
+
+## v2.12.1 (2023-03-14)
+
+* Activity:
+ * Fix: Stop checking for deprecated sync items sessions.
+ * Change: Do not show audio language on activity cards for music.
+* Other:
+ * Fix: Tautulli not starting on macOS.
+
+
+## v2.12.0 (2023-03-13)
+
+* Notifications:
+ * New: Added support for Telegram group topics. (#1980)
+ * New: Added anidb_id and anidb_url notification parameters. (#1973)
+ * New: Added notification triggers for Intro Marker, Commercial Marker, and Credits Marker.
+ * New: Added various intro, commercial, and credits marker notification parameters.
+ * New: Allow setting a custom Pushover notification sound. (#2005)
+ * Change: Notification images are now uploaded directly to Discord without the need for a 3rd party image hosting service.
+ * Change: Automatically strip whitespace from notification condition values.
+ * Change: Trigger watched notifications based on the video watched completion behaviour setting.
+* Exporter:
+ * Fix: Unable to run exporter when using the Snap package. (#2007)
+ * New: Added credits marker, and audio/subtitle settings to export fields.
+* UI:
+ * Fix: Incorrect styling and missing content for collection media info pages.
+ * New: Added edition details field on movie media info pages. (#1957) (Thanks @herby2212)
+ * New: Added setting to change the video watched completion behaviour.
+ * New: Added watch time and user statistics to collection and playlist media info pages. (#1982, #2012) (Thanks @herby2212)
+ * New: Added history table to collection and playlist media info pages.
+ * New: Dynamically change watched status in the UI based on video watched completion behaviour setting.
+ * New: Added hidden setting to override server name.
+ * Change: Move track artist to a details field instead of in the title on track media info pages.
+* API:
+ * New: Added section_id and user_id parameters to get_home_stats API command. (#1944)
+ * New: Added marker info to get_metadata API command results.
+ * New: Added media_type parameter to get_item_watch_time_stats and get_item_user_stats API commands. (#1982) (Thanks @herby2212)
+ * New: Added last_refreshed timestamp to get_library_media_info API command response.
+* Other:
+ * Change: Migrate analytics to Google Analytics 4.
+
+
+## v2.11.1 (2022-12-22)
+
+* Activity:
+ * Fix: Use source language instead of stream language on activity cards.
+* Notifications:
+ * Fix: Blank start time notification parameters causing recently added notifications to fail. (#1940)
+* Other:
+ * Fix: Tautulli failing to start when using python 3.7.
+ * Fix: Snap install failing to start. (#1941)
+ * Fix: Update check crashing when git is missing. (#1943) (Thanks @Minituff)
+
+
+## v2.11.0 (2022-12-22)
+
+* Activity:
+ * New: Added audio and subtitle language to activity cards. (#1831, #1900) (Thanks @fscorrupt)
+* History:
+ * New: Log subtitle language and subtitle forced to database. (#1826)
+* Notifications:
+ * Fix: Validating condition operators would fail with a blank parameter.
+ * New: Added start time and stop time notification parameters. (#1931)
+ * New: Added session_key to LunaSea notification payload. (#1929) (Thanks @JagandeepBrar)
+* Newsletters:
+ * Fix: Allow CSS to support light and dark themes.
+* Exporter:
+ * New: Added editionTitle to movie exporter fields.
+ * Change: m3u8 export changed to .m3u file extension. File is still encoded using UTF-8.
+* UI:
+ * Fix: Link watch statistics to media page using metadata from history. (#1882)
+ * New: Show subtitle language and subtitle forced flag in stream data modal.
+* Other:
+ * Fix: Mask more user and metadata fields for guest access. (#1913)
+ * Change: Disable TLS 1.0 and 1.1 for the webserver. Minimum TLS version is 1.2. (#1870)
+ * Change: Use system language for requests to Plex Media Server.
+
+
+## v2.10.5 (2022-11-07)
+
+* Notifications:
+ * New: Added edition_title notification parameter. (#1838)
+ * Change: Track notifications link to MusicBrainz track instead of album.
+* Newsletters:
+ * New: Added months time frame for newsletters. (#1876)
+* UI:
+ * Fix: Broken link on library statistic cards. (#1852)
+ * Fix: Check for IPv6 host when generating QR code for app registration.
+ * Fix: Missing padding on condition operator dropdown on small screens.
+* Other:
+ * Fix: Launching browser when webserver is bound to IPv6.
+ * New: Tautulli can be installed via the Windows Package Manager (winget).
+ * Change: Separate stdout and stderr console logging. (#1874)
+* API:
+ * Fix: API not returning 400 response code.
+ * New: Added edition_title to get_metadata API response.
+ * New: Added collections to get_children_metadata API response.
+ * New: Added user_thumb to get_history API response.
+ * New: Validate custom notification conditions before saving notification agents. (#1846)
+ * Change: Fallback to parent_thumb for seasons in get_metadata API response.
+
+
+## v2.10.4 (2022-09-05)
+
+* Activity:
+ * New: Added tooltip for quality profile on activity cards.
+* Notifications:
+ * New: Added "does not begin with" and "does not end with" condition operators.
+* UI:
+ * Fix: Album count showing 0 on library statistics.
+ * Fix: Library statistics not showing up for libraries without any history.
+
+
+## v2.10.3 (2022-08-09)
+
+* Notifications:
+ * New: Added JSON support for MQTT notifications. (#1763)
+ * New: Added show year notification parameter.
+* Exporter:
+ * New: Added guids to artist, album, and track metadata export fields.
+ * New: Added languageTag to stream media info export fields.
+* UI:
+ * Fix: Long channel identifier overflowing activity card. (#1802)
+ * Change: Use the last played item's artwork for library statistics cards.
+* Other:
+ * Fix: Username log filter causing database to lock up. (#1705)
+ * Change: Username log filter only applies to usernames longer than 3 characters. (#1806)
+* API:
+ * New: Added parent_year and grandparent_year to get_metadata_details API command.
+ * New: Added last played metadata to top_libraries and top_users in get_home_stats API command.
+ * New: Allow fallback to another PMS image in pms_image_proxy API command.
+
+
+## v2.10.2 (2022-07-03)
+
+* Activity:
+ * Fix: Incorrect audio stream info shown on the activity card when playing a secondary audio track.
+* UI:
+ * Fix: Usernames not showing on the home statistics cards.
+ * Fix: Do not save a user's friendly name if it is the same as the username.
+ * Change: Update library icons to the latest Plex style.
+
+
+## v2.10.1 (2022-06-01)
+
+* Notifications:
+ * New: Added support for MusicBrainz (mbid://) guids in notification parameters without MusicBrainz lookup enabled. Requires Plex Media Server 1.27.0 or newer with refreshed Plex Music agent metadata.
+* Mobile App:
+ * Fix: OneSignal validation failing when registering a device.
+* API:
+ * New: Added grandparent_guids and parent_guids to get_metadata API command.
+ * Change: Updated continent in get_geoip_lookup API command.
+ * Change: Removed server_token from from get_users API command.
+ * Change: shared_libraries changed to a list instead of a string for get_users API command.
+
+
+## v2.10.0 (2022-05-23)
+
+* Activity:
+ * Fix: Detection of Dolby Vision missing for PMS 1.26.1.
+* Notifications:
+ * Fix: Parsing of filename notification parameter incorrect for Windows PMS.
+* Exporter:
+ * New: Added additional theme and label export fields.
+* UI:
+ * Fix: Slow loading of collections and playlists tables.
+ * Change: Update default user thumbnail image to match Plex Web.
+* API:
+ * Change: Values for get_users_table and get_libraries_table return an integer instead of "Checked".
+
+
+## v2.9.7 (2022-04-11)
+
+* UI:
+ * Fix: Managed user missing the username in the Users table.
+
+
+## v2.9.6 (2022-04-10)
+
+* Activity:
+ * New: Improved display of dynamic range on the activity cards. (Thanks @herby2212)
+* Notifications:
+ * Change: Make include summary option apply to all media types for Discord and Slack notifications.
+* UI:
+ * Fix: Validating Plex login in the setup wizard. (#1697)
+ * New: Added hidden username, email, and full name columns to users table.
+* Other:
+ * Fix: Apply pms_timeout setting to websocket connection.
+ * Fix: Importing of Plex username instead of the full name. (#1710)
+
+
+## v2.9.5 (2022-03-26)
+
+* Note:
+ * Updated Snap packages are currently unavailable due to an upstream issue.
+* Activity:
+ * Change: Improve calculation for transcode progress bar percentage on the activity cards.
+* History:
+ * Fix: Live TV history filter not working. (#1691)
+* Newsletter:
+ * Fix: Newsletter not showing different album types. (#1559)
+* UI:
+ * Fix: Display season summary on the media info page if available with a fallback to show summary. (#1657)
+ * Change: Colour active filter buttons to improve contrast. (#1663)
+* API:
+ * New: Added transcode offset keys to get_activity command.
+* Other:
+ * Fix: Reschedule backup task after changing backup interval. (#1662)
+ * Fix: Dynamic anonymous redirect setting not being enabled by default after the setup wizard.
+ * Fix: Usernames with special characters not being filtered in the logs.
+
+
+## v2.9.4 (2022-02-12)
+
+* UI:
+ * Fix: Setup wizard appearing when restarting after saving settings.
+* Other:
+ * Fix: Stop Tautulli from starting multiple instances on Windows after a clean reinstall. Check the startup items in Windows Task Manager if it is still occurring.
+
+
+## v2.9.3 (2022-02-09)
+
+* UI:
+ * Fix: Setup wizard looping.
+* Other:
+ * Fix: Logger username masking preventing Tautulli from starting on new installs.
+
+
+## v2.9.2 (2022-02-08)
+
+* Notification:
+ * New: Added support for additional Telegram HTML tags.
+ * Removed: Revert Telegram defaulting to MarkdownV2 and only support HTML. (#1635)
+* Other:
+ * Fix: The Local user being masked in the logs.
+
+
+## v2.9.1 (2022-02-07)
+
+* Other:
+ * Fix: Incorrect changelog version number and date.
+
+
+## v2.9.0 (2022-02-07)
+
+* Notification:
+ * New: Added track disc number notification parameter.
+ * Change: Default Telegram messages to MarkdownV2 when HTML is disabled. (#1635)
+* Exporter:
+ * Fix: Images not being included in export zip file download.
+* UI:
+ * Fix: Favicon missing from the newsletter authentication page.
+ * Fix: IPv6 details not being shown in IP address modal. (#1629)
+ * Fix: PWA not respecting device rotation settings. (#1633)
+ * New: Added intermediary login page to the Plex XML shortcuts.
+ * New: Added setting to mask usernames in logs (enabled by default).
+ * New: Added location, secure connection, and Plex Relay details to IP address modal.
+ * Change: Remove Plex token from the settings page.
+ * Change: Increase verifying server timeout to 30 seconds.
+* API:
+ * New: Added get_tautulli_info API command.
+ * New: Added location, secure, and relayed to get_history API response.
+ * Change: Null pms_token and jwt_token in the response of the get_settings API command. (#1616)
+* Other:
+ * Fix: Better validation of config when saving settings.
+ * Fix: Correct section_id and prevent rating_key collisions when updating metadata. (#1640)
+ * Change: Proxy Plex token check and Plex downloads json through the Tautulli server.
+ * Change: Remove tokens from downloaded database and config files.
+ * Change: Do not import pms_token or jwt_secret when importing a config file.
+
+
+## v2.8.1 (2022-01-04)
+
+* API:
+ * New: Added grouping and query_days parameters to the get_item_watch_time_stats API command.
+ * New: Added grouping parameter to the get_item_user_stats API command.
+ * New: Added total_time to the get_library_user_stats, get_user_player_stats, and get_item_user_stats API command responses.
+ * Removed: media_type parameter no longer required for the get_item_watch_time_stats, and get_item_user_stats API commands. The media type is determined automatically.
+* Other:
+ * Fix: Clean .pyc files automatically after updating.
+ * New: Allow Snap package to access /media and /mnt locations. Refer to the FAQ for instructions on how to enable access.
+
+
+## v2.8.0 (2021-12-15)
+
+* History:
+ * Fix: Live TV history filter not working correctly when combined with other filters.
+ * Fix: Direct Stream history filter not remembering the state when reloading the page.
+ * Fix: History table not loading when no filters are selected.
+ * New: Added watch time and user stats to media info pages. (Thanks @herby2212) (#1417, #1471)
+* Notifications:
+ * New: Added Microsoft Teams notification agent. (#1514)
+ * New: Added Gotify notification agent. (#1584)
+ * New: Add warning message that passwords are not copied when duplicating a notification or newsletter agent. (#1540)
+* Newsletters:
+ * Fix: Different album types not shown on newsletter. (#1559)
+* Exporter:
+ * New: Added album formats, subformats, and sonic analysis export fields.
+* UI:
+ * Fix: Docker config volume message overlapping modal windows. (#1567)
+ * Fix: Different album types not shown on artist media info page.
+ * New: Added show more/less toggle for summaries on media info pages. (#1546)
+ * Change: Do not save datatable page or search states when reloading the page. (#1532)
+ * Change: Improve the Plex log reader.
+* API:
+ * New: Added before and after parameters to the get_history API command.
+* Other:
+ * Fix: Updated Python dependencies. (#1499)
+ * Fix: Some websocket connections not respecting the verify SSL setting. (Thanks @nmaggioni) (#1541)
+ * New: Support for Python 3.10. (#1522)
+ * New: Added dynamic anonymous redirect service setting. (#1526)
+
+
+## v2.7.7 (2021-10-14)
+
+* Notifications:
+ * Fix: Colons and exclamation marks being replaced outside of expressions.
+ * New: Added LunaSea notification agent. Note: Requires a future LunaSea app update to function.
+* Newsletters:
+ * Fix: Star rating not showing on newsletter with the new Plex metadata agents. (#1511)
+* UI:
+ * Fix: Sorting of mobile devices table with uppercase and lowercase device names.
+ * Fix: Various dropdown menus with centered text to left-aligned text.
+* Other:
+ * Fix: Plex.tv account token not changing when fetching a new token.
+ * New: Added check and warning message for missing Docker container volume mount.
+
+
+## v2.7.6 (2021-08-31)
+
+* Notifications:
+ * Fix: Unable to parse colons (:) and exclamation marks (!) in notification text eval strings.
+* Exporter:
+ * Fix: Unable to export playlists and collections from a library. (#1484)
+ * New: Added new episode export fields.
+* Mobile App:
+ * Fix: Unable to scan QR code with dark mode enabled.
+ * New: Tautulli Remote App is out of beta for iOS and can be downloaded in the App Store.
+* Other:
+ * New: Update PlexAPI to 4.6.3.
+ * New: Added popup alert message for Windows and macOS when Tautulli fails to start.
+
+
+## v2.7.5 (2021-07-15)
+
+* History:
+ * Fix: Guest users were unable to view history.
+ * Fix: Most Active Library statistics was counting deleted libraries.
+* Newsletters:
+ * Fix: Incorrect padding on the newsletter configuration modal.
+* Mobile App:
+ * New: Tautulli Remote App is out of beta on Android. The iOS app is available for beta testing on TestFlight.
+* API:
+ * New: Added mobile device platform and version to device registration.
+* Other:
+ * Fix: Unable to remove authentication.
+ * Change: Improve API key and device token security on Python 3.
+ * Remove: Basic Authentication setting.
+
+
+## v2.7.4 (2021-06-19)
+
+* Activity:
+ * Fix: Incorrect quality profile shown on the activity card.
+* Notifications:
+ * New: Added ability to evaluate Python expressions in notification parameters.
+ * New: Added tilde (~) to represent blank notification condition values.
+* Exporter:
+ * Fix: Blank fields missing from csv and json exports.
+ * New: Added some new exporter fields.
+* Graphs:
+ * Fix: Play counts and durations not matching the homepage statistics.
+* UI:
+ * New: Show search bar in the collapsed menu on the mobile layout. (#1446)
+ * Change: Do not show seconds for total played duration on Users and Libraries tables.
+* Other:
+ * Fix: Check the Tautulli data folder is writable on startup. (#1441)
+ * New: Update PlexAPI to 4.6.1.
+ * Change: Always hash HTTP password in config file.
+
+
+## v2.7.3 (2021-05-22)
+
+* Activity:
+ * Fix: Incorrect quality profile being shown when transcoding to a higher bitrate.
+* Notifications:
+ * New: Added notification parameters for duration values in seconds. (#1434)
+ * New: Added setting to allow repeat Tautulli update notifications. By default the Tautulli update notification will only notify once.
+ * New: Added setting to allow repeat Plex Media Server update notifications. By default the Plex Media Server update notification will only notify once.
+ * New: Added setting to configure the Tautulli update check interval.
+* UI:
+ * Fix: Prevent accidentally closing modals when dragging the mouse outside the window.
+ * Fix: Recently added queue modal not loading. (#1429)
+ * New: Show collections tab in music libraries. (#1421)
+ * New: Added method to logout of active Tautulli sessions from the login logs.
+* API:
+ * Fix: Update edit_user and edit_library doc strings for required parameters. (#1432)
+* Other:
+ * New: Added advanced hidden setting for CherryPy thread pool size. (Thanks @psaab #1425)
+
+
+## v2.7.2 (2021-04-24)
+
+* UI:
+ * New: Show smart collections in the library collections tab.
+
+
+## v2.7.1 (2021-04-22)
+
+* Notifications:
+ * Fix: Recently added single episode being sent as a show notification. (#1420)
+* Newsletters:
+ * Change: Ignore items with incorrect added at dates in the future.
+* Exporter:
+ * Fix: Exporting not working for libraries, collections, and playlists. (#1408)
+* UI:
+ * Fix: Collections and playlist tabs not loading on library and user pages. (#1408)
+ * Fix: Header overlapping graphs tabs on mobile layout.
+ * Change: Rename "Plays by Period" graph tab to "Media Type".
+ * Removed: Clear logs button removed from main Tautulli logs.
+
+
+## v2.7.0 (2021-04-10)
+
+* History:
+ * New: Added transcode decision filter added to history tables.
+ * New: History table filters changed to allow multiple selections.
+* Notifications:
+ * Fix: Recently added notifications failing due to metadata not being available yet on the Plex server. (#1392)
+ * New: Added separate SSL/TLS support for Email notifications.
+ * New: Added notification image type setting for Tautulli Remote App notifications.
+ * New: Added guid notification parameter.
+ * New: Added a Plex server down notification threshold setting.
+* Newsletters:
+ * Fix: Newsletters would fail if an episode was missing a season number.
+* UI:
+ * Fix: Fixed spacing of rating images on the media info pages.
+ * Fix: Fixed refreshing cached image in the browser.
+ * Fix: Bootstrap tooltips logging javascript errors in some instances.
+ * Fix: Activity card progress bar not filling at 100%. (#1404)
+ * New: Added blurred background to the Most Active Users statistics card.
+ * New: Added transcode decision filter for all history tables.
+ * New: Added an error popup message if the Plex.tv token is no longer valid when visiting the settings page.
+ * New: Added Amazon Alexa platform logo.
+ * Change: Improved loading times for the homepage watch statistics.
+ * Change: Improved loading times for user and library watch time statistics.
+ * Change: Improved loading of the graph's history modal popup.
+ * Change: Automatically trim trailing slashes from the Tautulli Public Domain setting.
+ * Change: Renamed the Plex Media Server "Use SSL" setting to "Use Secure Connection".
+ * Change: Update Microsoft Edge platform logo.
+ * Change: Consider link local IP addresses as local addresses.
+ * Change: Reveal token fields if they are blank to make it easier to input new values.
+* Mobile App:
+ * New: Accept disabled OneSignal ID during device registration.
+* API:
+ * New: Added user fallback image option to the pms_image_proxy command.
+ * New: Added optional include_last_seen parameter to the get_user command.
+ * New: Added optional include_last_accessed parameter to the get_library command.
+ * New: Allow comma separated filter values for the get_history command.
+* Other:
+ * Fix: Importing the newsletter table would fail when manually repairing a corrupted database.
+ * Fix: Make fix match in Tautulli for music case-insensitive.
+ * New: Update PlexAPI to 4.5.2.
+ * Change: Migrate section_id from the session_history_metadata database table to session_history.
+ * Change: Copy the database file to the cache folder when importing a database using the browse option.
+ * Change: Delete the cached database file after successfully importing.
+
+
+## v2.6.10 (2021-03-17)
+
+* Other:
+ * Fix: Configuration upgrade would fail if the Most Active User card was disabled. (#1395)
+
+
+## v2.6.9 (2021-03-17)
+
+* Notifications:
+ * New: Added tautulli_update_exe and tautulli_update_exe notification parameters for Tautulli update notifications.
+* Exporter:
+ * New: Added new TV show export fields for the beta Plex TV agent.
+* UI:
+ * Fix: Some popover images not showing up on hover. (#1391)
+ * Remove: HTTP Host setting removed from the UI. This setting may still be changed in the config file.
+ * New: Added a Most Active Libraries statistics card to the homepage. (Thanks @herby2212)
+ * New: Mask sensitive text fields in the settings. Settings can be revealed by clicking on the eye icon.
+* Mobile App:
+ * Change: Make OneSignal validation asynchronous to help timeout issues when registering a device.
+* API:
+ * Added top_libraries stat_id option to get_home_stats API commaand.
+* Ohter:
+ * New: Updated PlexAPI to 4.4.1.
+
+
+## v2.6.8 (2021-03-08)
+
+* Mobile App:
+ * New: An all new Tautulli Remote App 2.0. Go to the Google Play link in the settings to download the new version.
+ * Fix: Registering the new app would fail if OneSignal is blocked.
+
+
+## v2.6.7 (2021-03-07)
+
+* History:
+ * New: Added audio language to detailed stream info. (Thanks @herby2212)
+* Notifications:
+ * New: Added season_name notification parameter.
+ * New: Update notifications to support custom season titles.
+* Newsletters:
+ * New: Update recently added newsletter template to support custom season titles.
+* Exporter:
+ * New: Added originalTitle and bannerFile to TV show export fields.
+* UI:
+ * New: Added TVDB rating image to info page for the new Plex TV agent.
+ * New: Update the UI to support custom season titles.
+* API:
+ * Fix: Return rating key for collections/playlists in get_synced_items.
+ * Fix: Return error when delete_synced_item fails.
+ * New: Return sync_media_type for collections/playlist in get_synced_items.
+ * New: Update pms_image_proxy to support playlist composite images.
+* Other:
+ * Remove: Auto-updater for the Windows exe installer due to it being flagged by antivirus software.
+ * New: Updated PlexAPI to 4.4.0.
+
+
+## v2.6.6 (2021-02-06)
+
+* Exporter:
+ * Fix: Exporting failed with long file paths on Windows.
+ * New: Updated various exporter fields.
+ * Change: Renamed collection children to collection items.
+* UI:
+ * Fix: Client side login redirect changed to server side.
+ * Change: Renamed "Fix Metadata" button to "Fix Match".
+* API:
+ * New: Added get_children_metadata API command.
+ * New: Return more metadata from the get_home_stats API command.
+* Other:
+ * New: Updated PlexAPI to 4.3.1.
+
+
+## v2.6.5 (2021-01-09)
+
+* Other:
+ * Fix: Some IP addresses not being masked in the logs.
+ * New: Auto-updater for Windows exe installer.
+ * Change: Allow Snap package to access the user home directory.
+ * Change: Migrate Snap user data to a persistent location that is retained if Tautulli is reinstalled.
+
+
+## v2.6.4 (2020-12-20)
+
+* Other:
+ * Fix: Restore Snap data folder from previous installs.
+
+
+## v2.6.3 (2020-12-19)
+
+* Announcements:
+ * This is the last Tautulli version to support Python 2. Python 3 will be required to continue receiving updates. You can check your Python version on the settings page.
+* Exporter:
+ * Fix: Accessible and exists attributes were blank for media info export level 9.
+* UI:
+ * Fix: Guest usernames were not masked on mouse hover.
+* Other:
+ * Fix: macOS menu bar icon for light and dark mode.
+ * New: Tautulli can officially be installed on Linux using a Snap package. See the installation wiki for details.
+
+
+## v2.6.2 (2020-12-05)
+
+* Notifications:
+ * Change: Send a notification of a user new device for the first time only. This can be toggled off in the settings.
+* Exporter:
+ * Fix: Allow exporting child fields only without requiring the parent fields as well.
+ * Fix: Exporting individual collection would fail.
+ * Change: Remove accessible and exists fields from the default media info export levels. This prevents the Plex server from reading the media files unnecessarily.
+* Other:
+ * Fix: Enable high resolution for the macOS system tray icon and menu.
+ * New: Added rate limiting for failed login attempts.
+ * Change: Use a white logo for the macOS system tray icon.
+* API:
+ * New: Added machine_id to the get_history API response.
+
+
## v2.6.1 (2020-11-03)
* Other:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e687432e..46a644e5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -9,12 +9,12 @@ All pull requests should be based on the `nightly` branch, to minimize cross mer
### Python Code
#### Compatibility
-The code should work with Python 2.7.17 or Python 3.6+. Note that Tautulli runs on many different platforms.
+The code should work with Python 3.8+. Note that Tautulli runs on many different platforms.
Re-use existing code. Do not hesitate to add logging in your code. You can the logger module `plexpy.logger.*` for this. Web requests are invoked via `plexpy.request.*` and derived ones. Use these methods to automatically add proper and meaningful error handling.
#### Code conventions
-Although Tautulli did not adapt a code convention in the past, we try to follow the [PEP8](http://legacy.python.org/dev/peps/pep-0008/) conventions for future code. A short summary to remind you (copied from http://wiki.ros.org/PyStyleGuide):
+Although Tautulli did not adopt a code convention in the past, we try to follow [PEP8](http://legacy.python.org/dev/peps/pep-0008/) conventions for future code. A short summary to remind you (copied from http://wiki.ros.org/PyStyleGuide):
* 4 space indentation
* 80 characters per line
diff --git a/Dockerfile b/Dockerfile
index f82e7551..8d8c324b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM tautulli/tautulli-baseimage:python3
+FROM ghcr.io/tautulli/tautulli-baseimage:python3
LABEL maintainer="Tautulli"
@@ -9,18 +9,20 @@ ENV TAUTULLI_DOCKER=True
ENV TZ=UTC
WORKDIR /app
-
+COPY . /app
RUN \
groupadd -g 1000 tautulli && \
useradd -u 1000 -g 1000 tautulli && \
echo ${BRANCH} > /app/branch.txt && \
echo ${COMMIT} > /app/version.txt
-COPY . /app
+RUN \
+ mkdir /config && \
+ touch /config/DOCKER
+VOLUME /config
CMD [ "python", "Tautulli.py", "--datadir", "/config" ]
ENTRYPOINT [ "./start.sh" ]
-VOLUME /config
EXPOSE 8181
-HEALTHCHECK --start-period=90s CMD curl -ILfSs http://localhost:8181/status > /dev/null || curl -ILfkSs https://localhost:8181/status > /dev/null || exit 1
+HEALTHCHECK --start-period=90s CMD curl -ILfks https://localhost:8181/status > /dev/null || curl -ILfs http://localhost:8181/status > /dev/null || exit 1
diff --git a/README.md b/README.md
index 74968cc8..37829290 100644
--- a/README.md
+++ b/README.md
@@ -1,65 +1,163 @@
# Tautulli
-A python based web application for monitoring, analytics and notifications for [Plex Media Server](https://plex.tv).
+A python based web application for monitoring, analytics and notifications for
+[Plex Media Server](https://plex.tv).
-This project is based on code from [Headphones](https://github.com/rembo10/headphones) and [PlexWatchWeb](https://github.com/ecleese/plexWatchWeb).
+This project is based on code from [Headphones](https://github.com/rembo10/headphones)
+and [PlexWatchWeb](https://github.com/ecleese/plexWatchWeb).
## Features
-* Responsive web design viewable on desktop, tablet and mobile web browsers.
-* Themed to complement Plex/Web.
-* Easy configuration setup (no separate web server required).
-* Monitor current Plex Media Server activity.
-* Fully customizable notifications for stream activity and recently added media.
-* Top statistics on home page with configurable duration and measurement metric.
-* Global watching history with search/filtering & dynamic column sorting.
-* Full user list with general information and comparison stats.
-* Individual user information including devices IP addresses.
-* Complete library statistics and media file information.
-* Rich analytics presented using Highcharts graphing.
-* Beautiful content information pages.
-* Full sync list data on all users syncing items from your library.
-* And many more!!
+- Responsive web design viewable on desktop, tablet and mobile web browsers.
+- Themed to complement Plex/Web.
+- Easy configuration setup (no separate web server required).
+- Monitor current Plex Media Server activity.
+- Fully customizable notifications for stream activity and recently added media.
+- Top statistics on home page with configurable duration and measurement metric.
+- Global watching history with search/filtering & dynamic column sorting.
+- Full user list with general information and comparison stats.
+- Individual user information including devices IP addresses.
+- Complete library statistics and media file information.
+- Rich analytics presented using Highcharts graphing.
+- Beautiful content information pages.
+- Full sync list data on all users syncing items from your library.
+- And many more!!
## Preview
-* [Full preview gallery available on our website](https://tautulli.com)
+[Full preview gallery available on our website][Tautulli]

-## Installation & Support
+## Installation
-[](https://python.org/downloads)
-[](https://hub.docker.com/r/tautulli/tautulli)
-[](https://hub.docker.com/r/tautulli/tautulli)
-[](https://github.com/Tautulli/Tautulli/releases/latest)
+[![Python][badge-python]][Python]
+[![Docker Pulls][badge-docker-pulls]][DockerHub]
+[![Docker Stars][badge-docker-stars]][DockerHub]
+[![Downloads][badge-downloads]][Releases Latest]
+
+[badge-python]: https://img.shields.io/badge/python->=3.9-blue?style=flat-square
+[badge-docker-pulls]: https://img.shields.io/docker/pulls/tautulli/tautulli?style=flat-square
+[badge-docker-stars]: https://img.shields.io/docker/stars/tautulli/tautulli?style=flat-square
+[badge-downloads]: https://img.shields.io/github/downloads/Tautulli/Tautulli/total?style=flat-square
| Status | Branch: `master` | Branch: `beta` | Branch: `nightly` |
| --- | --- | --- | --- |
-| Release | [](https://github.com/Tautulli/Tautulli/releases/latest)
[](https://github.com/Tautulli/Tautulli/releases/latest) | [](https://github.com/Tautulli/Tautulli/releases)
[](https://github.com/Tautulli/Tautulli/commits/beta) | [](https://github.com/Tautulli/Tautulli/commits/nightly)
[](https://github.com/Tautulli/Tautulli/commits/nightly) |
-| Docker | [](https://hub.docker.com/r/tautulli/tautulli)
[](https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Docker"+branch%3Amaster) | [](https://hub.docker.com/r/tautulli/tautulli)
[](https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Docker"+branch%3Abeta) | [](https://hub.docker.com/r/tautulli/tautulli)
[](https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Docker"+branch%3Anightly) |
-| Installer | [](https://github.com/Tautulli/Tautulli/releases/latest)
[](https://github.com/Tautulli/Tautulli/releases/latest)
[](https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Release"+branch%3Amaster) | [](https://github.com/Tautulli/Tautulli/releases)
[](https://github.com/Tautulli/Tautulli/releases)
[](https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Release"+branch%3Abeta) | [](https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Release"+branch%3Anightly) |
+| Release | [![Release@master][badge-release-master]][Releases Latest]
[![Release Date@master][badge-release-master-date]][Releases Latest] | [![Release@beta][badge-release-beta]][Releases]
[![Commits@beta][badge-release-beta-commits]][Commits Beta] | [![Last Commits@nightly][badge-release-nightly-last-commit]][commits Nightly]
[![Commits@nightly][badge-release-nightly-commits]][Commits Nightly] |
+| Docker | [![Docker@master][badge-docker-master]][DockerHub]
[![Docker Build@master][badge-docker-master-ci]][Publish Docker Master] | [![Docker@beta][badge-docker-beta]][DockerHub]
[![Docker Build@beta][badge-docker-beta-ci]][Publish Docker Beta] | [![Docker@nightly][badge-docker-nightly]][DockerHub]
[![Docker Build@nightly][badge-docker-nightly-ci]][Publish Docker Nightly] |
+| Snap | [![Snap@master][badge-snap-master]][Snapcraft]
[![Snap Build@master][badge-snap-master-ci]][Publish Snap Master] | [![Snap@beta][badge-snap-beta]][Snapcraft]
[![Snap Build@beta][badge-snap-beta-ci]][Publish Snap Beta] | [![Snap@nightly][badge-snap-nightly]][Snapcraft]
[![Snap Build@nightly][badge-snap-nightly-ci]][Publish Snap Nightly] |
+| Installer | [![Windows@master][badge-installer-master-win]][Releases Latest]
[![MacOS@master][badge-installer-master-macos]][Releases Latest]
[![Installer Build@master][badge-installer-master-ci]][Publish Installer Master] | [![Windows@beta][badge-installer-beta-win]][Releases]
[![MacOS@beta][badge-installer-beta-macos]][Releases]
[![Installer Build@beta][badge-installer-beta-ci]][Publish Installer Beta] | [![Installer Build@nightly][badge-installer-nightly-ci]][Publish Installer Nightly] |
-[](https://github.com/Tautulli/Tautulli-Wiki/wiki)
-[](https://tautulli.com/discord)
-[](https://www.reddit.com/r/Tautulli/)
-[](https://forums.plex.tv/t/tautulli-monitor-your-plex-media-server/225242)
+Read the [Installation Guides][Installation] for instructions on how to install Tautulli.
-* Read the [Installation Guides](https://github.com/Tautulli/Tautulli-Wiki/wiki/Installation) for instructions to install Tautulli.
-* The [Frequently Asked Questions](https://github.com/Tautulli/Tautulli-Wiki/wiki/Frequently-Asked-Questions) in the wiki can help you with common problems.
-* Support is available on [Discord](https://tautulli.com/discord), [Reddit](https://www.reddit.com/r/Tautulli), or the [Plex Forums](https://forums.plex.tv/t/tautulli-monitor-your-plex-media-server/225242).
+[badge-release-master]: https://img.shields.io/github/v/release/Tautulli/Tautulli?style=flat-square
+[badge-release-master-date]: https://img.shields.io/github/release-date/Tautulli/Tautulli?style=flat-square&color=blue
+[badge-release-beta]: https://img.shields.io/github/v/release/Tautulli/Tautulli?include_prereleases&style=flat-square
+[badge-release-beta-commits]: https://img.shields.io/github/commits-since/Tautulli/Tautulli/latest/beta?style=flat-square&color=blue
+[badge-release-nightly-last-commit]: https://img.shields.io/github/last-commit/Tautulli/Tautulli/nightly?style=flat-square&color=blue
+[badge-release-nightly-commits]: https://img.shields.io/github/commits-since/Tautulli/Tautulli/latest/nightly?style=flat-square&color=blue
+[badge-docker-master]: https://img.shields.io/badge/docker-latest-blue?style=flat-square
+[badge-docker-master-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-docker.yml?style=flat-square&branch=master
+[badge-docker-beta]: https://img.shields.io/badge/docker-beta-blue?style=flat-square
+[badge-docker-beta-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-docker.yml?style=flat-square&branch=beta
+[badge-docker-nightly]: https://img.shields.io/badge/docker-nightly-blue?style=flat-square
+[badge-docker-nightly-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-docker.yml?style=flat-square&branch=nightly
+[badge-snap-master]: https://img.shields.io/badge/snap-stable-blue?style=flat-square
+[badge-snap-master-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-snap.yml?style=flat-square&branch=master
+[badge-snap-beta]: https://img.shields.io/badge/snap-beta-blue?style=flat-square
+[badge-snap-beta-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-snap.yml?style=flat-square&branch=beta
+[badge-snap-nightly]: https://img.shields.io/badge/snap-edge-blue?style=flat-square
+[badge-snap-nightly-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-snap.yml?style=flat-square&branch=nightly
+[badge-installer-master-win]: https://img.shields.io/github/v/release/Tautulli/Tautulli?label=windows&style=flat-square
+[badge-installer-master-macos]: https://img.shields.io/github/v/release/Tautulli/Tautulli?label=macos&style=flat-square
+[badge-installer-master-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-installers.yml?style=flat-square&branch=master
+[badge-installer-beta-win]: https://img.shields.io/github/v/release/Tautulli/Tautulli?label=windows&include_prereleases&style=flat-square
+[badge-installer-beta-macos]: https://img.shields.io/github/v/release/Tautulli/Tautulli?label=macos&include_prereleases&style=flat-square
+[badge-installer-beta-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-installers.yml?style=flat-square&branch=beta
+[badge-installer-nightly-ci]: https://img.shields.io/github/actions/workflow/status/Tautulli/Tautulli/.github/workflows/publish-installers.yml?style=flat-square&branch=nightly
-## Issues & Feature Requests
+## Support
-[](https://github.com/Tautulli/Tautulli-Issues)
-[](https://feathub.com/Tautulli/Tautulli)
+[![Wiki][badge-wiki]][Wiki]
+[![Discord][badge-discord]][Discord]
+[![Reddit][badge-reddit]][Reddit]
+[![Plex Forums][badge-forums]][Plex Forums]
+[![Issues][badge-issues]][Issues]
-* Please see the [Issues Repository](https://github.com/Tautulli/Tautulli-Issues).
+[badge-wiki]: https://img.shields.io/badge/github-wiki-black?style=flat-square
+[badge-discord]: https://img.shields.io/discord/183396325142822912?label=discord&style=flat-square&color=7289DA
+[badge-reddit]: https://img.shields.io/reddit/subreddit-subscribers/tautulli?label=reddit&style=flat-square&color=FF5700
+[badge-forums]: https://img.shields.io/badge/plex%20forums-discussion-E5A00D?style=flat-square
+[badge-issues]: https://img.shields.io/badge/github-issues-black?style=flat-square
+
+If you think you've found a bug in Tautulli make sure you have read the [FAQ][]
+first to make sure it hasn't been covered by one of the questions there. If your
+problem isn't answered in the FAQ try the following first:
+
+- Update to the latest version of Tautulli.
+- Turning your device off and on again.
+- Analyzing your logs, you just might find the solution yourself!
+- Using the **search** function to see if this issue has already been reported/solved.
+- Checking the [Wiki][] for [Installation][] instructions and reading the [FAQs][FAQ].
+- For basic questions try asking on [Discord][], [Reddit][],
+ or the [Plex Forums][] first before opening an issue.
+
+**If nothing has worked:**
+
+1. Please check the [issues tracker][Issues] to see if someone else has already reported the bug.
+2. If this is a new bug, open a [bug report][Issue New] on the issues tracker.
+3. Provide a clear title to easily help identify your problem.
+4. Use proper [Markdown syntax][] to structure your post (i.e. code/log in code blocks).
+5. Make sure to fill out the required information on the issue template.
+6. Close your issue when it's solved! If you found the solution yourself please
+ comment so that others benefit from it.
+
+## Feature Requests
+
+1. Pleases check the [issues tracker][Issues] to see if someone else has already requested the feature.
+ If a similar idea has already been requested, _give it a thumbs up_. **Do not comment
+ with `+1` or something similar as it creates unnecessary spam.**
+2. If this is a new feature request, open a [feature request][Issue New] on the issues tracker.
## License
-[](https://github.com/Tautulli/Tautulli/blob/master/LICENSE)
+[![License][badge-license]][License]
-This is free software under the GPL v3 open source license. Feel free to do with it what you wish, but any modification must be open sourced. A copy of the license is included.
+[badge-license]: https://img.shields.io/github/license/Tautulli/Tautulli?style=flat-square
-This software includes Highsoft software libraries which you may freely distribute for non-commercial use. Commerical users must licence this software, for more information visit https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution.
\ No newline at end of file
+This is free software under the GPL v3 open source license. Feel free to do with it what you wish,
+but any modification must be open sourced. A copy of the license is included.
+
+This software includes Highsoft software libraries which you may freely distribute for
+non-commercial use. Commercial users must licence this software, for more information visit
+https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution.
+
+
+[Python]: https://python.org/downloads
+[DockerHub]: https://hub.docker.com/r/tautulli/tautulli
+[Releases]: https://github.com/Tautulli/Tautulli/releases
+[Releases Latest]: https://github.com/Tautulli/Tautulli/releases/latest
+[License]: https://github.com/Tautulli/Tautulli/blob/master/LICENSE
+[FAQ]: https://github.com/Tautulli/Tautulli/wiki/Frequently-Asked-Questions
+[Installation]: https://github.com/Tautulli/Tautulli/wiki/Installation
+[Issues]: https://github.com/Tautulli/Tautulli/issues
+[Issue New]: https://github.com/Tautulli/Tautulli/issues/new/choose
+[Markdown syntax]: https://help.github.com/articles/github-flavored-markdown
+[Tautulli]: http://tautulli.com
+[Wiki]: https://github.com/Tautulli/Tautulli/wiki
+[Discord]: https://tautulli.com/discord
+[Reddit]: https://reddit.com/r/Tautulli
+[Plex Forums]: https://forums.plex.tv/t/tautulli-monitor-your-plex-media-server/225242
+[Snapcraft]: https://snapcraft.io/tautulli
+[Commits Beta]: https://github.com/Tautulli/Tautulli/commits/beta
+[Commits Nightly]: https://github.com/Tautulli/Tautulli/commits/nightly
+
+[Publish Docker Master]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Docker"+branch%3Amaster
+[Publish Docker Beta]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Docker"+branch%3Abeta
+[Publish Docker Nightly]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Docker"+branch%3Anightly
+[Publish Snap Master]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Snap"+branch%3Amaster
+[Publish Snap Beta]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Snap"+branch%3Abeta
+[Publish Snap Nightly]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Snap"+branch%3Anightly
+[Publish Installer Master]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Installers"+branch%3Amaster
+[Publish Installer Beta]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Installers"+branch%3Abeta
+[Publish Installer Nightly]: https://github.com/Tautulli/Tautulli/actions?query=workflow%3A"Publish+Installers"+branch%3Anightly
diff --git a/Tautulli.py b/Tautulli.py
index 0a15f2c6..b3cf4736 100755
--- a/Tautulli.py
+++ b/Tautulli.py
@@ -23,17 +23,18 @@ import sys
# Ensure lib added to path, before any other imports
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib'))
-from future.builtins import str
-import appdirs
import argparse
import datetime
import locale
+import platformdirs
import pytz
import signal
+import shutil
import time
import threading
import tzlocal
+import ctypes
import plexpy
from plexpy import common, config, database, helpers, logger, webstart
@@ -69,8 +70,26 @@ def main():
plexpy.SYS_ENCODING = None
try:
- locale.setlocale(locale.LC_ALL, "")
- plexpy.SYS_LANGUAGE, plexpy.SYS_ENCODING = locale.getdefaultlocale()
+
+ # Attempt to get the system's locale settings
+ language_code, encoding = locale.getlocale()
+
+ # Special handling for Windows platform
+ if sys.platform == 'win32':
+ # Get the user's current language settings on Windows
+ windll = ctypes.windll.kernel32
+ lang_id = windll.GetUserDefaultLCID()
+
+ # Map Windows language ID to locale identifier
+ language_code = locale.windows_locale.get(lang_id, '')
+
+ # Get the preferred encoding
+ encoding = locale.getpreferredencoding()
+
+ # Assign values to application-specific variable
+ plexpy.SYS_LANGUAGE = language_code
+ plexpy.SYS_ENCODING = encoding
+
except (locale.Error, IOError):
pass
@@ -110,7 +129,7 @@ def main():
if args.quiet:
plexpy.QUIET = True
- # Do an intial setup of the logger.
+ # Do an initial setup of the logger.
# Require verbose for pre-initilization to see critical errors
logger.initLogger(console=not plexpy.QUIET, log_dir=False, verbose=True)
@@ -124,6 +143,9 @@ def main():
if helpers.bool_true(os.getenv('TAUTULLI_DOCKER', False)):
plexpy.DOCKER = True
+ plexpy.DOCKER_MOUNT = not os.path.isfile('/config/DOCKER')
+ if helpers.bool_true(os.getenv('TAUTULLI_SNAP', False)):
+ plexpy.SNAP = True
if args.dev:
plexpy.DEV = True
@@ -182,10 +204,19 @@ def main():
if args.datadir:
plexpy.DATA_DIR = args.datadir
elif plexpy.FROZEN:
- plexpy.DATA_DIR = appdirs.user_data_dir("Tautulli", False)
+ plexpy.DATA_DIR = platformdirs.user_data_dir("Tautulli", False)
else:
plexpy.DATA_DIR = plexpy.PROG_DIR
+ # Migrate Snap data dir
+ if plexpy.SNAP:
+ snap_common = os.environ['SNAP_COMMON']
+ old_data_dir = os.path.join(snap_common, 'Tautulli')
+ if os.path.exists(old_data_dir) and os.listdir(old_data_dir):
+ plexpy.SNAP_MIGRATE = True
+ logger.info("Migrating Snap user data.")
+ shutil.move(old_data_dir, plexpy.DATA_DIR)
+
if args.config:
config_file = args.config
else:
@@ -200,9 +231,18 @@ def main():
'Could not create data directory: ' + plexpy.DATA_DIR + '. Exiting....')
# Make sure the DATA_DIR is writeable
- if not os.access(plexpy.DATA_DIR, os.W_OK):
+ test_file = os.path.join(plexpy.DATA_DIR, '.TEST')
+ try:
+ with open(test_file, 'w'):
+ pass
+ except IOError:
raise SystemExit(
'Cannot write to the data directory: ' + plexpy.DATA_DIR + '. Exiting...')
+ finally:
+ try:
+ os.remove(test_file)
+ except OSError:
+ pass
# Put the database in the DATA_DIR
plexpy.DB_FILE = os.path.join(plexpy.DATA_DIR, database.FILENAME)
@@ -224,23 +264,13 @@ def main():
# Start the background threads
plexpy.start()
- # Force the http port if neccessary
+ # Force the http port if necessary
if args.port:
plexpy.HTTP_PORT = args.port
logger.info('Using forced web server port: %i', plexpy.HTTP_PORT)
else:
plexpy.HTTP_PORT = int(plexpy.CONFIG.HTTP_PORT)
- # Check if pyOpenSSL is installed. It is required for certificate generation
- # and for CherryPy.
- if plexpy.CONFIG.ENABLE_HTTPS:
- try:
- import OpenSSL
- except ImportError:
- logger.warn("The pyOpenSSL module is missing. Install this "
- "module to enable HTTPS. HTTPS will be disabled.")
- plexpy.CONFIG.ENABLE_HTTPS = False
-
# Try to start the server. Will exit here is address is already in use.
webstart.start()
diff --git a/contrib/clean_pyc.bat b/contrib/clean_pyc.bat
new file mode 100755
index 00000000..e4436dea
--- /dev/null
+++ b/contrib/clean_pyc.bat
@@ -0,0 +1,11 @@
+@echo off
+:: Display information
+echo This script will remove *.pyc files. These files are generated by Python, but they can cause conflicts after an upgrade. It's safe to remove them, because they will be regenerated.
+echo Press enter to continue, or CTRL + C to quit.
+pause
+
+cd ..\
+:: Remove *.pyc files
+del /S *.pyc
+:: Remove __pycache__ folders
+for /d /r . %%d in (__pycache__) do @if exist "%%d" rd /s /q "%%d"
\ No newline at end of file
diff --git a/contrib/clean_pyc.sh b/contrib/clean_pyc.sh
index 9283fb59..ea555159 100755
--- a/contrib/clean_pyc.sh
+++ b/contrib/clean_pyc.sh
@@ -5,5 +5,7 @@ echo "This script will remove *.pyc files. These files are generated by Python,
echo "Press enter to continue, or CTRL + C to quit."
read
-# Remove the *.pyc
-find "`dirname $0`/.." -type f -name "*.pyc" -exec rm -rf {} \;
\ No newline at end of file
+# Remove *.pyc files
+find "`dirname $0`/.." -type f -name "*.pyc" -exec rm -rf {} \;
+# Remove __pycache__ folders
+find "`dirname $0`/.." -type d -name "__pycache__" -exec rm -rf {} \;
\ No newline at end of file
diff --git a/data/interfaces/default/app_import.html b/data/interfaces/default/app_import.html
index a96009a7..74af4313 100644
--- a/data/interfaces/default/app_import.html
+++ b/data/interfaces/default/app_import.html
@@ -32,7 +32,7 @@
-
Upload the ${app} database file you wish to import.
+Upload the ${app} database file you wish to import (max file size is 1GB).
Click the button below to continue to GitHub.
- - Sponsor - ++ + Sponsor + +
+(GitHub does not have a fee)
Click the button below to continue to PayPal.
- -
+
+
+
+
(PayPal has a fee)
++ Select a cryptocurrency. +
+ + ++ Or click the button below to continue to Coinbase. +
+ + Donate with Crypto