Last active
December 15, 2015 22:50
-
-
Save adngdb/5336158 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import base64 | |
import libtorrent as lt | |
import os | |
import shutil | |
import thread | |
import time | |
import tkFont | |
import urllib2 | |
from bs4 import BeautifulSoup | |
from Tkinter import * | |
class App: | |
def __init__(self, master): | |
self.master = master | |
master.title('Download Console Lite') | |
try: | |
URL = 'http://i.imgur.com/B89o9PR.gif' | |
u = urllib2.urlopen(URL) | |
raw_data = u.read() | |
u.close() | |
b64_data = base64.encodestring(raw_data) | |
bg = PhotoImage(data=b64_data) | |
except: | |
master.exit() | |
bgwidth = bg.width() | |
bgheight = bg.height() | |
master.maxsize(bgwidth, bgheight) | |
master.minsize(bgwidth, bgheight) | |
print bg.width() | |
print bg.height() | |
master.geometry('%dx%d+%d+%d' % ( | |
bgwidth, | |
bgheight, | |
(master.winfo_screenwidth() - bgwidth) / 2, | |
(master.winfo_screenheight() - bgheight) / 2 | |
)) | |
master.bind('<Return>',lambda event:self.download()) | |
self.panel1 = Label(self.master,image=bg) | |
self.panel1.image = bg | |
self.panel1.pack() | |
self.aboutFont = tkFont.Font( | |
family='Segoe UI', | |
weight='normal', | |
slant='roman', | |
size=10 | |
) | |
self.entryFont = tkFont.Font( | |
family='Helvetica', | |
size=16 | |
) | |
self.buttonFont = tkFont.Font( | |
family='Helvetica', | |
size=11, | |
weight='bold' | |
) | |
master.e = Entry(master, width=38, font=self.entryFont) | |
master.e.insert(0, 'Type a movie title') | |
master.e.place(relx=0.5, rely=0.3, anchor=CENTER) | |
master.increments = 0.485 | |
self.dlsite = 'thepiratebay.se' | |
self.sites = { | |
'thepiratebay.se':PIRATE, | |
'cpasbien.me':CPASBIEN, | |
'kat.ph':KATPH | |
} | |
def txtdlt(): | |
master.e.delete(0, END) | |
master.e.unbind('<Button-1>') | |
master.e.bind('<Button-1>', txtdlt) | |
self.b = Button( | |
master, | |
text='DOWNLOAD', | |
command=self.download, | |
font=self.buttonFont | |
) | |
self.b.place(relx=0.5, rely=0.4, anchor=CENTER) | |
menu = Menu(self.master, tearoff=0) | |
menu.add_command(label='thepiratebay.se', command=self.pirate) | |
menu.add_command(label='cpasbien.me', command=self.cpasbien) | |
#menu.add_command(label='kat.ph', command=self.katph) | |
menu.add_command(label='About', command=self.bringAbout) | |
def popup(event): | |
menu.post(event.x_root, event.y_root) | |
self.panel1.bind('<Button-3>', popup) | |
master.dlDict = {} | |
# Est-ce que ce n'est pas le même que self.sites ? | |
self.sitesDict = { | |
'cpasbien.me': CPASBIEN, | |
'thepiratebay.se': PIRATE, | |
'kat.ph': KATPH | |
} | |
if os.path.exists('dldict.txt'): | |
with open('dldict.txt') as data: | |
for line in data.read().splitlines(): | |
if line.split()[-1] in self.sites: | |
key = ' '.join([word for word in line.split()[:-1]]) | |
master.dlDict[key] = line.split()[-1] | |
else: | |
master.dlDict[line.split()] = self.dlsite | |
os.unlink('dldict.txt') | |
for element in master.dlDict: | |
self.download(element,master.dlDict[element]) | |
master.protocol('WM_DELETE_WINDOW',self.quitHandler) | |
master.mainloop() | |
def pirate(self): | |
self.dlsite = 'thepiratebay.se' | |
def cpasbien(self): | |
self.dlsite = 'cpasbien.me' | |
def katph(self): | |
self.dlsite = 'kat.ph' | |
def download(self, movie=None, dlsite=None): | |
'''Launches download of either movie argument searching in dlsite argument website, | |
or of Entry widget contents in self.dlsite website. | |
''' | |
# This launches unfinished downloads on startup | |
if movie: | |
movieList = [movie] | |
if dlsite: | |
self.dlsite = dlsite | |
# This launches download for movies typed in text field | |
else: | |
movieList = (self.master.e.get().split(',')) | |
for movie in movieList: | |
if movie and movie != 'Type a movie title': | |
a = self.sites[self.dlsite](movie, self.master) | |
ent = a.dlDictEntry(movie) | |
if a.isLink(): | |
self.master.dlDict[ent[0]] = ent[1] | |
def quitHandler(self): | |
'''Saves current unfinised downloads in dllist.txt upon closeup | |
in order to start them again on startup. | |
''' | |
if os.path.isfile('dlc.pid'): | |
os.unlink('dlc.pid') | |
if self.master.dlDict: | |
with open('dldict.txt','w') as data: | |
data.truncate() | |
data.write('\n'.join( | |
['%s %s' % (element, self.master.dlDict[element]) | |
for element in self.master.dlDict] | |
)) | |
self.master.destroy() | |
self.master.quit() | |
def bringAbout(self): | |
'''brings About menu''' | |
top = Toplevel(self.master, takefocus=True, bg='black') | |
top.overrideredirect(True) | |
top.geometry('370x280+500+350') | |
messageContent = '''dl console lite: a klb python project | |
design by elysirbu | |
made with tkinter | |
using libtorrent and beautifulsoup | |
currently searching on %s | |
press enter to go back | |
''' | |
msg = Label(top, | |
width=370, | |
height=280, | |
anchor=NW, | |
text=messageContent % self.dlsite, | |
bg='#3c3c3c', | |
fg='white', | |
justify=LEFT, | |
font=self.aboutFont | |
) | |
msg.pack() | |
top.focus() | |
top.bind('<Return>', top.destroy) | |
class Downloader: | |
def __init__(self, movie, master): | |
self.master = master | |
self.movie = movie | |
self.link = self.findLink(movie) | |
if self.link: | |
# starts download in new thread | |
thread.start_new_thread(self.dlTorrent, (self.link,)) | |
master.e.delete(0, END) | |
else: | |
print 'not found' | |
errorLab = (Label( | |
master, | |
text='NOT FOUND', | |
bg='#3c3c3c', | |
fg='red' | |
)) | |
errorLab.place(relx=0.75, rely=0.4, anchor=CENTER) | |
errorLab.after(5000, errorLab.destroy) | |
def findLink(self, movie): | |
raise NotImplementedError | |
def dlTorrent(self, link): | |
raise NotImplementedError | |
def setSite(self): | |
raise NotImplementedError | |
def dlDictEntry(self,movie): | |
print [movie, self.setSite()] | |
return [movie, self.setSite()] | |
def isLink(self): | |
return bool(self.link) | |
def manageWidgets(self): | |
self.stringvar = StringVar() | |
self.label = Label( | |
self.master, | |
textvariable=self.stringvar, | |
bg='#3c3c3c', | |
fg='white', | |
anchor=W | |
) | |
self.label.place( | |
relx=0.37, | |
rely=self.master.increments, | |
width=300, | |
height=15, | |
anchor=CENTER | |
) | |
self.button = Button( | |
self.master, | |
text='CANCEL', | |
command=self.removeTorrent | |
) | |
self.button.place( | |
relx=0.8, | |
rely=self.master.increments + 0.01, | |
anchor=CENTER | |
) | |
self.master.increments += 0.08 | |
## to fix as it works only for magnet links | |
while not self.handle.has_metadata(): | |
time.sleep(1) | |
self.stringvar.set('Starting %s download...' % self.movie.title()) | |
time.sleep(2) | |
while self.handle.status().state != lt.torrent_status.seeding: | |
print repr(self.handle.status().state) | |
time.sleep(1) | |
if self.stringvar.get() != '%s download aborted.' % self.movie.title(): | |
self.stringvar.set( | |
'%s %d %% done' % ( | |
self.movie.title(), | |
self.handle.status().progress * 100 | |
) | |
) | |
time.sleep(2) | |
else: | |
thread.exit() | |
self.stringvar.set('%s downloaded.' % self.movie.title()) | |
del self.master.dldict[self.movie] | |
thread.exit() | |
def removeTorrent(self): | |
if self.stringvar.get() != '%s downloaded.' % self.movie.title(): | |
try: | |
self.ses.remove_torrent(self.handle, 1) | |
self.stringvar.set('%s download aborted.' % self.movie.title()) | |
del self.master.dlDict[self.movie] | |
time.sleep(.5) | |
self.stringvar.set('%s download aborted.' % self.movie.title()) | |
except: | |
pass | |
def destroyBoth(): | |
self.label.destroy() | |
self.button.destroy() | |
self.master.after(1000, destroyBoth) | |
class CPASBIEN(Downloader): | |
def findLink(self,movie): | |
''' | |
Finds link and downloads torrent file | |
in temp.torrent. Returns None if link not found. | |
''' | |
movie = '-'.join([e for e in movie.split()]) | |
search = 'http://www.cpasbien.me/recherche/'+movie+'.html,trie-seeds-d' | |
soup = BeautifulSoup(urllib2.urlopen(search).read()) | |
moviepage = None | |
for url in soup.find_all('a'): | |
## should be fixed so search terms do not have to be so literal | |
if movie + '-' in str(url): | |
moviepage = url.get('href') | |
break | |
if moviepage: | |
soup = BeautifulSoup(urllib2.urlopen(moviepage).read()) | |
for url in soup.find_all('a'): | |
if '.torrent' in str(url): | |
link = url.get('href') | |
break | |
r = urllib2.urlopen(urllib2.Request(link)) | |
with open('temp.torrent', 'wb') as f: | |
shutil.copyfileobj(r,f) | |
r.close() | |
return link | |
return None | |
def dlTorrent(self,link): | |
self.ses = lt.session() | |
self.ses.listen_on(27041, 27042) | |
info = lt.torrent_info('temp.torrent') | |
self.handle = self.ses.add_torrent({ | |
'ti': info, | |
'save_path': os.path.join(os.path.expanduser('~'), 'Desktop') | |
}) | |
os.unlink('temp.torrent') | |
self.manageWidgets() | |
def setSite(self): | |
self.site = 'cpasbien.me' | |
return self.site | |
class PIRATE(Downloader): | |
def findLink(self,movie): | |
movie = '%20'.join([e for e in movie.split()]) | |
search = 'http://thepiratebay.se/search/%s/0/7/200' % movie | |
soup = BeautifulSoup(urllib2.urlopen(search).read()) | |
for link in soup.find_all('a'): | |
if link.get('href')[0:8] == 'magnet:?': | |
return link.get('href') | |
return None | |
def dlTorrent(self,link): | |
self.ses = lt.session() | |
self.handle = lt.add_magnet_uri( | |
self.ses, | |
link, | |
{'save_path': os.path.join(os.path.expanduser('~'), 'Desktop')} | |
) | |
self.manageWidgets() | |
def setSite(self): | |
self.site = 'thepiratebay.se' | |
return self.site | |
class KATPH(Downloader): | |
def findLink(self,movie): ## TO IMPLEMENT | |
pass | |
def dlTorrent(self,link): ## TO IMPLEMENT | |
pass | |
def setSite(self): | |
self.site = 'kat.ph' | |
return self.site | |
if __name__ == "__main__": | |
App(Tk()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment