/**
* @file This file adds upvote functionality to KERISSE search results.
* It listens for clicks on elements with the class "upvote" and captures
* relevant search result data.
*
* The script also prompts users for a simple anti spam check.
* Once the user's answer is verified by a remote PHP script, an upvote is sent to another
* remote PHP script. A token is stored in a cookie for future upvotes without requiring
* the user to answer the prompt again.
*
* Dependencies:
* - Octokit, App from 'octokit'
* - Awesome-Notifications (AWN) for user notifications
*
* Configuration variables are specified under the CONFIG section.
* They include the URLs for the remote PHP scripts for upvoting and answer-checking,
* as well as messages displayed to the user.
*
* https://f3oall.github.io/awesome-notifications/docs/why-such-awesome
* https://www.npmjs.com/package/awesome-notifications
* https://github.com/f3oall/awesome-notifications#readme
* @author Kor Dwarshuis
* @version 1.0.0
* @since 2023-09-18
*/
import { Octokit, App } from 'octokit';
// import AWN from 'awesome-notifications';
import AWN from './libs/awesome-notifications.js';
// Initialize instance of AWN, awesome notifications
let notifier = new AWN({
maxNotifications: 6,
durations: {
alert: 0,
success: 4000,
},
icons: {
enabled: false,
},
});
const upvoteSearchResult = () => {
// CONFIG
const remoteUpvoteScript = 'https://dwarshuis.com/various/kerisse/php_scripts/upvotes.php';
const remoteCheckAnswerScript = 'https://dwarshuis.com/various/kerisse/php_scripts/checkAnswer.php';
const promptText = '- - - - - - - - -\nCheck: What is the four letter word (in lowercase) for the identity system based secure overlay for the Internet?\n\nSet the cookie. Go!!!';
const upvoteSentText = 'Your upvote has been sent. This is a test and currently we are manually checking and processing the results.';
const upvoteNotSentText = `Not the answer we expected. Your upvote has NOT been sent.`;
const continueText = 'You are upvoting a search result.';
// END CONFIG
let activeButton = null;
let upvoteData = {};
// Add event listener to the upvote buttons.
document.addEventListener('click', (event) => {
if (event.target.classList.contains('upvote')) {
// Take the url from the href in the previous element
let searchHitUrl = event.target.previousElementSibling.getAttribute('href');
// Take the search term from the search box
let searchTerm = document.querySelector(".ais-SearchBox-input").value;
// Create the upvote data object
upvoteData.name = searchTerm.replace(/ /g, '-') + "-" + Math.floor(Date.now() / 1000); // Replace spaces with dashes, unix timestamp to make unique
upvoteData.url = searchHitUrl;
upvoteData.query = searchTerm;
upvoteData.position = "1";
upvoteData.match = "exact";
activeButton = event.target;
submitAnswer();
}
});
function submitAnswer() {
// First, check if there is any cookie set at all.
if (document.cookie.indexOf("upvoteAnswer=") !== -1) {
// Read the stored token from the cookie
let cookieValue = document.cookie
.split('; ')
.find(row => row.startsWith('upvoteAnswer='))
.split('=')[1];
// Here we could validate the token against the server, but this is a basic check, we will leave it for now.
// For now, we skip the question.
// sendContent(upvoteData, cookieValue);
const userResponse = confirm(continueText);
if (userResponse) {
// Code to execute if the user clicks "OK"
console.log("You chose to continue!");
sendContent(upvoteData, cookieValue);
console.log("sendContent");
// Disable the upvote button
activeButton.disabled = true;
} else {
// Code to execute if the user clicks "Cancel"
console.log("You chose to cancel.");
return
}
} else {
// User has not yet answered the question
const userAnswer = prompt(promptText, "");
fetch(remoteCheckAnswerScript, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `user_answer=${userAnswer}`
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log("Correct answer!");
document.cookie = `upvoteAnswer=${data.token}; max-age=31536000`; // Expires after 1 year
const userResponse = confirm(continueText);
if (userResponse) {
// Code to execute if the user clicks "OK"
console.log("You chose to continue!");
sendContent(upvoteData, data.token);
console.log("sendContent");
// Disable the upvote button
activeButton.disabled = true;
} else {
// Code to execute if the user clicks "Cancel"
console.log("You chose to cancel.");
return
}
} else {
console.log("Incorrect answer!");
notifier.confirm(
upvoteNotSentText,
onOk,
false,
{
labels: {
confirm: 'Info',
},
}
);
}
});
}
}
let onOk = () => {
// notifier.info('You pressed OK');
};
function sendContent(data, token) {
var formData = new FormData();
formData.append('content', JSON.stringify(data));
formData.append('token', token); // Add the token
// Send the data to the remote script
fetch(remoteUpvoteScript, { method: 'POST', body: formData });
notifier.confirm(
upvoteSentText,
onOk,
false,
{
labels: {
confirm: 'Info',
},
}
);
}
};
export function onRouteDidUpdate({ location, previousLocation }) {
// Don't execute if we are still on the same page; the lifecycle may be fired
// because the hash changes (e.g. when navigating between headings)
// if (location.pathname === previousLocation?.pathname) return;
upvoteSearchResult();
}