Example #1
0
def getAuthorImage(authorid=None):
    # tbm=isch      search images
    # tbs=ift:jpg  jpeg file type
    if not authorid:
        logger.error("getAuthorImage: No authorid")
        return None

    cachedir = lazylibrarian.CACHEDIR
    coverfile = os.path.join(cachedir, "author", authorid + '.jpg')

    if os.path.isfile(coverfile):  # use cached image if there is one
        lazylibrarian.CACHE_HIT = int(lazylibrarian.CACHE_HIT) + 1
        logger.debug(u"getAuthorImage: Returning Cached response for %s" %
                     coverfile)
        coverlink = 'cache/author/' + authorid + '.jpg'
        return coverlink

    lazylibrarian.CACHE_MISS = int(lazylibrarian.CACHE_MISS) + 1
    myDB = database.DBConnection()
    authors = myDB.select(
        'select AuthorName from authors where AuthorID="%s"' % authorid)
    if authors:
        authorname = safe_unicode(authors[0][0]).encode(
            lazylibrarian.SYS_ENCODING)
        safeparams = urllib.quote_plus("author %s" % authorname)
        URL = "https://www.google.com/search?tbm=isch&tbs=ift:jpg&as_q=" + safeparams
        result, success = fetchURL(URL)
        if success:
            try:
                img = result.split('url?q=')[1].split('">')[1].split(
                    'src="')[1].split('"')[0]
            except IndexError:
                img = None
            if img and img.startswith('http'):
                coverlink, success = cache_img("author", authorid, img)
                if success:
                    logger.debug("Cached google image for %s" % authorname)
                    return coverlink
                else:
                    logger.debug("Error getting google image %s, [%s]" %
                                 (img, coverlink))
            else:
                logger.debug("No image found in google page for %s" %
                             authorname)
        else:
            logger.debug("Error getting google page for %s, [%s]" %
                         (safeparams, result))
    else:
        logger.debug("No author found for %s" % authorid)
    return None
Example #2
0
    def pauseAuthor(self, AuthorID):
        myDB = database.DBConnection()
        authorsearch = myDB.select(
            'SELECT AuthorName from authors WHERE AuthorID=?', [AuthorID])
        AuthorName = authorsearch[0]['AuthorName']
        logger.info("Pausing author: %s" % AuthorName)

        controlValueDict = {'AuthorID': AuthorID}
        newValueDict = {'Status': 'Paused'}
        myDB.upsert("authors", newValueDict, controlValueDict)
        logger.debug(
            'AuthorID [%s]-[%s] Paused - redirecting to Author home page' %
            (AuthorID, AuthorName))
        raise cherrypy.HTTPRedirect("authorPage?AuthorName=%s" % AuthorName)
Example #3
0
    def authorPage(self, AuthorName):
        myDB = database.DBConnection()

        queryauthors = "SELECT * from authors WHERE AuthorName='%s'" % AuthorName
        querybooks = "SELECT * from books WHERE AuthorName='%s' order by BookName ASC" % AuthorName

        author = myDB.action(queryauthors).fetchone()
        books = myDB.select(querybooks)
        if author is None:
            raise cherrypy.HTTPRedirect("home")
        return serve_template(templatename="author.html",
                              title=author['AuthorName'],
                              author=author,
                              books=books)
Example #4
0
def deleteEmptySeries():
    """ remove any series from series table that have no entries in member table, return how many deleted """
    myDB = database.DBConnection()
    series = myDB.select('SELECT SeriesID,SeriesName from series')
    count = 0
    for item in series:
        match = myDB.match('SELECT BookID from member where SeriesID="%s"' %
                           item['SeriesID'])
        if not match:
            logger.debug('Deleting empty series %s' % item['SeriesName'])
            count += 1
            myDB.action('DELETE from series where SeriesID="%s"' %
                        item['SeriesID'])
    return count
Example #5
0
 def _Serve(self, **kwargs):
     if 'bookid' in kwargs:
         if 'fmt' in kwargs:
             fmt = kwargs['fmt']
         else:
             fmt = ''
         myid = kwargs['bookid']
         myDB = database.DBConnection()
         res = myDB.match(
             'SELECT BookFile,BookName from books where bookid=?', (myid, ))
         bookfile = res['BookFile']
         if fmt:
             bookfile = os.path.splitext(bookfile)[0] + '.' + fmt
         self.file = bookfile
         self.filename = os.path.split(bookfile)[1]
         return
     elif 'issueid' in kwargs:
         myid = kwargs['issueid']
         myDB = database.DBConnection()
         res = myDB.match('SELECT IssueFile from issues where issueid=?',
                          (myid, ))
         self.file = res['IssueFile']
         self.filename = os.path.split(res['IssueFile'])[1]
         return
     elif 'audioid' in kwargs:
         myid = kwargs['audioid']
         myDB = database.DBConnection()
         res = myDB.match(
             'SELECT AudioFile,BookName from books where BookID=?',
             (myid, ))
         basefile = res['AudioFile']
         # zip up all the audiobook parts
         if basefile and os.path.isfile(basefile):
             target = zipAudio(os.path.dirname(basefile), res['BookName'])
             self.file = target
             self.filename = res['BookName'] + '.zip'
         return
