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

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/[email protected]?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/[email protected]/+esm").then(m => m.default);
                        pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdn.jsdelivr.net/npm/[email protected]/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);
    }
});

Custom JavaScript code - accesses and extracts content from live web and pdf URLs

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(' ');
}

oc.thread.on("MessageAdded", async function ({ message }) {
  if (message.author === "user") {
    // Extract URLs from the user's message
    let urlsInLastMessage = [...message.content.matchAll(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g)].map(m => m[0]);

    // If no URLs were found, exit without doing anything
    if (urlsInLastMessage.length === 0) return;

    // Load the Readability library if not already loaded
    if (!window.Readability) {
      window.Readability = await import("https://esm.sh/@mozilla/[email protected]?no-check").then(m => m.Readability);
    }

    // Process the last URL in the message
    let url = urlsInLastMessage.at(-1); // Use the last URL
    let blob = await fetch(url).then(r => r.blob());
    let output;

    // 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/[email protected]/+esm").then(m => m.default);
        pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdn.jsdelivr.net/npm/[email protected]/build/pdf.worker.min.js";
      }
      let text = await getPdfText(await blob.arrayBuffer());
      output = text.slice(0, 5000); // Grab only the first 5000 characters
    } else {
      // 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
    }

    // 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 of the webpage that was linked in the previous message: \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);
  }
});
Edit
Pub: 14 Oct 2024 08:45 UTC
Edit: 15 Oct 2024 15:19 UTC
Views: 484