├── .dockerignore ├── .github ├── FUNDING.yml ├── stale.yml └── workflows │ └── build_images.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── premiumizer ├── DownloadTask.py ├── __init__.py ├── docker-entrypoint.sh ├── premiumizer.py ├── settings.cfg.tpl ├── static │ ├── css │ │ └── style.css │ ├── img │ │ └── favicon.ico │ └── js │ │ └── control.js ├── templates │ ├── 404.html │ ├── about.html │ ├── base.html │ ├── history.html │ ├── index.html │ ├── log.html │ ├── login.html │ └── settings.html └── utils.py └── requirements.txt /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.git 2 | **/.gitignore 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: pieterjanssens13976 2 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: > 18 | Feel free to reopen if the issue persists on the latest version. -------------------------------------------------------------------------------- /.github/workflows/build_images.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'build images' 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | docker: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | 16 | - name: Prepare 17 | id: prep 18 | run: | 19 | DOCKER_IMAGE=${{ secrets.DOCKER_USERNAME }}/${GITHUB_REPOSITORY#*/} 20 | VERSION=latest 21 | SHORTREF=${GITHUB_SHA::8} 22 | 23 | # If this is git tag, use the tag name as a docker tag 24 | if [[ $GITHUB_REF == refs/tags/* ]]; then 25 | VERSION=${GITHUB_REF#refs/tags/v} 26 | fi 27 | TAGS="${DOCKER_IMAGE}:${VERSION},${DOCKER_IMAGE}:${SHORTREF}" 28 | 29 | # If the VERSION looks like a version number, assume that 30 | # this is the most recent version of the image and also 31 | # tag it 'latest'. 32 | if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then 33 | TAGS="$TAGS,${DOCKER_IMAGE}:latest" 34 | fi 35 | 36 | # Set output parameters. 37 | echo ::set-output name=tags::${TAGS} 38 | echo ::set-output name=docker_image::${DOCKER_IMAGE} 39 | 40 | - name: Set up QEMU 41 | uses: docker/setup-qemu-action@master 42 | with: 43 | platforms: all 44 | 45 | - name: Set up Docker Buildx 46 | id: buildx 47 | uses: docker/setup-buildx-action@master 48 | 49 | - name: Login to DockerHub 50 | if: github.event_name != 'pull_request' 51 | uses: docker/login-action@v1 52 | with: 53 | username: ${{ secrets.DOCKER_USERNAME }} 54 | password: ${{ secrets.DOCKER_PASSWORD }} 55 | 56 | - name: Build 57 | uses: docker/build-push-action@v2 58 | with: 59 | builder: ${{ steps.buildx.outputs.name }} 60 | context: . 61 | file: ./Dockerfile 62 | platforms: linux/amd64,linux/arm64 63 | push: true 64 | tags: ${{ steps.prep.outputs.tags }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Premiumizer Specific 2 | conf/ 3 | 4 | .vscode/ 5 | 6 | **.DS_Store 7 | 8 | #PyCharm 9 | .idea/ 10 | 11 | # Byte-compiled / optimized / DLL files 12 | __pycache__/ 13 | *.py[cod] 14 | 15 | # C extensions 16 | *.so 17 | 18 | # Distribution / packaging 19 | .Python 20 | nzbtomedia/ 21 | env/ 22 | build/ 23 | develop-eggs/ 24 | dist/ 25 | downloads/ 26 | eggs/ 27 | .eggs/ 28 | #lib/ 29 | lib64/ 30 | parts/ 31 | sdist/ 32 | var/ 33 | *.egg-info/ 34 | .installed.cfg 35 | *.egg 36 | 37 | # PyInstaller 38 | # Usually these files are written by a python script from a template 39 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 40 | *.manifest 41 | *.spec 42 | 43 | # PIP 44 | pip-log.txt 45 | pip-delete-this-directory.txt 46 | virtualenv/ 47 | 48 | # Unit test / coverage reports 49 | htmlcov/ 50 | .tox/ 51 | .coverage 52 | .coverage.* 53 | .cache 54 | nosetests.xml 55 | coverage.xml 56 | *,cover 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3-alpine 2 | 3 | WORKDIR /app 4 | COPY requirements.txt requirements.txt 5 | COPY premiumizer . 6 | 7 | RUN apk add --update --no-cache libffi-dev openssl-dev build-base su-exec shadow 8 | 9 | RUN pip install --no-cache-dir -r requirements.txt 10 | 11 | RUN addgroup -S -g 6006 premiumizer 12 | RUN adduser -S -D -u 6006 -G premiumizer -s /bin/sh premiumizer 13 | 14 | VOLUME /conf 15 | EXPOSE 5000 16 | 17 | ENTRYPOINT ["/bin/sh","docker-entrypoint.sh"] 18 | CMD ["/usr/local/bin/python", "premiumizer.py"] 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Pieter Janssens 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Premiumizer 2 | 3 | ![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/piejanssens/premiumizer) ![GitHub contributors](https://img.shields.io/github/contributors/piejanssens/premiumizer) 4 | 5 | Premiumizer is a download management tool for premiumize.me cloud downloads, which allows automatic downloading to your personal computer/server. 6 | 7 | - Web interface to manage premiumize.me downloads: cloud Torrent & Nzb and Filehosts links 8 | - Category based automatic downloader of finished cloud tasks to local file system 9 | - Picks up new taks through black hole 10 | - Integrates with nzbToMedia (post processing) 11 | 12 | Enjoying it so far? Great! If you want to show your appreciation, feel free to: 13 | 14 | 15 | 16 | ## About premiumize.me 17 | 18 | Premiumize.me combines anonymous cloud torrent downloads, usenet and premium hosters in one subscription. Cloud torrent downloads are cached, meaning if some other premiumize.me member downloaded the torrent through premiumize.me before, you can immediately download the files from that torrent over HTTPS at top speeds. 19 | 20 | Get your account [right here](https://www.premiumize.me/ref/198754075). 21 | 22 | ## How does it work? 23 | 24 | Premiumizer will monitor download tasks on premiumize.me. 25 | Once the download in the cloud finishes and the download task has a category that needs to be automatically downloaded premiumizer will start downloading all the files to your local computer where premiumizer is running. Download tasks without a category will not be automatically downloaded locally. Categories can be setup through the web interface's setup page. 26 | 27 | When enabled, premiumizer can inform nzbToMedia whenever the local download is finished. 28 | 29 | ## Web Interface 30 | 31 | By default, premiumizer's web interface listens on port 5000. 32 | When premiumizer is running you can access it at http://localhost:5000/ 33 | 34 | ## Installation using Docker 35 | 36 | We have provide images for `amd64` & `arm64v8`. If you have a different architecture, you can build this yourself using our Dockerfile. 37 | 38 | You need to set the correct PUID and PGID equal to the user that has rw access to the mounted volumes. 39 | 40 | ```shell 41 | docker run \ 42 | --name premiumizer \ 43 | -e PUID=1000 \ 44 | -e PGID=1000 \ 45 | -e TZ=Europe/London \ 46 | -p 5000:5000 \ 47 | -v /path/to/conf:/conf \ 48 | -v /path/to/blackhole:/blackhole \ 49 | -v /path/to/downloads:/downloads \ 50 | --restart unless-stopped \ 51 | piejanssens/premiumizer 52 | ``` 53 | 54 | ### Synology DSM 55 | 56 | 1. Create a folder using File Station where Premiumizer can store its config and logs (e.g. /volume1/docker/premiumizer) 57 | 2. Identify (or create) the locations for blackhole and downloads that Premiumizer will use 58 | 3. SSH into your syno and figure out the PUID and PGID of the user that has access to these folders 59 | 4. Open Docker app 60 | 5. Under 'Registry': Download the piejanssens/premiumizer image 61 | 6. Under 'Image': Select the image and click 'launch' 62 | 7. Map a port of your chosing to '5000' (e.g. Chosing 5555 to 5000, means your Premiumizer will be accessible through 5555) 63 | 8. Map your blackhole folder to '/blackhole' 64 | 9. Map your downloads folder to '/downloads' 65 | 10. Map your premiumizer conf folder to '/conf' 66 | 11. Set the following environment variables: 67 | 68 | - PUID (see step 3.) 69 | - PGID (see step 3.) 70 | - TZ (e.g. Europe/London) 71 | 72 | #### Updating images on Synology 73 | 74 | 1. Stop the container 75 | 2. Right click the container: Action -> Clear/Rest 76 | 3. Under 'Registry': Download the piejanssens/premiumizer image (this will pull in the latest image) 77 | 4. Start the container 78 | 79 | ## Windows Installer 80 | 81 | [PremiumizerInstaller](https://github.com/neox387/PremiumizerInstaller/releases) 82 | 83 | Open services.msc & edit Premiumizer service to logon using your account that is an administrator. 84 | 85 | ## Manual Installation 86 | 87 | Required: Git & Python 3 (with pip) 88 | 89 | ### Windows 90 | 91 | ```shell 92 | git clone https://github.com/piejanssens/premiumizer.git C:\Premiumizer 93 | python -m pip install --upgrade pip 94 | python -m pip install -pywin32 95 | python -m pip install -r c:\Premiumizer\requirements.txt 96 | python C:\Premiumizer\premiumizer\premiumizer.py 97 | ``` 98 | 99 | ### Unix / macOS 100 | 101 | ```shell 102 | $ brew install python3 103 | $ git clone https://github.com/piejanssens/premiumizer.git premiumizer 104 | $ cd premiumizer 105 | $ pip install -r requirements.txt 106 | $ python premiumizer/premiumizer.py 107 | ``` 108 | 109 | ## Updating 110 | 111 | Update from the settings page / enable automatic updates 112 | Update button & changes will be displayed when an update is available. 113 | 114 | ## Settings 115 | 116 | Once you can access the premiumizer web interface make sure you head over to the settings page. 117 | 118 | ## Development 119 | 120 | Want to contribute? Great! 121 | Just fork the github repo, do some awesome stuff and create a pull request. 122 | 123 | Report issues or feature enhancements/requests on the [Issues](https://github.com/piejanssens/premiumizer/issues) page 124 | -------------------------------------------------------------------------------- /premiumizer/DownloadTask.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | class DownloadTask: 5 | def __init__(self, callback, id, folder_id, size, name, category, dldir, dlext, dlext_blacklist, delsample, dlnzbtomedia, type): 6 | self.progress = None 7 | self.speed = None 8 | self.size = size 9 | self.id = id 10 | self.folder_id = folder_id 11 | self.file_id = None 12 | self.name = name 13 | self.category = category 14 | self.timestamp = int(time.time()) 15 | self.previous_timestamp = None 16 | self.speed = None 17 | self.cloud_status = None 18 | self.cloud_ratio = None 19 | self.local_status = None 20 | self.eta = None 21 | self.callback = callback 22 | self.dldir = dldir 23 | self.dlext = dlext 24 | self.dlext_blacklist = dlext_blacklist 25 | self.delsample = delsample 26 | self.dlnzbtomedia = dlnzbtomedia 27 | self.dltime = 0 28 | self.dlsize = '' 29 | self.type = type 30 | self.download_list = [] 31 | 32 | def update(self, **kwargs): 33 | self.previous_timestamp = self.timestamp 34 | self.timestamp = int(time.time()) 35 | if 'progress' in kwargs: 36 | self.progress = kwargs.get('progress') 37 | if 'cloud_status' in kwargs: 38 | self.cloud_status = kwargs.get('cloud_status') 39 | if 'local_status' in kwargs: 40 | self.local_status = kwargs.get('local_status') 41 | if 'name' in kwargs: 42 | self.name = kwargs.get('name') 43 | if 'size' in kwargs: 44 | self.size = kwargs.get('size') 45 | if self.cloud_status == "finished" and not self.local_status: 46 | self.progress = 100 47 | if 'speed' in kwargs: 48 | self.speed = kwargs.get('speed') 49 | if 'eta' in kwargs: 50 | self.eta = kwargs.get('eta') 51 | if 'category' in kwargs: 52 | self.category = kwargs.get('category') 53 | if 'dldir' in kwargs: 54 | self.dldir = kwargs.get('dldir') 55 | if 'dlext' in kwargs: 56 | self.dlext = kwargs.get('dlext') 57 | if 'dlext_blacklist' in kwargs: 58 | self.dlext_blacklist = kwargs.get('dlext_blacklist') 59 | if 'delsample' in kwargs: 60 | self.delsample = kwargs.get('delsample') 61 | if 'dlnzbtomedia' in kwargs: 62 | self.dlnzbtomedia = kwargs.get('dlnzbtomedia') 63 | if 'dltime' in kwargs: 64 | self.dltime = kwargs.get('dltime') 65 | if 'dlsize' in kwargs: 66 | self.dlsize = kwargs.get('dlsize') 67 | if 'type' in kwargs: 68 | self.type = kwargs.get('type') 69 | if 'id' in kwargs: 70 | self.id = kwargs.get('id') 71 | if 'folder_id' in kwargs: 72 | self.folder_id = kwargs.get('folder_id') 73 | if 'file_id' in kwargs: 74 | self.file_id = kwargs.get('file_id') 75 | if 'download_list' in kwargs: 76 | self.download_list = kwargs.get('download_list') 77 | self.callback('update_task', {'task': self.get_json()}) 78 | 79 | def get_json(self): 80 | return {'progress': self.progress, 'speed': self.speed, 'dlsize': self.dlsize, 'eta': self.eta, 'id': self.id, 81 | 'folder_id': self.folder_id, 'file_id': self.file_id, 'name': self.name, 'type': self.type, 82 | 'cloud_status': self.cloud_status, 'local_status': self.local_status, 'category': self.category} 83 | -------------------------------------------------------------------------------- /premiumizer/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piejanssens/premiumizer/83982c7b686cc0f69080af1f8cb59ef989e039bf/premiumizer/__init__.py -------------------------------------------------------------------------------- /premiumizer/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | PUID=${PUID:-6006} 4 | PGID=${PGID:-6006} 5 | 6 | groupmod -o -g "$PGID" premiumizer || true 7 | usermod -o -u "$PUID" premiumizer || true 8 | 9 | chown -R premiumizer:premiumizer /conf || true 10 | 11 | # Allow write access on downloaded files to group and others 12 | umask 0000 13 | 14 | exec su-exec premiumizer "$@" 15 | -------------------------------------------------------------------------------- /premiumizer/settings.cfg.tpl: -------------------------------------------------------------------------------- 1 | [global] 2 | server_port = 5000 3 | bind_ip = 0.0.0.0 4 | reverse_proxy_path = 5 | custom_domain = 6 | active_interval = 3 7 | idle_interval = 300 8 | debug_enabled = 0 9 | 10 | [security] 11 | login_enabled = 0 12 | username = 13 | password = 14 | 15 | [premiumize] 16 | apikey = 17 | 18 | [downloads] 19 | time_shed = 0 20 | time_shed_start = 00:00 21 | time_shed_stop = 06:00 22 | download_enabled = 0 23 | download_all = 0 24 | download_rss = 0 25 | download_max = 1 26 | download_threads = 1 27 | download_speed = -1 28 | remove_cloud = 0 29 | remove_cloud_delay = 0 30 | seed_torrent = 0 31 | download_location = 32 | nzbtomedia_location = [Change to path]\nzbToMedia.py 33 | jd_enabled = 0 34 | jd_username = 35 | jd_password = 36 | jd_device_name = 37 | aria2_enabled = 0 38 | aria2_host = localhost 39 | aria2_port = 6800 40 | aria2_secret = premiumizer 41 | 42 | [categories] 43 | cat_name[1] = tv 44 | cat_dir[1] = 45 | cat_ext[1] = 46 | cat_ext_blacklist[1] = 0 47 | cat_delsample[1] = 0 48 | cat_nzbtomedia[1] = 0 49 | cat_name[2] = movie 50 | cat_dir[2] = 51 | cat_ext[2] = 52 | cat_ext_blacklist[2] = 0 53 | cat_delsample[2] = 0 54 | cat_nzbtomedia[2] = 0 55 | cat_name[3] = 56 | cat_dir[3] = 57 | cat_ext[3] = 58 | cat_ext_blacklist[3] = 0 59 | cat_delsample[3] = 0 60 | cat_nzbtomedia[3] = 0 61 | cat_name[4] = 62 | cat_dir[4] = 63 | cat_ext[4] = 64 | cat_ext_blacklist[4] = 0 65 | cat_delsample[4] = 0 66 | cat_nzbtomedia[4] = 0 67 | cat_name[5] = 68 | cat_dir[5] = 69 | cat_ext[5] = 70 | cat_ext_blacklist[5] = 0 71 | cat_delsample[5] = 0 72 | cat_nzbtomedia[5] = 0 73 | cat_name[6] = default 74 | cat_dir[6] = 75 | cat_ext[6] = 76 | cat_ext_blacklist[6] = 0 77 | cat_delsample[6] = 0 78 | cat_nzbtomedia[6] = 0 79 | 80 | [upload] 81 | watchdir_enabled = 0 82 | watchdir_location = 83 | watchdir_walk_enabled = 0 84 | watchdir_walk_interval = 60 85 | 86 | [notifications] 87 | email_enabled = 0 88 | email_on_failure = 0 89 | email_from = 90 | email_to = 91 | email_server = 92 | email_port = 93 | email_encryption = 0 94 | email_username = 95 | email_password = 96 | apprise_enabled = 0 97 | apprise_push_on_failure = 0 98 | apprise_url = 99 | 100 | [update] 101 | #Do not change these values# 102 | updated = 1 103 | auto_update = 0 104 | update_date = Never 105 | config_version = 2.9 106 | req_version = 11.0 -------------------------------------------------------------------------------- /premiumizer/static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 70px; 3 | } 4 | 5 | .pointer { 6 | cursor: pointer; 7 | } 8 | 9 | .center-block { 10 | float: none; 11 | margin-left: auto; 12 | margin-right: auto; 13 | } 14 | 15 | .input-group .icon-addon .form-control { 16 | border-radius: 0; 17 | } 18 | 19 | .icon-addon { 20 | position: relative; 21 | color: #555; 22 | display: block; 23 | } 24 | 25 | .icon-addon:after, 26 | .icon-addon:before { 27 | display: table; 28 | content: " "; 29 | } 30 | 31 | .icon-addon:after { 32 | clear: both; 33 | } 34 | 35 | .icon-addon.addon-md .glyphicon, 36 | .icon-addon .glyphicon, 37 | .icon-addon.addon-md .fa, 38 | .icon-addon .fa { 39 | position: absolute; 40 | z-index: 2; 41 | left: 10px; 42 | font-size: 14px; 43 | width: 20px; 44 | margin-left: -2.5px; 45 | text-align: center; 46 | padding: 10px 0; 47 | top: 1px 48 | } 49 | 50 | .icon-addon.addon-lg .form-control { 51 | line-height: 1.33; 52 | height: 46px; 53 | font-size: 18px; 54 | padding: 10px 16px 10px 40px; 55 | } 56 | 57 | .icon-addon.addon-sm .form-control { 58 | height: 30px; 59 | padding: 5px 10px 5px 28px; 60 | font-size: 12px; 61 | line-height: 1.5; 62 | } 63 | 64 | .icon-addon.addon-lg .fa, 65 | .icon-addon.addon-lg .glyphicon { 66 | font-size: 18px; 67 | margin-left: 0; 68 | left: 11px; 69 | top: 4px; 70 | } 71 | 72 | .icon-addon.addon-md .form-control, 73 | .icon-addon .form-control { 74 | padding-left: 30px; 75 | float: left; 76 | font-weight: normal; 77 | } 78 | 79 | .icon-addon.addon-sm .fa, 80 | .icon-addon.addon-sm .glyphicon { 81 | margin-left: 0; 82 | font-size: 12px; 83 | left: 5px; 84 | top: -1px 85 | } 86 | 87 | .icon-addon .form-control:focus + .glyphicon, 88 | .icon-addon:hover .glyphicon, 89 | .icon-addon .form-control:focus + .fa, 90 | .icon-addon:hover .fa { 91 | color: #2580db; 92 | } 93 | 94 | .table tbody > tr > td.vert-align { 95 | vertical-align: middle; 96 | } 97 | 98 | .table tbody > tr > td.taskname { 99 | word-wrap: break-word; 100 | word-break: break-all; 101 | white-space: normal; 102 | } 103 | 104 | .bootstrap-switch-container { 105 | white-space: nowrap; 106 | } 107 | 108 | .panel-body { 109 | padding-left: 30px; 110 | padding-right: 30px; 111 | padding-top: 10px; 112 | padding-bottom: 10px; 113 | } 114 | 115 | .dropdown-menu { 116 | position: relative; 117 | } 118 | 119 | h4 { 120 | word-wrap: break-word; 121 | } 122 | 123 | .col:not(:first-child), .col:not(:last-child) { 124 | padding-right: 7px; 125 | padding-left: 7px; 126 | } 127 | 128 | .padding-xs { 129 | padding: .25em; 130 | } 131 | 132 | .padding-sm { 133 | padding: .5em; 134 | } 135 | 136 | .padding-md { 137 | padding: 1em; 138 | } 139 | 140 | .padding-lg { 141 | padding: 1.5em; 142 | } 143 | 144 | .padding-xl { 145 | padding: 3em; 146 | } 147 | 148 | .padding-x-xs { 149 | padding: .25em 0; 150 | } 151 | 152 | .padding-x-sm { 153 | padding: .5em 0; 154 | } 155 | 156 | .padding-x-md { 157 | padding: 1em 0; 158 | } 159 | 160 | .padding-x-lg { 161 | padding: 1.5em 0; 162 | } 163 | 164 | .padding-x-xl { 165 | padding: 3em 0; 166 | } 167 | 168 | .padding-y-xs { 169 | padding: 0 .25em; 170 | } 171 | 172 | .padding-y-sm { 173 | padding: 0 .5em; 174 | } 175 | 176 | .padding-y-md { 177 | padding: 0 1em; 178 | } 179 | 180 | .padding-y-lg { 181 | padding: 0 1.5em; 182 | } 183 | 184 | .padding-y-xl { 185 | padding: 0 3em; 186 | } 187 | 188 | .padding-top-xs { 189 | padding-top: .25em; 190 | } 191 | 192 | .padding-top-sm { 193 | padding-top: .5em; 194 | } 195 | 196 | .padding-top-md { 197 | padding-top: 1em; 198 | } 199 | 200 | .padding-top-lg { 201 | padding-top: 1.5em; 202 | } 203 | 204 | .padding-top-xl { 205 | padding-top: 3em; 206 | } 207 | 208 | .padding-right-xs { 209 | padding-right: .25em; 210 | } 211 | 212 | .padding-right-sm { 213 | padding-right: .5em; 214 | } 215 | 216 | .padding-right-md { 217 | padding-right: 1em; 218 | } 219 | 220 | .padding-right-lg { 221 | padding-right: 1.5em; 222 | } 223 | 224 | .padding-right-xl { 225 | padding-right: 3em; 226 | } 227 | 228 | .padding-bottom-xs { 229 | padding-bottom: .25em; 230 | } 231 | 232 | .padding-bottom-sm { 233 | padding-bottom: .5em; 234 | } 235 | 236 | .padding-bottom-md { 237 | padding-bottom: 1em; 238 | } 239 | 240 | .padding-bottom-lg { 241 | padding-bottom: 1.5em; 242 | } 243 | 244 | .padding-bottom-xl { 245 | padding-bottom: 3em; 246 | } 247 | 248 | .padding-left-xs { 249 | padding-left: .25em; 250 | } 251 | 252 | .padding-left-sm { 253 | padding-left: .5em; 254 | } 255 | 256 | .padding-left-md { 257 | padding-left: 1em; 258 | } 259 | 260 | .padding-left-lg { 261 | padding-left: 1.5em; 262 | } 263 | 264 | .padding-left-xl { 265 | padding-left: 3em; 266 | } 267 | 268 | .margin-xs { 269 | margin: .25em; 270 | } 271 | 272 | .margin-sm { 273 | margin: .5em; 274 | } 275 | 276 | .margin-md { 277 | margin: 1em; 278 | } 279 | 280 | .margin-lg { 281 | margin: 1.5em; 282 | } 283 | 284 | .margin-xl { 285 | margin: 3em; 286 | } 287 | 288 | .margin-x-xs { 289 | margin: .25em 0; 290 | } 291 | 292 | .margin-x-sm { 293 | margin: .5em 0; 294 | } 295 | 296 | .margin-x-md { 297 | margin: 1em 0; 298 | } 299 | 300 | .margin-x-lg { 301 | margin: 1.5em 0; 302 | } 303 | 304 | .margin-x-xl { 305 | margin: 3em 0; 306 | } 307 | 308 | .margin-y-xs { 309 | margin: 0 .25em; 310 | } 311 | 312 | .margin-y-sm { 313 | margin: 0 .5em; 314 | } 315 | 316 | .margin-y-md { 317 | margin: 0 1em; 318 | } 319 | 320 | .margin-y-lg { 321 | margin: 0 1.5em; 322 | } 323 | 324 | .margin-y-xl { 325 | margin: 0 3em; 326 | } 327 | 328 | .margin-top-xs { 329 | margin-top: .25em; 330 | } 331 | 332 | .margin-top-sm { 333 | margin-top: .5em; 334 | } 335 | 336 | .margin-top-md { 337 | margin-top: 1em; 338 | } 339 | 340 | .margin-top-lg { 341 | margin-top: 1.5em; 342 | } 343 | 344 | .margin-top-xl { 345 | margin-top: 3em; 346 | } 347 | 348 | .margin-right-xs { 349 | margin-right: .25em; 350 | } 351 | 352 | .margin-right-sm { 353 | margin-right: .5em; 354 | } 355 | 356 | .margin-right-md { 357 | margin-right: 1em; 358 | } 359 | 360 | .margin-right-lg { 361 | margin-right: 1.5em; 362 | } 363 | 364 | .margin-right-xl { 365 | margin-right: 3em; 366 | } 367 | 368 | .margin-bottom-xs { 369 | margin-bottom: .25em; 370 | } 371 | 372 | .margin-bottom-sm { 373 | margin-bottom: .5em; 374 | } 375 | 376 | .margin-bottom-md { 377 | margin-bottom: 1em; 378 | } 379 | 380 | .margin-bottom-lg { 381 | margin-bottom: 1.5em; 382 | } 383 | 384 | .margin-bottom-xl { 385 | margin-bottom: 3em; 386 | } 387 | 388 | .margin-left-xs { 389 | margin-left: .25em; 390 | } 391 | 392 | .margin-left-sm { 393 | margin-left: .5em; 394 | } 395 | 396 | .margin-left-md { 397 | margin-left: 1em; 398 | } 399 | 400 | .margin-left-lg { 401 | margin-left: 1.5em; 402 | } 403 | 404 | .margin-left-xl { 405 | margin-left: 3em; 406 | } 407 | -------------------------------------------------------------------------------- /premiumizer/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piejanssens/premiumizer/83982c7b686cc0f69080af1f8cb59ef989e039bf/premiumizer/static/img/favicon.ico -------------------------------------------------------------------------------- /premiumizer/static/js/control.js: -------------------------------------------------------------------------------- 1 | var socket; 2 | var loaded_tasks = false; 3 | var download_categories = []; 4 | 5 | function start_loading_upload() { 6 | $("#loading_upload").attr('style', 'display: inline'); 7 | } 8 | 9 | function stop_loading_upload() { 10 | $("#loading_upload").attr('style', 'display: none'); 11 | $('#magnet-input').val(''); 12 | } 13 | 14 | function stop_loading_download_tasks() { 15 | $("#loading_download_tasks").attr('style', 'display: none'); 16 | } 17 | 18 | function show_no_downloads() { 19 | $("#no_downloads").attr('style', 'display: inline'); 20 | } 21 | 22 | function hide_no_downloads() { 23 | $("#no_downloads").attr('style', 'display: none'); 24 | } 25 | 26 | function show_premiumize_connect_error() { 27 | $('#premiumize_connect_error').attr('style', 'display: inline'); 28 | $('#main_container').attr('style', 'display: none'); 29 | } 30 | 31 | function category_selected(id, category) { 32 | socket.emit('change_category', { 33 | data: { 34 | id: id, 35 | category: category 36 | } 37 | }); 38 | } 39 | 40 | function update_task(task) { 41 | var stateColor; 42 | var stateIcon; 43 | var stateStr; 44 | var categoryState; 45 | if (task.cloud_status == 'running') { 46 | stateColor = 'info'; 47 | stateStr = 'Downloading'; 48 | stateIcon = 'cloud-download'; 49 | categoryState = ''; 50 | } else if (task.cloud_status == 'waiting') { 51 | stateColor = 'warning'; 52 | stateStr = 'Downloading'; 53 | stateIcon = 'cloud'; 54 | categoryState = ''; 55 | } else if (task.cloud_status == 'queued') { 56 | stateColor = 'warning'; 57 | stateStr = 'Download queued'; 58 | stateIcon = 'cloud-upload'; 59 | categoryState = ''; 60 | } else if (task.cloud_status == 'finished' && task.local_status == null) { 61 | stateColor = 'success'; 62 | stateStr = 'Finished'; 63 | stateIcon = 'cloud'; 64 | categoryState = ''; 65 | } else if (task.cloud_status == 'seeding' && task.local_status == null) { 66 | stateColor = 'success'; 67 | stateStr = 'Seeding'; 68 | stateIcon = 'cloud'; 69 | categoryState = ''; 70 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'queued') { 71 | stateColor = 'primary'; 72 | stateStr = 'Download Queue'; 73 | stateIcon = 'desktop'; 74 | categoryState = ''; 75 | } else if (task.cloud_status == 'finished' && task.local_status == 'waiting') { 76 | stateColor = 'info'; 77 | stateStr = 'Waiting on category'; 78 | stateIcon = 'desktop'; 79 | categoryState = ''; 80 | } else if (task.cloud_status == 'seeding' && task.local_status == 'waiting') { 81 | stateColor = 'info'; 82 | stateStr = 'Waiting on category / Seeding'; 83 | stateIcon = 'desktop'; 84 | categoryState = ''; 85 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'download_disabled') { 86 | stateColor = 'info'; 87 | stateStr = 'Downloads are disabled'; 88 | stateIcon = 'desktop'; 89 | categoryState = ''; 90 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'paused') { 91 | stateColor = 'warning'; 92 | stateStr = 'Download paused'; 93 | stateIcon = 'desktop'; 94 | categoryState = ''; 95 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'downloading') { 96 | stateColor = 'primary'; 97 | stateStr = 'Downloading'; 98 | stateIcon = 'desktop'; 99 | categoryState = ''; 100 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'finished') { 101 | stateColor = 'success'; 102 | stateStr = 'Finished'; 103 | stateIcon = 'desktop'; 104 | categoryState = ''; 105 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'finished_waiting') { 106 | stateColor = 'success'; 107 | stateStr = 'Waiting to delete'; 108 | stateIcon = 'desktop'; 109 | categoryState = ''; 110 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'finished_seeding') { 111 | stateColor = 'success'; 112 | stateStr = 'Waiting to delete / Seeding'; 113 | stateIcon = 'desktop'; 114 | categoryState = ''; 115 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'stopped') { 116 | stateColor = 'warning'; 117 | stateStr = 'Download stopped'; 118 | stateIcon = 'desktop'; 119 | categoryState = ''; 120 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'failed: download retrying') { 121 | stateColor = 'warning'; 122 | stateStr = 'Failed: download retrying soon'; 123 | stateIcon = 'desktop'; 124 | categoryState = ''; 125 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'failed: download') { 126 | stateColor = 'danger'; 127 | stateStr = 'Failed: download'; 128 | stateIcon = 'desktop'; 129 | categoryState = ''; 130 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'failed: nzbToMedia') { 131 | stateColor = 'danger'; 132 | stateStr = 'Failed: nzbToMedia'; 133 | stateIcon = 'desktop'; 134 | categoryState = ''; 135 | } else if ((task.cloud_status == 'finished' || task.cloud_status == 'seeding') && task.local_status == 'failed: Filehost') { 136 | stateColor = 'danger'; 137 | stateStr = 'Failed: Filehost'; 138 | stateIcon = 'desktop'; 139 | categoryState = ''; 140 | } else if (task.cloud_status == 'error') { 141 | stateColor = 'danger'; 142 | stateStr = 'Cloud: Error'; 143 | stateIcon = 'cloud-download'; 144 | categoryState = ''; 145 | } else { 146 | stateColor = 'danger'; 147 | stateStr = 'check js console'; 148 | stateIcon = 'exclamation-triangle'; 149 | console.log('UNKNOWN STATUS - cloud: ' + task.cloud_status + ', local: ' + task.local_status); 150 | } 151 | 152 | var update = false; 153 | if ($("#" + task.id).length > 0) { 154 | update = true; 155 | } 156 | 157 | var dropDown = ''; 163 | 164 | var htmlString = '
' + 165 | '

' + task.name.substring(0, 100) + '

' + 166 | '
' + 167 | '' 168 | + (task.cloud_status == "finished" ? (!task.file_id ? '' : "") 169 | + (task.file_id ? '' : "") : "") 170 | + (task.local_status == "downloading" || (task.local_status == 'paused') ? '' : "") 171 | + (task.local_status == "downloading" ? '' : "") 172 | + (task.local_status == "paused" ? '' : "") + 173 | '
' + 174 | '
' + 175 | '
' + 176 | '
' + 177 | '
' + 178 | '
' + 179 | '
' + stateStr + '
' + 180 | '
' + task.type + '
' + 181 | '
' + 182 | '
' + 183 | '
' + (task.progress != 100 ? "Speed: " + task.speed + "Size: " + task.dlsize + " ETA: " + task.eta : 'Inactive') + '
' + 184 | '
' + task.progress + '% ' + '
' + 185 | '
' + 186 | '
' + 187 | '
 
' + 188 | '
' + dropDown + '
' + 189 | '
' + 190 | '
' + 191 | '
' + 192 | '
'; 193 | 194 | if (update) { 195 | $("#" + task.id).replaceWith(htmlString); 196 | } else { 197 | $("#download_section").prepend(htmlString); 198 | } 199 | } 200 | 201 | 202 | +function ($) { 203 | 'use strict'; 204 | var originalFilePlaceHolder; 205 | var originalFileLabelClass; 206 | 207 | var uploadFile = function (file) { 208 | start_loading_upload(); 209 | var data = new FormData(); 210 | data.append('file', file); 211 | $.ajax({ 212 | type: "POST", 213 | url: 'upload', 214 | data: data, 215 | processData: false, 216 | contentType: false, 217 | cache: false, 218 | success: function (data, textStatus, jqXHR) { 219 | //data - response from server 220 | console.log('done'); 221 | stop_loading_upload(); 222 | }, 223 | error: function (jqXHR, textStatus, errorThrown) { 224 | console.log(errorThrown); 225 | stop_loading_upload(); 226 | } 227 | }); 228 | }; 229 | 230 | var uploadMagnet = function (magnet) { 231 | console.log(magnet); 232 | $.ajax({ 233 | type: "POST", 234 | url: 'upload', 235 | data: magnet, 236 | contentType: 'text/plain', 237 | success: function (data, textStatus, jqXHR) { 238 | //data - response from server 239 | console.log('done'); 240 | $('#magnet-input').val(''); 241 | }, 242 | error: function (jqXHR, textStatus, errorThrown) { 243 | console.log(errorThrown); 244 | $('#magnet-input').val(''); 245 | } 246 | }); 247 | }; 248 | 249 | var uploadFilehostUrls = function (filehosturls) { 250 | console.log(filehosturls); 251 | $.ajax({ 252 | type: "POST", 253 | url: 'upload', 254 | data: filehosturls, 255 | contentType: 'text/plain', 256 | success: function (data, textStatus, jqXHR) { 257 | //data - response from server 258 | console.log('done'); 259 | $('#filehost_urls').val(''); 260 | }, 261 | error: function (jqXHR, textStatus, errorThrown) { 262 | console.log(errorThrown); 263 | $('#filehost_urls').val(''); 264 | } 265 | }); 266 | }; 267 | 268 | $('#filehost_urls').on('click', function () { 269 | var element = document.getElementsByClassName("form-control custom-control"); 270 | setTimeout(function () { 271 | var urls = $(element).val(); 272 | uploadFilehostUrls(urls); 273 | }, 100); 274 | }); 275 | 276 | $('#file-file-upload').on('change', function (e) { 277 | e.preventDefault(); 278 | var files = $(this).prop('files'); 279 | if (files.length > 0) { 280 | var file = files[0]; 281 | var fileName = file.name; 282 | var fileExt = '.' + fileName.split('.').pop(); 283 | if (fileExt == '.torrent' || fileExt == '.nzb' || fileExt == '.magnet') { 284 | uploadFile(file); 285 | } else { 286 | alert('Nope, not a valid file...'); 287 | } 288 | } 289 | $('#file-file-upload[type="file"]').val(null); 290 | }); 291 | 292 | $('#magnet-input').on('paste', function (e) { 293 | var element = this; 294 | setTimeout(function () { 295 | var magnet = $(element).val(); 296 | if (magnet.match(/magnet:\?xt=urn:btih:[a-z0-9]{20,50}.+/i) != null) { 297 | uploadMagnet(magnet); 298 | } else { 299 | alert('Nope, not a valid magnet...'); 300 | } 301 | }, 100); 302 | }); 303 | 304 | $('#magnet-input').on('drop', function (e) { 305 | e.preventDefault(); 306 | var magnet = e.originalEvent.dataTransfer.getData('Text'); 307 | setTimeout(function () { 308 | if (magnet.match(/magnet:\?xt=urn:btih:[a-z0-9]{20,50}.+/i) != null) { 309 | uploadMagnet(magnet); 310 | } else { 311 | alert('Nope, not a valid magnet...'); 312 | } 313 | }, 100); 314 | this.placeholder = originalFilePlaceHolder; 315 | this.nextElementSibling.className = originalFileLabelClass; 316 | }); 317 | 318 | $('#magnet-input').on('dragenter', function (e) { 319 | originalFilePlaceHolder = this.placeholder; 320 | var fileLabel = this.nextElementSibling; 321 | originalFileLabelClass = fileLabel.className; 322 | fileLabel.className = "fa fa-check"; 323 | this.placeholder = 'Drop it!'; 324 | return false; 325 | }); 326 | 327 | $('#magnet-input').on('dragleave', function () { 328 | this.placeholder = originalFilePlaceHolder; 329 | this.nextElementSibling.className = originalFileLabelClass; 330 | return false; 331 | }); 332 | 333 | $('#file-input').on('drop', function (e) { 334 | e.preventDefault(); 335 | var file = e.originalEvent.dataTransfer.files[0]; 336 | var fileName = file.name; 337 | var fileExt = '.' + fileName.split('.').pop(); 338 | if (fileExt == '.torrent' || fileExt == '.nzb' || fileExt == '.magnet') { 339 | uploadFile(file); 340 | } else { 341 | alert('Nope, not a valid file...'); 342 | } 343 | this.placeholder = originalFilePlaceHolder; 344 | this.nextElementSibling.className = originalFileLabelClass; 345 | }); 346 | 347 | $('#file-input').on('dragenter', function (e) { 348 | originalFilePlaceHolder = this.placeholder; 349 | var fileLabel = this.nextElementSibling; 350 | originalFileLabelClass = fileLabel.className; 351 | fileLabel.className = "fa fa-check"; 352 | this.placeholder = 'Drop it!'; 353 | return false; 354 | }); 355 | 356 | $('#file-input').on('dragleave', function () { 357 | this.placeholder = originalFilePlaceHolder; 358 | this.nextElementSibling.className = originalFileLabelClass; 359 | return false; 360 | }); 361 | 362 | // Disable default drop behavior in body 363 | $(document.body).bind("dragover", function (e) { 364 | e.preventDefault(); 365 | return false; 366 | }); 367 | 368 | $(document.body).bind("drop", function (e) { 369 | e.preventDefault(); 370 | return false; 371 | }); 372 | 373 | // start up the SocketIO connection to the server 374 | socket = io.connect('//' + document.domain + ':' + location.port, { 375 | 'path': window.location.pathname + 'socket.io' 376 | }); 377 | socket.on('download_categories', function (msg) { 378 | download_categories = msg.data; 379 | }); 380 | 381 | socket.on('tasks_updated', function (msg) { 382 | if (!loaded_tasks) { 383 | loaded_tasks = true; 384 | stop_loading_download_tasks(); 385 | } 386 | check_empty(); 387 | }); 388 | 389 | socket.on('update_task', function (msg) { 390 | console.log(msg.task); 391 | update_task(msg.task); 392 | }); 393 | 394 | socket.on('delete_failed', function (msg) { 395 | console.log('Delete failed: ' + msg.data); 396 | }); 397 | 398 | socket.on('premiumize_connect_error', function (msg) { 399 | show_premiumize_connect_error(); 400 | }); 401 | 402 | socket.on('delete_success', function (msg) { 403 | console.log('Delete success: ' + msg.data); 404 | $("#" + msg.data).addClass('animated fadeOutRightBig'); 405 | $("#" + msg.data).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () { 406 | $("#" + msg.data).remove(); 407 | }); 408 | check_empty(); 409 | }); 410 | 411 | }(jQuery); 412 | 413 | function delete_task(e) { 414 | var elem = $(e.target); 415 | var id = elem.closest('.panel').attr('id'); 416 | socket.emit('delete_task', { 417 | data: id 418 | }); 419 | } 420 | 421 | function delete_all_failed_tasks() { 422 | var confirmationResult = confirm('Are you sure, you want to delete all failed tasks?') 423 | if(confirmationResult == true) 424 | { 425 | socket.emit('delete_all_failed_tasks'); 426 | } 427 | } 428 | 429 | function pause_resume_task(e) { 430 | var elem = $(e.target); 431 | var id = elem.closest('.panel').attr('id'); 432 | socket.emit('pause_resume_task', { 433 | data: id 434 | }); 435 | } 436 | 437 | function stop_task(e) { 438 | var elem = $(e.target); 439 | var id = elem.closest('.panel').attr('id'); 440 | socket.emit('stop_task', { 441 | data: id 442 | }); 443 | } 444 | 445 | function check_empty() { 446 | if ($("#download_section").find(".task_panel").length == 0) 447 | show_no_downloads(); 448 | else 449 | hide_no_downloads(); 450 | } 451 | -------------------------------------------------------------------------------- /premiumizer/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %} - Page Not Found{% endblock %} 3 | {% block barbuttons %}{% endblock %} 4 | {% block content %} 5 |

Page Not Found

6 |

home

7 | {% endblock %} -------------------------------------------------------------------------------- /premiumizer/templates/about.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% set active_page = "about" %} 3 | {% block title %} - Home{% endblock %} 4 | {% block content %} 5 |

