Skip to content

Instantly share code, notes, and snippets.

@nikhilweee
Last active August 14, 2024 06:03
Show Gist options
  • Save nikhilweee/84d942252fecfaa9f33186be878d12ac to your computer and use it in GitHub Desktop.
Save nikhilweee/84d942252fecfaa9f33186be878d12ac to your computer and use it in GitHub Desktop.
Search Query Generator
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Google Search Query Generator</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f4f4f4;
}
h1 {
text-align: center;
color: #333;
}
form {
max-width: 500px;
margin: 0 auto;
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
label {
display: block;
margin-top: 10px;
margin-bottom: 8px;
font-weight: bold;
color: #555;
}
input[type="text"] {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
button {
width: 100%;
padding: 10px;
background-color: #28a745;
color: #fff;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
}
button:hover {
background-color: #218838;
}
h2 {
text-align: center;
color: #333;
margin-top: 20px;
}
a {
text-decoration: dashed;
font-weight: normal;
}
p {
max-width: 500px;
margin-bottom: 20px;
background: #fff;
border-radius: 8px;
word-break: break-word;
color: #555;
}
textarea {
text-wrap: balance;
margin: 20px 0;
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
resize: none;
overflow: hidden;
}
/* Responsive adjustments */
@media (max-width: 600px) {
form {
padding: 15px;
margin: 10px;
}
button {
font-size: 14px;
}
}
</style>
</head>
<body>
<h1>Google Search Query Generator</h1>
<form id="queryForm">
<p>Separate multiple entries by a comma.</p>
<label for="sites">Sites to Include</label>
<input type="text" id="sites" name="sites" />
<div id="include-group">
<label for="include"
>Keywords to Include
<span style="float: right"
><a href="#" onclick="addIncludeGroup(); return false;"
>Add Group</a
></span
></label
>
<input type="text" id="include" class="include" name="include" />
</div>
<label for="exclude">Keywords to Exclude</label>
<input type="text" id="exclude" name="exclude" />
<label for="after">Show Results After</label>
<input type="text" id="after" name="after" />
<button type="button" onclick="handleSubmit()">
Generate Search Query
</button>
<textarea id="generated"></textarea>
<button type="button" onclick="searchGoogle()">Search on Google</button>
</form>
<script>
// Function to save values to localStorage
function saveValues() {
const fields = ["sites", "exclude"];
fields.forEach((field) => {
const value = document.getElementById(field).value;
localStorage.setItem(field, value);
});
const includeFields = Array.from(document.querySelectorAll(".include"));
const includeValues = includeFields
.map((input) => input.value)
.filter((value) => value.trim() !== "");
localStorage.setItem("include", JSON.stringify(includeValues));
}
// Function to load saved values from localStorage
function loadValues() {
const fields = ["sites", "exclude"];
fields.forEach((field) => {
const value = localStorage.getItem(field);
if (value) document.getElementById(field).value = value;
});
// Load multiple include fields
const savedIncludes = JSON.parse(
localStorage.getItem("include") || "[]"
);
const includeContainer = document.getElementById("include-group");
// Remove existing include fields
Array.from(includeContainer.getElementsByClassName("include")).forEach(
(input) => input.remove()
);
// Create and append new input fields
savedIncludes.forEach((value) => {
const input = document.createElement("input");
input.type = "text";
input.className = "include";
input.name = "include";
input.value = value;
includeContainer.appendChild(input);
});
const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
.toISOString()
.split("T")[0];
document.getElementById("after").value = sevenDaysAgo;
}
function generateQuery() {
const sites = document
.getElementById("sites")
.value.split(",")
.map((site) => `site:${site.trim()}`)
.join(" OR ");
const include = Array.from(document.querySelectorAll(".include"))
.map((input) =>
input.value
.split(",")
.map((word) => `"${word.trim()}"`)
.join(" OR ")
)
.filter((group) => group.trim() !== "")
.map((group) => `(${group})`)
.join(" ");
const exclude = document
.getElementById("exclude")
.value.split(",")
.filter((word) => word.trim() !== "")
.map((word) => `-"${word.trim()}"`)
.join(" ");
const after = document.getElementById("after").value;
const queryParts = [];
if (sites) queryParts.push(`(${sites})`);
if (include) queryParts.push(`${include}`);
if (exclude) queryParts.push(`${exclude}`);
if (after) queryParts.push(`after:${after}`);
const query = queryParts.join(" ");
const textarea = document.getElementById("generated");
textarea.value = query;
adjustTextAreaHeight(textarea);
}
function searchGoogle() {
const query = document.getElementById("generated").value;
const url = `https://www.google.com/search?q=${encodeURIComponent(
query
)}`;
window.open(url, "_blank");
}
function handleSubmit() {
saveValues();
loadValues();
generateQuery();
}
function addIncludeGroup() {
const input = document.createElement("input");
input.className = "include";
input.name = "include";
input.type = "text";
document.getElementById("include-group").appendChild(input);
}
function adjustTextAreaHeight(textarea) {
textarea.style.height = "auto";
textarea.style.height = textarea.scrollHeight + "px";
}
// Resize textarea on user input
document.querySelectorAll("textarea").forEach((textarea) => {
textarea.addEventListener("input", () => {
adjustTextAreaHeight(textarea);
});
});
window.onload = loadValues;
</script>
</body>
</html>
@nikhilweee
Copy link
Author

Additionally, you can host this using NGINX on Docker. Rename querygen.html to /path/to/html/index.html on the host machine.

services:
  jobs:
    container_name: query
    restart: always
    image: nginx:alpine
    volumes:
      - '/path/to/html:/usr/share/nginx/html'
    networks:
      - proxyman_default

networks:
  proxyman_default:
    external: true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment