Add subscribe to RSS button to Ao3 works
This commit is contained in:
130
ao3-subscribe.user.js
Normal file
130
ao3-subscribe.user.js
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
// ==UserScript==
|
||||||
|
// @name ao3 subscribe to feed
|
||||||
|
// @version 1
|
||||||
|
// @require http://crypto.stanford.edu/sjcl/sjcl.js
|
||||||
|
// @grant GM.getValue
|
||||||
|
// @grant GM.setValue
|
||||||
|
// @include https://archiveofourown.org/works/*
|
||||||
|
// ==/UserScript==
|
||||||
|
// User script for Firefox
|
||||||
|
|
||||||
|
// Password management
|
||||||
|
|
||||||
|
async function decodeOrPrompt(targVar, userPrompt, setValVarName, encKey) {
|
||||||
|
if (targVar) {
|
||||||
|
targVar = unStoreAndDecrypt(targVar, encKey);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
targVar = prompt(
|
||||||
|
userPrompt + ' not set for ' + location.hostname + '. Please enter it now:',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
await GM.setValue(setValVarName, encryptAndStore(targVar, encKey));
|
||||||
|
}
|
||||||
|
return targVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
function encryptAndStore(clearText, encKey) {
|
||||||
|
return JSON.stringify(sjcl.encrypt(encKey, clearText));
|
||||||
|
}
|
||||||
|
|
||||||
|
function unStoreAndDecrypt(jsonObj, encKey) {
|
||||||
|
return sjcl.decrypt(encKey, JSON.parse(jsonObj));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCredentials() {
|
||||||
|
var encKey = await GM.getValue("encKey", "");
|
||||||
|
var usr = await GM.getValue("ttrssUser", "");
|
||||||
|
var pword = await GM.getValue("ttrssPass", "");
|
||||||
|
|
||||||
|
if (!encKey) {
|
||||||
|
encKey = prompt(
|
||||||
|
'Script key not set for ' + location.hostname + '. Please enter a random string:',
|
||||||
|
''
|
||||||
|
);
|
||||||
|
await GM.setValue("encKey", encKey);
|
||||||
|
|
||||||
|
usr = pword = ""; // New key makes prev stored values (if any) unable to decode.
|
||||||
|
}
|
||||||
|
usr = await decodeOrPrompt(usr, "TTRSS user", "ttrssUser", encKey);
|
||||||
|
pword = await decodeOrPrompt(pword, "TTRSS password", "ttrssPass", encKey);
|
||||||
|
return { usr: usr, pword: pword };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to add a button to the <ul> element
|
||||||
|
function addSubscriptionButton() {
|
||||||
|
const ulElement = document.querySelector("ul.work");
|
||||||
|
if (ulElement) {
|
||||||
|
const newLi = document.createElement("li");
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.textContent = "Subscribe to RSS";
|
||||||
|
button.onclick = async function () {
|
||||||
|
// Extract work_id from the URL
|
||||||
|
const workIdMatch = window.location.href.match(/works\/(\d+)/);
|
||||||
|
if (workIdMatch) {
|
||||||
|
const workId = workIdMatch[1];
|
||||||
|
const rssURL = `https://nas.franpenedo.com/rss-bridge/?action=display&bridge=AO3Bridge&context=Work&id=${workId}&format=atom`;
|
||||||
|
|
||||||
|
// Call the login method to get a session ID
|
||||||
|
try {
|
||||||
|
const sessionID = await loginToTinyTinyRSS();
|
||||||
|
|
||||||
|
// Subscribe to the RSS feed using the session ID
|
||||||
|
try {
|
||||||
|
await subscribeToFeed(rssURL, sessionID);
|
||||||
|
alert("Subscribed successfully!");
|
||||||
|
} catch (error) {
|
||||||
|
alert("Error subscribing to feed: " + error);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
alert("Error logging in: " + error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("Unable to extract work_id from the URL.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
newLi.appendChild(button);
|
||||||
|
ulElement.appendChild(newLi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to simulate a login to Tiny Tiny RSS
|
||||||
|
async function loginToTinyTinyRSS() {
|
||||||
|
const creds = await getCredentials();
|
||||||
|
const loginResponse = await fetch("https://news.nas.franpenedo.com/api/", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ op: "login", user: creds.usr, password: creds.pword }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await loginResponse.json();
|
||||||
|
if (data.content.hasOwnProperty("session_id")) {
|
||||||
|
return data.content.session_id;
|
||||||
|
} else {
|
||||||
|
console.log(data);
|
||||||
|
throw new Error("Login failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to subscribe to an RSS feed in Tiny Tiny RSS
|
||||||
|
async function subscribeToFeed(feedURL, sessionID) {
|
||||||
|
const subscribeResponse = await fetch("https://news.nas.franpenedo.com/api/", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ op: "subscribeToFeed", feed_url: feedURL, category_id: 11, sid: sessionID }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const subscribeData = await subscribeResponse.json();
|
||||||
|
if (subscribeData.content.status.code !== 1) {
|
||||||
|
console.log(subscribeData);
|
||||||
|
throw new Error("Subscription failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function to add the button
|
||||||
|
addSubscriptionButton();
|
||||||
Reference in New Issue
Block a user