Github:

6 | https://github.com/piejanssens/premiumizer 7 |

 

8 |

 

9 |

Windows installer:

10 | https://github.com/neox387/PremiumizerInstaller/releases 11 |

 

12 |

 

13 |

Premiumize.me:

14 | https://www.premiumize.me/ 15 | 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /premiumizer/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% block head %} 5 | Premiumizer {% block title %}{% endblock %} 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 20 | 23 | {% endblock %} 24 | 25 | 26 | {% block navbar %} 27 | 63 | {% endblock %} 64 |
65 |
66 | {% block content %} 67 | {% endblock %} 68 |
69 |
70 | {% block js_footer %} 71 | 75 | 78 | 81 | 82 | {% endblock %} 83 | 84 | -------------------------------------------------------------------------------- /premiumizer/templates/history.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% set active_page = "history" %} 3 | {% block title %} - Home{% endblock %} 4 | {% block content %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {% for item in history|sort(attribute='date', reverse=True) %} 20 | 21 | 22 | 23 | 24 | 25 | {% if item.downloaded == '1' %} 26 | 27 | {% elif item.downloaded == '0' %} 28 | 29 | {% else %} 30 | 31 | {% endif %} 32 | {% if item.deleted == '1' %} 33 | 34 | {% elif item.deleted == '0' %} 35 | 36 | {% else %} 37 | 38 | {% endif %} 39 | {% if item.nzbtomedia == '1' %} 40 | 42 | {% elif item.nzbtomedia == '0' %} 43 | 45 | {% else %} 46 | 47 | {% endif %} 48 | {% if item.email == '1' %} 49 | 50 | {% elif item.email == '0' %} 51 | 52 | {% else %} 53 | 54 | {% endif %} 55 | 60 | {% endif %} 61 | 62 | {% endfor %} 63 |
DateNameCategoryTypeDownloadedDeletednzbToMediaEmailInfo
{{ item.date }}{{ item.name }}{{ item.category }}{{ item.type }}SUCCESSFAILEDN/ASUCCESSFAILEDN/ASUCCESS 41 | FAILED 44 | N/ASUCCESSFAILEDN/A 56 | {% if item.info %} 57 | {% for line in item.info.splitlines() %} 58 | {{ line }}
59 | {% endfor %}
64 | {% endblock %} -------------------------------------------------------------------------------- /premiumizer/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% set active_page = "home" %} 3 | {% block title %} - Home{% endblock %} 4 | {% block content %} 5 | 6 | 11 | {% if cfg.jd_connected == 0 and cfg.jd_enabled %} 12 |

 

