diff --git a/readme.md b/readme.md index c3f3470..1a1a7ee 100644 --- a/readme.md +++ b/readme.md @@ -1,32 +1,41 @@ -# Pirate.py +# The Pirate -Command line torrent downloader with [Pushbullet](https://pushbullet.com) notifications. +#####Command line torrent downloader with [Pushbullet](https://pushbullet.com) notifications. + +Add torrents to your Transmission download queue from anywhere, either via Pushbullet magnet link push or remote procedure calls[https://trac.transmissionbt.com/wiki/rpc] direct to the machine. + +- Default behavior parses HTML pages on [ThePirateBay](https://thepiratebay.se) based on a search string provided, then passes the magnet link to a locally running Transmission-Daemon (localhost or same LAN). Can also add direct HTML pages of the desired torrent with --url, and direct magnet links and torrent files with --file. +This script was written in Python version 2.7. Version 3 compatibility requires rewriting some code, and may be done at a later time. Pull requests welcome. + ---- ### Requirements -#### Client Side (pirate.py) +2 Parter. Either do it all on localhost, or configure a second machine for headless management. -This script was written in Python version 2.7. Version 3 compatibility requires rewriting some code, and may be done at a later time. Pull requests welcome. + * Client setup + * Server setup + +#### Client Side (thepirate) -3 external Python libraries needed. Please ensure the following are installed to the system: +3 external Python libraries needed. Please ensure the following are installed to the system * transmissionrpc * requests * beautifulsoup4 -If pip is installed, just run the following as root: +> TIP: If pip is installed, just run the following as root: ``` $ pip install transmissionrpc requests beautifulsoup4 ``` -Then edit the pirate.py file, and change the __rpcserver__ variable to the server's IP/hostname (if not localhost) +Then edit the thepirate.py file, and change the __rpcserver__ variable to the server's IP/hostname (if not localhost) #### Server Side (transmission-daemon and pirate-remote.py) @@ -57,6 +66,7 @@ Put your PushBullet API key in api variable in the script and set a cron job to Make sure the server running Transmission (if not localhost) is accepting traffic on TCP/9091 and RPC is enabled in the Transmission settings.json file. Read about configuring Transmission [here](https://trac.transmissionbt.com/wiki/EditConfigFiles). +![img](img/transmissionrpc_config.conf.png) ### Usage @@ -65,13 +75,13 @@ Place the script somewhere in your executable path. I like ~/bin ``` $ mkdir ~/bin $ echo 'PATH=$PATH:~/bin' >> ~/.bashrc && source ~/.bashrc -$ cp pirate/pirate.py ~/bin +$ cp pirate/thepirate.py ~/bin/thepirate ``` Then just run it ``` -$ pirate.py +$ thepirate ``` @@ -80,3 +90,5 @@ $ pirate.py * Refactor code; not a fan of the spaghetti code functions * Comment script better; for personal reasons. I hate being confused 6 months later * Pushbullet read/download new torrents + * Add config file support + diff --git a/thepirate-satellite.py b/thepirate-satellite.py new file mode 100755 index 0000000..dfc9d3c --- /dev/null +++ b/thepirate-satellite.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +""" +This Python script auto-adds new torrents from Pushbullet notes if string starts with magnet:? +and combs through transmission downloads and removes torrents when 100% fully downloaded. Great for keeping my +ISP off my back. Sends Pushbullet notes on torrent add/remove + +Run this as a cron job on the same server as transmission + +Learn more about PushBullet here: +pushbullet.com +""" + +__author__ = 'lance - github.com/lalanza808' + + +import transmissionrpc +import pushbullet +import requests +from time import sleep +from os import path,system + +# Put your API key into a text file +api = 'xxxxxxxxxx' + +# Get rid of the SSL warnings +requests.packages.urllib3.disable_warnings() + +################################################## +# Connect to transmission + +t = transmissionrpc.Client('localhost', port=9091) +pb = pushbullet.Pushbullet(api) + +# Remove completed torrents +for torrent in t.get_torrents(): + if torrent.percentDone == 1: + print "[+] Removing torrent:\t{}".format(torrent.name) + pb.push_note("Torrent Complete", torrent.name) + sleep(3) + t.remove_torrent(torrent.id) + +# Add new torrents +pushes = pb.get_pushes() +for push in pushes[1]: + if push['body'].startswith('magnet:?'): + system('/opt/pirate/pirate.py --file {}'.format(str(push['body']))) + pb.delete_push(push['iden']) + diff --git a/thepirate.py b/thepirate.py new file mode 100755 index 0000000..94a0e35 --- /dev/null +++ b/thepirate.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python + + +""" +The Pirate Bay scraper - This is the client + +Uses 3 external libraries for scraping HTML elements from ThePirateBay and interacting with transmission-daemon. +Asks user for a search selection, offers a list of choices, and grabs the magnet link for the selection in a menu style fashion. + +""" + +__author__ = 'LANCE - https://github.com/lalanza808' + + +################################################## +# Libraries + +# Built-in libraries +from os import path +import argparse + +# 3rd party libraries +import requests +import bs4 +import transmissionrpc + +################################################## +# Variables + +# Dictionaries/Arrays for storing search results +results = {} +links = [] +choice = "" + +# Current/working PirateBay URL +tpb = "https://thepiratebay.se" + +# Torrent server IP; can be any machine running transmission-daemon +# with a firewall inbound allowed to TCP/9091 (transmissionrpc) +rpcserver = 'localhost' + +# Squelch HTTPS insecure warnings +requests.packages.urllib3.disable_warnings() + +################################################## +# Parsing and Arguments + +parser = argparse.ArgumentParser(description='Scrape The Pirate Bay for torrents.') + +parser.add_argument('--search', '-s', dest='searcharg', help='The string to search for on TPB', required=False) + +parser.add_argument('--top', '-t', dest='top', action='store_true', help='Automatically grab the torrent with most seeds', required=False) + +parser.add_argument('--file', '-l', dest='file', help='Direct link to magnet or torrent file', required=False) + +parser.add_argument('--url', '-u', dest='url', help='HTML page of the torrent file', required=False) + +args = parser.parse_args() + + +################################################## +# Functions + +def checkTransmission(): + """ + Checks to see if transmission-daemon is running on rpcserver + and and initiates the function to ask user for input + """ + try: + transmissionrpc.Client(rpcserver, port=9091) + getSearchURL() + except KeyboardInterrupt: + print "\n\nLater bro." + exit(1) + except transmissionrpc.error.TransmissionError: + print "[!] Transmission-daemon not running on {}!".format(rpcserver) + exit(2) + + +def getSearchURL(): + """ + Takes input string to search for on TPB. + Formats string into proper url + Gets HTML source of search page for use in the next function + """ + if args.file: + transmissionrpc.Client(rpcserver).add_torrent(args.file) + exit(0) + elif args.url: + downloadTorrent(args.url) + exit(0) + elif args.searcharg: + searchString = args.searcharg + else: + searchString = raw_input("[+] What would you like to search?\n>>> ") + + searchURL = "{}/search/{}/0/7/0".format(tpb, searchString) #/0/7/0 tells TPB to sort descending by seeds + + pageSource = requests.get(searchURL, verify=False).text #Use requests lib to fetch page source for bs4 parsing + + analyzeURL(pageSource) #Run analyzeURL function, passing page source + + +def analyzeURL(source): + """ + Takes the page source and parses it with BeautifulSoup. + Finds all anchor elements on the page, pre-sorted by seeders + Enumerates list of elements, and adds them to results dictionary + """ + print "\n" + global links, results + + #Update the links array with the returned torrents + pageSoup = bs4.BeautifulSoup(source) #Create Beautiful Soup object + for link in pageSoup.find_all('a'): #Find all anchor elements in page source + if link.get('href').startswith('/torrent'): #Filter items that don't start with /torrent + links.append(link.get('href')) #Set the initial results to array 'links' + + + #If -t is supplied, bypass this section of code and go on to download the top torrent + if args.top and links: + downloadTorrent("{}/{}".format(tpb, links[0])) + else: + for number,link in enumerate(links): #Enumerate the array so the numbers start at 0 + results.update({number:link}) #Append results to results dictionary + print "({}) {}".format(number, path.basename(link)) + + if results: #If dict is not empty, continue with script + print "\n(98) Search again" + print "(99) Exit" + chooseTorrent() + else: #If dict is empty (no results from search) re-run script + print "\nNo results found. Try again." + results = {} + links = [] + args.searcharg = '' + getSearchURL() #Loop back to script start + + +def chooseTorrent(): + """ + Asks for selection of torrent, and prepares for the download + """ + global links, results + + try: + selection = int(raw_input("\n[+] Enter the digit of the torrent to download.\n>>> ")) + if selection == 98: + print "\nStarting over" + results = {} + links = [] + args.searcharg = '' + getSearchURL() #Loop back to start + elif selection == 99: + print "\nBye.\n" + exit() #Quit script + elif selection in results: #If selection exists, set value to 'choice' variable + choice = results[selection] #Updates variable based on key provided above, matches it with results dict + downloadTorrent("{}/{}".format(tpb, choice)) + else: #If anything other than 98, 99, or valid key number entered, loop back to selection input + print "\nNot a valid number" + chooseTorrent() + + except ValueError: + print "\nThat is not a digit." + chooseTorrent() + + +def downloadTorrent(torrentURL): + """ + Grabs the first magnet link and initiates the download using the transmissionrpc python library + """ + + magnetLinks = [] + + torrentPage = requests.get(torrentURL, verify=False) + torrentPageSoup = bs4.BeautifulSoup(torrentPage.content) + + for link in torrentPageSoup.find_all('a'): + if str(link.get('href')).startswith('magnet:?xt'): + magnetLinks.append(link.get('href')) + + magnetLink = magnetLinks[0] + + print "\n[+] Adding magnet link for torrent:\n\n{}".format(torrentURL) + + transmissionrpc.Client(rpcserver).add_torrent(magnetLink) + + print "\n[.] Done!\n" + + exit(0) + +if __name__ == "__main__": + checkTransmission()