Example #6
0
def export_CSV(search_dir=None, status="Wanted"):
    """ Write a csv file to the search_dir containing all books marked as "Wanted" """
    try:
        if not search_dir:
            msg = "Alternate Directory not configured"
            logger.warn(msg)
            return msg
        elif not os.path.isdir(search_dir):
            msg = "Alternate Directory [%s] not found" % search_dir
            logger.warn(msg)
            return msg
        elif not os.access(search_dir, os.W_OK | os.X_OK):
            msg = "Alternate Directory [%s] not writable" % search_dir
            logger.warn(msg)
            return msg

        csvFile = os.path.join(search_dir, "%s - %s.csv" % (status, now().replace(':', '-')))

        myDB = database.DBConnection()

        cmd = 'SELECT BookID,AuthorName,BookName,BookIsbn,books.AuthorID FROM books,authors '
        cmd += 'WHERE books.Status=? and books.AuthorID = authors.AuthorID'
        find_status = myDB.select(cmd, (status,))

        if not find_status:
            msg = "No books marked as %s" % status
            logger.warn(msg)
        else:
            count = 0
            with open(csvFile, 'wb') as csvfile:
                csvwrite = csv.writer(csvfile, delimiter=',',
                                      quotechar='"', quoting=csv.QUOTE_MINIMAL)

                # write headers, change AuthorName BookName BookIsbn to match import csv names (Author, Title, ISBN10)
                csvwrite.writerow(['BookID', 'Author', 'Title', 'ISBN', 'AuthorID'])

                for resulted in find_status:
                    logger.debug(u"Exported CSV for book %s" % resulted['BookName'])
                    row = ([resulted['BookID'], resulted['AuthorName'], resulted['BookName'],
                            resulted['BookIsbn'], resulted['AuthorID']])
                    csvwrite.writerow([("%s" % s).encode(lazylibrarian.SYS_ENCODING) for s in row])
                    count += 1
            msg = "CSV exported %s book%s to %s" % (count, plural(count), csvFile)
            logger.info(msg)
        return msg
    except Exception:
        msg = 'Unhandled exception in exportCSV: %s' % traceback.format_exc()
        logger.error(msg)
        return msg
Example #7
0
    def addBook(self, bookid=None):
        myDB = database.DBConnection()

        booksearch = myDB.select("SELECT * from books WHERE BookID=?", [bookid])
        if booksearch:
            myDB.upsert("books", {'Status': 'Wanted'}, {'BookID': bookid})
            for book in booksearch:
                AuthorName = book['AuthorName']
                authorsearch = myDB.select("SELECT * from authors WHERE AuthorName=?", [AuthorName])
                if authorsearch:
                    #update authors needs to be updated every time a book is marked differently
                    lastbook = myDB.action("SELECT BookName, BookLink, BookDate from books WHERE AuthorName='%s' AND Status != 'Ignored' order by BookDate DESC" % AuthorName).fetchone()
                    unignoredbooks = myDB.select("SELECT COUNT(BookName) as unignored FROM books WHERE AuthorName='%s' AND Status != 'Ignored'" % AuthorName)
                    bookCount = myDB.select("SELECT COUNT(BookName) as counter FROM books WHERE AuthorName='%s'" % AuthorName)  
                    countbooks = myDB.action('SELECT COUNT(*) FROM books WHERE AuthorName="%s" AND (Status="Have" OR Status="Open")' % AuthorName).fetchone()
                    havebooks = int(countbooks[0]) 

                    controlValueDict = {"AuthorName": AuthorName}
                    newValueDict = {
                            "TotalBooks": bookCount[0]['counter'],
                            "UnignoredBooks": unignoredbooks[0]['unignored'],
                            "HaveBooks": havebooks,
                            "LastBook": lastbook['BookName'],
                            "LastLink": lastbook['BookLink'],
                            "LastDate": lastbook['BookDate']
                            }
                    myDB.upsert("authors", newValueDict, controlValueDict)
        else:
            if lazylibrarian.BOOK_API == "GoogleBooks":
                GB = GoogleBooks(bookid)
                queue = Queue.Queue()
                find_book = threading.Thread(target=GB.find_book, args=[bookid, queue])
                find_book.start()
            elif lazylibrarian.BOOK_API == "GoodReads":
                queue = Queue.Queue()
                GR = GoodReads(bookid)
                find_book = threading.Thread(target=GR.find_book, args=[bookid, queue])
                find_book.start()
            if len(bookid) == 0:
                raise cherrypy.HTTPRedirect("config")

            find_book.join()

        books = []
        mags = False
        books.append({"bookid": bookid})
        threading.Thread(target=searchbook, args=[books, mags]).start()

        raise cherrypy.HTTPRedirect("books")
    def _notify(message, event, force=False):

        # suppress notifications if the notifier is disabled but the notify options are checked
        if not lazylibrarian.CONFIG['USE_CUSTOM'] and not force:
            return False

        subject = event

        logger.debug('Custom Event: %s' % event)
        logger.debug('Custom Message: %s' % message)
        myDB = database.DBConnection()
        if subject == "Test":
            # grab the first entry in the book table
            data = myDB.match('SELECT * from books')
        else:
            # message is a bookid or a magazineid
            data = myDB.match('SELECT * from books where BookID=?',
                              (message, ))
            if not data:
                data = myDB.match('SELECT * from magazines where BookID=?',
                                  (message, ))
        dictionary = dict(zip(data.keys(), data))
        dictionary['Event'] = event

        try:
            # call the custom notifier script here, passing dictionary deconstructed as strings
            if lazylibrarian.CONFIG['CUSTOM_SCRIPT']:
                params = [lazylibrarian.CONFIG['CUSTOM_SCRIPT']]
                for item in dictionary:
                    params.append(item)
                    if hasattr(dictionary[item], 'encode'):
                        params.append(dictionary[item].encode('utf-8'))
                    else:
                        params.append(str(dictionary[item]))

                try:
                    res = subprocess.check_output(
                        params, stderr=subprocess.STDOUT).strip()
                    return res
                except Exception as e:
                    logger.warn('Error sending command: %s' % e)
                    return False
            else:
                logger.warn('Error sending custom notification: Check config')
                return False

        except Exception as e:
            logger.warn('Error sending custom notification: %s' % e)
            return False
