├── torrentDownloader ├── __init__.py ├── gmail.storage ├── record.txt ├── config.yaml ├── setup.py ├── background.py ├── transmission_control.py ├── main.py ├── helper.py └── kickass.py ├── torrentDownloader.egg-info ├── top_level.txt ├── entry_points.txt ├── dependency_links.txt ├── requires.txt ├── SOURCES.txt └── PKG-INFO ├── requirements.txt ├── screenshot ├── web.png ├── addshow.png ├── gmail.png ├── terminal.png └── current_watching.png ├── MANIFEST.in ├── setup.cfg ├── install ├── trans.sh ├── cron.sh ├── install.sh └── edit.py ├── setup.py ├── PKG-INFO └── README.md /torrentDownloader/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /torrentDownloader/gmail.storage: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /torrentDownloader/record.txt: -------------------------------------------------------------------------------- 1 | { } -------------------------------------------------------------------------------- /torrentDownloader.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | torrentDownloader 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pypi-publisher pyyaml simplejson bs4 Click requests==2.2.1 ndg-httpsclient certifi -------------------------------------------------------------------------------- /screenshot/web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tejaspandey1992/torrentDownloader/HEAD/screenshot/web.png -------------------------------------------------------------------------------- /torrentDownloader.egg-info/entry_points.txt: -------------------------------------------------------------------------------- 1 | [console_scripts] 2 | tc = torrentDownloader.main:cli 3 | 4 | -------------------------------------------------------------------------------- /screenshot/addshow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tejaspandey1992/torrentDownloader/HEAD/screenshot/addshow.png -------------------------------------------------------------------------------- /screenshot/gmail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tejaspandey1992/torrentDownloader/HEAD/screenshot/gmail.png -------------------------------------------------------------------------------- /torrentDownloader.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | pypi-publisher pyyaml simplejson bs4 Click requests==2.2.1 2 | -------------------------------------------------------------------------------- /screenshot/terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tejaspandey1992/torrentDownloader/HEAD/screenshot/terminal.png -------------------------------------------------------------------------------- /torrentDownloader.egg-info/requires.txt: -------------------------------------------------------------------------------- 1 | pypi-publisher 2 | pyyaml 3 | simplejson 4 | bs4 5 | Click 6 | requests==2.2.1 -------------------------------------------------------------------------------- /screenshot/current_watching.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tejaspandey1992/torrentDownloader/HEAD/screenshot/current_watching.png -------------------------------------------------------------------------------- /torrentDownloader/config.yaml: -------------------------------------------------------------------------------- 1 | baseUrl: https://kat.cr 2 | 3 | quality: 'High' 4 | 5 | scrapDepth: 10 6 | 7 | emailId: 'example@gmail.com' 8 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | include requirements.txt 3 | include install/* 4 | include screenshot/* 5 | recursive-include torrentDownloader *.txt *.yaml *.storage 6 | 7 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 3 | 4 | [metadata] 5 | description-file = README.md 6 | 7 | [egg_info] 8 | tag_build = 9 | tag_date = 0 10 | tag_svn_revision = 0 11 | 12 | -------------------------------------------------------------------------------- /torrentDownloader/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup ( 4 | name='TorrentDownloader', 5 | version='1.0', 6 | py_modules=['main'], 7 | install_requires=[ 'Click','bs4','requests','simplejson' ], 8 | entry_points=''' 9 | [console_scripts] 10 | tc=main:cli 11 | ''', 12 | ) 13 | -------------------------------------------------------------------------------- /install/trans.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # build.sh 4 | # Copyright (C) 2016 tejas 5 | # 6 | # Distributed under terms of the BSD license. 7 | # 8 | echo -n "Enter your name and press [ENTER]: " 9 | read name 10 | sudo chgrp debian-transmission /home/$name/Downloads/torrent 11 | sudo chmod 777 /home/$name/Downloads/torrent 12 | sudo service transmission-daemon start 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /install/cron.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # build.sh 4 | # Copyright (C) 2016 tejas 5 | # 6 | # Distributed under terms of the BSD license. 7 | # 8 | mkdir /home/$USER/Downloads/torrent 9 | install="/usr/local/lib/python2.7/dist-packages/torrentDownloader" 10 | crontab -l | { cat; echo "*/30 * * * * /usr/bin/python $install/background.py >> /home/$USER/Desktop/log 2>&1 "; } | crontab - 11 | cwd=$(pwd) 12 | python $cwd/edit.py 13 | 14 | -------------------------------------------------------------------------------- /torrentDownloader/background.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim:fenc=utf-8 4 | # 5 | # Copyright © 2016 tejas 6 | # 7 | # Distributed under terms of the MIT license. 8 | 9 | import click 10 | import datetime 11 | from helper import showSeasonAll,show 12 | from transmission_control import Transmission 13 | from kickass import Kickass 14 | 15 | 16 | def maintaince(): 17 | click.echo('Starting Maintainence %s'%(datetime.datetime.now())) 18 | Transmission().removeCompletedTorrent() 19 | Kickass(None,None,None).scrap() 20 | Kickass(None,None,None).backUpdateRecord() 21 | click.echo('Ending Maintainence %s'%(datetime.datetime.now())) 22 | maintaince() 23 | 24 | 25 | -------------------------------------------------------------------------------- /install/install.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # build.sh 4 | # Copyright (C) 2016 tejas 5 | # 6 | # Distributed under terms of the BSD license. 7 | # 8 | 9 | install="/usr/local/lib/python2.7/dist-packages/torrentDownloader" 10 | sudo apt-get update 11 | sudo apt-get -y install python-pip 12 | sudo apt-get -y install transmission-daemon 13 | #sudo apt-get -y install vim 14 | sudo pip install --upgrade google-api-python-client 15 | sudo pip install --upgrade python-gflags 16 | sudo pip install torrentDownloader-2.0.tar.gz 17 | sudo chmod 777 $install/*.txt $install/*.yaml $install/*.py $install/*.json $install/*.storage 18 | sudo service transmission-daemon stop 19 | sudo chmod 777 /etc/transmission-daemon/settings.json 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /install/edit.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim:fenc=utf-8 4 | # 5 | # Copyright © 2016 tejas 6 | # 7 | # Distributed under terms of the BSD license. 8 | 9 | import simplejson 10 | 11 | 12 | basePath='/etc/transmission-daemon/' 13 | print ('Enter your name and press [ENTER]:') 14 | username=raw_input() 15 | downloadPath='/home/%s/Downloads/torrent'%(username) 16 | with open (basePath + 'settings.json') as f: 17 | jsonData=simplejson.load(f) 18 | jsonData['umask']=0 19 | jsonData['download-dir']=downloadPath 20 | print jsonData['umask'],jsonData['download-dir'] 21 | 22 | 23 | with open(basePath+'settings.json', 'w') as outfile: 24 | simplejson.dump(jsonData, outfile, sort_keys = True, indent = 4, 25 | ensure_ascii=False) 26 | 27 | -------------------------------------------------------------------------------- /torrentDownloader.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | MANIFEST.in 2 | README.md 3 | requirements.txt 4 | setup.cfg 5 | setup.py 6 | install/cron.sh 7 | install/edit.py 8 | install/install.sh 9 | install/trans.sh 10 | screenshot/addshow.png 11 | screenshot/current_watching.png 12 | screenshot/gmail.png 13 | screenshot/terminal.png 14 | screenshot/web.png 15 | torrentDownloader/__init__.py 16 | torrentDownloader/background.py 17 | torrentDownloader/config.yaml 18 | torrentDownloader/data.txt 19 | torrentDownloader/gmail.storage 20 | torrentDownloader/helper.py 21 | torrentDownloader/kickass.py 22 | torrentDownloader/main.py 23 | torrentDownloader/record.txt 24 | torrentDownloader/setup.py 25 | torrentDownloader/transmission_control.py 26 | torrentDownloader.egg-info/PKG-INFO 27 | torrentDownloader.egg-info/SOURCES.txt 28 | torrentDownloader.egg-info/dependency_links.txt 29 | torrentDownloader.egg-info/entry_points.txt 30 | torrentDownloader.egg-info/requires.txt 31 | torrentDownloader.egg-info/top_level.txt -------------------------------------------------------------------------------- /torrentDownloader/transmission_control.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim:fenc=utf-8 4 | # 5 | # Copyright © 2016 tejas 6 | # 7 | # Distributed under terms of the BSD license. 8 | 9 | 10 | from helper import executeCommand,sendEmail 11 | import click 12 | class Transmission: 13 | 14 | def listTorrent(self): 15 | cmd = 'transmission-remote --auth transmission:transmission -l' 16 | return executeCommand(cmd) 17 | 18 | def addTorrent(self,magnet): 19 | cmd = 'transmission-remote --auth transmission:transmission -a \'%s\' ' %(magnet) 20 | click.echo(executeCommand(cmd)) 21 | 22 | def removeAndDeleteTorrent(self,index): 23 | cmd ='transmission-remote --auth transmission:transmission -t %d --remove-and-delete' %(index) 24 | executeCommand(cmd) 25 | 26 | def removeTorrent(self,index): 27 | cmd ='transmission-remote --auth transmission:transmission -t %d --remove' %(index) 28 | click.echo(executeCommand(cmd)) 29 | 30 | 31 | def removeCompletedTorrent(self): 32 | curStatus=self.listTorrent().split(u'\n') 33 | for x in curStatus: 34 | x=x.split() 35 | if len(x) >= 9 and x[1]=='100%' : 36 | self.removeTorrent(int(x[0])) 37 | notify=u'' 38 | for i in range(9,len(x)): 39 | notify+=(x[i] + ' ') 40 | cmd='/usr/bin/notify-send Download-Complete -t 20 \"%s\"' %(notify) 41 | executeCommand(cmd) 42 | sendEmail('Download Complete of ' + notify) 43 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | from codecs import open 3 | from os import path 4 | 5 | __version__ = '2.0' 6 | 7 | here = path.abspath(path.dirname(__file__)) 8 | 9 | # Get the long description from the README file 10 | with open(path.join(here, 'README.md'), encoding='utf-8') as f: 11 | long_description = f.read() 12 | 13 | # get the dependencies and installs 14 | with open(path.join(here, 'requirements.txt'), encoding='utf-8') as f: 15 | all_reqs = f.read().split('\n') 16 | 17 | install_requires = [x.strip() for x in all_reqs if 'git+' not in x] 18 | dependency_links = [x.strip().replace('git+', '') for x in all_reqs if 'git+' not in x] 19 | 20 | setup( 21 | name='torrentDownloader', 22 | version=__version__, 23 | description='To automate process of downloading TV Shows', 24 | long_description=long_description, 25 | url='https://github.com/tejaspandey1992/torrentDownloader', 26 | download_url='https://github.com/tejaspandey1992/torrentDownloader/tarball/' + __version__, 27 | license='BSD', 28 | classifiers=[ 29 | 'Development Status :: Stable', 30 | 'Intended Audience :: Developers', 31 | 'Programming Language :: Python :: 2', 32 | ], 33 | keywords='', 34 | packages=find_packages(exclude=['docs', 'tests*']), 35 | include_package_data=True, 36 | author='Tejas Pandey', 37 | install_requires=install_requires, 38 | dependency_links=dependency_links, 39 | author_email='tejaspandey2010@gmail.com', 40 | entry_points={ 41 | 'console_scripts': [ 42 | 'tc =torrentDownloader.main:cli', 43 | ] 44 | } 45 | ) 46 | -------------------------------------------------------------------------------- /torrentDownloader/main.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim:fenc=utf-8 4 | # 5 | # Copyright © 2016 tejas 6 | # 7 | # Distributed under terms of the BSD license. 8 | 9 | import click 10 | from transmission_control import Transmission 11 | from kickass import Kickass 12 | 13 | @click.group() 14 | def cli(): 15 | pass 16 | 17 | 18 | @click.command() 19 | def lt(): 20 | ''' List The Torrent ''' 21 | click.echo(Transmission().listTorrent()) 22 | cli.add_command(lt) 23 | 24 | 25 | @click.command() 26 | @click.option('-n',prompt='Enter Show Name') 27 | @click.option('-s',prompt='Enter Season Number',type = int) 28 | @click.option('-e',prompt='Enter Episode Number',type = int) 29 | def addShow(n,s,e): 30 | '''To Add Show With Season Number And Episode Number''' 31 | cur=Kickass(n,s,e) 32 | if cur.validateShowSeasonEpisode() : 33 | cur.genShowSeasonEpisodeNumber() 34 | cur.addRecord() 35 | if cur.recordPresent==False: 36 | cur.search() 37 | if cur.torrentFound: 38 | cur.incrementRecord() 39 | else: 40 | click.echo('Torrent not Found') 41 | cur.deleteRecord() 42 | 43 | cli.add_command(addShow) 44 | 45 | @click.command() 46 | @click.option('-n',prompt='Enter Show Name') 47 | def removeShow(n): 48 | '''To Remove Show From Currently Watching''' 49 | cur=Kickass(n,None,None) 50 | cur.validateShowName() 51 | cur.deleteRecord() 52 | cli.add_command(removeShow) 53 | 54 | 55 | @click.command() 56 | def currentWatching(): 57 | '''List of Currently Watching Shows''' 58 | cur=Kickass(None,None,None) 59 | cur.displayRecord() 60 | cli.add_command(currentWatching) 61 | 62 | @click.command() 63 | def afterCare(): 64 | '''To Remove Completed Torrent From The List''' 65 | Transmission().removeCompletedTorrent() 66 | cli.add_command(afterCare) 67 | 68 | @click.command() 69 | def removeallshow(): 70 | '''To Remove All Show From The Record''' 71 | Kickass(None,None,None).deleteAllRecord() 72 | cli.add_command(removeallshow) 73 | 74 | @click.command() 75 | @click.option('-n',prompt='Enter Show Name') 76 | @click.option('-s',prompt='Enter Season Number',type = int) 77 | @click.option('-e',prompt='Enter Episode Number',type = int) 78 | def generalSearch(n,s,e): 79 | '''To Add Torrent Without Adding It To Record''' 80 | cur=Kickass(n,s,e) 81 | if cur.validateShowSeasonEpisode(): 82 | cur.genShowSeasonEpisodeNumber() 83 | cur.search() 84 | if cur.torrentFound == False: 85 | click.echo('Torrent not Found') 86 | cli.add_command(generalSearch) 87 | -------------------------------------------------------------------------------- /torrentDownloader/helper.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim:fenc=utf-8 4 | # 5 | # Copyright © 2016 tejas 6 | # 7 | # Distributed under terms of the BSD license. 8 | 9 | import requests 10 | import simplejson 11 | import sys 12 | import subprocess 13 | import base64 14 | import yaml 15 | import httplib2 16 | from email.mime.text import MIMEText 17 | from apiclient.discovery import build 18 | from oauth2client.client import flow_from_clientsecrets 19 | from oauth2client.file import Storage 20 | from oauth2client.tools import run_flow 21 | 22 | basePath='/usr/local/lib/python2.7/dist-packages/torrentDownloader/' 23 | 24 | with open(basePath+'config.yaml','r') as f: 25 | doc=yaml.load(f) 26 | emailId=doc['emailId'] 27 | 28 | def executeCommand(cmd): 29 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE,shell=True) 30 | output = p.communicate()[0].decode('utf-8') 31 | if p.returncode != 0: 32 | print "Error in Execution of %s Error Code: %d " % (cmd,p.returncode) 33 | else: 34 | return output 35 | 36 | def detailImdb(p): 37 | url ="http://www.omdbapi.com/" 38 | try: 39 | x=requests.get(url,params=p) 40 | except requests.exceptions.Timeout: 41 | print 'Timeout has occured' 42 | sys.exit(1) 43 | except requests.exceptions.RequestException as e: 44 | print e 45 | sys.exit(1) 46 | return x.json() 47 | 48 | 49 | def showSeasonAll(showName,season): 50 | p={'t':showName,'Season':season} 51 | return detailImdb(p) 52 | 53 | def showEpisode (showName,season,episode): 54 | p={'t':showName,'Season':season,'Episode':episode} 55 | return detailImdb(p) 56 | def show(showName): 57 | p={'t':showName}; 58 | return detailImdb(p) 59 | 60 | 61 | def sendEmail(msg): 62 | # Path to the client_secret.json file downloaded from the Developer Console 63 | CLIENT_SECRET_FILE = basePath+'client_secret.json' 64 | 65 | # Check https://developers.google.com/gmail/api/auth/scopes for all available scopes 66 | OAUTH_SCOPE = 'https://www.googleapis.com/auth/gmail.compose' 67 | 68 | # Location of the credentials storage file 69 | STORAGE = Storage(basePath + 'gmail.storage') 70 | 71 | # Start the OAuth flow to retrieve credentials 72 | flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope=OAUTH_SCOPE) 73 | http = httplib2.Http() 74 | 75 | # Try to retrieve credentials from storage or run the flow to generate them 76 | credentials = STORAGE.get() 77 | if credentials is None or credentials.invalid: 78 | credentials = run_flow(flow, STORAGE, http=http) 79 | 80 | # Authorize the httplib2.Http object with our credentials 81 | http = credentials.authorize(http) 82 | 83 | # Build the Gmail service from discovery 84 | gmail_service = build('gmail', 'v1', http=http) 85 | 86 | # create a message to send 87 | message = MIMEText(msg,"plain", "utf-8") 88 | message['to'] = emailId 89 | message['to'] = emailId 90 | message['subject'] = u"Torrent Downloader Status" 91 | body = {'raw': base64.b64encode(message.as_string())} 92 | try: 93 | message = (gmail_service.users().messages().send(userId="me", body=body).execute()) 94 | print('Message Id: %s' % message['id']) 95 | print(message) 96 | except Exception as error: 97 | print('An error occurred: %s' % error) 98 | 99 | -------------------------------------------------------------------------------- /PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.1 2 | Name: torrentDownloader 3 | Version: 0.0.1 4 | Summary: To automate process of downloading TV Shows 5 | Home-page: https://github.com/tejaspandey1992/torrentDownloader 6 | Author: Tejas Pandey 7 | Author-email: tejaspandey2010@gmail.com 8 | License: BSD 9 | Download-URL: https://github.com/tejaspandey1992/torrentDownloader/tarball/0.0.1 10 | Description: torrentDownloader 11 | =============================== 12 | 13 | version number: 0.0.1 14 | author: Tejas Pandey 15 | 16 | Overview 17 | -------- 18 | 19 | To automate process of downloading TV Shows 20 | 21 | Installation / Usage 22 | -------------------- 23 | 24 | Pre-Install 25 | ----------- 26 | 1)Run command crontab -e and select nano as a editor , this will happen only when crontab is never has been used 27 | in the system. 28 | 29 | 30 | Install 31 | ----------- 32 | 1)Extract the package-archive 33 | 2)Go to install folder and copy all the files and paste it where package-archive is present 34 | These scripts and package-archive must be in same folder . 35 | 3)Follow the command excatly without trying to become super using su 36 | 4)sudo ./install.sh 37 | 5)./cron.sh 38 | 6)sudo ./trans.h 39 | 40 | A folder will be created in Downloads folder with name "torrent" , this is where 41 | all torrents will be downloaded. 42 | 43 | 44 | Issues 45 | ------------ 46 | 1)It is possible transmission-daemon does not starts properly 47 | Then we should try to use following command 48 | sudo service transmission-daemon start 49 | sudo service transmission-daemon stop 50 | 51 | 2)Log of the command running will be present at the 'log' file at the Desktop 52 | 53 | Example 54 | ------- 55 | 56 | 1)To see the help and commands available 57 | 58 | tc --help 59 | 60 | 2)To addshow to the currently watching 61 | 62 | tc addshow 63 | 64 | At a time only one season of a show can be downloaded . It will increment 65 | the episode number once season is completely downloaded it will be removed. 66 | 67 | 3)Graphical user interface is also available for transmission-daemon 68 | Default address - http://127.0.0.1:9091/ 69 | Username- transmission 70 | Password- transmission 71 | 72 | 4) tc lt 73 | List all the torrent that are currently running in the system 74 | 75 | 5)tc generalsearch 76 | To add torrent without adding to the list of currently watching show. 77 | 78 | 6)tc aftercare 79 | To remove completed torrent without deleting the data. 80 | 81 | 82 | Configuration 83 | ---------------- 84 | 85 | Config.yaml 86 | ----------- 87 | Location :- /usr/local/lib/python2.7/dist-packages/torrentDownloader/config.yaml 88 | 89 | baseUrl: https://kat.cr 90 | 91 | Since there is possibility of kat.cr changes its domain , user can configure it form here . 92 | 93 | scrapDepth : 10 94 | Higher the number it will search for more pages for the torrent. In most cases does not require 95 | to change. 96 | 97 | quality : High 98 | By default it is set to High , can be changed to Low , for saving data or space. 99 | Valid values are - High or Low (case sensitive) 100 | 101 | 102 | crontab -e 103 | ----------- 104 | */30 * * * * /usr/bin/python /usr/local/lib/python2.7/dist-packages/torrentDownloader/background.py >> /home/tejas/Desktop/log 105 | 106 | Not exactly this entry will differ from system to system. 107 | 108 | */30 - Tells about the minutes at which scrapping and maintaince routine should run 109 | 110 | This time can be changed depending upon the need by defualt it is 5 minutes , can be changed depending upon need 111 | 112 | 113 | 114 | 115 | Platform: UNKNOWN 116 | Classifier: Development Status :: 3 - Alpha 117 | Classifier: Intended Audience :: Developers 118 | Classifier: Programming Language :: Python :: 3 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | torrentDownloader 2 | =============================== 3 | 4 | Version Number: 2.0 5 | Author: Tejas Pandey 6 | 7 | Overview 8 | ------------- 9 | 10 | To automate process of downloading TV Shows 11 |

