Note
Custom JavaScript code allows Chatbot to search Google by keyword enclosed in ' '. It will search and extract the first found web page content on google.
Adjust numMessagesInContext = number
to specify the scope of the search trigger.
Adjust const matches = message.content.match
to change the trigger syntax, if you don't like using ' '.
Adjust output = text.slice
to decide how many words will be extracted in the results page.
Adjust return data.items[0].link;
to increase the number of search results selected for extraction.
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | let lastSystemMessageId = null; // To store the ID of the last system-generated message
let numMessagesInContext = 1; // How many historical messages to include when updating
async function getPdfText(data) {
let doc = await window.pdfjsLib.getDocument({ data }).promise;
let pageTexts = Array.from({ length: doc.numPages }, async (v, i) => {
return (await (await doc.getPage(i + 1)).getTextContent()).items.map(token => token.str).join('');
});
return (await Promise.all(pageTexts)).join(' ');
}
async function loadReadability() {
// Check if Readability is already loaded
if (!window.Readability) {
// Load the Readability library
window.Readability = await import("https://esm.sh/@mozilla/readability@0.4.4?no-check").then(m => m.Readability);
}
}
async function googleSearch(query) {
const apiKey = "AIzaSyBWgqgce7RH6xsVDG_P2mj96jHnksFnzLo"; // Your Google API key
const searchEngineId = "11d886d58fb9547b2"; // Your Custom Search Engine ID
const searchUrl = `https://www.googleapis.com/customsearch/v1?key=${apiKey}&cx=${searchEngineId}&q=${encodeURIComponent(query)}`;
const response = await fetch(searchUrl);
const data = await response.json();
// Log the API response for debugging
console.log("API Response:", data);
if (!response.ok || !data.items || data.items.length === 0) {
throw new Error(`Google search failed: No results found for query "${query}"`);
}
return data.items[0].link; // Return the first search result URL
}
oc.thread.on("MessageAdded", async function ({ message }) {
if (message.author === "user") {
// Extract the text inside single quotes from the user's message
const matches = message.content.match(/'([^']+)'/); // Only match text in single quotes
const searchQuery = matches ? matches[1] : null; // Get the first matching group (the text inside the quotes)
if (!searchQuery) {
// If no query is found, exit the function
console.log("No search query found. Exiting without search.");
return;
}
console.log("Search Query:", searchQuery); // Log the search query
let output;
try {
// Perform a Google search
const firstResultUrl = await googleSearch(searchQuery);
if (!firstResultUrl) {
output = "No search results found.";
} else {
// Fetch the content of the first search result
let blob = await fetch(firstResultUrl).then(r => r.blob());
// Check if the fetched Blob is a PDF
if (blob.type === "application/pdf") {
if (!window.pdfjsLib) {
window.pdfjsLib = await import("https://cdn.jsdelivr.net/npm/pdfjs-dist@3.6.172/+esm").then(m => m.default);
pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdn.jsdelivr.net/npm/pdfjs-dist@3.6.172/build/pdf.worker.min.js";
}
let text = await getPdfText(await blob.arrayBuffer());
output = text.slice(0, 5000); // Grab only the first 5000 characters
} else {
// Load Readability
await loadReadability(); // Ensure Readability is loaded
// Process the Blob as HTML content
let html = await blob.text();
let doc = new DOMParser().parseFromString(html, "text/html");
let article = new Readability(doc).parse();
output = `# ${article.title || "(no page title)"}\n\n${article.textContent}`;
output = output.slice(0, 5000); // Grab only the first 5000 characters
}
}
} catch (error) {
output = `Error occurred while fetching the content: ${error.message}`;
}
// Send the extracted content back to the chat thread
let systemMessage = {
author: "system",
hiddenFrom: ["user"], // Hide the message from user
customData: { isSystemMessage: true }, // Mark this message as system-generated
content: "Here's the content from the first search result: \n\n" + output,
};
// Check if there's a previous system message to replace
let previousSystemMessage = oc.thread.messages.findLast(m => m.customData?.isSystemMessage);
if (previousSystemMessage) {
// Remove the previous system message
oc.thread.messages = oc.thread.messages.filter(m => m !== previousSystemMessage);
}
// Push the new system message
oc.thread.messages.push(systemMessage);
}
});
|