Example #9
0
def DownloadMethod(bookid=None, nzbprov=None, nzbtitle=None, nzburl=None):

    myDB = database.DBConnection()

    if lazylibrarian.SAB_HOST and not lazylibrarian.NZB_DOWNLOADER_BLACKHOLE:
        download = sabnzbd.SABnzbd(nzbtitle, nzburl)

    elif lazylibrarian.NZBGET_HOST and not lazylibrarian.NZB_DOWNLOADER_BLACKHOLE:
        headers = {'User-Agent': USER_AGENT}
        data = request.request_content(url=nzburl, headers=headers)
        nzb = classes.NZBDataSearchResult()
        nzb.extraInfo.append(data)
        nzb.name = nzbtitle
        nzb.url = nzburl
        download = nzbget.sendNZB(nzb)

    elif lazylibrarian.NZB_DOWNLOADER_BLACKHOLE:

        try:
            req = urllib2.Request(nzburl)
            if lazylibrarian.PROXY_HOST:
                req.set_proxy(lazylibrarian.PROXY_HOST,
                              lazylibrarian.PROXY_TYPE)
            req.add_header('User-Agent', USER_AGENT)
            nzbfile = urllib2.urlopen(req, timeout=90).read()

        except urllib2.URLError, e:
            logger.warn('Error fetching nzb from url: ' + nzburl + ' %s' % e)
            nzbfile = False

        if (nzbfile):

            nzbname = str(nzbtitle) + '.nzb'
            nzbpath = os.path.join(lazylibrarian.NZB_BLACKHOLEDIR, nzbname)

            try:
                f = open(nzbpath, 'w')
                f.write(nzbfile)
                f.close()
                logger.info('NZB file saved to: ' + nzbpath)
                download = True
                try:
                    os.chmod(nzbpath, 0777)
                except Exception, e:
                    logger.info("Could not chmod path: " + str(file2))
            except Exception, e:
                logger.error('%s not writable, NZB not saved. Error: %s' %
                             (nzbpath, e))
                download = False
Example #10
0
    def openBook(self, AuthorName=None, action=None, **args):
        myDB = database.DBConnection()
        for bookid in args:
            # ouch dirty workaround...
            if not bookid == 'book_table_length':

                controlValueDict = {'BookID': bookid}
                newValueDict = {'Status': action}
                myDB.upsert("books", newValueDict, controlValueDict)
                logger.debug('Status set to %s for BookID: %s' %
                             (action, bookid))

        # find book
        myDB = database.DBConnection()
        #data = myDB.select('SELECT * from wanted WHERE BookID=\'' + bookid + '\'')
        bookdata = myDB.select('SELECT * from books WHERE BookID=\'' + bookid +
                               '\'')
        dest_dir = lazylibrarian.DESTINATION_DIR + '\\' + bookdata[0][
            "AuthorName"] + '\\' + bookdata[0]["BookName"]
        for file2 in os.listdir(dest_dir):
            logger.info('file ' + str(file2))
            if file2.lower().find("." + lazylibrarian.EBOOK_TYPE) > 0:
                return serve_file(os.path.join(dest_dir, file2),
                                  "application/x-download", "attachment")