13 | 18 | {% endif %} 19 | {% if cfg.aria2_connected == 0 and cfg.aria2_enabled %} 20 |

 

21 | 26 | {% endif %} 27 | {% if debug_enabled == 1 %} 28 |

 

29 | 34 | {% endif %} 35 | {% if cfg.update_available == 1 %} 36 |

 

37 | 42 | {% endif %} 43 | {% if cfg.jd_update_available == 1 %} 44 |

 

45 | 50 | {% endif %} 51 | {% if download_speed != -1 %} 52 |

 

53 | 58 | {% endif %} 59 | {% if cfg.time_shed == 1 %} 60 |

 

61 | 66 | {% endif %} 67 | {% if cfg.download_enabled != 1 %} 68 |

 

69 | 74 | {% endif %} 75 | 76 |
77 |
78 |

79 |
80 |
81 | 82 |
83 |
84 |
85 |
86 | 89 | 90 | 92 |
93 |
94 |
95 |
96 |
97 |
98 | 100 | 101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | 111 | 112 |
113 | Add 114 |
115 |
116 |
117 | 123 |
124 |
125 |

126 | 127 | 129 |

130 |
131 |
132 | 133 |
134 |
135 | 136 |

Loading Download Tasks

137 |
138 |
139 | 140 | 146 | 147 |
148 | 149 |
150 | {% endblock %} 151 | 152 | {% block js_footer %} 153 | {{ super() }} 154 | 159 | 160 | {% endblock %} -------------------------------------------------------------------------------- /premiumizer/templates/log.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% set active_page = "log" %} 3 | {% block title %} - Home{% endblock %} 4 | {% block content %} 5 |
6 |
7 | 8 | 9 |
10 |
11 |

