Update to Python3 and some other fixes
This commit is contained in:
parent
db8d9e953b
commit
d062eb1dd8
@ -4,8 +4,14 @@ Python script to automate the use of FanFicFare CLI (https://github.com/JimmXinu
|
|||||||
|
|
||||||
Primary script is fanficdownload.py. Use -h or --help to see the options.
|
Primary script is fanficdownload.py. Use -h or --help to see the options.
|
||||||
|
|
||||||
|
All of the options can be loaded into the config file, of which the template is provided in `config_template.ini`, and utilized with `python3 fanficdownload.py -c path_to_config.ini`.
|
||||||
|
|
||||||
There is additional support for notifications, including pushbullet integration, through runner_notify. Use -h to see options.
|
There is additional support for notifications, including pushbullet integration, through runner_notify. Use -h to see options.
|
||||||
|
|
||||||
Works with Fanficfare 2.3.6+. Rewrite underway to take advantage of new features in Fanficfare 2.4.0
|
Works with Fanficfare 2.3.6+. Rewrite underway to take advantage of new features in Fanficfare 2.4.0
|
||||||
|
|
||||||
|
Requires Python 3.6.9. Unsure if it will work on higher versions of Python.
|
||||||
|
|
||||||
For basic cron usage, this is not needed, `fanficfare -dowload-imap -u` should work if you're not integrating into calibre. This script is best used if you want to update the calibre library, for the usage of calibre-server for instance.
|
For basic cron usage, this is not needed, `fanficfare -dowload-imap -u` should work if you're not integrating into calibre. This script is best used if you want to update the calibre library, for the usage of calibre-server for instance.
|
||||||
|
|
||||||
|
If anything does not work, please open a ticket.
|
@ -1,17 +1,27 @@
|
|||||||
|
# Email Login Information, so that the script can download from email subscription notifications.
|
||||||
[login]
|
[login]
|
||||||
|
# Username for email
|
||||||
user=
|
user=
|
||||||
|
# Password for email
|
||||||
password=
|
password=
|
||||||
|
# IMAP address for email
|
||||||
server=
|
server=
|
||||||
|
# The mailbox to look in the emails for, such as INBOX
|
||||||
mailbox=
|
mailbox=
|
||||||
|
|
||||||
[locations]
|
[locations]
|
||||||
|
# Web Address for the calibre library to update
|
||||||
library=
|
library=
|
||||||
|
# Path to file to read links from, or to output links that didn't work.
|
||||||
input=
|
input=
|
||||||
|
|
||||||
|
# If you want to user runner_notify.py to send alerts to your phone, fill out the fields here.
|
||||||
[runner]
|
[runner]
|
||||||
notification=
|
notification=
|
||||||
pushbullet=
|
pushbullet=
|
||||||
pbdevice=
|
pbdevice=
|
||||||
|
tag=
|
||||||
|
|
||||||
|
# How to display output. True will display as the program runs, false will wait until the end.
|
||||||
[output]
|
[output]
|
||||||
live=
|
live=
|
||||||
|
@ -5,7 +5,7 @@ from subprocess import check_output, STDOUT, call, PIPE
|
|||||||
import logging
|
import logging
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
import re
|
import re
|
||||||
from ConfigParser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
import socket
|
import socket
|
||||||
@ -61,7 +61,7 @@ def log(msg, color=None, output=True):
|
|||||||
bcolors.ENDC,
|
bcolors.ENDC,
|
||||||
msg)
|
msg)
|
||||||
if output:
|
if output:
|
||||||
print line
|
print(line)
|
||||||
return ""
|
return ""
|
||||||
else:
|
else:
|
||||||
return line + "\n"
|
return line + "\n"
|
||||||
@ -72,10 +72,11 @@ def touch(fname, times=None):
|
|||||||
utime(fname, times)
|
utime(fname, times)
|
||||||
|
|
||||||
|
|
||||||
ffnet = re.compile('(fanfiction.net/s/\d*)/?.*')
|
url_parsers = [(re.compile('(fanfiction.net/s/\d*)/?.*'), "www."), #ffnet
|
||||||
aooo = re.compile('(archiveofourown.org/works/\d*)/?.*')
|
(re.compile('(archiveofourown.org/works/\d*)/?.*'), ""), #ao3
|
||||||
ficpress = re.compile('(fictionpress.com/s/\d*)/?.*')
|
(re.compile('(fictionpress.com/s/\d*)/?.*'), ""), #fictionpress
|
||||||
neutral = re.compile('https?://(.*)')
|
(re.compile('(royalroad.com/fiction/\d*)/?.*'), ""), #royalroad
|
||||||
|
(re.compile('https?://(.*)'), "")] #other sites
|
||||||
story_name = re.compile('(.*)-.*')
|
story_name = re.compile('(.*)-.*')
|
||||||
|
|
||||||
equal_chapters = re.compile('.* already contains \d* chapters.')
|
equal_chapters = re.compile('.* already contains \d* chapters.')
|
||||||
@ -89,14 +90,10 @@ more_chapters = re.compile(
|
|||||||
|
|
||||||
|
|
||||||
def parse_url(url):
|
def parse_url(url):
|
||||||
if ffnet.search(url):
|
for cur_parser, cur_prefix in url_parsers:
|
||||||
url = "www." + ffnet.search(url).group(1)
|
if cur_parser.search(url):
|
||||||
elif aooo.search(url):
|
url = cur_prefix + cur_parser.search(url).group(1)
|
||||||
url = aooo.search(url).group(1)
|
return url
|
||||||
elif ficpress.search(url):
|
|
||||||
url = ficpress.search(url).group(1)
|
|
||||||
elif neutral.search(url):
|
|
||||||
url = neutral.search(url).group(1)
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
@ -135,12 +132,12 @@ def downloader(args):
|
|||||||
try:
|
try:
|
||||||
storyId = check_output(
|
storyId = check_output(
|
||||||
'calibredb search "Identifiers:{}" {}'.format(
|
'calibredb search "Identifiers:{}" {}'.format(
|
||||||
url, path), shell=True, stderr=STDOUT, stdin=PIPE, )
|
url, path), shell=True, stderr=STDOUT, stdin=PIPE, ).decode('utf-8')
|
||||||
output += log("\tStory is in calibre with id {}".format(storyId), 'BLUE', live)
|
output += log("\tStory is in calibre with id {}".format(storyId), 'BLUE', live)
|
||||||
output += log("\tExporting file", 'BLUE', live)
|
output += log("\tExporting file", 'BLUE', live)
|
||||||
res = check_output(
|
res = check_output(
|
||||||
'calibredb export {} --dont-save-cover --dont-write-opf --single-dir --to-dir "{}" {}'.format(
|
'calibredb export {} --dont-save-cover --dont-write-opf --single-dir --to-dir "{}" {}'.format(
|
||||||
storyId, loc, path), shell=True, stdin=PIPE, stderr=STDOUT)
|
storyId, loc, path), shell=True, stdin=PIPE, stderr=STDOUT).decode('utf-8')
|
||||||
cur = get_files(loc, ".epub", True)[0]
|
cur = get_files(loc, ".epub", True)[0]
|
||||||
output += log(
|
output += log(
|
||||||
'\tDownloading with fanficfare, updating file "{}"'.format(cur),
|
'\tDownloading with fanficfare, updating file "{}"'.format(cur),
|
||||||
@ -156,11 +153,11 @@ def downloader(args):
|
|||||||
shell=True,
|
shell=True,
|
||||||
stderr=STDOUT,
|
stderr=STDOUT,
|
||||||
stdin=PIPE,
|
stdin=PIPE,
|
||||||
)
|
).decode('utf-8')
|
||||||
output += log('\tRunning: {}fanficfare -u "{}" --update-cover'.format(
|
output += log('\tRunning: {}fanficfare -u "{}" --update-cover'.format(
|
||||||
moving, cur), 'BLUE', live)
|
moving, cur), 'BLUE', live)
|
||||||
res = check_output('{}fanficfare -u "{}" --update-cover'.format(
|
res = check_output('{}fanficfare -u "{}" --update-cover'.format(
|
||||||
moving, cur), shell=True, stderr=STDOUT, stdin=PIPE)
|
moving, cur), shell=True, stderr=STDOUT, stdin=PIPE).decode('utf-8')
|
||||||
check_regexes(res)
|
check_regexes(res)
|
||||||
if chapter_difference.search(res) or more_chapters.search(res):
|
if chapter_difference.search(res) or more_chapters.search(res):
|
||||||
output += log("\tForcing download update due to:",
|
output += log("\tForcing download update due to:",
|
||||||
@ -170,7 +167,7 @@ def downloader(args):
|
|||||||
output += log("\t\t{}".format(line), 'WARNING', live)
|
output += log("\t\t{}".format(line), 'WARNING', live)
|
||||||
res = check_output(
|
res = check_output(
|
||||||
'{}fanficfare -u "{}" --force --update-cover'.format(
|
'{}fanficfare -u "{}" --force --update-cover'.format(
|
||||||
moving, cur), shell=True, stderr=STDOUT, stdin=PIPE)
|
moving, cur), shell=True, stderr=STDOUT, stdin=PIPE).decode('utf-8')
|
||||||
check_regexes(res)
|
check_regexes(res)
|
||||||
cur = get_files(loc, '.epub', True)[0]
|
cur = get_files(loc, '.epub', True)[0]
|
||||||
|
|
||||||
@ -185,25 +182,25 @@ def downloader(args):
|
|||||||
shell=True,
|
shell=True,
|
||||||
stderr=STDOUT,
|
stderr=STDOUT,
|
||||||
stdin=PIPE,
|
stdin=PIPE,
|
||||||
)
|
).decode('utf-8')
|
||||||
except BaseException:
|
except BaseException:
|
||||||
if not live:
|
if not live:
|
||||||
print output.strip()
|
print(output.strip())
|
||||||
raise
|
raise
|
||||||
|
|
||||||
output += log("\tAdding {} to library".format(cur), 'BLUE', live)
|
output += log("\tAdding {} to library".format(cur), 'BLUE', live)
|
||||||
try:
|
try:
|
||||||
res = check_output(
|
res = check_output(
|
||||||
'calibredb add -d {} "{}"'.format(path, cur), shell=True, stderr=STDOUT, stdin=PIPE, )
|
'calibredb add -d {} "{}"'.format(path, cur), shell=True, stderr=STDOUT, stdin=PIPE, ).decode('utf-8')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
output += log(e)
|
output += log(e)
|
||||||
if not live:
|
if not live:
|
||||||
print output.strip()
|
print(output.strip())
|
||||||
raise
|
raise
|
||||||
try:
|
try:
|
||||||
res = check_output(
|
res = check_output(
|
||||||
'calibredb search "Identifiers:{}" {}'.format(
|
'calibredb search "Identifiers:{}" {}'.format(
|
||||||
url, path), shell=True, stderr=STDOUT, stdin=PIPE)
|
url, path), shell=True, stderr=STDOUT, stdin=PIPE).decode('utf-8')
|
||||||
output += log("\tAdded {} to library with id {}".format(cur,
|
output += log("\tAdded {} to library with id {}".format(cur,
|
||||||
res), 'GREEN', live)
|
res), 'GREEN', live)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
@ -216,7 +213,7 @@ def downloader(args):
|
|||||||
else:
|
else:
|
||||||
res = check_output(
|
res = check_output(
|
||||||
'cd "{}" && fanficfare -u "{}" --update-cover'.format(
|
'cd "{}" && fanficfare -u "{}" --update-cover'.format(
|
||||||
loc, url), shell=True, stderr=STDOUT, stdin=PIPE)
|
loc, url), shell=True, stderr=STDOUT, stdin=PIPE).decode('utf-8')
|
||||||
check_regexes(res)
|
check_regexes(res)
|
||||||
cur = get_files(loc, '.epub', True)[0]
|
cur = get_files(loc, '.epub', True)[0]
|
||||||
name = get_files(loc, '.epub', False)[0]
|
name = get_files(loc, '.epub', False)[0]
|
||||||
@ -228,12 +225,12 @@ def downloader(args):
|
|||||||
'GREEN',
|
'GREEN',
|
||||||
live)
|
live)
|
||||||
if not live:
|
if not live:
|
||||||
print output.strip()
|
print(output.strip())
|
||||||
rmtree(loc)
|
rmtree(loc)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
output += log("Exception: {}".format(e), 'FAIL', live)
|
output += log("Exception: {}".format(e), 'FAIL', live)
|
||||||
if not live:
|
if not live:
|
||||||
print output.strip()
|
print(output.strip())
|
||||||
try:
|
try:
|
||||||
rmtree(loc)
|
rmtree(loc)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
@ -409,7 +406,6 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
if not (options.user or options.password):
|
if not (options.user or options.password):
|
||||||
raise ValueError("User or Password not given")
|
raise ValueError("User or Password not given")
|
||||||
|
|
||||||
main(
|
main(
|
||||||
options.user,
|
options.user,
|
||||||
options.password,
|
options.password,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from StringIO import StringIO
|
from io import StringIO
|
||||||
import re
|
import re
|
||||||
from subprocess import check_output, STDOUT
|
from subprocess import check_output, STDOUT
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ from notifications import Notification
|
|||||||
from pushbullet import Pushbullet
|
from pushbullet import Pushbullet
|
||||||
|
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from ConfigParser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
|
|
||||||
def enable_notifications(options):
|
def enable_notifications(options):
|
||||||
@ -18,13 +18,13 @@ def enable_notifications(options):
|
|||||||
try:
|
try:
|
||||||
pb = Pushbullet(options.pushbullet)
|
pb = Pushbullet(options.pushbullet)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
print "Problem wtih connecting to pushbullet. API Key likely invalid"
|
print("Problem wtih connecting to pushbullet. API Key likely invalid")
|
||||||
fail = True
|
fail = True
|
||||||
if options.pbdevice and not fail:
|
if options.pbdevice and not fail:
|
||||||
try:
|
try:
|
||||||
pb = pb.get_device(options.pbdevice)
|
pb = pb.get_device(options.pbdevice)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
print "Cannot get this device."
|
print("Cannot get this device.")
|
||||||
fail = True
|
fail = True
|
||||||
pass
|
pass
|
||||||
if not fail:
|
if not fail:
|
||||||
@ -45,16 +45,17 @@ def touch(fname, times=None):
|
|||||||
def main(options):
|
def main(options):
|
||||||
try:
|
try:
|
||||||
res = check_output(
|
res = check_output(
|
||||||
"python fanficdownload.py -c config.ini",
|
"python3 fanficdownload.py -c config.ini",
|
||||||
shell=True,
|
shell=True,
|
||||||
stderr=STDOUT)
|
stderr=STDOUT)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print e
|
print(e)
|
||||||
res = None
|
res = None
|
||||||
if not res:
|
if not res:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
print res
|
res = res.decode('utf-8')
|
||||||
|
print(res)
|
||||||
buf = StringIO(res)
|
buf = StringIO(res)
|
||||||
regex = re.compile("Added (?:.*/)?(.*)-.* to library with id \d*")
|
regex = re.compile("Added (?:.*/)?(.*)-.* to library with id \d*")
|
||||||
searcher = regex.search
|
searcher = regex.search
|
||||||
|
Loading…
Reference in New Issue
Block a user