Example #11
0
    def searchForMag(self, bookid=None, action=None, **args):
        myDB = database.DBConnection()

        # find book
        bookdata = myDB.select("SELECT * from magazines WHERE Title='%s'" % bookid)
        if bookdata:
            # start searchthreads
            mags = []
            mags.append({"bookid": bookid})

            books=False

            threading.Thread(target=searchbook, args=[books, mags]).start()
            logger.debug("Searching for magazine with title: " + str(bookid));
            raise cherrypy.HTTPRedirect("magazines")
Example #12
0
    def _removeAuthor(self, **kwargs):
        if 'id' not in kwargs:
            self.data = 'Missing parameter: id'
            return
        else:
            self.id = kwargs['id']

        myDB = database.DBConnection()
        authorsearch = myDB.select(
            'SELECT AuthorName from authors WHERE AuthorID="%s"' % AuthorID)
        if len(authorsearch):  # to stop error if try to remove an author while they are still loading
            AuthorName = authorsearch[0]['AuthorName']
            logger.info(u"Removing all references to author: %s" % AuthorName)
            myDB.action('DELETE from authors WHERE AuthorID="%s"' % AuthorID)
            myDB.action('DELETE from books WHERE AuthorID="%s"' % AuthorID)
Example #13
0
def dbUpdate(forcefull=False):

    myDB = database.DBConnection()

    activeauthors = myDB.select(
        'SELECT AuthorID, AuthorName from authors WHERE Status="Active" \
                                or Status="Loading" order by DateAdded ASC')
    logger.info('Starting update for %i active authors' % len(activeauthors))

    for author in activeauthors:
        # authorid = author[0]
        authorname = author[1]
        importer.addAuthorToDB(authorname, refresh=True)

    logger.info('Active author update complete')
Example #14
0
 def markWanted(self, action=None, **args):
     myDB = database.DBConnection()
     #I think I need to consolidate bookid in args to unique values...
     for nzbtitle in args:
         if not nzbtitle == 'book_table_length':
             if action != "Delete":
                 controlValueDict = {"NZBtitle": nzbtitle}
                 newValueDict = {
                     "Status":       action,
                     }
                 myDB.upsert("wanted", newValueDict, controlValueDict)
                 logger.info('Status of wanted item %s changed to %s' % (nzbtitle, action))
             else:
                 myDB.action('DELETE from wanted WHERE NZBtitle=?', [nzbtitle])
                 logger.info('Item %s removed from wanted' % nzbtitle)
             raise cherrypy.HTTPRedirect("wanted")
Example #15
0
def showJobs():
    result = [
        "Cache %i hit%s, %i miss" %
        (int(lazylibrarian.CACHE_HIT), plural(int(
            lazylibrarian.CACHE_HIT)), int(lazylibrarian.CACHE_MISS))
    ]
    myDB = database.DBConnection()
    snatched = myDB.match(
        "SELECT count('Status') as counter from wanted WHERE Status = 'Snatched'"
    )
    wanted = myDB.match(
        "SELECT count('Status') as counter FROM books WHERE Status = 'Wanted'")
    result.append("%i item%s marked as Snatched" %
                  (snatched['counter'], plural(snatched['counter'])))
    result.append("%i item%s marked as Wanted" %
                  (wanted['counter'], plural(wanted['counter'])))
    author = myDB.match(
        'SELECT AuthorID, AuthorName, DateAdded from authors WHERE Status="Active" \
                                or Status="Loading" order by DateAdded ASC')
    dtnow = datetime.datetime.now()
    diff = datecompare(dtnow.strftime("%Y-%m-%d"), author['DateAdded'])
    result.append('Oldest author info is %s day%s old' % (diff, plural(diff)))
    for job in lazylibrarian.SCHED.get_jobs():
        job = str(job)
        if "search_magazines" in job:
            jobname = "Magazine search"
        elif "checkForUpdates" in job:
            jobname = "Check LazyLibrarian version"
        elif "search_tor_book" in job:
            jobname = "TOR book search"
        elif "search_nzb_book" in job:
            jobname = "NZB book search"
        elif "search_rss_book" in job:
            jobname = "RSS book search"
        elif "processDir" in job:
            jobname = "Process downloads"
        elif "authorUpdate" in job:
            jobname = "Update authors"
        else:
            jobname = job.split(' ')[0].split('.')[2]

        # jobinterval = job.split('[')[1].split(']')[0]
        jobtime = job.split('at: ')[1].split('.')[0]
        jobtime = next_run(jobtime)
        jobinfo = "%s: Next run in %s" % (jobname, jobtime)
        result.append(jobinfo)
    return result
