Use google scholar to fetch metadata

This commit is contained in:
cbartondock 2021-03-31 22:16:00 -04:00
parent c0623a949c
commit 26cc64bdd6
4 changed files with 389 additions and 290 deletions

View File

@ -27,6 +27,15 @@ import json
from shutil import copyfile from shutil import copyfile
from uuid import uuid4 from uuid import uuid4
# Improve this to check if scholarly is available in a global way, like other pythonic libraries
have_scholar = True
try:
from scholarly import scholarly
except ImportError:
have_scholar = False
pass
from flask import Blueprint, request, flash, redirect, url_for, abort, Markup, Response from flask import Blueprint, request, flash, redirect, url_for, abort, Markup, Response
from flask_babel import gettext as _ from flask_babel import gettext as _
from flask_login import current_user, login_required from flask_login import current_user, login_required
@ -996,6 +1005,26 @@ def convert_bookformat(book_id):
flash(_(u"There was an error converting this book: %(res)s", res=rtn), category="error") flash(_(u"There was an error converting this book: %(res)s", res=rtn), category="error")
return redirect(url_for('editbook.edit_book', book_id=book_id)) return redirect(url_for('editbook.edit_book', book_id=book_id))
@editbook.route("/scholarsearch/<query>",methods=['GET'])
@login_required_if_no_ano
@edit_required
def scholar_search(query):
if have_scholar:
scholar_gen = scholarly.search_pubs(' '.join(query.split('+')))
i=0
result = []
for publication in scholar_gen:
del publication['source']
result.append(publication)
i+=1
if(i>=10):
break
return Response(json.dumps(result),mimetype='application/json')
else:
return 'Scholarly not installed'
@editbook.route("/ajax/editbooks/<param>", methods=['POST']) @editbook.route("/ajax/editbooks/<param>", methods=['POST'])
@login_required_if_no_ano @login_required_if_no_ano
@edit_required @edit_required

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 175 KiB

View File