Log:

12 |
{{ log }}
13 |

DEBUG Log:

14 |
{{ debuglog }}
15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /premiumizer/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %} - Home{% endblock %} 3 | {% block content %} 4 | {% block barbuttons %}{% endblock %} 5 |
6 |
7 |
8 | 33 |
34 |
35 |
36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /premiumizer/templates/settings.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% set active_page = "settings" %} 3 | {% block title %} - Home{% endblock %} 4 | {% block content %} 5 |
7 |
8 | {% with info = get_flashed_messages(category_filter=["info"]) %} 9 | {% if info %} 10 | {%- for msg in info %} 11 |

{{ msg }} 12 | {% endfor -%} 13 | {% endif %} 14 | {% endwith %} 15 | 16 | 17 | 18 |

19 | 20 | 28 |
29 |
30 |

 

31 |

Changing these settings requires a restart.

32 |

 

33 |
34 | Updates: 35 |
36 | 37 |

{{ cfg.update_status }}

38 |

Premiumizer is running on commit: {{ cfg.update_localcommit }}

41 | {% if cfg.update_available %} 42 |

Pressing Update will restart Premiumizer.

43 | 44 | 45 |

Changes:

46 |
{{ cfg.update_diffcommit }}
47 |

 

48 | {% endif %} 49 | {% if cfg.jd_update_available %} 50 |