Example #16
0
def seriesInfo(bookid):
    """ Return series info for a bookid as a dict of formatted strings
        The strings are configurable, but by default...
        Full returns ( Lord of the Rings 2 )
        Name returns Lord of the Rings (with added Num part if that's not numeric, eg Lord of the Rings Book One)
        Num  returns Book #1 -    (or empty string if no numeric part)
        so you can combine to make Book #1 - Lord of the Rings  """
    mydict = {'Name': '', 'Full': '', 'Num': ''}
    myDB = database.DBConnection()
    cmd = 'SELECT SeriesID,SeriesNum from member WHERE bookid=?'
    res = myDB.match(cmd, (bookid,))
    if not res:
        return mydict

    seriesid = res['SeriesID']
    serieslist = getList(res['SeriesNum'])
    seriesnum = ''
    seriesname = ''
    # might be "Book 3.5" or similar, just get the numeric part
    while serieslist:
        seriesnum = serieslist.pop()
        try:
            _ = float(seriesnum)
            break
        except ValueError:
            seriesnum = ''
            pass

    if not seriesnum:
        # couldn't figure out number, keep everything we got, could be something like "Book Two"
        serieslist = res['SeriesNum']

    cmd = 'SELECT SeriesName from series WHERE seriesid=?'
    res = myDB.match(cmd, (seriesid,))
    if res:
        seriesname = res['SeriesName']
        if not seriesnum:
            # add what we got back to end of series name
            if serieslist:
                seriesname = "%s %s" % (seriesname, serieslist)

    mydict['Name'] = lazylibrarian.CONFIG['FMT_SERNAME'].replace('$SerName', seriesname).replace('$$', ' ')
    mydict['Num'] = lazylibrarian.CONFIG['FMT_SERNUM'].replace('$SerNum', seriesnum).replace('$$', ' ')
    mydict['Full'] = lazylibrarian.CONFIG['FMT_SERIES'].replace('$SerNum', seriesnum).replace(
                        '$SerName', seriesname).replace('$$', ' ')
    return mydict
Example #17
0
def update_totals(AuthorID):
    myDB = database.DBConnection()
    # author totals needs to be updated every time a book is marked differently
    match = myDB.select('SELECT AuthorID from authors WHERE AuthorID=?',
                        (AuthorID, ))
    if not match:
        logger.debug('Update_totals - authorid [%s] not found' % AuthorID)
        return

    cmd = 'SELECT BookName, BookLink, BookDate, BookID from books WHERE AuthorID=?'
    cmd += ' AND Status != "Ignored" order by BookDate DESC'
    lastbook = myDB.match(cmd, (AuthorID, ))

    cmd = "select sum(case status when 'Ignored' then 0 else 1 end) as unignored,"
    cmd += "sum(case when status == 'Have' then 1 when status == 'Open' then 1 "
    cmd += "when audiostatus == 'Have' then 1 when audiostatus == 'Open' then 1 "
    cmd += "else 0 end) as have, count(*) as total from books where authorid=?"
    totals = myDB.match(cmd, (AuthorID, ))

    controlValueDict = {"AuthorID": AuthorID}
    newValueDict = {
        "TotalBooks": totals['total'],
        "UnignoredBooks": totals['unignored'],
        "HaveBooks": totals['have'],
        "LastBook": lastbook['BookName'] if lastbook else None,
        "LastLink": lastbook['BookLink'] if lastbook else None,
        "LastBookID": lastbook['BookID'] if lastbook else None,
        "LastDate": lastbook['BookDate'] if lastbook else None
    }
    myDB.upsert("authors", newValueDict, controlValueDict)

    cmd = "select series.seriesid as Series,sum(case books.status when 'Ignored' then 0 else 1 end) as Total,"
    cmd += "sum(case when books.status == 'Have' then 1 when books.status == 'Open' then 1"
    cmd += " when books.audiostatus == 'Have' then 1 when books.audiostatus == 'Open' then 1"
    cmd += " else 0 end) as Have from books,member,series,seriesauthors where member.bookid=books.bookid"
    cmd += " and member.seriesid = series.seriesid and seriesauthors.seriesid = series.seriesid"
    cmd += " and seriesauthors.authorid=? group by series.seriesid"
    res = myDB.select(cmd, (AuthorID, ))
    if len(res):
        for series in res:
            myDB.action('UPDATE series SET Have=?, Total=? WHERE SeriesID=?',
                        (series['Have'], series['Total'], series['Series']))

    res = myDB.match('SELECT AuthorName from authors WHERE AuthorID=?',
                     (AuthorID, ))
    logger.debug('Updated totals for [%s]' % res['AuthorName'])
Example #18
0
	def find_book(self, bookid=None, queue=None):
		threading.currentThread().name = "GR-ADD-BOOK"
		myDB = database.DBConnection()

		URL = 'https://www.goodreads.com/book/show/' + bookid + '?' + urllib.urlencode(self.params)

		try:
			# Cache our request
			request = urllib2.Request(URL)
			if lazylibrarian.PROXY_HOST:
				request.set_proxy(lazylibrarian.PROXY_HOST, lazylibrarian.PROXY_TYPE)
			request.add_header('User-Agent', USER_AGENT)
			opener = urllib2.build_opener(SimpleCache.CacheHandler(".AuthorCache"), SimpleCache.ThrottlingProcessor(5))
			resp = opener.open(request)
			sourcexml = ElementTree.parse(resp)
		except Exception, e:
			logger.error("Error fetching book info: " + str(e))