@ -19,11 +19,12 @@
* Google Books api document: https://developers.google.com/books/docs/v1/using * Google Books api document: https://developers.google.com/books/docs/v1/using
* Douban Books api document: https://developers.douban.com/wiki/?title=book_v2 (Chinese Only) * Douban Books api document: https://developers.douban.com/wiki/?title=book_v2 (Chinese Only)
* ComicVine api document: https://comicvine.gamespot.com/api/documentation * ComicVine api document: https://comicvine.gamespot.com/api/documentation
*/ */
/* global _, i18nMsg, tinymce */ /* global _, i18nMsg, tinymce */
var dbResults = []; var dbResults = [];
var ggResults = []; var ggResults = [];
var cvResults = []; var cvResults = [];
var gsResults = [];
$(function () { $(function () {
var msg = i18nMsg; var msg = i18nMsg;
@ -39,6 +40,10 @@ $(function () {
var cvSearch = "/api/search/"; var cvSearch = "/api/search/";
var cvDone = 0; var cvDone = 0;
var googlescholar = window.location.href.split('/admin/book')[0];
var gsSearch = "/scholarsearch/"
var gsDone = 0;
var showFlag = 0; var showFlag = 0;
var templates = { var templates = {
@ -59,8 +64,10 @@ $(function () {
$("#book_title").val(book.title); $("#book_title").val(book.title);
$("#tags").val(uniqueTags.join(",")); $("#tags").val(uniqueTags.join(","));
$("#rating").data("rating").setValue(Math.round(book.rating)); $("#rating").data("rating").setValue(Math.round(book.rating));
if(book.cover !== null){
$(".cover img").attr("src", book.cover); $(".cover img").attr("src", book.cover);
$("#cover_url").val(book.cover); $("#cover_url").val(book.cover);
}
$("#pubdate").val(book.publishedDate); $("#pubdate").val(book.publishedDate);
$("#publisher").val(book.publisher); $("#publisher").val(book.publisher);
if (typeof book.series !== "undefined") { if (typeof book.series !== "undefined") {
@ -75,7 +82,8 @@ $(function () {
} }
if ((ggDone === 3 || (ggDone === 1 && ggResults.length === 0)) && if ((ggDone === 3 || (ggDone === 1 && ggResults.length === 0)) &&
(dbDone === 3 || (dbDone === 1 && dbResults.length === 0)) && (dbDone === 3 || (dbDone === 1 && dbResults.length === 0)) &&
(cvDone === 3 || (cvDone === 1 && cvResults.length === 0))) { (cvDone === 3 || (cvDone === 1 && cvResults.length === 0)) &&
(gsDone === 3 || (gsDone === 1 && gsResults.length === 0))) {
$("#meta-info").html("<p class=\"text-danger\">" + msg.no_result + "</p>"); $("#meta-info").html("<p class=\"text-danger\">" + msg.no_result + "</p>");
return; return;
} }
@ -94,6 +102,9 @@ $(function () {
return [year, month, day].join("-"); return [year, month, day].join("-");
} }
function generateID (title) {
return title.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0).toString().substr(0,12);
}
if (ggResults.length > 0) { if (ggResults.length > 0) {
if (ggDone < 2) { if (ggDone < 2) {
@ -130,6 +141,42 @@ $(function () {
} }
} }
if (gsResults.length > 0) {
if (gsDone < 2) {
gsResults.forEach(function(result) {
var book = {
id: generateID(result.bib.title),
title: result.bib.title,
authors: result.bib.author || [],
description: result.bib.abstract || "",
publisher: result.bib.venue || "",
publishedDate: result.bib.pub_year ? result.bib.pub_year+"-01-01" : "",
tags: [],
rating: 0,
series: "",
cover: null,
url: result.pub_url || result.eprint_url || "",
source: {
id: "googlescholar",
description: "Google Scholar",
link: "https://scholar.google.com/"
}
}
var $book = $(templates.bookResult(book));
$book.find("img").on("click", function () {
populateForm(book);
});
$("#book-list").append($book);
});
gsDone = 2;
}
else {
gsDone = 3;
}
}
if (dbResults.length > 0) { if (dbResults.length > 0) {
if (dbDone < 2) { if (dbDone < 2) {
dbResults.forEach(function(result) { dbResults.forEach(function(result) {
@ -295,17 +342,35 @@ $(function () {
}); });
} }
function gsSearchBook (title) {
$.ajax({
url: googlescholar + gsSearch + title.replace(/\s+/gm,'+'),
type: "GET",
dataType: "json",
success: function success(data) {
gsResults = data;
},
complete: function complete() {
gsDone = 1;
showResult();
$("#show-googlescholar").trigger("change");
}
})
}
function doSearch (keyword) { function doSearch (keyword) {
showFlag = 0; showFlag = 0;
dbDone = ggDone = cvDone = 0; dbDone = ggDone = cvDone = 0;
dbResults = []; dbResults = [];
ggResults = []; ggResults = [];
cvResults = []; cvResults = [];
gsResults = [];
$("#meta-info").text(msg.loading); $("#meta-info").text(msg.loading);
if (keyword) { if (keyword) {
dbSearchBook(keyword); dbSearchBook(keyword);
ggSearchBook(keyword); ggSearchBook(keyword);
cvSearchBook(keyword); cvSearchBook(keyword);
gsSearchBook(keyword);
} }
} }

View File

@ -227,6 +227,10 @@
<input type="checkbox" id="show-comics" class="pill" data-control="comicvine" checked> <input type="checkbox" id="show-comics" class="pill" data-control="comicvine" checked>
<label for="show-comics">ComicVine <span class="glyphicon glyphicon-ok"></span></label> <label for="show-comics">ComicVine <span class="glyphicon glyphicon-ok"></span></label>
<input type="checkbox" id="show-googlescholar" class="pill" data-control="googlescholar" checked>
<label for="show-googlescholar">Google Scholar <span class="glyphicon glyphicon-ok"></span></label>
</div> </div>
<div id="meta-info"> <div id="meta-info">
@ -248,7 +252,7 @@
<img class="pull-left img-responsive" <img class="pull-left img-responsive"
data-toggle="modal" data-toggle="modal"
data-target="#metaModal" data-target="#metaModal"
src="<%= cover %>" src="<%= cover || "{{ url_for('static', filename='img/academicpaper.svg') }}" %>"
alt="Cover" alt="Cover"
> >
<div class="media-body"> <div class="media-body">