Skip to content

Commit d33e543

Browse files
committed
Initial commit
0 parents  commit d33e543

4 files changed

Lines changed: 137 additions & 0 deletions

File tree

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Goodreads Libby Userscript
2+
3+
Userscript that will search for the book you are looking at on Goodreads across all your libby libraries.
4+
5+
## Installation
6+
7+
1. Make sure you have a browser extension that can run userscripts:
8+
9+
* [Tampermonkey](https://www.tampermonkey.net/)
10+
* [Violentmonkey](https://violentmonkey.github.io/get-it/)
11+
* [Greasemonkey](https://addons.mozilla.org/firefox/addon/greasemonkey/)
12+
13+
2. Install:
14+
15+
* Install the script directly from GitHub through this link: [Install](https://github.com/Dylancyclone/goodreads-libby-userscript/raw/main/goodreads-libby.user.js).
16+
* Install the script from [GreasyFork](https://greasyfork.org/en/scripts/440958-goodreads-libby-results) (GF)
17+
<!-- * Or, install the scripts from [OpenUserJS](https://openuserjs.org/users/Dylancyclone/scripts) (OU). -->
18+
19+
## Usage
20+
21+
Go to the libby web app's main menu (https://libbyapp.com/interview/menu) and click the "Save Libraries" button.
22+
23+
![The Save Libraries button](./libby.png)
24+
25+
Then, search for a book on Goodreads. When you've found a book, the userscript will search across all your libby libraries and show the results on the left side of the screen.
26+
27+
![The search results on Goodreads](./goodreads.png)
28+
29+
You can then click the number of results to be taken to the search page for that library.
30+
31+
## Updating
32+
33+
Userscripts are set up to automatically update. You can check for updates from within the Greasemonkey or Tampermonkey menu, or click on the install link again to get the update.
34+
35+
## Issues
36+
37+
Please report any issues within this repository's [issue section](https://github.com/Dylancyclone/goodreads-libby-userscript/issues). I'm not a very active userscript developer, so Greasyfork messages are a little more difficult to work with. Thanks!

goodreads-libby.user.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// ==UserScript==
2+
// @name Goodreads Libby Results
3+
// @namespace https://github.com/Dylancyclone/goodreads-libby-userscript
4+
// @version 1.0.0
5+
// @description Searches for the book you are looking at on Goodreads across all your libby libraries
6+
// @author Dylancyclone
7+
// @match https://libbyapp.com/interview/menu
8+
// @include /^https?://.*\.goodreads\.com/book/show.*$/
9+
// @icon https://www.google.com/s2/favicons?sz=64&domain=libbyapp.com
10+
// @grant GM.setValue
11+
// @grant GM.getValue
12+
// @license MIT
13+
// ==/UserScript==
14+
15+
(function () {
16+
"use strict";
17+
18+
const syncLibraries = () => {
19+
// Grab libraries from libby and remove circular references
20+
let libraries = unsafeWindow.APP.libraries.all.map((library) => {
21+
return {
22+
baseKey: library.baseKey,
23+
_: { activeKey: library._.activeKey, name: library._.name },
24+
};
25+
});
26+
libraries = JSON.stringify(libraries);
27+
GM.setValue("libraries", libraries);
28+
};
29+
30+
const createLibbyButton = () => {
31+
let builderDiv = document.createElement("div");
32+
builderDiv.innerHTML = `
33+
<div class="menu-library-buttons">
34+
<button class="menu-library-buttons-add-library halo" role="button" type="button">
35+
<span role="text">Save Libraries (userscript)</span>
36+
</button>
37+
</div>
38+
`.trim();
39+
let libbySyncButton = builderDiv.firstChild;
40+
libbySyncButton.onclick = syncLibraries;
41+
return libbySyncButton;
42+
};
43+
44+
/**
45+
* Add the button
46+
* Might outrun the rest of the dom,
47+
* so keep retrying until the container is ready
48+
*/
49+
const addLibbyButton = () => {
50+
let container = document.getElementsByClassName("menu-library-buttons");
51+
if (container && container[0]) {
52+
container[0].parentNode.insertBefore(
53+
createLibbyButton(),
54+
container[0].nextSibling
55+
);
56+
} else {
57+
setTimeout(addLibbyButton, 10);
58+
}
59+
};
60+
61+
const addGoodreadsResults = async () => {
62+
let bookTitle = document.getElementById("bookTitle").innerHTML.trim();
63+
let bookAuthor = document
64+
.getElementsByClassName("authorName")[0]
65+
.firstChild.innerHTML.trim();
66+
let searchString = encodeURIComponent(`${bookTitle} ${bookAuthor}`);
67+
let libraries = JSON.parse(await GM.getValue("libraries", "[]"));
68+
document.body.innerHTML += `<div style="position: fixed;
69+
top: 100px;
70+
left: 1em;
71+
width: 400px;
72+
background-color: #ececec;
73+
border: 1px solid black;
74+
padding: 1em;"><h3>Libby results</h3><div id="libby-results"></div></div>`;
75+
76+
if (libraries.length === 0) {
77+
document.getElementById(
78+
"libby-results"
79+
).innerHTML = `No libraries found, please visit <a href="https://libbyapp.com/interview/menu" target="_blank">here</a> to sync your libraries.`;
80+
}
81+
82+
libraries.map((library) => {
83+
let libraryKey = library._.activeKey || library.baseKey;
84+
let url = `https://thunder.api.overdrive.com/v2/libraries/${libraryKey}/media?query=${searchString}`;
85+
fetch(url)
86+
.then((response) => response.json())
87+
.then((result) => {
88+
document.getElementById(
89+
"libby-results"
90+
).innerHTML += `<div>${library._.name} <b><a href="https://libbyapp.com/search/${library.baseKey}/search/query-${searchString}/page-1" target="_blank">${result.totalItems} results</a></b></div>`;
91+
});
92+
});
93+
};
94+
95+
if (unsafeWindow.location.host == "libbyapp.com") {
96+
addLibbyButton();
97+
} else if (unsafeWindow.location.host == "www.goodreads.com") {
98+
addGoodreadsResults();
99+
}
100+
})();

goodreads.png

173 KB
Loading

libby.png

86.6 KB
Loading

0 commit comments

Comments
 (0)