Example #19
0
def CheckFolder():
    myDB = database.DBConnection()
    snatched = myDB.select('SELECT * from wanted WHERE Status="Snatched"')
    pp_path = lazylibrarian.SAB_DIR

    if snatched:
        for book in snatched:
            logger.info(book['BookID'])
            pp_pathsub = os.path.join(pp_path, book['NZBtitle'])

            if os.path.exists(pp_pathsub):
                logger.debug('Found %s. Processing %s' % (book['NZBtitle'], pp_pathsub))
                processPath(book['BookID'], pp_pathsub)
            else:
                logger.error('No path found for: %s. Can\'t process it.' % book['NZBtitle'])
    else:
        logger.info('No books with status Snatched are found, nothing to process.')
Example #20
0
    def _addMagazine(self, **kwargs):
        if 'name' not in kwargs:
            self.data = 'Missing parameter: name'
            return
        else:
            self.id = kwargs['name']

        myDB = database.DBConnection()
        controlValueDict = {"Title": self.id}
        newValueDict = {
            "Regex": None,
            "Status": "Active",
            "MagazineAdded": today(),
            "IssueStatus": "Wanted",
            "Reject": None
        }
        myDB.upsert("magazines", newValueDict, controlValueDict)
Example #21
0
def setAllBookSeries():
    """ Try to set series details for all books from workpages"""
    myDB = database.DBConnection()
    books = myDB.select('select BookID from books where Manual is not "1"')
    counter = 0
    if books:
        logger.info('Checking series for %s book%s' % (len(books), plural(len(books))))
        for book in books:
            bookid = book['BookID']
            seriesdict = getWorkSeries(bookid)
            if seriesdict:
                counter += 1
                setSeries(seriesdict, bookid)
    deleteEmptySeries()
    msg = 'Updated %s book%s' % (counter, plural(counter))
    logger.info('Series check complete: ' + msg)
    return msg
Example #22
0
def showJobs():
    result = ["Cache %i hit%s, %i miss" % (check_int(lazylibrarian.CACHE_HIT, 0),
                                           plural(check_int(lazylibrarian.CACHE_HIT, 0)),
                                           check_int(lazylibrarian.CACHE_MISS, 0))]
    myDB = database.DBConnection()
    snatched = myDB.match("SELECT count('Status') as counter from wanted WHERE Status = 'Snatched'")
    wanted = myDB.match("SELECT count('Status') as counter FROM books WHERE Status = 'Wanted'")
    result.append("%i item%s marked as Snatched" % (snatched['counter'], plural(snatched['counter'])))
    result.append("%i item%s marked as Wanted" % (wanted['counter'], plural(wanted['counter'])))
    for job in lazylibrarian.SCHED.get_jobs():
        job = str(job)
        if "search_magazines" in job:
            jobname = "Magazine search"
        elif "checkForUpdates" in job:
            jobname = "Check LazyLibrarian version"
        elif "search_book" in job:
            jobname = "Book search"
        elif "search_rss_book" in job:
            jobname = "RSS book search"
        elif "processDir" in job:
            jobname = "Process downloads"
        elif "authorUpdate" in job:
            jobname = "Update authors"
        elif "sync_to_gr" in job:
            jobname = "Goodreads Sync"
        else:
            jobname = job.split(' ')[0].split('.')[2]

        # jobinterval = job.split('[')[1].split(']')[0]
        jobtime = job.split('at: ')[1].split('.')[0]
        jobtime = next_run(jobtime)
        timeparts = jobtime.split(' ')
        if timeparts[0] == '1' and timeparts[1].endswith('s'):
            timeparts[1] = timeparts[1][:-1]
        jobinfo = "%s: Next run in %s %s" % (jobname, timeparts[0], timeparts[1])
        result.append(jobinfo)

    cmd = 'SELECT AuthorID, AuthorName, DateAdded from authors WHERE Status="Active" or Status="Loading"'
    cmd += 'or Status="Wanted" order by DateAdded ASC'
    author = myDB.match(cmd)
    dtnow = datetime.datetime.now()
    diff = datecompare(dtnow.strftime("%Y-%m-%d"), author['DateAdded'])
    result.append('Oldest author info (%s) is %s day%s old' % (author['AuthorName'], diff, plural(diff)))

    return result