Pressing Update will restart JDownloader.

51 | 52 | {% endif %} 53 |
54 | 55 | {% if settings.get('update', 'auto_update') == '1' %} 56 | 58 | {% else %} 59 | 61 | {% endif %} 62 |
63 |
64 |
65 |
66 | 67 |

 

68 |
69 | Logging: 70 |
71 | 72 | {% if settings.get('global', 'debug_enabled') == '1' %} 73 | 76 | {% else %} 77 | 79 | {% endif %} 80 |
81 |
82 |

 

83 |
84 | Security: 85 | 86 | {% if settings.get('security', 'login_enabled') == '1' %} 87 | 89 | {% else %} 90 | 92 | {% endif %} 93 |

 

94 | 95 | 97 | 98 | 101 |
102 |

 

103 |
104 | Start-Up 105 |
106 | 107 | 110 | 111 | 114 | 115 | 120 | 121 | 125 | 126 | 129 |
130 |
131 |
132 |
133 |
134 |

 

135 |
136 | 137 | 140 |
141 |
142 | 143 |
144 |

 

145 |
146 | 147 | {% if settings.get('downloads', 'time_shed') == '1' %} 148 | 151 | {% else %} 152 | 154 | {% endif %} 155 |

 

156 | 157 | 160 | 161 | 164 |

 

