mirror of
https://github.com/StuffAnThings/qbit_manage.git
synced 2025-10-06 11:57:20 +08:00
commit
d342d4e61a
16 changed files with 926 additions and 299 deletions
21
.dockerignore
Normal file
21
.dockerignore
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
**/dist
|
||||||
|
**/build
|
||||||
|
*.spec
|
||||||
|
**/__pycache__
|
||||||
|
/.vscode
|
||||||
|
**/log
|
||||||
|
README.md
|
||||||
|
LICENSE
|
||||||
|
.gitignore
|
||||||
|
.dockerignore
|
||||||
|
.git
|
||||||
|
.github
|
||||||
|
.vscode
|
||||||
|
*.psd
|
||||||
|
config/**/*
|
||||||
|
config
|
||||||
|
Dockerfile
|
||||||
|
venv
|
||||||
|
.idea
|
||||||
|
test.py
|
||||||
|
!config/config.yml.sample
|
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
github: bobokun
|
38
.github/workflows/develop.yml
vendored
Normal file
38
.github/workflows/develop.yml
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
name: Docker Develop Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ develop ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ develop ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
docker-develop:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Check Out Repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: develop
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: ./
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/qbit_manage:develop
|
36
.github/workflows/latest.yml
vendored
Normal file
36
.github/workflows/latest.yml
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
name: Docker Latest Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
docker-latest:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Check Out Repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: ./
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/qbit_manage:latest
|
18
.github/workflows/tag.yml
vendored
Normal file
18
.github/workflows/tag.yml
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
name: Tag
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tag-new-versions:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.PAT }}
|
||||||
|
fetch-depth: 2
|
||||||
|
- uses: salsify/action-detect-and-tag-new-version@v1.0.3
|
||||||
|
with:
|
||||||
|
version-command: |
|
||||||
|
cat VERSION
|
39
.github/workflows/version.yml
vendored
Normal file
39
.github/workflows/version.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
name: Docker Version Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
create:
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
docker-develop:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Check Out Repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Get the version
|
||||||
|
id: get_version
|
||||||
|
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: ./
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/qbit_manage:${{ steps.get_version.outputs.VERSION }}
|
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -1,3 +1,9 @@
|
||||||
*.log
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
*.log*
|
||||||
*.yml
|
*.yml
|
||||||
.vscode/settings.json
|
.vscode/*
|
||||||
|
!.github/**
|
10
Dockerfile
Normal file
10
Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
FROM python:3.9-slim
|
||||||
|
COPY requirements.txt /
|
||||||
|
RUN echo "**** install python packages ****" \
|
||||||
|
&& pip3 install --no-cache-dir --upgrade --requirement /requirements.txt \
|
||||||
|
&& apt-get autoremove -y \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /requirements.txt /tmp/* /var/tmp/* /var/lib/apt/lists/*
|
||||||
|
COPY . /
|
||||||
|
VOLUME /config
|
||||||
|
ENTRYPOINT ["python3","qbit_manage.py"]
|
40
README.md
40
README.md
|
@ -9,7 +9,8 @@ This is a program used to manage your qBittorrent instance such as:
|
||||||
* Recheck paused torrents sorted by lowest size and resume if completed
|
* Recheck paused torrents sorted by lowest size and resume if completed
|
||||||
* Remove orphaned files from your root directory that are not referenced by qBittorrent
|
* Remove orphaned files from your root directory that are not referenced by qBittorrent
|
||||||
* Tag any torrents that have no hard links and allows optional cleanup to delete these torrents and contents based on maximum ratio and/or time seeded
|
* Tag any torrents that have no hard links and allows optional cleanup to delete these torrents and contents based on maximum ratio and/or time seeded
|
||||||
|
* RecycleBin function to move files into a RecycleBin folder instead of deleting the data directly when deleting a torrent
|
||||||
|
* Built-in scheduler to run the script every x minutes. (Can use `--run` command to run without the scheduler)
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Check out the [wiki](https://github.com/StuffAnThings/qbit_manage/wiki) for installation help
|
Check out the [wiki](https://github.com/StuffAnThings/qbit_manage/wiki) for installation help
|
||||||
|
@ -20,10 +21,12 @@ To run the script in an interactive terminal run:
|
||||||
|
|
||||||
* copy the `config.yml.sample` file to `config.yml`
|
* copy the `config.yml.sample` file to `config.yml`
|
||||||
* add your qBittorrent host, user and pass. If you are not using a username and password you can remove the `user` and `pass` lines.
|
* add your qBittorrent host, user and pass. If you are not using a username and password you can remove the `user` and `pass` lines.
|
||||||
* add your `cross_seed` and `root_dir`. If you are using a docker container you must fill out `remote_dir` as well.
|
* add your `cross_seed` and `root_dir`. If you're running cross-seed in a docker container you must fill out `remote_dir` as well.
|
||||||
* Add your categories and save path to match with what is being used in your qBittorrent instance. I suggest using the full path when defining `save_path`
|
* Add your categories and save path to match with what is being used in your qBittorrent instance. I suggest using the full path when defining `save_path`
|
||||||
* Add the `tag` definition based on tracker URL
|
* Add the `tag` definition based on tracker URL
|
||||||
* Modify the `nohardlinks` by specifying your completed movies/series category to match with qBittorrent. Please ensure the `root_dir` and/or `remote_dir` is added in the `directory` section
|
* Modify the `nohardlinks` by specifying your completed movies/series category to match with qBittorrent. Please ensure the `root_dir` and/or `remote_dir` is added in the `directory` section
|
||||||
|
* `root_dir` needs to be defined in order to use the RecycleBin function. If optional `empty_after_x_days` is not defined then it will never empty the RecycleBin. Setting it to 0 will empty the RecycleBin immediately.
|
||||||
|
* Modify the `orphaned` section to define file patterns not to consider as orphans. Use this to exclude your incomplete torrents directory, or to ignore auto-generated files such as Thumbs.db.
|
||||||
* To run the script in an interactive terminal with a list of possible commands run:
|
* To run the script in an interactive terminal with a list of possible commands run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -32,21 +35,24 @@ python qbit_manage.py -h
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
| Shell Command | Description | Default Value |
|
| Shell Command |Docker Environment Variable |Description | Default Value |
|
||||||
| :------------ | :------------ | :------------ |
|
| :------------ | :------------ | :------------ | :------------ |
|
||||||
| `-c CONFIG` or `--config-file CONFIG` | This is used if you want to use a different name for your config.yml. `Example: tv.yml` | config.yml |
|
| `-r` or`--run` | QBT_RUN |Run without the scheduler. Script will exit after completion. | False |
|
||||||
| `-l LOGFILE,` or `--log-file LOGFILE,` | This is used if you want to use a different name for your log file. `Example: tv.log` | activity.log |
|
| `-sch` or `--schedule` | QBT_SCHEDULE | Schedule to run every x minutes. (Default set to 30) | 30 |
|
||||||
| `-m` or `--manage` | Use this if you would like to update your tags, categories, remove unregistered torrents, AND recheck/resume paused torrents. | |
|
| `-c CONFIG` or `--config-file CONFIG` | QBT_CONFIG | This is used if you want to use a different name for your config.yml. `Example: tv.yml` | config.yml |
|
||||||
| `-s` or `--cross-seed` | Use this after running [cross-seed script](https://github.com/mmgoodnow/cross-seed) to add torrents from the cross-seed output folder to qBittorrent | |
|
| `-lf LOGFILE,` or `--log-file LOGFILE,` | QBT_LOGFILE | This is used if you want to use a different name for your log file. `Example: tv.log` | activity.log |
|
||||||
| `-re` or `--recheck` | Recheck paused torrents sorted by lowest size. Resume if Completed. | |
|
| `-cs` or `--cross-seed` | QBT_CROSS_SEED | Use this after running [cross-seed script](https://github.com/mmgoodnow/cross-seed) to add torrents from the cross-seed output folder to qBittorrent | False |
|
||||||
| `-g` or `--cat-update` | Use this if you would like to update your categories. | |
|
| `-re` or `--recheck` | QBT_RECHECK | Recheck paused torrents sorted by lowest size. Resume if Completed. | False |
|
||||||
| `-t` or `--tag-update` | Use this if you would like to update your tags. (Only adds tags to untagged torrents) | |
|
| `-cu` or `--cat-update` | QBT_CAT_UPDATE | Use this if you would like to update your categories. | False |
|
||||||
| `-r` or `--rem-unregistered` | Use this if you would like to remove unregistered torrents. (It will the delete data & torrent if it is not being cross-seeded, otherwise it will just remove the torrent without deleting data) | |
|
| `-tu` or `--tag-update` | QBT_TAG_UPDATE | Use this if you would like to update your tags. (Only adds tags to untagged torrents) | False |
|
||||||
| `-ro` or `--rem-orphaned` | Use this if you would like to remove orphaned files from your `root_dir` directory that are not referenced by any torrents. It will scan your `root_dir` directory and compare it with what is in qBittorrent. Any data not referenced in qBittorrent will be moved into `/data/torrents/orphaned_data` folder for you to review/delete. | |
|
| `-ru` or `--rem-unregistered` | QBT_REM_UNREGISTERED | Use this if you would like to remove unregistered torrents. (It will the delete data & torrent if it is not being cross-seeded, otherwise it will just remove the torrent without deleting data) | False |
|
||||||
| `-tnhl` or `--tag-nohardlinks` | Use this to tag any torrents that do not have any hard links associated with any of the files. This is useful for those that use Sonarr/Radarr that hard links your media files with the torrents for seeding. When files get upgraded they no longer become linked with your media therefore will be tagged with a new tag noHL. You can then safely delete/remove these torrents to free up any extra space that is not being used by your media folder. | |
|
| `-ro` or `--rem-orphaned` | QBT_REM_ORPHANED | Use this if you would like to remove orphaned files from your `root_dir` directory that are not referenced by any torrents. It will scan your `root_dir` directory and compare it with what is in qBittorrent. Any data not referenced in qBittorrent will be moved into `/data/torrents/orphaned_data` folder for you to review/delete. | False |
|
||||||
| `--dry-run` | If you would like to see what is gonna happen but not actually move/delete or tag/categorize anything. | |
|
| `-tnhl` or `--tag-nohardlinks` | QBT_TAG_NOHARDLINKS | Use this to tag any torrents that do not have any hard links associated with any of the files. This is useful for those that use Sonarr/Radarr that hard links your media files with the torrents for seeding. When files get upgraded they no longer become linked with your media therefore will be tagged with a new tag noHL. You can then safely delete/remove these torrents to free up any extra space that is not being used by your media folder. | False |
|
||||||
| `--log LOGLEVEL` | Change the ouput log level. | INFO |
|
| `-sr` or `--skip-recycle` | QBT_SKIP_RECYCLE | Use this to skip emptying the Reycle Bin folder (`/root_dir/.RecycleBin`). | False |
|
||||||
|
| `-dr` or `--dry-run` | QBT_DRY_RUN | If you would like to see what is gonna happen but not actually move/delete or tag/categorize anything. | False |
|
||||||
|
| `-ll` or `--log-level LOGLEVEL` | QBT_LOG_LEVEL | Change the ouput log level. | INFO |
|
||||||
|
| `-d` or `--divider` | QBT_DIVIDER | Character that divides the sections (Default: '=') | = |
|
||||||
|
| `-w` or `--width` | QBT_WIDTH | Screen Width (Default: 100) | 100 |
|
||||||
### Config
|
### Config
|
||||||
|
|
||||||
To choose the location of the YAML config file
|
To choose the location of the YAML config file
|
||||||
|
|
1
VERSION
Normal file
1
VERSION
Normal file
|
@ -0,0 +1 @@
|
||||||
|
2.0
|
|
@ -7,8 +7,8 @@ qbt:
|
||||||
directory:
|
directory:
|
||||||
# Do not remove these
|
# Do not remove these
|
||||||
# Cross-seed var: </your/path/here/> #Output directory of cross-seed
|
# Cross-seed var: </your/path/here/> #Output directory of cross-seed
|
||||||
# root_dir var: </your/path/here/> #Root downloads directory used to check for orphaned files
|
# root_dir var: </your/path/here/> #Root downloads directory used to check for orphaned files and used in RecycleBin
|
||||||
# <OPTIONAL> remote_dir var: </your/path/here/> # Path of docker host mapping of root_dir
|
# <OPTIONAL> remote_dir var: </your/path/here/> # Path of docker host mapping of root_dir. Must be set if you are using docker!
|
||||||
cross_seed: "/your/path/here/"
|
cross_seed: "/your/path/here/"
|
||||||
root_dir: "/data/torrents/"
|
root_dir: "/data/torrents/"
|
||||||
remote_dir: "/mnt/user/data/torrents/"
|
remote_dir: "/mnt/user/data/torrents/"
|
||||||
|
@ -68,3 +68,20 @@ nohardlinks:
|
||||||
max_ratio: 4.0
|
max_ratio: 4.0
|
||||||
#<OPTIONAL> seeding time var: Will set the torrent Maximum seeding time (min) until torrent is stopped from seeding
|
#<OPTIONAL> seeding time var: Will set the torrent Maximum seeding time (min) until torrent is stopped from seeding
|
||||||
max_seeding_time: 86400
|
max_seeding_time: 86400
|
||||||
|
|
||||||
|
#Recycle Bin method of deletion will move files into the recycle bin instead of directly deleting them in qbit
|
||||||
|
recyclebin:
|
||||||
|
enabled: true
|
||||||
|
#<OPTIONAL> empty_after_x_days var: Will automatically remove all files and folders in recycle bin after x days.
|
||||||
|
# If this variable is not defined it, the RecycleBin will never be emptied.
|
||||||
|
# Setting this variable to 0 will delete files immediately.
|
||||||
|
empty_after_x_days: 60
|
||||||
|
|
||||||
|
# Orphaned files are those in the root_dir download directory that are not referenced by any active torrents.
|
||||||
|
orphaned:
|
||||||
|
# File patterns that will not be considered orphaned files. Handy for generated files that aren't part of the torrent but belong with the torrent's files
|
||||||
|
exclude_patterns:
|
||||||
|
- "**/.DS_Store"
|
||||||
|
- "**/Thumbs.db"
|
||||||
|
- "**/@eaDir"
|
||||||
|
- "/data/torrents/temp/**"
|
89
config/config.yml.sample
Normal file
89
config/config.yml.sample
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
# qBittorrent parameters
|
||||||
|
qbt:
|
||||||
|
host: "localhost:8080"
|
||||||
|
user: "username"
|
||||||
|
pass: "password"
|
||||||
|
|
||||||
|
directory:
|
||||||
|
# Do not remove these
|
||||||
|
# Cross-seed var: </your/path/here/> #Output directory of cross-seed
|
||||||
|
# root_dir var: </your/path/here/> #Root downloads directory used to check for orphaned files, noHL, and RecycleBin.
|
||||||
|
# <OPTIONAL> remote_dir var: </your/path/here/> # Path of docker host mapping of root_dir.
|
||||||
|
# Must be set if you're running qbit_manage locally and qBittorrent/cross_seed is in a docker
|
||||||
|
cross_seed: "/your/path/here/"
|
||||||
|
root_dir: "/data/torrents/"
|
||||||
|
remote_dir: "/mnt/user/data/torrents/"
|
||||||
|
|
||||||
|
# Category/Pathing Parameters
|
||||||
|
cat:
|
||||||
|
# <Category Name> : <save_path> #Path of your save directory. Can be a keyword or full path
|
||||||
|
movies: "/data/torrents/Movies"
|
||||||
|
tv: "TV"
|
||||||
|
|
||||||
|
# Tag Parameters
|
||||||
|
tags:
|
||||||
|
# <Tracker URL Keyword>: <Tag Name>
|
||||||
|
animebytes.tv: AnimeBytes
|
||||||
|
avistaz: Avistaz
|
||||||
|
beyond-hd: Beyond-HD
|
||||||
|
blutopia: Blutopia
|
||||||
|
cartoonchaos: CartoonChaos
|
||||||
|
digitalcore: DigitalCore
|
||||||
|
gazellegames: GGn
|
||||||
|
hdts: HDTorrents
|
||||||
|
landof.tv: BroadcasTheNet
|
||||||
|
myanonamouse: MaM
|
||||||
|
passthepopcorn: PassThePopcorn
|
||||||
|
privatehd: PrivateHD
|
||||||
|
tleechreload: TorrentLeech
|
||||||
|
torrentdb: TorrentDB
|
||||||
|
torrentleech: TorrentLeech
|
||||||
|
tv-vault: TV-Vault
|
||||||
|
|
||||||
|
#Tag Movies/Series that are not hard linked
|
||||||
|
nohardlinks:
|
||||||
|
# Mandatory to fill out directory parameter above to use this function (root_dir/remote_dir)
|
||||||
|
# This variable should be set to your category name of your completed movies/completed series in qbit. Acceptable variable can be any category you would like to tag if there are no hardlinks found
|
||||||
|
movies-completed:
|
||||||
|
#<OPTIONAL> exclude_tags var: Will exclude the following tags when searching through the category.
|
||||||
|
exclude_tags:
|
||||||
|
- Beyond-HD
|
||||||
|
- AnimeBytes
|
||||||
|
- MaM
|
||||||
|
#<OPTIONAL> cleanup var: WARNING!! Setting this as true Will remove and delete contents of any torrents that are in paused state and has the NoHL tag
|
||||||
|
cleanup: false
|
||||||
|
#<OPTIONAL> max_ratio var: Will set the torrent Maximum share ratio until torrent is stopped from seeding/uploading
|
||||||
|
max_ratio: 4.0
|
||||||
|
#<OPTIONAL> seeding time var: Will set the torrent Maximum seeding time (min) until torrent is stopped from seeding
|
||||||
|
max_seeding_time: 86400
|
||||||
|
|
||||||
|
#Can have additional categories set with separate ratio/seeding times defined.
|
||||||
|
series-completed:
|
||||||
|
#<OPTIONAL> exclude_tags var: Will exclude the following tags when searching through the category.
|
||||||
|
exclude_tags:
|
||||||
|
- Beyond-HD
|
||||||
|
- BroadcasTheNet
|
||||||
|
#<OPTIONAL> cleanup var: WARNING!! Setting this as true Will remove and delete contents of any torrents that are in paused state and has the NoHL tag
|
||||||
|
cleanup: false
|
||||||
|
#<OPTIONAL> max_ratio var: Will set the torrent Maximum share ratio until torrent is stopped from seeding/uploading
|
||||||
|
max_ratio: 4.0
|
||||||
|
#<OPTIONAL> seeding time var: Will set the torrent Maximum seeding time (min) until torrent is stopped from seeding
|
||||||
|
max_seeding_time: 86400
|
||||||
|
|
||||||
|
#Recycle Bin method of deletion will move files into the recycle bin (Located in /root_dir/.RecycleBin) instead of directly deleting them in qbit
|
||||||
|
#By default the Recycle Bin will be emptied on every run of the qbit_manage script if empty_after_x_days is defined.
|
||||||
|
recyclebin:
|
||||||
|
enabled: true
|
||||||
|
#<OPTIONAL> empty_after_x_days var: Will automatically remove all files and folders in recycle bin after x days. (Checks every script run)
|
||||||
|
# If this variable is not defined it, the RecycleBin will never be emptied.
|
||||||
|
# WARNING: Setting this variable to 0 will delete all files immediately upon script run!
|
||||||
|
empty_after_x_days: 60
|
||||||
|
|
||||||
|
# Orphaned files are those in the root_dir download directory that are not referenced by any active torrents.
|
||||||
|
orphaned:
|
||||||
|
# File patterns that will not be considered orphaned files. Handy for generated files that aren't part of the torrent but belong with the torrent's files
|
||||||
|
exclude_patterns:
|
||||||
|
- "**/.DS_Store"
|
||||||
|
- "**/Thumbs.db"
|
||||||
|
- "**/@eaDir"
|
||||||
|
- "/data/torrents/temp/**"
|
10
modules/docker.py
Normal file
10
modules/docker.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import signal
|
||||||
|
|
||||||
|
#Gracefully kill script when docker stops
|
||||||
|
class GracefulKiller:
|
||||||
|
kill_now = False
|
||||||
|
def __init__(self):
|
||||||
|
#signal.signal(signal.SIGINT, self.exit_gracefully)
|
||||||
|
signal.signal(signal.SIGTERM, self.exit_gracefully)
|
||||||
|
def exit_gracefully(self, *args):
|
||||||
|
self.kill_now = True
|
95
modules/util.py
Normal file
95
modules/util.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
import logging, traceback
|
||||||
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
|
logger = logging.getLogger("qBit Manage")
|
||||||
|
|
||||||
|
class TimeoutExpired(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Failed(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class NotScheduled(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
separating_character = "="
|
||||||
|
screen_width = 100
|
||||||
|
spacing = 0
|
||||||
|
|
||||||
|
|
||||||
|
def print_multiline(lines, loglevel='INFO'):
|
||||||
|
line_list = str(lines).split("\n")
|
||||||
|
for i, line in enumerate(line_list):
|
||||||
|
if len(line) > 0 and i != len(line_list)-1:
|
||||||
|
logger.log(getattr(logging, loglevel),line)
|
||||||
|
if i == 0:
|
||||||
|
logger.handlers[1].setFormatter(logging.Formatter(" " * 37 + "| %(message)s"))
|
||||||
|
logger.handlers[1].setFormatter(logging.Formatter("[%(asctime)s] %(levelname)-10s | %(message)s"))
|
||||||
|
|
||||||
|
def print_stacktrace():
|
||||||
|
print_multiline(traceback.format_exc())
|
||||||
|
|
||||||
|
def my_except_hook(exctype, value, tb):
|
||||||
|
for line in traceback.format_exception(etype=exctype, value=value, tb=tb):
|
||||||
|
print_multiline(line, critical=True)
|
||||||
|
|
||||||
|
|
||||||
|
def centered(text, sep=" "):
|
||||||
|
if len(text) > screen_width - 2:
|
||||||
|
return text
|
||||||
|
space = screen_width - len(text) - 2
|
||||||
|
text = f" {text} "
|
||||||
|
if space % 2 == 1:
|
||||||
|
text += sep
|
||||||
|
space -= 1
|
||||||
|
side = int(space / 2) - 1
|
||||||
|
final_text = f"{sep * side}{text}{sep * side}"
|
||||||
|
return final_text
|
||||||
|
|
||||||
|
def separator(text=None, space=True, border=True, loglevel='INFO'):
|
||||||
|
sep = " " if space else separating_character
|
||||||
|
for handler in logger.handlers:
|
||||||
|
apply_formatter(handler, border=False)
|
||||||
|
border_text = f"|{separating_character * screen_width}|"
|
||||||
|
if border:
|
||||||
|
logger.log(getattr(logging, loglevel),border_text)
|
||||||
|
if text:
|
||||||
|
text_list = text.split("\n")
|
||||||
|
for t in text_list:
|
||||||
|
logger.log(getattr(logging, loglevel),f"|{sep}{centered(t, sep=sep)}{sep}|")
|
||||||
|
if border:
|
||||||
|
logger.log(getattr(logging, loglevel),border_text)
|
||||||
|
for handler in logger.handlers:
|
||||||
|
apply_formatter(handler)
|
||||||
|
|
||||||
|
def apply_formatter(handler, border=True):
|
||||||
|
text = f"| %(message)-{screen_width - 2}s |" if border else f"%(message)-{screen_width - 2}s"
|
||||||
|
if isinstance(handler, RotatingFileHandler):
|
||||||
|
#text = f"[%(asctime)s] %(filename)-27s %(levelname)-10s {text}"
|
||||||
|
text = f"[%(asctime)s] %(levelname)-10s {text}"
|
||||||
|
handler.setFormatter(logging.Formatter(text))
|
||||||
|
|
||||||
|
def adjust_space(display_title):
|
||||||
|
display_title = str(display_title)
|
||||||
|
space_length = spacing - len(display_title)
|
||||||
|
if space_length > 0:
|
||||||
|
display_title += " " * space_length
|
||||||
|
return display_title
|
||||||
|
|
||||||
|
def insert_space(display_title,space_length=0):
|
||||||
|
display_title = str(display_title)
|
||||||
|
if space_length == 0:
|
||||||
|
space_length = spacing - len(display_title)
|
||||||
|
if space_length > 0:
|
||||||
|
display_title = " " * space_length + display_title
|
||||||
|
return display_title
|
||||||
|
|
||||||
|
def print_return(text):
|
||||||
|
print(adjust_space(f"| {text}"), end="\r")
|
||||||
|
global spacing
|
||||||
|
spacing = len(text) + 2
|
||||||
|
|
||||||
|
def print_end():
|
||||||
|
print(adjust_space(" "), end="\r")
|
||||||
|
global spacing
|
||||||
|
spacing = 0
|
769
qbit_manage.py
769
qbit_manage.py
File diff suppressed because it is too large
Load diff
|
@ -1,2 +1,3 @@
|
||||||
PyYAML
|
PyYAML
|
||||||
qbittorrent-api
|
qbittorrent-api
|
||||||
|
schedule
|
Loading…
Add table
Reference in a new issue