Example #23
0
    def _setimage(self, table, itemid, img):
        msg = "%s Image [%s] rejected" % (table, img)
        # Cache file image
        if os.path.isfile(img):
            extn = os.path.splitext(img)[1].lower()
            if extn and extn in ['.jpg', '.jpeg', '.png']:
                destfile = os.path.join(lazylibrarian.CACHEDIR, table,
                                        itemid + '.jpg')
                try:
                    shutil.copy(img, destfile)
                    setperm(destfile)
                    msg = ''
                except Exception as why:
                    msg += " Failed to copy file: %s %s" % (type(why).__name__,
                                                            str(why))
            else:
                msg += " invalid extension"

        if img.startswith('http'):
            # cache image from url
            extn = os.path.splitext(img)[1].lower()
            if extn and extn in ['.jpg', '.jpeg', '.png']:
                cachedimg, success = cache_img(table, itemid, img)
                if success:
                    msg = ''
                else:
                    msg += " Failed to cache file"
            else:
                msg += " invalid extension"
        elif msg:
            msg += " Not found"

        if msg:
            self.data = msg
            return

        myDB = database.DBConnection()
        dbentry = myDB.match('SELECT %sID from %ss WHERE %sID=%s' %
                             (table, table, table, itemid))
        if dbentry:
            myDB.action('UPDATE %ss SET %sImg="%s" WHERE %sID=%s' %
                        (table, table, 'cache' + os.sep + itemid + '.jpg',
                         table, itemid))
        else:
            self.data = "%sID %s not found" % (table, itemid)
Example #24
0
def isbn_from_words(words):
    """ Use Google to get an ISBN for a book from words in title and authors name.
        Store the results in the database """
    myDB = database.DBConnection()
    res = myDB.match("SELECT ISBN from isbn WHERE Words=?", (words,))
    if res:
        logger.debug('Found cached ISBN for %s' % words)
        return res['ISBN']

    baseurl = "http://www.google.com/search?q=ISBN+"
    if not PY2:
        search_url = baseurl + quote(words.replace(' ', '+'))
    else:
        search_url = baseurl + words.replace(' ', '+')

    headers = {'User-Agent': 'w3m/0.5.3',
               'Content-Type': 'text/plain; charset="UTF-8"',
               'Content-Transfer-Encoding': 'Quoted-Printable',
               }
    content, success = fetchURL(search_url, headers=headers)
    # noinspection Annotator
    RE_ISBN13 = re.compile(r'97[89]{1}(?:-?\d){10,16}|97[89]{1}[- 0-9]{10,16}')
    RE_ISBN10 = re.compile(r'ISBN\x20(?=.{13}$)\d{1,5}([- ])\d{1,7}\1\d{1,6}\1(\d|X)$|[- 0-9X]{10,16}')

    # take the first valid looking answer
    res = RE_ISBN13.findall(content)
    logger.debug('Found %s ISBN13 for %s' % (len(res), words))
    for item in res:
        if len(item) > 13:
            item = item.replace('-', '').replace(' ', '')
        if len(item) == 13:
            myDB.action("INSERT into isbn (Words, ISBN) VALUES (?, ?)", (words, item))
            return item

    res = RE_ISBN10.findall(content)
    logger.debug('Found %s ISBN10 for %s' % (len(res), words))
    for item in res:
        if len(item) > 10:
            item = item.replace('-', '').replace(' ', '')
        if len(item) == 10:
            myDB.action("INSERT into isbn (Words, ISBN) VALUES (?, ?)", (words, item))
            return item

    logger.debug('No valid ISBN found for %s' % words)
    return None
Example #25
0
def finditem(item, preferred_authorname):
    """
    Try to find book matching the csv item in the database
    Return database entry, or False if not found
    """
    myDB = database.DBConnection()
    bookmatch = ""
    isbn10 = ""
    isbn13 = ""
    bookid = ""
    bookname = item['Title']

    bookname = makeUnicode(bookname)
    if 'ISBN' in item:
        isbn10 = item['ISBN']
    if 'ISBN13' in item:
        isbn13 = item['ISBN13']
    if 'BookID' in item:
        bookid = item['BookID']

    # try to find book in our database using bookid or isbn, or if that fails, name matching
    cmd = 'SELECT AuthorName,BookName,BookID,books.Status FROM books,authors where books.AuthorID = authors.AuthorID '
    if bookid:
        fullcmd = cmd + 'and BookID=?'
        bookmatch = myDB.match(fullcmd, (bookid, ))
    if not bookmatch:
        if is_valid_isbn(isbn10):
            fullcmd = cmd + 'and BookIsbn=?'
            bookmatch = myDB.match(fullcmd, (isbn10, ))
    if not bookmatch:
        if is_valid_isbn(isbn13):
            fullcmd = cmd + 'and BookIsbn=?'
            bookmatch = myDB.match(fullcmd, (isbn13, ))
    if not bookmatch:
        bookid, mtype = find_book_in_db(preferred_authorname,
                                        bookname,
                                        ignored=False)
        if bookid and mtype == "Ignored":
            logger.warn(
                "Book %s by %s is marked Ignored in database, importing anyway"
                % (bookname, preferred_authorname))
        if bookid:
            fullcmd = cmd + 'and BookID=?'
            bookmatch = myDB.match(fullcmd, (bookid, ))
    return bookmatch
