Support for fimfiction.net's story passwords and fimfic fail_on_password option.

This commit is contained in:
Jim Miller
2012-02-29 20:11:05 -06:00
parent 9b1b415fec
commit 8d2a1341ce
8 changed files with 48 additions and 18 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ class FanFictionDownLoaderBase(InterfaceActionBase):
description = 'UI plugin to download FanFiction stories from various sites.'
supported_platforms = ['windows', 'osx', 'linux']
author = 'Jim Miller'
version = (1, 5, 4)
version = (1, 5, 5)
minimum_calibre_version = (0, 8, 30)
#: This field defines the GUI plugin class that contains all the code
+22 -7
View File
@@ -159,25 +159,40 @@ class AddNewDialog(SizePersistedDialog):
def get_urlstext(self):
return unicode(self.url.toPlainText())
class FakeLineEdit():
def __init__(self):
pass
def text(self):
pass
class UserPassDialog(QDialog):
'''
Need to collect User/Pass for some sites.
'''
def __init__(self, gui, site):
def __init__(self, gui, site, exception=None):
QDialog.__init__(self, gui)
self.gui = gui
self.status=False
self.setWindowTitle('User/Password')
self.l = QGridLayout()
self.setLayout(self.l)
self.l.addWidget(QLabel("%s requires you to login to download this story."%site),0,0,1,2)
if exception.passwdonly:
self.setWindowTitle('Password')
self.l.addWidget(QLabel("Author requires a password for this story(%s)."%exception.url),0,0,1,2)
# user isn't used, but it's easier to still have it for
# post processing.
self.user = FakeLineEdit()
else:
self.setWindowTitle('User/Password')
self.l.addWidget(QLabel("%s requires you to login to download this story."%site),0,0,1,2)
self.l.addWidget(QLabel("User:"),1,0)
self.user = QLineEdit(self)
self.l.addWidget(self.user,1,1)
self.l.addWidget(QLabel("User:"),1,0)
self.user = QLineEdit(self)
self.l.addWidget(self.user,1,1)
self.l.addWidget(QLabel("Password:"),2,0)
self.passwd = QLineEdit(self)
+2 -2
View File
@@ -419,9 +419,9 @@ class FanFictionDownLoaderPlugin(InterfaceAction):
for x in range(0,2):
try:
adapter.getStoryMetadataOnly()
except exceptions.FailedToLogin:
except exceptions.FailedToLogin, f:
print("Login Failed, Need Username/Password.")
userpass = UserPassDialog(self.gui,url)
userpass = UserPassDialog(self.gui,url,f)
userpass.exec_() # exec_ will make it act modal
if userpass.status:
adapter.username = userpass.user.text()
+5
View File
@@ -381,6 +381,11 @@ output_filename: ${title}-${siteabbrev}_${authorId}_${storyId}${formatext}
## this should go in your personal.ini, not defaults.ini.
#is_adult:true
## fimfiction.net stories can be locked requiring individual
## passwords. If fail_on_password is set, the downloader will fail
## when a password is required rather than prompting every time.
#fail_on_password: false
[www.tthfanfic.org]
## Some sites do not require a login, but do require the user to
## confirm they are adult for adult content. In commandline version,
+7 -4
View File
@@ -137,10 +137,13 @@ def main():
for x in range(0,2):
try:
adapter.getStoryMetadataOnly()
except exceptions.FailedToLogin:
print "Login Failed, Need Username/Password."
sys.stdout.write("Username: ")
adapter.username = sys.stdin.readline().strip()
except exceptions.FailedToLogin, f:
if f.passwdonly:
print "Story requires a password."
else:
print "Login Failed, Need Username/Password."
sys.stdout.write("Username: ")
adapter.username = sys.stdin.readline().strip()
adapter.password = getpass.getpass(prompt='Password: ')
#print("Login: `%s`, Password: `%s`" % (adapter.username, adapter.password))
except exceptions.AdultCheckRequired:
@@ -96,7 +96,10 @@ class FimFictionNetSiteAdapter(BaseSiteAdapter):
data = self._postUrl(self.url,params)
if "Enter the password the author set for this story to view it." in data:
raise exceptions.FailedToLogin(self.url,"Story requires individual password")
if self.getConfig('fail_on_password'):
raise exceptions.FailedToDownload("%s requires story password and fail_on_password is true."%self.url)
else:
raise exceptions.FailedToLogin(self.url,"Story requires individual password",passwdonly=True)
soup = bs.BeautifulSoup(data).find("div", {"class":"content_box post_content_box"})
+1 -1
View File
@@ -313,7 +313,7 @@ class BaseSiteAdapter(Configurable):
if self.getConfig('replace_hr'):
# replacing a self-closing tag with a container tag in the
# soup is more difficult than it first appears. So cheat.
retval = retval.replace("<hr />","<div class='center'>* * *</div>")
retval = retval.replace("<hr />","<div class='center'>* * *</div>")
# Don't want body tags in chapter html--writers add them.
# This is primarily for epub updates.
+6 -2
View File
@@ -34,12 +34,16 @@ class InvalidStoryURL(Exception):
return "Bad Story URL: (%s) for site: (%s) Example: (%s)" % (self.url, self.domain, self.example)
class FailedToLogin(Exception):
def __init__(self,url,username):
def __init__(self,url, username, passwdonly=False):
self.url=url
self.username=username
self.passwdonly=passwdonly
def __str__(self):
return "Failed to Login for URL: (%s) with username: (%s)" % (self.url, self.username)
if self.passwdonly:
return "URL Failed, password required: (%s) " % (self.url)
else:
return "Failed to Login for URL: (%s) with username: (%s)" % (self.url, self.username)
class AdultCheckRequired(Exception):
def __init__(self,url):