12 | List Torrent 13 | Adding Show 14 | Current Watching 15 | Browser View 16 | Gmail Message 17 | 18 |

19 | 20 | Installation / Usage 21 | --------------------------- 22 | 23 | Pre-Install 24 | -------------- 25 | 26 | - Run command `crontab -e` and select nano as a editor , this will happen only when crontab is never has been used 27 | in the system. 28 | 29 | - Follow the **Step 1: Turn on the Gmail API** on [wizard](https://developers.google.com/gmail/api/quickstart/python) to activate Gmail. 30 | 31 | 32 | 33 | > Don't share client_secret.json to anyone . This will be used in later stages of installation. 34 | 35 | 36 | 37 | Install 38 | ----------- 39 | - Extract the Source code (tar.gz) from Release. 40 | - Go to install folder and copy all the files and paste it where Source code (tar.gz) is present These scripts and Source code (tar.gz) must be in same folder . 41 | - Follow the command excatly without trying to become super using su . 42 | - `sudo ./install.sh` 43 | - `./cron.sh` 44 | - `sudo ./trans.sh` 45 | - Copy as a sudo user **client_secret.json** to `/usr/local/lib/python2.7/dist-packages/torrentDownloader/ ` 46 | - `sudo chmod 777 /usr/local/lib/python2.7/dist-packages/torrentDownloader/client_secret.json`. 47 | 48 | > A folder will be created in Downloads folder with name "torrent" , 49 | > this is where all torrents will be downloaded. 50 | > Log of the software running will be present at the **log** file at the **Desktop** 51 | 52 | Issues 53 | ------------ 54 | 55 | - It is possible transmission-daemon does not starts properly 56 | Then we should try to use following command. 57 | `sudo service transmission-daemon start` 58 | `sudo service transmission-daemon stop` 59 | 60 | Example 61 | ------------ 62 | 63 | - To see the help and commands available 64 | 65 | **tc - -help** 66 | 67 | - To addshow to the currently watching. 68 | 69 | **tc addshow** 70 | 71 | At a time only one season of a show can be downloaded . It will increment the episode number once season is completely downloaded it will be removed. 72 | 73 | - Graphical user interface is also available for transmission-daemon 74 | Default address - [Web Interface](http://127.0.0.1:9091/) 75 | **Username - transmission** 76 | **Password - transmission** 77 | 78 | 79 | - **tc lt** 80 | List all the torrent that are currently running in the system . 81 | 82 | 83 | - **tc generalsearch** 84 | To add torrent without adding to the list of currently watching show. 85 | 86 | - **tc aftercare** 87 | To remove completed torrent without deleting the data. 88 | 89 | 90 | Configuration 91 | ---------------- 92 | 93 | Config.yaml 94 | ----------------- 95 | **Location :- /usr/local/lib/python2.7/dist-packages/torrentDownloader/config.yaml** 96 | 97 | - **baseUrl: https://kat.cr** 98 | Since there is possibility of kat.cr changes its domain , user can configure it form here . 99 | 100 | - **scrapDepth : 10** 101 | Higher the number it will search for more pages for the torrent. In most cases does not require to change. 102 | 103 | - **quality : 'High'** 104 | By default it is set to High , can be changed to Low , for saving data or space. Valid values are - High or Low (case sensitive) 105 | 106 | - **emailId: 'example@gmail.com'** 107 | Set this to your gmail id to get the email when torrent download is complete. 108 | 109 | crontab -e 110 | ----------- 111 | 112 | */30 * * * * /usr/bin/python /usr/local/lib/python2.7/dist-packages/torrentDownloader/background.py >> /home/tejas/Desktop/log 2>&1 113 | 114 | 115 | Not exactly this entry will differ from system to system. 116 | 117 | ***/30** - Tells about the minutes at which scrapping and maintenance routine should run 118 | 119 | This time can be changed depending upon the need by default it is 30 minutes , can be changed depending upon need . 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /torrentDownloader.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.1 2 | Name: torrentDownloader 3 | Version: 2.0 4 | Summary: To automate process of downloading TV Shows 5 | Home-page: https://github.com/tejaspandey1992/torrentDownloader 6 | Author: Tejas Pandey 7 | Author-email: tejaspandey2010@gmail.com 8 | License: BSD 9 | Download-URL: https://github.com/tejaspandey1992/torrentDownloader/tarball/2.0 10 | Description: torrentDownloader 11 | =============================== 12 | 13 | Version Number: 2.0 14 | Author: Tejas Pandey 15 | 16 | Overview 17 | ------------- 18 | 19 | To automate process of downloading TV Shows 20 |

21 | List Torrent 22 | Adding Show 23 | Current Watching 24 | Browser View 25 | Gmail Message 26 | 27 |

28 | 29 | Installation / Usage 30 | --------------------------- 31 | 32 | Pre-Install 33 | -------------- 34 | 35 | - Run command `crontab -e` and select nano as a editor , this will happen only when crontab is never has been used 36 | in the system. 37 | 38 | - Follow the **Step 1: Turn on the Gmail API** on [wizard](https://developers.google.com/gmail/api/quickstart/python) to activate Gmail. 39 | 40 | 41 | 42 | > Don't share client_secret.json to anyone . This will be used in later stages of installation. 43 | 44 | 45 | 46 | Install 47 | ----------- 48 | - Extract the Source code (tar.gz) from Release. 49 | - Go to install folder and copy all the files and paste it where Source code (tar.gz) is present These scripts and Source code (tar.gz) must be in same folder . 50 | - Follow the command excatly without trying to become super using su . 51 | - `sudo ./install.sh` 52 | - `./cron.sh` 53 | - `sudo ./trans.sh` 54 | - Copy as a sudo user **client_secret.json** to `/usr/local/lib/python2.7/dist-packages/torrentDownloader/ ` 55 | - `sudo chmod 777 /usr/local/lib/python2.7/dist-packages/torrentDownloader/client_secret.json`. 56 | 57 | > A folder will be created in Downloads folder with name "torrent" , 58 | > this is where all torrents will be downloaded. 59 | > Log of the software running will be present at the **log** file at the **Desktop** 60 | 61 | Issues 62 | ------------ 63 | 64 | - It is possible transmission-daemon does not starts properly 65 | Then we should try to use following command. 66 | `sudo service transmission-daemon start` 67 | `sudo service transmission-daemon stop` 68 | 69 | Example 70 | ------------ 71 | 72 | - To see the help and commands available 73 | 74 | **tc - -help** 75 | 76 | - To addshow to the currently watching. 77 | 78 | **tc addshow** 79 | 80 | At a time only one season of a show can be downloaded . It will increment the episode number once season is completely downloaded it will be removed. 81 | 82 | - Graphical user interface is also available for transmission-daemon 83 | Default address - [Web Interface](http://127.0.0.1:9091/) 84 | **Username - transmission** 85 | **Password - transmission** 86 | 87 | 88 | - **tc lt** 89 | List all the torrent that are currently running in the system . 90 | 91 | 92 | - **tc generalsearch** 93 | To add torrent without adding to the list of currently watching show. 94 | 95 | - **tc aftercare** 96 | To remove completed torrent without deleting the data. 97 | 98 | 99 | Configuration 100 | ---------------- 101 | 102 | Config.yaml 103 | ----------------- 104 | **Location :- /usr/local/lib/python2.7/dist-packages/torrentDownloader/config.yaml** 105 | 106 | - **baseUrl: https://kat.cr** 107 | Since there is possibility of kat.cr changes its domain , user can configure it form here . 108 | 109 | - **scrapDepth : 10** 110 | Higher the number it will search for more pages for the torrent. In most cases does not require to change. 111 | 112 | - **quality : 'High'** 113 | By default it is set to High , can be changed to Low , for saving data or space. Valid values are - High or Low (case sensitive) 114 | 115 | - **emailId: 'example@gmail.com'** 116 | Set this to your gmail id to get the email when torrent download is complete. 117 | 118 | crontab -e 119 | ----------- 120 | 121 | */30 * * * * /usr/bin/python /usr/local/lib/python2.7/dist-packages/torrentDownloader/background.py >> /home/tejas/Desktop/log 2>&1 122 | 123 | 124 | Not exactly this entry will differ from system to system. 125 | 126 | ***/30** - Tells about the minutes at which scrapping and maintenance routine should run 127 | 128 | This time can be changed depending upon the need by default it is 30 minutes , can be changed depending upon need . 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | Platform: UNKNOWN 137 | Classifier: Development Status :: Stable 138 | Classifier: Intended Audience :: Developers 139 | Classifier: Programming Language :: Python :: 2 140 | -------------------------------------------------------------------------------- /torrentDownloader/kickass.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim:fenc=utf-8 4 | # 5 | # Copyright © 2016 tejas 6 | # 7 | # Distributed under terms of the BSD license. 8 | import requests 9 | import click 10 | import simplejson 11 | import ast 12 | import yaml 13 | from datetime import date 14 | from helper import showSeasonAll,show 15 | from bs4 import BeautifulSoup 16 | from transmission_control import Transmission 17 | from time import sleep 18 | import certifi 19 | 20 | 21 | class Kickass: 22 | def __init__(self,showName,seasonNumber,episodeNumber): 23 | self.showName=showName 24 | self.seasonNumber=seasonNumber 25 | self.episodeNumber=episodeNumber 26 | 27 | self.isValidEpisode=True 28 | self.isValidSeasonNumber=True 29 | self.isValidShowName=True 30 | self.isValidShowSeasonEpisode=True 31 | 32 | self.maxSeason=0 33 | self.maxEpisode=0 34 | self.showEpisodeNumber='' 35 | 36 | self.torrentFound=False 37 | self.torrentPage='' 38 | self.recordPresent=False 39 | self.basePath='/usr/local/lib/python2.7/dist-packages/torrentDownloader/' 40 | with open(self.basePath + 'config.yaml','r') as f: 41 | config=yaml.load(f) 42 | self.baseUrl=config['baseUrl'] 43 | self.quality=config['quality'] 44 | self.depth=config['scrapDepth'] 45 | 46 | def genNumber(self,x): 47 | genNumber="" 48 | if x<10: 49 | genNumber+='0'+str(x) 50 | else: 51 | genNumber=str(x) 52 | return genNumber 53 | 54 | 55 | def genShowSeasonEpisodeNumber(self): 56 | self.showEpisodeNumber+=self.showName+' '+'S'+self.genNumber(self.seasonNumber)+'E'+self.genNumber(self.episodeNumber) 57 | return self.showEpisodeNumber 58 | 59 | def validateShowName(self): 60 | imdbResponse = showSeasonAll(self.showName,1) 61 | self.isValidShowName=ast.literal_eval(imdbResponse['Response']) 62 | 63 | if self.isValidShowName == False: 64 | click.echo('Show Name Is Not Valid %s\n' %(self.showName)) 65 | else: 66 | self.showName=imdbResponse['Title'] 67 | self.isValidShowSeasonEpisode = self.isValidShowSeasonEpisode and self.isValidShowName 68 | return self.isValidShowName 69 | 70 | def numberPositive(self): 71 | if self.seasonNumber < 0 : 72 | click.echo('Negative Season Number Not Possible %d\n' %(self.seasonNumber)) 73 | self.isValidShowSeasonEpisode=False 74 | if self.episodeNumber < 0: 75 | click.echo ('Negative Episode Number Not Possible %d\n' %(self.episodeNumber)) 76 | self.isValidShowSeasonEpisode=False 77 | 78 | def setMaxSeason(self): 79 | if self.isValidShowSeasonEpisode: 80 | year=show(self.showName)['Year'].split(u'\u2013') 81 | if year[1] == '' : 82 | self.maxSeason=date.today().year-int(year[0])+1 83 | else: 84 | year=map(int,show(self.showName)['Year'].split(u'\u2013')) 85 | self.maxSeason=year[1]-year[0]+1 86 | 87 | def validateSeasonNumber(self): 88 | if self.seasonNumber > self.maxSeason and self.isValidShowSeasonEpisode: 89 | click.echo ('Exceeding Maximum Available Season %d\n' %(self.maxSeason)) 90 | self.isValidSeasonNumber=False 91 | 92 | self.isValidShowSeasonEpisode = self.isValidShowSeasonEpisode and self.isValidSeasonNumber 93 | 94 | def validateEpisodeNumber(self): 95 | if self.isValidShowSeasonEpisode: 96 | imdbResponse=showSeasonAll(self.showName,self.seasonNumber) 97 | self.maxEpisode=len(imdbResponse['Episodes']) 98 | if self.episodeNumber > self.maxEpisode: 99 | click.echo ('Exceeding Maximum Available Episodes %d\n' %(self.maxEpisode)) 100 | self.isValidEpisode=False 101 | 102 | self.isValidShowSeasonEpisode = self.isValidShowSeasonEpisode and self.isValidSeasonNumber 103 | 104 | 105 | def validateShowSeasonEpisode(self): 106 | self.validateShowName() 107 | self.numberPositive() 108 | self.setMaxSeason() 109 | self.validateSeasonNumber() 110 | self.validateEpisodeNumber() 111 | return self.isValidShowSeasonEpisode 112 | 113 | def getTorrentPage(self,url): 114 | url = self.baseUrl + url 115 | r=requests.get(url,verify=False) 116 | self.torrentPage=BeautifulSoup(r.text,'html.parser') 117 | 118 | def getMagnetLink(self,url): 119 | return self.torrentPage.find('a',{'title':'Magnet link'})['href'] 120 | 121 | def getTorrentSize(self,url): 122 | x=self.torrentPage.find('div',{'class':'widgetSize'}).text.split() 123 | size=float(x[0]) 124 | if x[1]=='GB': 125 | size*=1024 126 | elif x[1]=='KB': 127 | size/=1024 128 | return size 129 | 130 | 131 | def search(self): 132 | availabeTorrent=[] 133 | query=self.showEpisodeNumber.split() 134 | with open(self.basePath + 'data.txt', 'r') as f: 135 | jsonData=simplejson.load(f) 136 | for key,value in jsonData.iteritems(): 137 | found = True 138 | k=key.split() 139 | for q in query: 140 | if q not in k: 141 | found=False 142 | break 143 | if found: 144 | self.getTorrentPage(value) 145 | self.torrentFound=True 146 | availabeTorrent.append([value,self.getTorrentSize(value),self.getMagnetLink(value)]) 147 | availabeTorrent.sort(key=lambda x:float(x[1])) 148 | if self.torrentFound: 149 | if self.quality=='High': 150 | Transmission().addTorrent(availabeTorrent[-1][2]) 151 | else: 152 | Transmission().addTorrent(availabeTorrent[0][2]) 153 | 154 | def addRecord(self): 155 | with open(self.basePath + 'record.txt','r') as f: 156 | save=simplejson.load(f) 157 | if self.showName in save: 158 | click.echo('Show already exists') 159 | self.recordPresent=True 160 | else: 161 | save[self.showName]=[[self.seasonNumber,self.episodeNumber]] 162 | with open(self.basePath + 'record.txt','w') as f: 163 | simplejson.dump(save,f, sort_keys = True, indent = 4, 164 | ensure_ascii=False) 165 | 166 | def deleteAllRecord(self): 167 | with open(self.basePath + 'record.txt','w') as f: 168 | f.write('{ }') 169 | 170 | def deleteRecord(self): 171 | with open(self.basePath + 'record.txt','r') as f: 172 | save=simplejson.load(f) 173 | if self.showName in save: 174 | del save[self.showName] 175 | click.echo('Record Deleted Successfully') 176 | print save 177 | else: 178 | click.echo('Show does not Exist') 179 | with open(self.basePath + 'record.txt','w') as f: 180 | simplejson.dump(save,f, sort_keys = True, indent = 4, 181 | ensure_ascii=False) 182 | 183 | def displayRecord(self): 184 | with open(self.basePath + 'record.txt','r') as f: 185 | save=simplejson.load(f) 186 | for key,value in save.iteritems(): 187 | click.echo('Show Name : %s'%(key)) 188 | click.echo('Season Number : %s'%(value[0][0])) 189 | click.echo('Episode Number : %s'%(value[0][1])) 190 | print 191 | 192 | def incrementRecord(self): 193 | with open(self.basePath + 'record.txt','r') as f: 194 | save=simplejson.load(f) 195 | if self.showName in save: 196 | if save[self.showName][0][1]+1 > self.maxEpisode: 197 | self.deleteRecord() 198 | return 199 | else: 200 | save[self.showName][0][1]+=1 201 | with open(self.basePath + 'record.txt','w') as f: 202 | simplejson.dump(save,f, sort_keys = True, indent = 4, 203 | ensure_ascii=False) 204 | 205 | def scrap(self): 206 | print 'Starting Scrapping' 207 | with open(self.basePath+'data.txt','r') as f: 208 | jsonData=simplejson.load(f) 209 | for i in range(1,self.depth+1): 210 | try: 211 | url=self.baseUrl+'/user/ettv/uploads' 212 | r=requests.get(url,params={'page':i},verify = certifi.where()) 213 | except requests.exceptions.Timeout: 214 | print 'Timeout has occured' 215 | except requests.exceptions.RequestException as e: 216 | print e 217 | soup=BeautifulSoup(r.text,'html.parser') 218 | for x in soup.findAll('a',{'class':'cellMainLink'}): 219 | jsonData[x.string]=x['href'] 220 | print 'End of Page',i 221 | with open(self.basePath + 'data.txt', 'w') as outfile: 222 | simplejson.dump(jsonData, outfile, sort_keys = True, indent = 4, 223 | ensure_ascii=False) 224 | sleep(5) 225 | print 'End Scrapping' 226 | 227 | 228 | def backUpdateRecord(self): 229 | print 'Start Back Updating Record' 230 | with open(self.basePath + 'record.txt','r') as f: 231 | save=simplejson.load(f) 232 | for key,value in save.iteritems(): 233 | click.echo('Show Name : %s'%(key)) 234 | click.echo('Season Number : %s'%(value[0][0])) 235 | click.echo('Episode Number : %s'%(value[0][1])) 236 | print 237 | cur=Kickass(key,value[0][0],value[0][1]) 238 | if cur.validateShowSeasonEpisode() : 239 | cur.genShowSeasonEpisodeNumber() 240 | cur.search() 241 | if cur.torrentFound: 242 | cur.incrementRecord() 243 | else: 244 | click.echo('Torrent not Found') 245 | print 'End Back Updating Record' 246 | 247 | 248 | 249 | --------------------------------------------------------------------------------