Example #26
0
def DownloadMethod(bookid=None, nzbprov=None, nzbtitle=None, nzburl=None):

    myDB = database.DBConnection()

    if lazylibrarian.SAB_HOST and not lazylibrarian.BLACKHOLE:
        download = sabnzbd.SABnzbd(nzbtitle, nzburl)
        logger.debug('Nzbfile has been downloaded from ' + str(nzburl))
        myDB.action('UPDATE books SET status = "Snatched" WHERE BookID=?',
                    [bookid])
        myDB.action('UPDATE wanted SET status = "Snatched" WHERE BookID=?',
                    [bookid])

    elif lazylibrarian.BLACKHOLE:

        try:
            req = urllib2.Request(nzburl)
            req.add_header(
                'User-Agent',
                'lazylibrary/0.0 +https://github.com/herman-rogers/LazyLibrarian-1'
            )
            nzbfile = urllib2.urlopen(req, timeout=90).read()

        except urllib2.URLError, e:
            logger.warn('Error fetching nzb from url: ' + nzburl + ' %s' % e)
            nzbfile = False

        if (nzbfile):

            nzbname = str(nzbtitle) + '.nzb'
            nzbpath = os.path.join(lazylibrarian.BLACKHOLEDIR, nzbname)

            try:
                f = open(nzbpath, 'w')
                f.write(nzbfile)
                f.close()
                logger.info('NZB file saved to: ' + nzbpath)
                download = True
                try:
                    os.chmod(nzbpath, 0777)
                except Exception, e:
                    logger.info("Could not chmod path: " + str(file2))
            except Exception, e:
                logger.error('%s not writable, NZB not saved. Error: %s' %
                             (nzbpath, e))
                download = False
Example #27
0
    def _findBook(self, **kwargs):
        if 'name' not in kwargs:
            self.data = 'Missing parameter: name'
            return
        myDB = database.DBConnection()
        if lazylibrarian.BOOK_API == "GoogleBooks":
            GB = GoogleBooks(kwargs['name'])
            queue = Queue.Queue()
            search_api = threading.Thread(target=GB.find_results, name='API-GBRESULTS', args=[kwargs['name'], queue])
            search_api.start()
        elif lazylibrarian.BOOK_API == "GoodReads":
            queue = Queue.Queue()
            GR = GoodReads(kwargs['name'])
            search_api = threading.Thread(target=GR.find_results, name='API-GRRESULTS', args=[kwargs['name'], queue])
            search_api.start()

        search_api.join()
        self.data = queue.get()
Example #28
0
 def _writeAllOPF(self, **kwargs):
     myDB = database.DBConnection()
     books = myDB.select(
         'select BookID from books where BookFile is not null')
     counter = 0
     if books:
         for book in books:
             bookid = book['BookID']
             if 'refresh' in kwargs:
                 self._writeOPF(id=bookid, refresh=True)
             else:
                 self._writeOPF(id=bookid)
             try:
                 if self.data[1] is True:
                     counter += 1
             except IndexError:
                 counter = counter
     self.data = 'Updated opf for %s book%s' % (counter, plural(counter))
Example #29
0
def setAllBookAuthors():
    myDB = database.DBConnection()
    myDB.action('drop table if exists bookauthors')
    myDB.action('create table bookauthors (AuthorID TEXT, BookID TEXT, Role TEXT, UNIQUE (AuthorID, BookID, Role))')
    books = myDB.select('SELECT AuthorID,BookID from books')
    for item in books:
        myDB.action('insert into bookauthors (AuthorID, BookID, Role) values (?, ?, ?)',
                    (item['AuthorID'], item['BookID'], ''), suppress='UNIQUE')
    totalauthors = 0
    totalrefs = 0
    books = myDB.select('select bookid,bookname,authorid from books where workpage is not null and workpage != ""')
    for book in books:
        newauthors, newrefs = setBookAuthors(book)
        totalauthors += newauthors
        totalrefs += newrefs
    msg = "Added %s new authors to database, %s new bookauthors" % (totalauthors, totalrefs)
    logger.debug(msg)
    return totalauthors, totalrefs
Example #30
0
    def searchForBook(self, bookid=None, action=None, **args):
        myDB = database.DBConnection()

        # find book
        bookdata = myDB.select("SELECT * from books WHERE BookID='%s'" % bookid)
        if bookdata:
            AuthorName = bookdata[0]["AuthorName"];

            # start searchthreads
            books = []
            books.append({"bookid": bookid})

            mags=False

            threading.Thread(target=searchbook, args=[books, mags]).start()
            logger.debug("Searching for book with id: " + str(bookid));
        if AuthorName:
            raise cherrypy.HTTPRedirect("authorPage?AuthorName=%s" % AuthorName)