165 | 166 | {% if settings.get('downloads', 'download_enabled') == '1' %} 167 | 170 | {% else %} 171 | 173 | {% endif %} 174 |

 

175 | 176 | {% if settings.get('downloads', 'download_all') == '1' %} 177 | 180 | {% else %} 181 | 183 | {% endif %} 184 |

 

185 | 186 | {% if settings.get('downloads', 'download_rss') == '1' %} 187 | 190 | {% else %} 191 | 193 | {% endif %} 194 |

 

195 | 196 | {% if settings.get('downloads', 'remove_cloud') == '1' %} 197 | 200 | {% else %} 201 | 203 | {% endif %} 204 | 205 | 208 |

 

209 | 210 | {% if settings.get('downloads', 'seed_torrent') == '1' %} 211 | 214 | {% else %} 215 | 217 | {% endif %} 218 |

 

219 | 220 | 223 |
224 |

 

225 |
226 | Watchdir / Blackhole 227 |
228 | 229 | {% if settings.get('upload', 'watchdir_enabled') == '1' %} 230 | 233 |

Disabling will require restart

234 | {% else %} 235 | 237 | {% endif %} 238 | 239 | {% if settings.get('upload', 'watchdir_walk_enabled') == '1' %} 240 | 243 | {% else %} 244 | 246 | {% endif %} 247 |

Enable when watching is not possible (for example with network file systems). Changing 248 | requires 249 | restart.

250 |
251 | 252 | 256 |

 

257 |

Subfolders will be created based on categories names

258 |

Downloads will automatically set category based on subfolder name

259 | 260 | 265 |
266 |
267 |
268 |
269 |

 

270 |
271 | General 272 |
273 | 274 | 279 | 280 | 282 | 284 | 289 |
290 |
291 |

 

292 |
293 | pySmartDL (default) 294 |
295 | {% if cfg.download_builtin == 1 and cfg.download_enabled == 1 %} 296 | Enabled 298 | {% else %} 299 | Disabled 301 | {% endif %} 302 |

 

303 | 304 | 307 |
308 |
309 |

 

310 |
311 | JDownloader 312 |
313 | 314 | {% if settings.get('downloads', 'jd_enabled') == '1' %} 315 | 317 | {% else %} 318 | 320 | {% endif %} 321 | {% if cfg.jd_connected == 1 and cfg.download_enabled == 1 %} 322 | Enabled 324 | {% else %} 325 | Disabled 327 | {% endif %} 328 |

 

329 | 330 | 332 | 333 | 335 | 336 | 339 |
340 |
341 |

 

342 |
343 | Aria2 344 |
345 | 346 | {% if settings.get('downloads', 'aria2_enabled') == '1' %} 347 | 349 | {% else %} 350 | 352 | {% endif %} 353 | {% if cfg.aria2_connected == 1 and cfg.download_enabled == 1 %} 354 | Enabled 356 | {% else %} 357 | Disabled 359 | {% endif %} 360 |

Start aria2 with: aria2c --disable-ipv6=true --enable-rpc --rpc-allow-origin-all 361 | --rpc-listen-all 362 | --rpc-listen-port=6800 --rpc-secret=premiumizer --max-connection-per-server=16 363 | --file-allocation=none --disk-cache=0

364 | 365 | 368 | 369 | 372 | 373 | 375 |
376 |
377 | 378 |
379 | 380 |
381 |

 

382 |
Download Location: overwrite default download location + subdirectory based on category 383 | name
384 |
Delete samples: Will not download any media file < 150MB with sample or rarbg.com.mp4 in 385 | url
386 |
Extensions: whitelist or blacklist extensions to download; example mkv,mp4,srt
387 |

 

388 | {% for x in range(1,categories_amount) %} 389 |
390 | 394 | 398 | 402 | {% if settings.get('categories', 'cat_ext_blacklist['+x|string+']') == '1' %} 403 | 406 | {% else %} 407 | 410 | {% endif %} 411 | {% if settings.get('categories', 'cat_delsample['+x|string+']') == '1' %} 412 | 415 | {% else %} 416 | 419 | {% endif %} 420 | {% if settings.get('categories', 'cat_nzbtomedia['+x|string+']') == '1' %} 421 | 424 | {% else %} 425 | 428 | {% endif %} 429 |
430 | {% endfor %} 431 |
432 | 433 |
434 |

435 | 436 |

437 |
438 | Email 439 | 440 | {% if settings.get('notifications', 'email_enabled') == '1' %} 441 | 444 | {% else %} 445 | 447 | {% endif %} 448 |

 

449 | 450 | {% if settings.get('notifications', 'email_on_failure') == '1' %} 451 | 454 | {% else %} 455 | 457 | {% endif %} 458 |

 

459 | 460 | {% if settings.get('notifications', 'email_encryption') == '1' %} 461 | 464 | {% else %} 465 | 467 | {% endif %} 468 |

 

469 | 470 | 474 | 475 | 477 | 478 | 480 | 481 | 485 | 486 | 489 | 490 | 493 |
494 |

 

495 |
496 | Push Notifications 497 |

Push notifications are handled via Apprise.

498 | 499 | {% if settings.get('notifications', 'apprise_enabled') == '1' %} 500 | 503 | {% else %} 504 | 506 | {% endif %} 507 |

 

508 | 509 | {% if settings.get('notifications', 'apprise_push_on_failure') == '1' %} 510 | 513 | {% else %} 514 | 516 | {% endif %} 517 |

 

518 | 519 | 522 |
523 | 524 |

 

525 |
526 | 527 | 530 | {% endblock %} 531 | -------------------------------------------------------------------------------- /premiumizer/utils.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import logging 3 | import os 4 | import subprocess 5 | import sys 6 | import time 7 | 8 | runningdir = os.path.split(os.path.abspath(os.path.realpath(sys.argv[0])))[0] 9 | rootdir = os.path.dirname(runningdir) 10 | ConfDir = os.path.join(rootdir, 'conf') 11 | LogsDir = os.path.join(ConfDir, 'logs') 12 | 13 | # logging 14 | log_format = '%(asctime)-20s %(name)-41s: %(levelname)-8s : %(message)s' 15 | logging.basicConfig(filename=os.path.join(LogsDir, 'update.log'), level=logging.DEBUG, format=log_format, 16 | datefmt='%m-%d %H:%M:%S') 17 | logging.debug('runningdir = %s', runningdir) 18 | 19 | 20 | def uncaught_exception(exc_type, exc_value, exc_traceback): 21 | if issubclass(exc_type, (SystemExit, KeyboardInterrupt)): 22 | return 23 | logging.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) 24 | pass 25 | 26 | 27 | sys.excepthook = uncaught_exception 28 | 29 | 30 | def restart(): 31 | logging.debug('def restart') 32 | time.sleep(4) 33 | exec(compile(open(os.path.join(runningdir, 'premiumizer.py'), "rb").read(), 34 | os.path.join(runningdir, 'premiumizer.py'), 'exec'), globals(), globals()) 35 | 36 | 37 | def update(): 38 | logging.debug('def restart') 39 | del sys.argv[1:] 40 | time.sleep(2) 41 | logging.info('Git pull nzbtomedia & premiumizer') 42 | subprocess.call(['git', '-C', os.path.join(rootdir, 'nzbtomedia'), 'pull']) 43 | subprocess.call(['git', '-C', rootdir, 'pull']) 44 | prem_config = configparser.ConfigParser() 45 | default_config = configparser.ConfigParser() 46 | prem_config.read(os.path.join(ConfDir, 'settings.cfg')) 47 | default_config.read(os.path.join(runningdir, 'settings.cfg.tpl')) 48 | prem_config.set('update', 'updated', '1') 49 | with open(os.path.join(ConfDir, 'settings.cfg'), 'w') as configfile: 50 | prem_config.write(configfile) 51 | if prem_config.getfloat('update', 'req_version') < default_config.getfloat('update', 'req_version'): 52 | logging.info('updating pip requirements') 53 | subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip']) 54 | subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-r', os.path.join(rootdir, 'requirements.txt')]) 55 | prem_config.set('update', 'req_version', str(default_config.getfloat('update', 'req_version'))) 56 | with open(os.path.join(ConfDir, 'settings.cfg'), 'w') as configfile: 57 | prem_config.write(configfile) 58 | if prem_config.getfloat('update', 'config_version') < default_config.getfloat('update', 'config_version'): 59 | logging.info('updating config file') 60 | import shutil 61 | shutil.copy(os.path.join(ConfDir, 'settings.cfg'), os.path.join(ConfDir, 'settings.cfg.old')) 62 | shutil.copy(os.path.join(runningdir, 'settings.cfg.tpl'), os.path.join(ConfDir, 'settings.cfg')) 63 | prem_config.read(os.path.join(ConfDir, 'settings.cfg.old')) 64 | default_config.read(os.path.join(ConfDir, 'settings.cfg')) 65 | for section in prem_config.sections(): 66 | if section in default_config.sections() and section != 'update': 67 | for key in prem_config.options(section): 68 | if key in default_config.options(section): 69 | default_config.set(section, key, (prem_config.get(section, key))) 70 | with open(os.path.join(ConfDir, 'settings.cfg'), 'w') as configfile: 71 | default_config.write(configfile) 72 | 73 | if os_arg == '--windows': 74 | pass 75 | else: 76 | time.sleep(3) 77 | exec(compile(open(os.path.join(runningdir, 'premiumizer.py'), "rb").read(), 78 | os.path.join(runningdir, 'premiumizer.py'), 'exec'), globals(), globals()) 79 | 80 | 81 | if len(sys.argv) == 3: 82 | option_arg = sys.argv[1] 83 | os_arg = sys.argv[2] 84 | if not os_arg == '--windows': 85 | os_arg = '' 86 | if option_arg == '--restart': 87 | restart() 88 | elif option_arg == '--update': 89 | update() 90 | else: 91 | sys.exit() 92 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | APScheduler==3.9.1 2 | apprise==1.0.0 3 | bencode.py==4.0.0 4 | chardet==5.0.0 5 | click==8.1.3 6 | flask-compress==1.13 7 | flask-login==0.6.2 8 | flask==2.2.2 9 | flask_apscheduler==1.12.4 10 | flask_socketio==5.3.1 11 | gevent-websocket==0.10.1 12 | gevent==21.12.0 13 | greenlet==1.1.3 14 | itsdangerous==2.1.2 15 | jinja2==3.1.2 16 | myjdapi==1.1.6 17 | pathtools==0.1.2 18 | pySmartDL==1.3.4 19 | python-dateutil==2.8.2 20 | python-engineio==4.3.4 21 | python-socketio==5.7.1 22 | requests==2.28.1 23 | six==1.16.0 24 | tzlocal==4.2 25 | urllib3==1.26.12 26 | watchdog==2.1.9 27 | werkzeug==2.2.2 --------------------------------------------------------------------------------