├── .replit ├── .gitignore ├── replit.nix ├── public ├── Cheesgle.png ├── Img │ ├── cheese.png │ ├── cheesgle_long.png │ └── mouldy_cheese.png ├── robots.txt ├── Credits │ ├── about.js │ ├── about.css │ └── credits.html ├── Verified │ ├── about.js │ ├── about.css │ └── about.html ├── 404.html ├── About │ ├── about.js │ ├── about.css │ └── about.html ├── Add │ ├── add.js │ ├── add.css │ └── add.html ├── sitemap.xml ├── Search │ ├── search.css │ ├── search.html │ ├── search.js │ └── cheeses.json ├── index.html └── style.css ├── saveDatabase.js ├── README.md ├── reliableSites.json ├── package.json └── index.js /.replit: -------------------------------------------------------------------------------- 1 | run = "npm start" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | db.txt 3 | dbb.txt -------------------------------------------------------------------------------- /replit.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: { 2 | deps = [ 3 | pkgs.nodejs-16_x 4 | ]; 5 | } -------------------------------------------------------------------------------- /public/Cheesgle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingMASTER398/Cheesgle/HEAD/public/Cheesgle.png -------------------------------------------------------------------------------- /public/Img/cheese.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingMASTER398/Cheesgle/HEAD/public/Img/cheese.png -------------------------------------------------------------------------------- /public/Img/cheesgle_long.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingMASTER398/Cheesgle/HEAD/public/Img/cheesgle_long.png -------------------------------------------------------------------------------- /public/Img/mouldy_cheese.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingMASTER398/Cheesgle/HEAD/public/Img/mouldy_cheese.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /Search 3 | Allow: / 4 | Allow: /index.html 5 | Allow: /About/about.html 6 | Allow: /Credits/credits.html 7 | Allow: /Add/add.html -------------------------------------------------------------------------------- /saveDatabase.js: -------------------------------------------------------------------------------- 1 | const { parentPort, workerData } = require("worker_threads"); 2 | var jsonpack = require("jsonpack"); 3 | var fs = require("fs"); 4 | 5 | fs.writeFileSync("./dbb.txt", jsonpack.pack(workerData)); 6 | fs.writeFileSync("./db.txt", jsonpack.pack(workerData)); 7 | 8 | parentPort.postMessage(true); 9 | process.exit(); 10 | -------------------------------------------------------------------------------- /public/Credits/about.js: -------------------------------------------------------------------------------- 1 | function newSearch() { 2 | window.location.href = 3 | "../Search/search.html?q=" + 4 | document.getElementsByClassName("searchbar")[0].value; 5 | } 6 | 7 | document 8 | .getElementsByClassName("searchbar")[0] 9 | .addEventListener("keyup", function (event) { 10 | event.preventDefault(); 11 | if (event.keyCode === 13) { 12 | newSearch(); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /public/Verified/about.js: -------------------------------------------------------------------------------- 1 | function newSearch() { 2 | window.location.href = 3 | "../Search/search.html?q=" + 4 | document.getElementsByClassName("searchbar")[0].value; 5 | } 6 | 7 | document 8 | .getElementsByClassName("searchbar")[0] 9 | .addEventListener("keyup", function (event) { 10 | event.preventDefault(); 11 | if (event.keyCode === 13) { 12 | newSearch(); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cheesgle 2 | The world's best worst search engine, based on cheese. 3 | See it live at [Cheesgle.com](https://cheesgle.com/) 4 | 5 | This repository has now been linked to the Replit counterpart found at [https://replit.com/@codingMASTER398/Cheesgle](https://replit.com/@codingMASTER398/Cheesgle). 6 | 7 | Don't `git push main --force`, kids. 8 | 9 | Best way to set this up is just to fork the Replit repo. 10 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 6 |

Four hundred and four

7 |
8 |

9 | Looks like ye've encountered a dead end. Such a shame!
10 | Try one of these links on for size:
11 | Random cheese
12 | Home
13 | Search 'foot cheese'
14 | Hope one of 'em is of help. 15 |

16 | -------------------------------------------------------------------------------- /public/About/about.js: -------------------------------------------------------------------------------- 1 | function newSearch() { 2 | window.location.href = 3 | "../Search/search.html?q=" + 4 | document.getElementsByClassName("searchbar")[0].value; 5 | } 6 | 7 | document 8 | .getElementsByClassName("searchbar")[0] 9 | .addEventListener("keyup", function (event) { 10 | event.preventDefault(); 11 | if (event.keyCode === 13) { 12 | newSearch(); 13 | } 14 | }); 15 | 16 | fetch("../pageCount").then(async function (r) { 17 | document.getElementById("websites").innerText = await r.text(); 18 | }); 19 | -------------------------------------------------------------------------------- /public/Add/add.js: -------------------------------------------------------------------------------- 1 | function newSearch() { 2 | window.location.href = 3 | "../Search/search.html?q=" + 4 | document.getElementsByClassName("searchbar")[0].value; 5 | } 6 | 7 | document 8 | .getElementsByClassName("searchbar")[0] 9 | .addEventListener("keyup", function (event) { 10 | event.preventDefault(); 11 | if (event.keyCode === 13) { 12 | newSearch(); 13 | } 14 | }); 15 | 16 | fetch("../submitSiteInfo").then(async function (r) { 17 | document.getElementsByClassName("submitInfo")[0].innerHTML = await r.text(); 18 | }); 19 | -------------------------------------------------------------------------------- /reliableSites.json: -------------------------------------------------------------------------------- 1 | [ 2 | "mainland.com.au", 3 | "cheese.com", 4 | "www.dairy.com.au", 5 | "thedairy.com", 6 | "www.dairyaustralia.com.au", 7 | "www.cheesescience.org", 8 | "forevercheese.com", 9 | "www.taste.com.au", 10 | "cheesgle.com", 11 | "www.cheesgle.com", 12 | "www.littlecreekcheese.com.au", 13 | "milawacheese.com.au", 14 | "en.wikipedia.org", 15 | "www.murrayscheese.com", 16 | "wikipedia.org", 17 | "www.cheese.com", 18 | "culturecheesemag.com", 19 | "worldcheeseawards.com", 20 | "www.finecheese.co.uk", 21 | "youtube.com", 22 | "en.wikipedia.org", 23 | "wikipedia.org" 24 | ] -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://cheesgle.com/ 5 | 1 6 | 7 | 8 | https://cheesgle.com/Add/add.html 9 | 0.8 10 | 11 | 12 | https://cheesgle.com/About/about.html 13 | 0.7 14 | 15 | 16 | https://cheesgle.com/Verified/about.html 17 | 0.7 18 | 19 | 20 | https://cheesgle.com/Credits/credits.html 21 | 0.5 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Cheesle", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "axios": "^0.25.0", 8 | "body-parser": "^1.19.1", 9 | "cheerio": "^1.0.0-rc.10", 10 | "cheese-name": "^2.0.1", 11 | "cors": "^2.8.5", 12 | "express": "^4.17.2", 13 | "express-rate-limit": "^6.2.0", 14 | "jsonpack": "^1.1.5", 15 | "minisearch": "^3.2.0", 16 | "prettier": "^2.8.1", 17 | "request-ip": "^2.1.3", 18 | "robots-txt-parser": "^2.0.2", 19 | "sitemap-xml-parser": "0.0.2", 20 | "typo-js": "^1.2.1" 21 | }, 22 | "scripts": { 23 | "start": "node index.js", 24 | "fm": "npx prettier --write ." 25 | }, 26 | "keywords": [], 27 | "author": "", 28 | "license": "ISC" 29 | } 30 | -------------------------------------------------------------------------------- /public/Add/add.css: -------------------------------------------------------------------------------- 1 | .topimg { 2 | width: 15%; 3 | } 4 | .top { 5 | width: 90%; 6 | height: 30%; 7 | display: flex; 8 | align-items: center; 9 | } 10 | .padding { 11 | padding: 15px 15px; 12 | } 13 | .morePadding { 14 | padding: 20px 20px; 15 | } 16 | .top input { 17 | padding: 10px 10px; 18 | width: 30%; 19 | border: 0px; 20 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 21 | } 22 | .top button { 23 | padding: 10px 10px; 24 | width: 5%; 25 | border: 0px; 26 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 27 | transition: 0.5s; 28 | } 29 | .top button:hover { 30 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.5); 31 | color: orange; 32 | } 33 | 34 | @media screen and (max-width: 800px) { 35 | .top input { 36 | width: 60%; 37 | } 38 | .topimg { 39 | width: 40%; 40 | } 41 | .top button { 42 | width: 10%; 43 | } 44 | } 45 | 46 | * { 47 | font-family: Verdana, Geneva, Tahoma, sans-serif; 48 | } 49 | 50 | .bottom button { 51 | padding: 10px 10px; 52 | border: 0px; 53 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 54 | transition: 0.5s; 55 | font-size: large; 56 | } 57 | 58 | @media screen and (max-width: 800px) { 59 | .page { 60 | font-size: x-large; 61 | } 62 | .page button { 63 | font-size: x-large; 64 | } 65 | } 66 | 67 | .material-symbols-outlined { 68 | font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; 69 | font-size: inherit !important; 70 | } 71 | -------------------------------------------------------------------------------- /public/About/about.css: -------------------------------------------------------------------------------- 1 | .topimg { 2 | width: 15%; 3 | } 4 | .top { 5 | width: 90%; 6 | height: 30%; 7 | display: flex; 8 | align-items: center; 9 | } 10 | .padding { 11 | padding: 15px 15px; 12 | } 13 | .morePadding { 14 | padding: 20px 20px; 15 | } 16 | .top input { 17 | padding: 10px 10px; 18 | width: 30%; 19 | border: 0px; 20 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 21 | } 22 | .top button { 23 | padding: 10px 10px; 24 | width: 5%; 25 | border: 0px; 26 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 27 | transition: 0.5s; 28 | } 29 | .top button:hover { 30 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.5); 31 | color: orange; 32 | } 33 | 34 | @media screen and (max-width: 800px) { 35 | .top input { 36 | width: 60%; 37 | } 38 | .topimg { 39 | width: 40%; 40 | } 41 | .top button { 42 | width: 10%; 43 | } 44 | } 45 | 46 | * { 47 | font-family: Verdana, Geneva, Tahoma, sans-serif; 48 | } 49 | 50 | .bottom button { 51 | padding: 10px 10px; 52 | border: 0px; 53 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 54 | transition: 0.5s; 55 | font-size: large; 56 | } 57 | 58 | @media screen and (max-width: 800px) { 59 | .page { 60 | font-size: x-large; 61 | } 62 | .page button { 63 | font-size: x-large; 64 | } 65 | } 66 | 67 | .material-symbols-outlined { 68 | font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; 69 | font-size: inherit !important; 70 | } 71 | -------------------------------------------------------------------------------- /public/Credits/about.css: -------------------------------------------------------------------------------- 1 | .topimg { 2 | width: 15%; 3 | } 4 | .top { 5 | width: 90%; 6 | height: 30%; 7 | display: flex; 8 | align-items: center; 9 | } 10 | .padding { 11 | padding: 15px 15px; 12 | } 13 | .morePadding { 14 | padding: 20px 20px; 15 | } 16 | .top input { 17 | padding: 10px 10px; 18 | width: 30%; 19 | border: 0px; 20 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 21 | } 22 | .top button { 23 | padding: 10px 10px; 24 | width: 5%; 25 | border: 0px; 26 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 27 | transition: 0.5s; 28 | } 29 | .top button:hover { 30 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.5); 31 | color: orange; 32 | } 33 | 34 | @media screen and (max-width: 800px) { 35 | .top input { 36 | width: 60%; 37 | } 38 | .topimg { 39 | width: 40%; 40 | } 41 | .top button { 42 | width: 10%; 43 | } 44 | } 45 | 46 | * { 47 | font-family: Verdana, Geneva, Tahoma, sans-serif; 48 | } 49 | 50 | .bottom button { 51 | padding: 10px 10px; 52 | border: 0px; 53 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 54 | transition: 0.5s; 55 | font-size: large; 56 | } 57 | 58 | @media screen and (max-width: 800px) { 59 | .page { 60 | font-size: x-large; 61 | } 62 | .page button { 63 | font-size: x-large; 64 | } 65 | } 66 | 67 | .material-symbols-outlined { 68 | font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; 69 | font-size: inherit !important; 70 | } 71 | -------------------------------------------------------------------------------- /public/Verified/about.css: -------------------------------------------------------------------------------- 1 | .topimg { 2 | width: 15%; 3 | } 4 | .top { 5 | width: 90%; 6 | height: 30%; 7 | display: flex; 8 | align-items: center; 9 | } 10 | .padding { 11 | padding: 15px 15px; 12 | } 13 | .morePadding { 14 | padding: 20px 20px; 15 | } 16 | .top input { 17 | padding: 10px 10px; 18 | width: 30%; 19 | border: 0px; 20 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 21 | } 22 | .top button { 23 | padding: 10px 10px; 24 | width: 5%; 25 | border: 0px; 26 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 27 | transition: 0.5s; 28 | } 29 | .top button:hover { 30 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.5); 31 | color: orange; 32 | } 33 | 34 | @media screen and (max-width: 800px) { 35 | .top input { 36 | width: 60%; 37 | } 38 | .topimg { 39 | width: 40%; 40 | } 41 | .top button { 42 | width: 10%; 43 | } 44 | } 45 | 46 | * { 47 | font-family: Verdana, Geneva, Tahoma, sans-serif; 48 | } 49 | 50 | .bottom button { 51 | padding: 10px 10px; 52 | border: 0px; 53 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 54 | transition: 0.5s; 55 | font-size: large; 56 | } 57 | 58 | @media screen and (max-width: 800px) { 59 | .page { 60 | font-size: x-large; 61 | } 62 | .page button { 63 | font-size: x-large; 64 | } 65 | } 66 | 67 | .material-symbols-outlined { 68 | font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; 69 | font-size: inherit !important; 70 | } 71 | -------------------------------------------------------------------------------- /public/Add/add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cheesgle | Add a website 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 30 | 31 | 32 | 36 | 45 | 46 | 47 |
48 |
49 | 50 | 55 | 56 | 62 | 65 |
66 |
67 |

Loading info

68 |
69 |
70 |
71 |
72 | 73 |
74 |
75 |
76 | 79 | 82 | 85 |

86 | Submit a website 87 |
88 |
89 |
90 | 91 | 92 | -------------------------------------------------------------------------------- /public/Search/search.css: -------------------------------------------------------------------------------- 1 | .topimg { 2 | width: 15%; 3 | } 4 | .top { 5 | width: 90%; 6 | height: 30%; 7 | display: flex; 8 | align-items: center; 9 | } 10 | .padding { 11 | padding: 15px 15px; 12 | } 13 | .morePadding { 14 | padding: 20px 20px; 15 | } 16 | .top input { 17 | padding: 10px 10px; 18 | width: 30%; 19 | border: 0px; 20 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 21 | } 22 | .top button { 23 | padding: 10px 10px; 24 | width: 5%; 25 | border: 0px; 26 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 27 | transition: 0.5s; 28 | } 29 | .top button:hover { 30 | box-shadow: 0 1px 3px orange; 31 | color: orange; 32 | } 33 | 34 | @media screen and (max-width: 800px) { 35 | .top input { 36 | width: 60%; 37 | } 38 | .topimg { 39 | width: 40%; 40 | } 41 | .top button { 42 | width: 10%; 43 | } 44 | } 45 | 46 | * { 47 | font-family: Verdana, Geneva, Tahoma, sans-serif; 48 | } 49 | 50 | /* 51 | input[type="checkbox"]{ 52 | border: 1px solid #ccc; 53 | box-shadow: 0 1px 3px rgba(23,23,23,0.24); 54 | transition: 0.5s; 55 | width: 10px; 56 | height: 10px; 57 | } 58 | input[type="checkbox"]:hover{ 59 | border: 1px solid rgb(0, 0, 0); 60 | box-shadow: 0 1px 3px rgba(23,23,23,0.3); 61 | } 62 | */ 63 | 64 | .result { 65 | padding: 6px; 66 | } 67 | 68 | .result p { 69 | margin: 0; 70 | } 71 | .result .description { 72 | font-size: large; 73 | } 74 | .result .urlText { 75 | font-size: smaller; 76 | color: grey; 77 | } 78 | .result a { 79 | margin: 0; 80 | font-size: larger; 81 | transition: 0.25s; 82 | } 83 | .result a:hover { 84 | color: cyan; 85 | transition: 0.25s; 86 | } 87 | 88 | .bottom button { 89 | padding: 10px 10px; 90 | border: 0px; 91 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 92 | transition: 0.5s; 93 | font-size: large; 94 | } 95 | 96 | .topResults { 97 | font-size: small; 98 | } 99 | 100 | .page { 101 | display: flex; 102 | align-items: center; 103 | } 104 | 105 | .page button { 106 | border: none; 107 | } 108 | 109 | @media screen and (max-width: 800px) { 110 | .page { 111 | font-size: x-large; 112 | } 113 | .page button { 114 | font-size: x-large; 115 | } 116 | } 117 | 118 | .cheeseSmall { 119 | width: 2.5%; 120 | } 121 | 122 | .rotate { 123 | animation: rotation 0.6s infinite linear; 124 | } 125 | 126 | @keyframes rotation { 127 | from { 128 | transform: rotate(0deg); 129 | } 130 | to { 131 | transform: rotate(359deg); 132 | } 133 | } 134 | 135 | .material-symbols-outlined { 136 | font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; 137 | font-size: inherit !important; 138 | } 139 | 140 | #cheeseEmbed{ 141 | box-sizing: border-box; 142 | padding: 6px; 143 | background-color: #f5f5f5; 144 | border-radius: 6px; 145 | width: 600px; 146 | overflow: auto; 147 | } 148 | 149 | #cheeseEmbed *{ 150 | margin: 12px; 151 | } 152 | 153 | #cheeseEmbed img{ 154 | float: right; 155 | height: 150px; 156 | padding-bottom: 12px; 157 | } 158 | 159 | #cheeseEmbed button { 160 | padding: 10px 10px; 161 | border: 0px; 162 | box-shadow: 0 1px 3px rgba(23, 23, 23, 0.24); 163 | transition: 0.5s; 164 | margin-top: 0; 165 | } 166 | 167 | @media screen and (max-width: 800px) { 168 | #cheeseEmbed{ 169 | width: 100%; 170 | } 171 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cheesgle 6 | 7 | 8 | 9 | Cheesgle | World's worst cheesey search engine 10 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 27 | 28 | 29 | 33 | 42 | 43 | 44 | 45 |
46 | 47 | 48 |
49 |
50 |
51 |
52 | 53 |
54 |
55 | 56 |
57 |
58 |
63 | 70 | 71 | Byte One 74 | Corp 79 |
80 |

The world's best worst search engine.

81 |

82 | 88 |
89 |
90 |
91 |
92 |
93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /public/About/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cheesgle | About 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 33 | 42 | 43 | 44 |
45 |
46 | 47 | 52 | 53 | 59 | 62 |
63 |
64 |

What is Cheesgle?

65 |
66 |

67 | Cheesgle is the world's best worst search engine.
We only index 68 | websites that are about cheese, making this search engine yet more 69 | useless.
Start searching here, and 70 | submit a page here.
71 | Credits are here. 72 |

73 |

...

74 |
75 |
76 | 79 | 82 | 85 |

86 | Submit a website 87 |
88 |
89 |
90 | 91 | 92 | -------------------------------------------------------------------------------- /public/Verified/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cheesgle | About verified sites 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 33 | 42 | 43 | 44 |
45 |
46 | 47 | 52 | 53 | 54 | 60 | 63 |
64 |
65 |

66 | check About verified 67 | sites 68 |

69 |

70 | Verified sites are basically our way to filter out spam.
Verified 71 | sites have the 72 | check next to them in 73 | search results, so you can easily spot them out.
They can also 74 | have more pages crawled overall (see 75 | add a page).
If you would like a 76 | website to be verified, join my 77 | Discord. 78 |

79 |
80 |
81 | 84 | 87 | 90 |

91 | Sumbit a website 92 |
93 |
94 |
95 | 96 | 97 | -------------------------------------------------------------------------------- /public/Search/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cheesgle | Search 7 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 42 | 43 | 44 | 48 | 57 | 58 | 59 |
60 |
61 | 62 | 67 | 68 | 74 | 77 |
78 |
79 |
80 | 85 | 91 |

Searching...

92 | 107 |
108 |
109 |
110 | 113 | 116 | 119 |

120 | Submit a website 121 |
122 |
123 |
124 | 125 | 126 | -------------------------------------------------------------------------------- /public/Search/search.js: -------------------------------------------------------------------------------- 1 | // Prepare to see the messiest code, like, ever. 2 | 3 | function getParameterByName(name) { 4 | return new URLSearchParams(window.location.search).get(name); 5 | } 6 | 7 | var query = getParameterByName("q"); 8 | var page = getParameterByName("page"); 9 | 10 | document.getElementsByClassName("searchbar")[0].value = query; 11 | 12 | function mould(error) { 13 | document.getElementById("searchingCheese").setAttribute("hidden", true); 14 | document.getElementById("searchingMould").removeAttribute("hidden"); 15 | document.getElementsByClassName("status")[0].innerText = error; 16 | } 17 | 18 | function protect(text) { 19 | // Replaces stuff with stuff 20 | return text 21 | .replace(/&/g, "&") 22 | .replace(/>/g, ">") 23 | .replace(/ { 50 | var verified = (await (await fetch("../Verified/list.json")).json()) || []; 51 | var cheeses = (await (await fetch("./cheeses.json")).json()) || []; 52 | 53 | fetch(urlToFetch) 54 | .then(async function (r) { 55 | if (r.status == 204) { 56 | mould(`No results found for ${query}`); 57 | return; 58 | } 59 | 60 | const json = await r.json(); 61 | if (json.error) { 62 | mould(json.reason); 63 | return; 64 | } 65 | 66 | document.getElementById("searchingCheese").setAttribute("hidden", true); 67 | document.getElementsByClassName("status")[0].setAttribute("hidden", true); 68 | 69 | let results = ``; 70 | for (let i = 0; i < json.results.length; i++) { 71 | const element = json.results[i]; 72 | results += `
`; 73 | if (verified.includes(new URL(element.href).host)) { 74 | results += `check ${element.title}`; 75 | } else 76 | results += `${element.title}`; 77 | results += ` 78 |

${element.description}

79 |

${protect(element.href)}

80 |

`; 81 | } 82 | 83 | let didYouMean = ""; 84 | if (query !== json.didYouMean) { 85 | didYouMean = `

Did you meen ${json.didYouMean}?

`; 88 | } 89 | 90 | let cheeseEmbed = ""; 91 | let titleParsed = query.trim().toLowerCase().replace(/ /g, "").replace(/'/g,"") 92 | console.log(titleParsed) 93 | for(let i=0; i 96 | 97 |

${cheeses[i].displayTitle}

98 |

Sourced fresh from cheese.com

99 | 100 | 101 | ` 102 | } 103 | } 104 | 105 | let resultsHtml = `
${json.resultsCount 106 | .toString() 107 | .replace(/\B(?=(\d{3})+(?!\d))/g, ",")} results for '${protect( 108 | query 109 | )}' found in aboot ${json.timeInSeconds} seconds.

${didYouMean} 110 |
111 |
112 | ${cheeseEmbed} 113 | ${results} 114 |
115 |

Page ${json.page}/${json.pages}
116 | 119 | 124 | 129 | 134 |

135 |
136 |

`; 137 | document 138 | .getElementsByClassName("morePadding")[0] 139 | .insertBefore( 140 | document.createElement("div"), 141 | document.getElementsByClassName("morePadding")[0].firstChild 142 | ).innerHTML = resultsHtml; 143 | }) 144 | .catch(function (e) { 145 | mould(`Unexpected error: ${e}`); 146 | }); 147 | })(); 148 | -------------------------------------------------------------------------------- /public/Credits/credits.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cheesgle | Credits 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 30 | 31 | 32 | 36 | 45 | 46 | 47 |
48 |
49 | 50 | 55 | 56 | 57 | 63 | 66 |
67 |
68 |

Credits & license

69 |

70 | Created by 71 | coding398 (codingMASTER398)
72 | Not modified (add your name here if you modified this Cheesgle)
73 | index design by Himm Lai
74 | NPM modules used: 75 |

76 | 77 |
    78 |
  • body-parser to parse form JSON when adding sites
  • 79 |
  • cors for development purposes
  • 80 |
  • cheerio for crawling
  • 81 |
  • axios for crawling
  • 82 |
  • express for... the entire website
  • 83 |
  • express-rate-limit for stopping spammers
  • 84 |
  • minisearch for really fast searches
  • 85 |
  • jsonpack for compressing database
  • 86 |
  • robots-txt-parser to parse robots.txt files
  • 87 |
  • sitemap-xml-parser to parse sitemaps
  • 88 |
  • cheese-name for the /randomCheese endpoint
  • 89 |
  • request-ip for assisting express-rate-limit
  • 90 |
  • typo-js did you mean results
  • 91 |
92 |
93 | License: 94 |

95 | MIT License Copyright (c) 2022 coding398 Permission is hereby granted, 96 | free of charge, to any person obtaining a copy of this software and 97 | associated documentation files (the "Software"), to deal in the 98 | Software without restriction, including without limitation the rights 99 | to use, copy, modify, merge, publish, distribute, sublicense, and/or 100 | sell copies of the Software, and to permit persons to whom the 101 | Software is furnished to do so, subject to the following conditions: 102 | The above copyright notice and this permission notice shall be 103 | included in all copies or substantial portions of the Software. THE 104 | SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 105 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 106 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 107 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 108 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 109 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 110 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 111 |

112 |
113 |
114 | 117 | 120 | 123 |

124 | Submit a website 125 |
126 |
127 |
128 | 129 | 130 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: sans-serif; 3 | -ms-text-size-adjust: 100%; 4 | -webkit-text-size-adjust: 100%; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | position: absolute; 10 | top: 30%; 11 | left: 50%; 12 | -ms-transform: translate(-50%, -50%); 13 | transform: translate(-50%, -50%); 14 | } 15 | 16 | article, 17 | aside, 18 | details, 19 | figcaption, 20 | figure, 21 | footer, 22 | header, 23 | hgroup, 24 | main, 25 | menu, 26 | nav, 27 | section, 28 | summary { 29 | display: block; 30 | } 31 | 32 | audio, 33 | canvas, 34 | progress, 35 | video { 36 | display: inline-block; 37 | vertical-align: baseline; 38 | } 39 | 40 | audio:not([controls]) { 41 | display: none; 42 | height: 0; 43 | } 44 | 45 | [hidden], 46 | template { 47 | display: none; 48 | } 49 | 50 | a { 51 | background-color: transparent; 52 | } 53 | 54 | a:active { 55 | outline: 0; 56 | } 57 | a:hover { 58 | outline: 0; 59 | } 60 | 61 | abbr[title] { 62 | border-bottom: 1px dotted; 63 | } 64 | 65 | b, 66 | strong { 67 | font-weight: bold; 68 | } 69 | 70 | dfn { 71 | font-style: italic; 72 | } 73 | 74 | h1 { 75 | font-size: 2em; 76 | margin: 0.67em 0; 77 | } 78 | 79 | mark { 80 | background: #ff0; 81 | color: #000; 82 | } 83 | 84 | small { 85 | font-size: 80%; 86 | } 87 | 88 | sub, 89 | sup { 90 | font-size: 75%; 91 | line-height: 0; 92 | position: relative; 93 | vertical-align: baseline; 94 | } 95 | 96 | sup { 97 | top: -0.5em; 98 | } 99 | 100 | sub { 101 | bottom: -0.25em; 102 | } 103 | 104 | img { 105 | border: 0; 106 | } 107 | 108 | svg:not(:root) { 109 | overflow: hidden; 110 | } 111 | 112 | figure { 113 | margin: 1em 40px; 114 | } 115 | 116 | hr { 117 | box-sizing: content-box; 118 | height: 0; 119 | } 120 | 121 | pre { 122 | overflow: auto; 123 | } 124 | 125 | code, 126 | kbd, 127 | pre, 128 | samp { 129 | font-family: monospace, monospace; 130 | font-size: 1em; 131 | } 132 | 133 | button, 134 | input, 135 | optgroup, 136 | select, 137 | textarea { 138 | color: inherit; 139 | font: inherit; 140 | margin: 0; 141 | } 142 | 143 | button { 144 | overflow: visible; 145 | } 146 | 147 | button, 148 | select { 149 | text-transform: none; 150 | } 151 | 152 | button, 153 | html input[type="button"], 154 | input[type="reset"], 155 | input[type="submit"] { 156 | -webkit-appearance: button; 157 | cursor: pointer; 158 | } 159 | 160 | button[disabled], 161 | html input[disabled] { 162 | cursor: default; 163 | } 164 | 165 | button::-moz-focus-inner, 166 | input::-moz-focus-inner { 167 | border: 0; 168 | padding: 0; 169 | } 170 | 171 | input { 172 | line-height: normal; 173 | } 174 | 175 | input[type="checkbox"], 176 | input[type="radio"] { 177 | box-sizing: border-box; 178 | padding: 0; 179 | } 180 | 181 | input[type="number"]::-webkit-inner-spin-button, 182 | input[type="number"]::-webkit-outer-spin-button { 183 | height: auto; 184 | } 185 | 186 | input[type="search"] { 187 | -webkit-appearance: textfield; 188 | box-sizing: content-box; 189 | } 190 | 191 | input[type="search"]::-webkit-search-cancel-button, 192 | input[type="search"]::-webkit-search-decoration { 193 | -webkit-appearance: none; 194 | } 195 | 196 | fieldset { 197 | border: 1px solid #c0c0c0; 198 | margin: 0 2px; 199 | padding: 0.35em 0.625em 0.75em; 200 | } 201 | 202 | legend { 203 | border: 0; 204 | padding: 0; 205 | } 206 | 207 | textarea { 208 | overflow: auto; 209 | } 210 | 211 | optgroup { 212 | font-weight: bold; 213 | } 214 | 215 | table { 216 | border-collapse: collapse; 217 | border-spacing: 0; 218 | } 219 | 220 | td, 221 | th { 222 | padding: 0; 223 | } 224 | 225 | /* 226 | * Skeleton V2.0.4 227 | * Copyright 2014, Dave Gamache 228 | * www.getskeleton.com 229 | * Free to use under the MIT license. 230 | * http://www.opensource.org/licenses/mit-license.php 231 | * 12/9/2014 232 | * Sass Version by Seth Coelen https://github.com/whatsnewsaes 233 | */ 234 | html { 235 | font-size: 62.5%; 236 | } 237 | 238 | body { 239 | font-size: 1.5em; 240 | line-height: 1.6; 241 | font-weight: 400; 242 | font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, 243 | sans-serif; 244 | color: #222; 245 | } 246 | 247 | a { 248 | color: #1eaedb; 249 | } 250 | a:hover { 251 | color: #1b9cc5; 252 | } 253 | 254 | hr { 255 | margin-top: 3rem; 256 | margin-bottom: 3.5rem; 257 | border-width: 0; 258 | border-top: 1px solid #e1e1e1; 259 | } 260 | 261 | .u-full-width { 262 | width: 100%; 263 | box-sizing: border-box; 264 | } 265 | 266 | .u-max-full-width { 267 | max-width: 100%; 268 | box-sizing: border-box; 269 | } 270 | 271 | .u-pull-right { 272 | float: right; 273 | } 274 | 275 | .u-pull-left { 276 | float: left; 277 | } 278 | 279 | h1, 280 | h2, 281 | h3, 282 | h4, 283 | h5, 284 | h6 { 285 | margin-top: 0; 286 | margin-bottom: 2rem; 287 | font-weight: 300; 288 | } 289 | 290 | h1 { 291 | font-size: 4rem; 292 | line-height: 1.2; 293 | letter-spacing: -0.1rem; 294 | } 295 | 296 | h2 { 297 | font-size: 3.6rem; 298 | line-height: 1.25; 299 | letter-spacing: -0.1rem; 300 | } 301 | 302 | h3 { 303 | font-size: 3rem; 304 | line-height: 1.3; 305 | letter-spacing: -0.1rem; 306 | } 307 | 308 | h4 { 309 | font-size: 2.4rem; 310 | line-height: 1.35; 311 | letter-spacing: -0.08rem; 312 | } 313 | 314 | h5 { 315 | font-size: 1.8rem; 316 | line-height: 1.5; 317 | letter-spacing: -0.05rem; 318 | } 319 | 320 | h6 { 321 | font-size: 1.5rem; 322 | line-height: 1.6; 323 | letter-spacing: 0; 324 | } 325 | 326 | @media (min-width: 550px) { 327 | h1 { 328 | font-size: 5rem; 329 | } 330 | 331 | h2 { 332 | font-size: 4.2rem; 333 | } 334 | 335 | h3 { 336 | font-size: 3.6rem; 337 | } 338 | 339 | h4 { 340 | font-size: 3rem; 341 | } 342 | 343 | h5 { 344 | font-size: 2.4rem; 345 | } 346 | 347 | h6 { 348 | font-size: 1.5rem; 349 | } 350 | } 351 | p { 352 | margin-top: 0; 353 | } 354 | 355 | .container { 356 | position: relative; 357 | width: 100%; 358 | max-width: 1140px; 359 | margin: 0 auto; 360 | padding: 0 20px; 361 | box-sizing: border-box; 362 | } 363 | 364 | .column, 365 | .columns { 366 | width: 100%; 367 | float: left; 368 | box-sizing: border-box; 369 | } 370 | 371 | @media (min-width: 400px) { 372 | .container { 373 | width: 85%; 374 | padding: 0; 375 | } 376 | } 377 | @media (min-width: 750px) { 378 | .container { 379 | width: 80%; 380 | } 381 | 382 | .column, 383 | .columns { 384 | margin-left: 4%; 385 | } 386 | 387 | .column:first-child, 388 | .columns:first-child { 389 | margin-left: 0; 390 | } 391 | 392 | .one.column, 393 | .one.columns { 394 | width: 4.66667%; 395 | } 396 | 397 | .two.columns { 398 | width: 13.33333%; 399 | } 400 | 401 | .three.columns { 402 | width: 22%; 403 | } 404 | 405 | .four.columns { 406 | width: 30.66667%; 407 | } 408 | 409 | .five.columns { 410 | width: 39.33333%; 411 | } 412 | 413 | .six.columns { 414 | width: 48%; 415 | } 416 | 417 | .seven.columns { 418 | width: 56.66667%; 419 | } 420 | 421 | .eight.columns { 422 | width: 65.33333%; 423 | } 424 | 425 | .nine.columns { 426 | width: 74%; 427 | } 428 | 429 | .ten.columns { 430 | width: 82.66667%; 431 | } 432 | 433 | .eleven.columns { 434 | width: 91.33333%; 435 | } 436 | 437 | .twelve.columns { 438 | width: 100%; 439 | margin-left: 0; 440 | } 441 | 442 | .one-third.column { 443 | width: 30.66667%; 444 | } 445 | 446 | .two-thirds.column { 447 | width: 65.33333%; 448 | } 449 | 450 | .one-half.column { 451 | width: 48%; 452 | } 453 | 454 | .offset-by-one.column, 455 | .offset-by-one.columns { 456 | margin-left: 8.66667%; 457 | } 458 | 459 | .offset-by-two.column, 460 | .offset-by-two.columns { 461 | margin-left: 17.33333%; 462 | } 463 | 464 | .offset-by-three.column, 465 | .offset-by-three.columns { 466 | margin-left: 26%; 467 | } 468 | 469 | .offset-by-four.column, 470 | .offset-by-four.columns { 471 | margin-left: 34.66667%; 472 | } 473 | 474 | .offset-by-five.column, 475 | .offset-by-five.columns { 476 | margin-left: 43.33333%; 477 | } 478 | 479 | .offset-by-six.column, 480 | .offset-by-six.columns { 481 | margin-left: 52%; 482 | } 483 | 484 | .offset-by-seven.column, 485 | .offset-by-seven.columns { 486 | margin-left: 60.66667%; 487 | } 488 | 489 | .offset-by-eight.column, 490 | .offset-by-eight.columns { 491 | margin-left: 69.33333%; 492 | } 493 | 494 | .offset-by-nine.column, 495 | .offset-by-nine.columns { 496 | margin-left: 78%; 497 | } 498 | 499 | .offset-by-ten.column, 500 | .offset-by-ten.columns { 501 | margin-left: 86.66667%; 502 | } 503 | 504 | .offset-by-eleven.column, 505 | .offset-by-eleven.columns { 506 | margin-left: 95.33333%; 507 | } 508 | 509 | .offset-by-one-third.column, 510 | .offset-by-one-third.columns { 511 | margin-left: 34.66667%; 512 | } 513 | 514 | .offset-by-two-thirds.column, 515 | .offset-by-two-thirds.columns { 516 | margin-left: 69.33333%; 517 | } 518 | 519 | .offset-by-one-half.column, 520 | .offset-by-one-half.column { 521 | margin-left: 52%; 522 | } 523 | } 524 | .container:after, 525 | .row:after, 526 | .u-cf { 527 | content: ""; 528 | display: table; 529 | clear: both; 530 | } 531 | 532 | .button, 533 | button { 534 | display: inline-block; 535 | height: 38px; 536 | padding: 0 40px; 537 | color: #555555; 538 | text-align: center; 539 | font-size: 11px; 540 | font-weight: 600; 541 | line-height: 38px; 542 | letter-spacing: 0.1rem; 543 | text-transform: uppercase; 544 | text-decoration: none; 545 | white-space: nowrap; 546 | background-color: transparent; 547 | border-radius: 4px; 548 | border: 1px solid #bbb; 549 | cursor: pointer; 550 | box-sizing: border-box; 551 | } 552 | 553 | input[type="submit"], 554 | input[type="reset"], 555 | input[type="button"] { 556 | display: inline-block; 557 | height: 38px; 558 | padding: 0 30px; 559 | color: #555555; 560 | text-align: center; 561 | font-size: 11px; 562 | font-weight: 600; 563 | line-height: 38px; 564 | letter-spacing: 0.1rem; 565 | text-transform: uppercase; 566 | text-decoration: none; 567 | white-space: nowrap; 568 | background-color: transparent; 569 | border-radius: 4px; 570 | border: 1px solid #bbb; 571 | cursor: pointer; 572 | box-sizing: border-box; 573 | } 574 | 575 | .button:hover, 576 | button:hover { 577 | color: #333; 578 | border-color: #888888; 579 | outline: 0; 580 | } 581 | 582 | input[type="submit"]:hover, 583 | input[type="reset"]:hover, 584 | input[type="button"]:hover { 585 | color: #333; 586 | border-color: #888888; 587 | outline: 0; 588 | } 589 | 590 | .button:focus, 591 | button:focus { 592 | color: #333; 593 | border-color: #888888; 594 | outline: 0; 595 | } 596 | 597 | input[type="submit"]:focus, 598 | input[type="reset"]:focus, 599 | input[type="button"]:focus { 600 | color: #333; 601 | border-color: #888888; 602 | outline: 0; 603 | } 604 | 605 | .button.button-primary, 606 | button.button-primary { 607 | color: #fff; 608 | background-color: #33c3f0; 609 | border-color: #33c3f0; 610 | } 611 | 612 | input[type="submit"].button-primary, 613 | input[type="reset"].button-primary, 614 | input[type="button"].button-primary { 615 | color: #fff; 616 | background-color: #33c3f0; 617 | border-color: #33c3f0; 618 | } 619 | 620 | .button.button-primary:hover, 621 | button.button-primary:hover { 622 | color: #fff; 623 | background-color: #1eaedb; 624 | border-color: #1eaedb; 625 | } 626 | 627 | input[type="submit"].button-primary:hover, 628 | input[type="reset"].button-primary:hover, 629 | input[type="button"].button-primary:hover { 630 | color: #fff; 631 | background-color: #1eaedb; 632 | border-color: #1eaedb; 633 | } 634 | 635 | .button.button-primary:focus, 636 | button.button-primary:focus { 637 | color: #fff; 638 | background-color: #1eaedb; 639 | border-color: #1eaedb; 640 | } 641 | 642 | input[type="submit"].button-primary:focus, 643 | input[type="reset"].button-primary:focus, 644 | input[type="button"].button-primary:focus { 645 | color: #fff; 646 | background-color: #1eaedb; 647 | border-color: #1eaedb; 648 | } 649 | input[type="email"], 650 | input[type="number"], 651 | input[type="search"], 652 | input[type="text"], 653 | input[type="tel"], 654 | input[type="url"], 655 | input[type="password"] { 656 | height: 38px; 657 | padding: 6px 10px; 658 | background-color: #fff; 659 | border: 1px solid #d1d1d1; 660 | border-radius: 4px; 661 | box-shadow: none; 662 | box-sizing: border-box; 663 | } 664 | 665 | textarea, 666 | select { 667 | height: 38px; 668 | padding: 6px 10px; 669 | background-color: #fff; 670 | border: 1px solid #d1d1d1; 671 | border-radius: 4px; 672 | box-shadow: none; 673 | box-sizing: border-box; 674 | } 675 | 676 | input[type="email"], 677 | input[type="number"], 678 | input[type="search"], 679 | input[type="text"], 680 | input[type="tel"], 681 | input[type="url"], 682 | input[type="password"] { 683 | -webkit-appearance: none; 684 | -moz-appearance: none; 685 | appearance: none; 686 | } 687 | 688 | textarea { 689 | -webkit-appearance: none; 690 | -moz-appearance: none; 691 | appearance: none; 692 | min-height: 65px; 693 | padding-top: 6px; 694 | padding-bottom: 6px; 695 | } 696 | 697 | input[type="email"]:focus, 698 | input[type="number"]:focus, 699 | input[type="search"]:focus, 700 | input[type="text"]:focus, 701 | input[type="tel"]:focus, 702 | input[type="url"]:focus, 703 | input[type="password"]:focus { 704 | border: 1px solid #33c3f0; 705 | outline: 0; 706 | } 707 | 708 | textarea:focus, 709 | select:focus { 710 | border: 1px solid #33c3f0; 711 | outline: 0; 712 | } 713 | 714 | label, 715 | legend { 716 | display: block; 717 | margin-bottom: 0.5rem; 718 | font-weight: 600; 719 | } 720 | 721 | fieldset { 722 | padding: 0; 723 | border-width: 0; 724 | } 725 | 726 | input[type="checkbox"], 727 | input[type="radio"] { 728 | display: inline; 729 | } 730 | 731 | label > .label-body { 732 | display: inline-block; 733 | margin-left: 0.5rem; 734 | font-weight: normal; 735 | } 736 | 737 | ul { 738 | list-style: circle inside; 739 | } 740 | 741 | ol { 742 | list-style: decimal inside; 743 | padding-left: 0; 744 | margin-top: 0; 745 | } 746 | 747 | ul { 748 | padding-left: 0; 749 | margin-top: 0; 750 | } 751 | ul ul, 752 | ul ol { 753 | margin: 1.5rem 0 1.5rem 3rem; 754 | font-size: 90%; 755 | } 756 | 757 | ol ol, 758 | ol ul { 759 | margin: 1.5rem 0 1.5rem 3rem; 760 | font-size: 90%; 761 | } 762 | 763 | li { 764 | margin-bottom: 1rem; 765 | } 766 | 767 | code { 768 | padding: 0.2rem 0.5rem; 769 | margin: 0 0.2rem; 770 | font-size: 90%; 771 | white-space: nowrap; 772 | background: #f1f1f1; 773 | border: 1px solid #e1e1e1; 774 | border-radius: 4px; 775 | } 776 | 777 | pre > code { 778 | display: block; 779 | padding: 1rem 1.5rem; 780 | white-space: pre; 781 | } 782 | 783 | th, 784 | td { 785 | padding: 12px 15px; 786 | text-align: left; 787 | border-bottom: 1px solid #e1e1e1; 788 | } 789 | 790 | th:first-child, 791 | td:first-child { 792 | padding-left: 0; 793 | } 794 | 795 | th:last-child, 796 | td:last-child { 797 | padding-right: 0; 798 | } 799 | 800 | button, 801 | .button { 802 | margin-bottom: 1rem; 803 | } 804 | 805 | input, 806 | textarea, 807 | select, 808 | fieldset { 809 | margin-bottom: 1.5rem; 810 | } 811 | 812 | pre, 813 | blockquote, 814 | dl, 815 | figure, 816 | table, 817 | p, 818 | ul, 819 | ol, 820 | form { 821 | margin-bottom: 2.5rem; 822 | } 823 | 824 | /*Custom Styles Start Here*/ 825 | body { 826 | background-color: #fffdfa; 827 | } 828 | 829 | h1 { 830 | font-family: "Montserrat", sans-serif; 831 | } 832 | 833 | .home { 834 | margin-top: 18em; 835 | text-align: center; 836 | } 837 | 838 | .wiki-search-form { 839 | margin: 1.5em 0; 840 | } 841 | 842 | #wiki-search-input { 843 | width: 120%; 844 | margin-left: -8%; 845 | } 846 | 847 | .button { 848 | margin-top: 2em; 849 | margin-left: 10px; 850 | } 851 | 852 | .header { 853 | background-color: #ededed; 854 | padding: 5px 0 0; 855 | border-bottom: 1px solid #999; 856 | } 857 | 858 | img { 859 | display: inline-block; 860 | margin-top: 10px; 861 | max-height: 85%; 862 | max-width: 85%; 863 | object-fit: contain; 864 | object-position: center bottom; 865 | width: auto; 866 | } 867 | 868 | @media screen and (max-width: 700px) { 869 | img { 870 | width: 85%; 871 | } 872 | } 873 | 874 | @media screen and (max-width: 1400px) { 875 | .container { 876 | width: 75vw; 877 | } 878 | } 879 | 880 | .result-wiki-search-form { 881 | display: inline-block; 882 | margin: 10px 0 0; 883 | } 884 | 885 | #result-wiki-search-form-input { 886 | width: 350px; 887 | } 888 | 889 | .result-list { 890 | margin-top: 20px; 891 | } 892 | 893 | .result-title a { 894 | color: #2619af; 895 | line-height: 1.2em; 896 | font-size: 18px; 897 | text-decoration: none; 898 | } 899 | 900 | .result-title a:hover { 901 | text-decoration: underline; 902 | } 903 | 904 | .result-title a:visited { 905 | color: #670199; 906 | } 907 | 908 | .result-snippet { 909 | color: #545454; 910 | } 911 | 912 | .searchmatch { 913 | font-weight: bold; 914 | } 915 | 916 | .result-metadata { 917 | color: #078307; 918 | } 919 | 920 | .result-9 { 921 | margin-bottom: 5em; 922 | } 923 | 924 | .credit { 925 | position: absolute; 926 | left: 0; 927 | bottom: 0; 928 | text-align: center; 929 | } 930 | 931 | .credit a { 932 | text-decoration: none; 933 | } 934 | 935 | .error { 936 | margin-top: 4em; 937 | line-height: 20px; 938 | } 939 | 940 | .error p { 941 | line-height: 10px; 942 | } 943 | 944 | .keyword { 945 | font-weight: bold; 946 | } 947 | 948 | .hidden { 949 | display: none; 950 | } 951 | 952 | @media screen and (max-width: 720px) { 953 | .home { 954 | margin-top: 7em; 955 | } 956 | } 957 | 958 | #result-wiki-search-form-input { 959 | width: 100%; 960 | } 961 | 962 | .bottom { 963 | font-size: smaller; 964 | width: 100%; 965 | position: absolute; 966 | top: 95%; 967 | transform: translateY(-100%); 968 | text-align: center; 969 | color: black; 970 | } 971 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* SETTINGS AND LONG DESCRIPTIONS */ 2 | const reliableSitesFile = "./reliableSites.json"; // Site hosts (don't include the https://) that can have more pages queued per 10 minutes and that have a lil tick next to them in search results. 3 | // The reliableSites will re-require every minute. 4 | 5 | const nonReliableLimitPer10Minutes = 150; // The limit of pages that can be queued per non-reliable site in 10 minute intervals 6 | 7 | const reliableLimitPer10Minutes = 1000; // The limit of pages that can be queued per reliable site in 10 minute intervals 8 | 9 | const pageSize = 15; // How many results to show for each page 10 | 11 | const host = `https://cheesgle.com/`; // Where cheesgle is being hosted 12 | 13 | const blockUrlsThatInclude = [ 14 | "facebook.com/c", 15 | "twitter.com/share", 16 | "creativecommons", 17 | "t/contact_us", 18 | "new/new", 19 | ]; // Any URLS with this inside them will not be able to be queued 20 | 21 | const siteCap = 50000; // Maximum amount of pages that can be stored. If the amount of sites stored goes over this, adding pages to the queue won't work until pages are removed to go under this limit or the limit is increased. 22 | 23 | const maxConnections = 10; // See https://github.com/bda-research/node-crawler 24 | 25 | const queueSuccessfulMessage = `We have queued the page successfully, and will now *attempt* to crawl it. The queue is currently queuesize page(s) long, and we go through each page in the queue at a rate of 300ms. Thank you for your input. You can now go back to Cheesgle.`; 26 | 27 | const queryParameterNoCutoff = ["youtube.com", "www.youtube.com"]; // Site hosts that don't have the ? query parameters cut off 28 | 29 | const rateLimit = require("express-rate-limit"); 30 | const requestIp = require("request-ip"); 31 | 32 | const sumbitPageRateLimit = rateLimit({ 33 | windowMs: 60 * 60 * 1000, // 1 hour 34 | max: 100, 35 | message: 36 | "This IP has requested we crawl a bunch of websites, and under the rules of this Cheesgle's owner, we're gonna block you from adding any more for a bit.", 37 | standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers 38 | legacyHeaders: false, // Disable the `X-RateLimit-*` headers 39 | keyGenerator: (req, res) => { 40 | return req.clientIp; 41 | }, 42 | }); 43 | 44 | const searchRateLimit = rateLimit({ 45 | windowMs: 120 * 1000, // 2 Minutes 46 | max: 30, 47 | message: JSON.stringify({ 48 | error: true, 49 | reason: "Stop spamming ):<", 50 | code: "spam", 51 | }), 52 | standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers 53 | legacyHeaders: false, // Disable the `X-RateLimit-*` headers 54 | keyGenerator: (req, res) => { 55 | return req.clientIp; 56 | }, 57 | }); 58 | 59 | /* Requiring and init of database */ 60 | 61 | const SitemapXMLParser = require("sitemap-xml-parser"); 62 | const robotsParser = require("robots-txt-parser"); 63 | const { Worker } = require("worker_threads"); 64 | const cheerio = require("cheerio"); 65 | const axios = require("axios"); 66 | var jsonpack = require("jsonpack"); 67 | const MiniSearch = require("minisearch"); 68 | var Typo = require("typo-js"); 69 | var fs = require("fs"); 70 | 71 | /* DB init */ 72 | let db; 73 | try { 74 | db = jsonpack.unpack(fs.readFileSync("./db.txt", { encoding: "utf8" })); 75 | } catch { 76 | db = jsonpack.unpack(fs.readFileSync("./dbb.txt", { encoding: "utf8" })); 77 | } 78 | console.log(Object.keys(db)); 79 | 80 | /* Reliable sites init */ 81 | var reliableSites = require(reliableSitesFile); 82 | setInterval(function () { 83 | reliableSites = require(reliableSitesFile); 84 | }, 60000); 85 | 86 | /* Crawling logic (messy code ahead) */ 87 | 88 | var noCrawl = []; // Don't touch this 89 | 90 | let hosts = []; 91 | const robots = robotsParser({ 92 | userAgent: "Cheesgle-crawlie", // The default user agent to use when looking for allow/disallow rules, if this agent isn't listed in the active robots.txt, we use *. 93 | allowOnNeutral: false, // The value to use when the robots.txt rule's for allow and disallow are balanced on whether a link can be crawled. 94 | }); 95 | 96 | process.on("unhandledRejection", function () {}); 97 | 98 | var crawling = {}; 99 | 100 | function truncate(str, n) { 101 | return str.length > n ? str.substr(0, n - 1) + "..." : str; 102 | } 103 | 104 | function getRandomInt(min, max) { 105 | return min + Math.floor(Math.random() * (max - min + 1)); 106 | } 107 | 108 | function crawlXml(url) { 109 | const sitemapXMLParser = new SitemapXMLParser(url, { 110 | delay: 3000, 111 | limit: 5, 112 | }); 113 | sitemapXMLParser 114 | .fetch() 115 | .then((result) => { 116 | result.forEach((thing) => { 117 | if (thing.loc[0]) 118 | queue(thing.loc[0], { userAgent: "Cheesgle-crawlie" }, true); 119 | }); 120 | }) 121 | .catch(() => {}); 122 | } 123 | 124 | const siteQueue = []; 125 | 126 | setInterval(() => { 127 | if (siteQueue.length > 0) { 128 | actualQueue(siteQueue[Math.floor(Math.random()*siteQueue.length)]); 129 | siteQueue.shift(); 130 | } 131 | }, 300); 132 | 133 | function actualQueue(url) { 134 | url = new URL(url).href; 135 | console.log(`Crawling ${url}`); 136 | axios 137 | .get(url, { headers: { "User-Agent": "Cheesgle-crawlie" } }) 138 | .then((response) => { 139 | if (response.status === 200) { 140 | if (typeof response.data !== "string") return; 141 | const html = response.data; 142 | const $ = cheerio.load(html); 143 | 144 | // Fix up the URL 145 | url = new URL(response.config.url).href; 146 | 147 | let title = "No title"; 148 | let desc = "No description"; 149 | let keywords = []; 150 | 151 | try { 152 | title = 153 | truncate( 154 | $("title") 155 | .first() 156 | .text() 157 | .replace(/ /g, " "), 158 | 60 159 | ) || "No title"; 160 | desc = 161 | truncate( 162 | $("meta[name=description]") 163 | .attr("content") 164 | .replace(/ /g, " "), 165 | 200 166 | ) || "No description"; 167 | keywords = 168 | $("meta[name=keywords]").attr("content").split(",").slice(0, 20) || 169 | []; 170 | } catch {} 171 | 172 | if (typeof title !== "string") title = "No title"; 173 | if (typeof desc !== "string") desc = "No description"; 174 | if (keywords == "") keywords = ["cheese"]; 175 | 176 | let cheeseRating = 0; 177 | cheeseRating += 178 | (title.toLowerCase().match(/cheese/g) || []).length * 60; 179 | cheeseRating += (desc.toLowerCase().match(/cheese/g) || []).length * 24; 180 | keywords.forEach((element) => { 181 | cheeseRating += 182 | (element.toLowerCase().match(/cheese/g) || []).length * 9; 183 | }); 184 | if (cheeseRating < 10) return; 185 | 186 | noCrawl = noCrawl.filter(function (item) { 187 | return item !== new URL(url).href; 188 | }); 189 | 190 | db.sites = db.sites.filter((item) => item.u !== new URL(url).href); 191 | 192 | db.sites.push({ 193 | t: title, 194 | dc: desc, 195 | kw: keywords.join(", "), 196 | u: new URL(url).href, 197 | }); 198 | db.list[new URL(url).href] = Date.now(); 199 | 200 | links = $("a"); 201 | $(links).each((i, link) => { 202 | if (!$(link).attr("href")) return; 203 | let href = $(link).attr("href"); 204 | if (href !== "#" && !href.startsWith("/?") && !href.startsWith("?")) { 205 | queue(href, { userAgent: "Cheesgle-crawlie" }); 206 | } 207 | }); 208 | } 209 | }) 210 | .catch(() => {}); 211 | } 212 | 213 | var c = { 214 | queue: function (url) { 215 | siteQueue.push(url); 216 | }, 217 | }; 218 | 219 | function canCrawl(h) { 220 | return new Promise((resolve, reject) => { 221 | if (hosts[new URL(h).host]) { 222 | resolve(robots.canCrawlSync(h)); 223 | } else { 224 | robots 225 | .useRobotsFor(`https://${new URL(h).host}`) 226 | .then(function () { 227 | hosts.push(new URL(h).host); 228 | resolve(robots.canCrawlSync(h)); 229 | }) 230 | .catch(function () { 231 | reject(); 232 | }); 233 | } 234 | }); 235 | } 236 | 237 | var canqueue = true; 238 | if (db.sites.length > siteCap) { 239 | canqueue = false; 240 | } 241 | 242 | function saveDatabase() { 243 | if (db.sites.length > siteCap) { 244 | canqueue = false; 245 | } else { 246 | console.log( 247 | `Saving database. ${db.sites.length} stored, (${noCrawl.length} noCrawl)` 248 | ); 249 | 250 | var saverWorker = new Worker("./saveDatabase.js", { 251 | workerData: db, 252 | }); 253 | saverWorker.once("message", () => { 254 | console.log("Saved database"); 255 | setTimeout(saveDatabase, 300000); 256 | }); 257 | } 258 | } 259 | setTimeout(saveDatabase, 300000); 260 | 261 | function queue(h, smh, sub) { 262 | return new Promise(async (resolve, reject) => { 263 | if (h.substring(0, h.indexOf("#")) !== "") { 264 | h = h.substring(0, h.indexOf("#")); 265 | } 266 | if (!queryParameterNoCutoff.includes(new URL(h).host)) { 267 | if (h.substring(0, h.indexOf("?")) !== "") { 268 | h = h.substring(0, h.indexOf("?")); 269 | } 270 | } 271 | 272 | h = h.replace("http://", "https://"); 273 | 274 | h = h.replace(/(https?:\/\/)|(\/)+/g, "$1$2"); 275 | 276 | if (h.startsWith("https://www.youtube.com") && h.includes("/new/")) { 277 | reject( 278 | "Youtube.com watch URL that has /new/ in it. That can lead to spam of /new/ URLs." 279 | ); 280 | return; 281 | } 282 | 283 | if (!sub) { 284 | if (noCrawl.includes(new URL(h).href)) { 285 | reject( 286 | "noCrawl includes the URL, will queue if it's sumbitted by a user." 287 | ); 288 | return; 289 | } 290 | } 291 | noCrawl.push(new URL(h).href); 292 | 293 | if (!canqueue) { 294 | reject( 295 | "The limit of sites that can be added to this Cheesgle has been reached." 296 | ); 297 | return; 298 | } 299 | 300 | if (new URL(h).href.length > 150) { 301 | reject("The URL is over 150 characters long."); 302 | return; 303 | } 304 | 305 | if (h.endsWith("/")) { 306 | if (db.list[h.slice(0, -1)]) { 307 | if (new Date() - new Date(db.list[h.slice(0, -1)]) < 1800000) 308 | reject("Duplicate entry of that page without a slash"); 309 | } 310 | } else { 311 | if (db.list[h + "/"]) { 312 | if (new Date() - new Date(db.list[h + "/"]) < 1800000) 313 | reject("Duplicate entry of that page with a slash"); 314 | } 315 | } 316 | 317 | if (crawling[new URL(h).host]) { 318 | if (reliableSites.includes(crawling[new URL(h).host])) { 319 | if (crawling[new URL(h).host] > reliableLimitPer10Minutes) { 320 | reject( 321 | `The host website (reliable) has had too many pages crawled in the last 10 minutes. The maximum for that host website is ${reliableLimitPer10Minutes} pages added per 10 minutes.` 322 | ); 323 | return; 324 | } 325 | } else { 326 | if (crawling[new URL(h).host] > nonReliableLimitPer10Minutes) { 327 | reject( 328 | `The host website has had too many pages crawled in the last 10 minutes. The maximum for that host website is ${nonReliableLimitPer10Minutes} pages added per 10 minutes.` 329 | ); 330 | return; 331 | } 332 | } 333 | 334 | crawling[new URL(h).host]++; 335 | } else { 336 | crawling[new URL(h).host] = 1; 337 | setInterval(() => { 338 | crawling[new URL(h).host] = 0; 339 | }, 600000); 340 | } 341 | 342 | if (blockUrlsThatInclude.some((v) => h.includes(v))) { 343 | reject( 344 | `blockUrlsThatInclude includes something that this URL has. The blockUrlsThatInclude list includes: ${blockUrlsThatInclude.join( 345 | ", " 346 | )}` 347 | ); 348 | return; 349 | } 350 | 351 | canCrawl(h) 352 | .then(function (can) { 353 | if (can) { 354 | c.queue(h, { userAgent: "Cheesgle-crawlie" }); 355 | resolve(); 356 | } else { 357 | reject( 358 | `The robots.txt file of that website doesn't allow the us to crawl that page.` 359 | ); 360 | } 361 | }) 362 | .catch((e) => { 363 | reject(`That site doesn't have a robots.txt file.`); 364 | }); 365 | }); 366 | } 367 | 368 | /* Searching and refreshing collection */ 369 | var search = new MiniSearch({ 370 | fields: ["t", "dc", "kw"], // fields to index for full-text search 371 | storeFields: ["t", "u", "dc"], // fields to return with search results 372 | idField: "u", 373 | }); 374 | search.addAll(db.sites); 375 | 376 | setInterval(async () => { 377 | await search.removeAll(); 378 | await search.addAll(db.sites); 379 | }, 400000); 380 | 381 | /* Here you can manually queue sitemaps and websites upon runtime */ 382 | 383 | [].forEach((element) => { 384 | crawlXml(element); 385 | }); 386 | 387 | [].forEach((element) => { 388 | queue(element, { userAgent: "Cheesgle-crawlie" }); 389 | }); // Replace the starting array (e.g ['https://site.one/','https://site.two/']) 390 | 391 | /* Web app logic, starting with requiring express and other middleware */ 392 | 393 | var bodyParser = require("body-parser"); 394 | const express = require("express"); 395 | const { time } = require("console"); 396 | const cors = require("cors"); 397 | const app = express(); 398 | const port = 3000; 399 | 400 | app.use(cors()); 401 | 402 | function chunk(arr, len) { 403 | // Chunk function from stackoverflow 404 | var chunks = [], 405 | i = 0, 406 | n = arr.length; 407 | while (i < n) { 408 | chunks.push(arr.slice(i, (i += len))); 409 | } 410 | return chunks; 411 | } 412 | 413 | //Init Typo 414 | var dictionary = new Typo("en_US"); 415 | 416 | // app.use(something) 417 | 418 | app.on("/index.html", (req, res) => { 419 | res.redirect("/"); 420 | }); 421 | 422 | // Adding this before express.static 423 | 424 | app.use("/Search/search.html", function (req, res, next) { 425 | if (!req.query.q) { 426 | res.redirect("/Search/search.html?q=question%20here"); 427 | return; 428 | } 429 | next(); 430 | }); 431 | 432 | app.use(express.static("./public/")); 433 | 434 | app.use(requestIp.mw()); 435 | 436 | app.use( 437 | express.urlencoded({ 438 | extended: true, 439 | }) 440 | ); 441 | 442 | /* Index */ 443 | 444 | function protect(text) { 445 | // Replaces stuff with stuff 446 | return text 447 | .replace(/&/g, "&") 448 | .replace(/>/g, ">") 449 | .replace(/ { 456 | res.setHeader("content-type", "application/json"); 457 | 458 | /*res.status(503);res.end(JSON.stringify({ 459 | "error":true, 460 | "reason":"Maintenace is underway. Not sorry for the inconvenicence.", 461 | "code":"maintenance" 462 | }));return*/ 463 | 464 | var { query, page } = req.params; 465 | 466 | if (isNaN(Number(page))) { 467 | page = 1; 468 | } 469 | 470 | if (!query) { 471 | res.status(400); 472 | res.end( 473 | JSON.stringify({ 474 | error: true, 475 | reason: "Query needed", 476 | code: "query", 477 | }) 478 | ); 479 | return; 480 | } 481 | 482 | if (query.length > 1000) { 483 | res.status(400); 484 | res.end( 485 | JSON.stringify({ 486 | error: true, 487 | reason: "Stop it", 488 | code: "tooLong", 489 | }) 490 | ); 491 | return; 492 | } 493 | 494 | if (query.length > 500) { 495 | res.status(400); 496 | res.end( 497 | JSON.stringify({ 498 | error: true, 499 | reason: "Shut up", 500 | code: "tooLong", 501 | }) 502 | ); 503 | return; 504 | } 505 | 506 | if (query.length > 50) { 507 | console.log(`Query too long for '${query}'`); 508 | res.status(400); 509 | res.end( 510 | JSON.stringify({ 511 | error: true, 512 | reason: "Query too long, please have a query under 50 characters long.", 513 | code: "tooLong", 514 | }) 515 | ); 516 | return; 517 | } 518 | 519 | let censoredIp = req.clientIp.split("."); 520 | censoredIp[censoredIp.length - 1] = "#"; 521 | censoredIp[censoredIp.length - 2] = "#"; 522 | censoredIp = censoredIp.join("."); 523 | 524 | if (query.startsWith("bramley")) { 525 | res.end( 526 | JSON.stringify({ 527 | error: false, 528 | resultsCount: 1, 529 | timeInSeconds: 42.69, 530 | didYouMean: "bed monster", 531 | results: [ 532 | { 533 | href: "https://www.youtube.com/watch?v=dQw4w9WgXcQ", 534 | title: protect("Bramley's favourite song"), 535 | description: protect( 536 | "Bramley loves this | 2022 confirmed bramley best song!!1!" 537 | ), 538 | }, 539 | ], 540 | pages: 1, 541 | page: 1, 542 | }) 543 | ); 544 | return; 545 | } 546 | 547 | const time1 = performance.now(); // Gets the current time in ms 548 | var resp = await search.search(query); // Search with query 549 | const allResults = resp.length; 550 | resp = chunk(resp, pageSize); // Chunk into pages 551 | const pages = resp.length; 552 | 553 | if (page > pages || page < 1) { 554 | page = 1; 555 | } 556 | page = Math.round(page); 557 | resp = resp[page - 1]; 558 | 559 | const timeTook = ( 560 | (Math.round(performance.now() - time1) % 60000) / 561 | 1000 562 | ).toFixed(2); 563 | 564 | if (resp == undefined) { 565 | console.log(`No results found for query: ${query}`); 566 | res.status(204); 567 | res.end( 568 | JSON.stringify({ 569 | error: true, 570 | reason: "No results found", 571 | code: "noResults", 572 | }) 573 | ); 574 | return; 575 | } 576 | 577 | let results = resp.length; 578 | let resultsJson = []; 579 | 580 | if (query.toLowerCase() == "cheese") { 581 | resultsJson.push({ 582 | href: host, 583 | title: "Try searching something else", 584 | description: 585 | "Searching 'cheese' can often lead to spam. Try searching something else, like 'toe cheese' perhaps.", 586 | }); 587 | } 588 | 589 | if (query.startsWith("hello")) { 590 | resultsJson.push({ 591 | href: "https://www.youtube.com/watch?v=dQw4w9WgXcQ", 592 | title: "Hello my child", 593 | description: 594 | "I think I have your answer here. Feel free to click! -coding398", 595 | }); 596 | } 597 | 598 | if (getRandomInt(1, 21) == 20) { 599 | resultsJson.push({ 600 | href: "https://replit.com/@codingMASTER398/Cheesgle?v=1", 601 | title: "Do you like Cheesgle?", 602 | description: 603 | "Consider liking and commenting on the repl. It will help me a lot!", 604 | }); 605 | } 606 | if (getRandomInt(1, 100) == 69) { 607 | resultsJson.push({ 608 | href: "https://www.youtube.com/watch?v=dQw4w9WgXcQ", 609 | title: protect(query), 610 | description: protect(query), 611 | }); 612 | } 613 | 614 | for (let i = 0; i < results; i++) { 615 | resultsJson.push({ 616 | href: encodeURI(resp[i].u), 617 | title: protect(resp[i].t.replace(/"/g, '\\"')), 618 | description: protect(resp[i].dc.replace(/"/g, "'")), 619 | }); 620 | } 621 | 622 | // Typo checking 623 | let checkingQuery = query.split(" "); 624 | let outFromTheCheckingLab = []; 625 | checkingQuery.forEach((element) => { 626 | let suggest = dictionary.suggest(element); 627 | if (suggest.length > 0) { 628 | outFromTheCheckingLab.push(suggest[0]); 629 | } else { 630 | outFromTheCheckingLab.push(element); 631 | } 632 | }); 633 | 634 | console.log( 635 | `From: ${censoredIp} Took: ${timeTook}s Results: ${allResults} Query: ${query}` 636 | ); 637 | 638 | res.end( 639 | JSON.stringify({ 640 | error: false, 641 | resultsCount: allResults, 642 | timeInSeconds: timeTook, 643 | results: resultsJson, 644 | pages: pages, 645 | page: page, 646 | didYouMean: protect(outFromTheCheckingLab.join(" ")), 647 | }) 648 | ); 649 | }); 650 | 651 | app.use("/submitSite", sumbitPageRateLimit); 652 | 653 | app.post("/submitSite", bodyParser.json(), async (req, res) => { 654 | try { 655 | setTimeout(() => { 656 | if (!res.writableEnded) { 657 | res.end( 658 | `This is taking too long. There is a chance the site will still be crawled, but because of how long it's taking, I don't think so. Try again!` 659 | ); 660 | } 661 | }, 5000); 662 | 663 | let censoredIp = req.clientIp.split("."); 664 | censoredIp[censoredIp.length - 1] = "#"; 665 | censoredIp[censoredIp.length - 2] = "#"; 666 | censoredIp = censoredIp.join("."); 667 | 668 | if (req.body.url) { 669 | if (req.body.url.startsWith("https://")) { 670 | if(siteQueue.includes(req.body.url)){ 671 | res.end( 672 | `We're already gonna crawl this one.` 673 | ); 674 | return; 675 | } 676 | 677 | if (req.body.url.endsWith(".xml")) { 678 | crawlXml(req.body.url); 679 | res.end( 680 | `Looks like you gave us an XML, so we are assuming that's just a sitemap. We put it through our sitemap crawler, so hopefully that does something and doesn't break the website. (:` 681 | ); 682 | console.log(`${censoredIp} submitted ${req.body.url} as a sitemap`); 683 | return; 684 | } 685 | queue(req.body.url, "a", true) 686 | .then(() => { 687 | console.log(`${censoredIp} submitted ${req.body.url} as a page`); 688 | res.end( 689 | queueSuccessfulMessage.replace("queuesize", siteQueue.length) 690 | ); 691 | }) 692 | .catch((e) => { 693 | res.end(`There was an error while trying to queue that page: ${e}`); 694 | }); 695 | } else { 696 | res.end("We need the URL to start with https://"); 697 | } 698 | } else { 699 | res.end("An URL is needed"); 700 | } 701 | } catch {} // Random try catch just in case 702 | }); 703 | 704 | app.get("/submitSiteInfo", (req, res) => { 705 | res.end(`

Page submission


706 | Here you can submit a URL for us to crawl and add to our engine.
707 | Keep in mind, these conditions must be met for the page to be crawled.
708 | 715 |
716 | Ready to add a page to this useless search engine? Go ahead! The form is below.`); 717 | }); 718 | 719 | app.get("/Verified/list.json", (req, res) => { 720 | res.end(JSON.stringify(reliableSites)); 721 | }); 722 | 723 | app.get("/pageCount", (req, res) => { 724 | if (canqueue) { 725 | res.end( 726 | `Cheesgle is proudly tasting ${db.sites.length 727 | .toString() 728 | .replace(/\B(?=(\d{3})+(?!\d))/g, ",")} pages.` 729 | ); 730 | } else { 731 | res.end( 732 | `Cheesgle has capped out at ${db.sites.length} pages and no more can be added for the time being.` 733 | ); 734 | } 735 | }); 736 | 737 | app.get("/queueSize", (req, res) => { 738 | res.end(`Queue size is currently ${siteQueue.length} page(s) long.`); 739 | }); 740 | 741 | app.get("/github", (req, res) => { 742 | res.redirect("https://github.com/codingMASTER398/Cheesgle"); 743 | }); 744 | 745 | app.get("/search", (req, res) => { 746 | if (req.query.q) { 747 | res.redirect("/Search/search.html?q=" + req.query.q); 748 | } else { 749 | res.redirect("/"); 750 | } 751 | }); 752 | 753 | var randomCheese = require("cheese-name"); 754 | app.get("/randomCheese", (req, res) => { 755 | res.redirect("/Search/search.html?q=" + randomCheese()); 756 | }); 757 | 758 | app.get("*", (req, res) => { 759 | res.status(404); 760 | res.sendfile("./public/404.html"); 761 | }); 762 | 763 | app.listen(port, () => { 764 | console.log(`Example app listening at http://localhost:${port}`); 765 | }); 766 | -------------------------------------------------------------------------------- /public/Search/cheeses.json: -------------------------------------------------------------------------------- 1 | [{"displayTitle":"Abbaye du Mont des Cats","title":"abbayedumontdescats","image":"https://cheese.com/media/img/cheese/Mont_des_Cats_kaas.jpg","url":"https://cheese.com/abbaye-du-mont-des-cats/"},{"displayTitle":"Abbaye de Tamié","title":"abbayedetamié","image":"https://cheese.com/media/img/cheese/Abbaye_ND_de_Tamie.jpg","url":"https://cheese.com/tamie/"},{"displayTitle":"Abbaye de Belloc","title":"abbayedebelloc","image":"https://cheese.com/media/img/cheese/Abbaye-de-Belloc.jpg","url":"https://cheese.com/abbaye-de-belloc/"},{"displayTitle":"Adelost","title":"adelost","image":"https://cheese.com/media/img/cheese/Adelost_QnxYLx6.jpg","url":"https://cheese.com/adelost/"},{"displayTitle":"Abondance","title":"abondance","image":"https://cheese.com/media/img/cheese/Abondance1.jpg","url":"https://cheese.com/abondance/"},{"displayTitle":"Ackawi","title":"ackawi","image":"https://cheese.com/media/img/cheese/450px-Akawi_Cheese.jpg","url":"https://cheese.com/ackawi/"},{"displayTitle":"Abbaye de Citeaux","title":"abbayedeciteaux","image":"https://cheese.com/media/img/cheese/Abbaye-de-citeaux.jpg","url":"https://cheese.com/abbaye-de-citeaux/"},{"displayTitle":"Aisy Cendre","title":"aisycendre","image":"https://cheese.com/media/img/cheese/Aisy_cendre.jpg","url":"https://cheese.com/aisy-cendre/"},{"displayTitle":"Abbaye de Timadeuc","title":"abbayedetimadeuc","image":"https://cheese.com/media/img/cheese/687-abbaye_de_timadeuc.jpg","url":"https://cheese.com/abbaye-de-timadeuc/"},{"displayTitle":"Afuega'l Pitu","title":"afuegalpitu","image":"https://cheese.com/media/img/cheese/Afuega_l_pitu.jpeg","url":"https://cheese.com/afuegal-pitu/"},{"displayTitle":"Aged Gouda","title":"agedgouda","image":"https://cheese.com/media/img/cheese/Aged_Gouda_cheese_1.jpg","url":"https://cheese.com/aged-gouda/"},{"displayTitle":"Aged British Cheddar","title":"agedbritishcheddar","image":"https://cheese.com/media/img/cheese/27-aged-british-cheddar-shutterstock_1125720782.jpg","url":"https://cheese.com/aged-british-cheddar/"},{"displayTitle":"Airag","title":"airag","image":"https://cheese.com/media/img/cheese/Airag_2.JPG","url":"https://cheese.com/airag/"},{"displayTitle":"Amul Processed Cheese","title":"amulprocessedcheese","image":"https://cheese.com/media/img/cheese/Amul-Processed-Cheese.jpg","url":"https://cheese.com/amul-processed-cheese/"},{"displayTitle":"Appenzeller","title":"appenzeller","image":"https://cheese.com/media/img/cheese/Appenzeller.jpg","url":"https://cheese.com/appenzeller/"},{"displayTitle":"Ambert","title":"ambert","image":"https://cheese.com/media/img/cheese/Ambert.jpg","url":"https://cheese.com/ambert/"},{"displayTitle":"Amarelo de Beira Baixa","title":"amarelodebeirabaixa","image":"https://cheese.com/media/img/cheese/Amarelo_de_Beira_Baixa_sfMBsRQ.jpg","url":"https://cheese.com/amarelo-de-beira-baixa/"},{"displayTitle":"American Cheese","title":"americancheese","image":"https://cheese.com/media/img/cheese/10-American-Cheese-shutterstock_1610208106.jpg","url":"https://cheese.com/american-cheese/"},{"displayTitle":"Amul Cheese Spread","title":"amulcheesespread","image":"https://cheese.com/media/img/cheese/Amul-Cheese-Spread.jpg","url":"https://cheese.com/amul-cheese-spread/"},{"displayTitle":"Anejo Enchilado","title":"anejoenchilado","image":"https://cheese.com/media/img/cheese/Anejo_Enchilado.JPG","url":"https://cheese.com/anejo-enchilado/"},{"displayTitle":"Aura","title":"aura","image":"https://cheese.com/media/img/cheese/Aura_Cheese.jpg","url":"https://cheese.com/aura/"},{"displayTitle":"Aragon","title":"aragon","image":"https://cheese.com/media/img/cheese/16-ARAGON-shutterstock_86220250.jpg","url":"https://cheese.com/aragon/"},{"displayTitle":"Ami du Chambertin","title":"amiduchambertin","image":"https://cheese.com/media/img/cheese/Ami_du_Chambertin.jpg","url":"https://cheese.com/ami-du-chambertin/"},{"displayTitle":"Ashley","title":"ashley","image":"https://cheese.com/media/img/cheese/Ashley.jpg","url":"https://cheese.com/ashley/"},{"displayTitle":"Anari","title":"anari","image":"https://cheese.com/media/img/cheese/Anari_Cheese.jpg","url":"https://cheese.com/anari/"},{"displayTitle":"Anthotyro","title":"anthotyro","image":"https://cheese.com/media/img/cheese/Anthotyro.jpg","url":"https://cheese.com/anthotyro/"},{"displayTitle":"Babybel","title":"babybel","image":"https://cheese.com/media/img/cheese/Babybel.jpg","url":"https://cheese.com/babybel/"},{"displayTitle":"Baby Brie","title":"babybrie","image":"https://cheese.com/media/img/cheese/mini_brie.webp","url":"https://cheese.com/baby-brie/"},{"displayTitle":"Ardrahan","title":"ardrahan","image":"https://cheese.com/media/img/cheese/Ardrahan-Cheese.jpg","url":"https://cheese.com/ardrahan/"},{"displayTitle":"Bandal","title":"bandal","image":"https://cheese.com/media/img/cheese/Bandel_Cheese.jpg","url":"https://cheese.com/bandal/"},{"displayTitle":"Asiago DOP","title":"asiagodop","image":"https://cheese.com/media/img/cheese/asiago_it.jpg","url":"https://cheese.com/asiago/"},{"displayTitle":"Asiago d’Allevo DOP","title":"asiagod’allevodop","image":"https://cheese.com/media/img/cheese/Asiago_d_Allevo_DOP.jpg","url":"https://cheese.com/asiago-dallevo/"},{"displayTitle":"Armenian String Cheese","title":"armenianstringcheese","image":"https://cheese.com/media/img/cheese/03-armenian-string-cheese-shutterstock_1447310846.jpg","url":"https://cheese.com/armenian-string-cheese/"},{"displayTitle":"Banon","title":"banon","image":"https://cheese.com/media/img/cheese/banon3a_1.jpg","url":"https://cheese.com/banon/"},{"displayTitle":"Asiago Pressato DOP","title":"asiagopressatodop","image":"https://cheese.com/media/img/cheese/Asiago-Fresh.jpg","url":"https://cheese.com/asiago-pressato/"},{"displayTitle":"Baron Bigod","title":"baronbigod","image":"https://cheese.com/media/img/cheese/Baron-Bigod.jpg","url":"https://cheese.com/baron-bigod/"},{"displayTitle":"Azeitao","title":"azeitao","image":"https://cheese.com/media/img/cheese/Queijo_de_Azeitao.jpg","url":"https://cheese.com/azeitao/"},{"displayTitle":"Basajo","title":"basajo","image":"https://cheese.com/media/img/cheese/33-basajo-shutterstock_1292932108.jpg","url":"https://cheese.com/basajo/"},{"displayTitle":"Bavaria blu","title":"bavariablu","image":"https://cheese.com/media/img/cheese/Bavaria_blu.jpg","url":"https://cheese.com/bavaria-blu/"},{"displayTitle":"Baladi","title":"baladi","image":"https://cheese.com/media/img/cheese/baladi_2.jpg","url":"https://cheese.com/baladi/"},{"displayTitle":"Ardi Gasna","title":"ardigasna","image":"https://cheese.com/media/img/cheese/ardi-gasna.jpg","url":"https://cheese.com/ardi-gasna/"},{"displayTitle":"Basket Cheese","title":"basketcheese","image":"https://cheese.com/media/img/cheese/04-basket-cheese-shutterstock_372489670.jpg","url":"https://cheese.com/basket-cheese/"},{"displayTitle":"Baby Swiss","title":"babyswiss","image":"https://cheese.com/media/img/cheese/1100-baby_swiss.jpg","url":"https://cheese.com/baby-swiss/"},{"displayTitle":"Carre de l'Est","title":"carredelest","image":"https://cheese.com/media/img/cheese/wiki/carre-de-l'est.jpg","url":"https://cheese.com/carre-de-lest/"},{"displayTitle":"Chevre","title":"chevre","image":"https://cheese.com/media/img/cheese/Goats_cheese.jpg","url":"https://cheese.com/chevre/"},{"displayTitle":"Creamy Lancashire","title":"creamylancashire","image":"https://cheese.com/media/img/cheese/Lancashire_cheese.jpg","url":"https://cheese.com/creamy-lancashire/"},{"displayTitle":"Fontina","title":"fontina","image":"https://cheese.com/media/img/cheese/25-fontina-shutterstock_20880790.jpg","url":"https://cheese.com/fontina/"},{"displayTitle":"Fromage Corse","title":"fromagecorse","image":"https://cheese.com/media/img/cheese/Fromage-Corse.jpg","url":"https://cheese.com/fromage-corse/"},{"displayTitle":"Emmental","title":"emmental","image":"https://cheese.com/media/img/cheese/wiki/emmental.jpg","url":"https://cheese.com/emmental/"},{"displayTitle":"Epoisses de Bourgogne","title":"epoissesdebourgogne","image":"https://cheese.com/media/img/cheese/Epoisses_Bourgogne.jpg","url":"https://cheese.com/epoisses-de-bourgogne/"},{"displayTitle":"Leerdammer","title":"leerdammer","image":"https://cheese.com/media/img/cheese/Leerdammer_kaas.jpg","url":"https://cheese.com/leerdammer/"},{"displayTitle":"Cashel Blue","title":"cashelblue","image":"https://cheese.com/media/img/cheese/550-cashel_blue.jpg","url":"https://cheese.com/cashel-blue/"},{"displayTitle":"Idiazábal","title":"idiazábal","image":"https://cheese.com/media/img/cheese/Idiazabal2_Kv9htrq.jpg","url":"https://cheese.com/idiazabal/"},{"displayTitle":"Formaggio di capra","title":"formaggiodicapra","image":"https://cheese.com/media/img/cheese/Formaggio-di-capra.jpg","url":"https://cheese.com/formaggio-di-capra/"},{"displayTitle":"Fromage Blanc","title":"fromageblanc","image":"https://cheese.com/media/img/cheese/1356-fromage_blanc.jpg","url":"https://cheese.com/fromage-blanc/"},{"displayTitle":"Castelmagno","title":"castelmagno","image":"https://cheese.com/media/img/cheese/Castelmagno.jpg","url":"https://cheese.com/castelmagno/"},{"displayTitle":"Gorgonzola Dolce DOP","title":"gorgonzoladolcedop","image":"https://cheese.com/media/img/cheese/Gorgonzola_Dolce_DOP.jpg","url":"https://cheese.com/gorgonzola-dolce-dop/"},{"displayTitle":"Emental Grand Cru","title":"ementalgrandcru","image":"https://cheese.com/media/img/cheese/1_12.JPG","url":"https://cheese.com/emental-grand-cru/"},{"displayTitle":"Chaource","title":"chaource","image":"https://cheese.com/media/img/cheese/545-chaource.jpg","url":"https://cheese.com/chaource/"},{"displayTitle":"Crottin de Chavignol","title":"crottindechavignol","image":"https://cheese.com/media/img/cheese/Crottin_de_Chavignol_95dKGld.jpg","url":"https://cheese.com/crottin-du-chavignol/"},{"displayTitle":"Five Counties","title":"fivecounties","image":"https://cheese.com/media/img/cheese/11-five-counties-shutterstock_88701973.jpg","url":"https://cheese.com/five-counties/"},{"displayTitle":"Cropwell Bishop Blue Stilton","title":"cropwellbishopbluestilton","image":"https://cheese.com/media/img/cheese/920_cropwell_bishop_blue_stilton.jpg","url":"https://cheese.com/cropwell-bishop-blue-stilton/"},{"displayTitle":"Processed Cheese","title":"processedcheese","image":"https://cheese.com/media/img/cheese/1_8.jpg","url":"https://cheese.com/pasteurized-processed/"},{"displayTitle":"Greve","title":"greve","image":"https://cheese.com/media/img/cheese/wiki/greve.jpg","url":"https://cheese.com/greve/"},{"displayTitle":"Grey Owl","title":"greyowl","image":"https://cheese.com/media/img/cheese/Grey_Owl.jpg","url":"https://cheese.com/grey-owl/"},{"displayTitle":"Glebe Brethan","title":"glebebrethan","image":"https://cheese.com/media/img/cheese/Glebe_Brethan.JPG","url":"https://cheese.com/glebe-brethan/"},{"displayTitle":"Goats' Milk Caciotta","title":"goatsmilkcaciotta","image":"https://cheese.com/media/img/cheese/44-goats-milk-caciotta-new-shutterstock_254107552.jpg","url":"https://cheese.com/goats-milk-caciotta/"},{"displayTitle":"Harbison","title":"harbison","image":"https://cheese.com/media/img/cheese/1156-harbison.jpg","url":"https://cheese.com/harbison/"},{"displayTitle":"Goat ricotta","title":"goatricotta","image":"https://cheese.com/media/img/cheese/Goat-Ricotta.jpg","url":"https://cheese.com/goat-ricotta/"},{"displayTitle":"Gloucester","title":"gloucester","image":"https://cheese.com/media/img/cheese/Gloucester-cheese.jpg","url":"https://cheese.com/gloucester/"},{"displayTitle":"Tommes","title":"tommes","image":"https://cheese.com/media/img/cheese/Tomme.jpg","url":"https://cheese.com/tommes/"},{"displayTitle":"Fleur du Maquis","title":"fleurdumaquis","image":"https://cheese.com/media/img/cheese/Fleur-du-Maquis.jpg","url":"https://cheese.com/fleur-du-maquis/"},{"displayTitle":"Fromage Frais","title":"fromagefrais","image":"https://cheese.com/media/img/cheese/14-FROMAGE-FRAIS-shutterstock_318526556.jpg","url":"https://cheese.com/fromage-frais/"},{"displayTitle":"Tymsboro","title":"tymsboro","image":"https://cheese.com/media/img/cheese/Tymsboro.JPG","url":"https://cheese.com/tymsboro/"},{"displayTitle":"Frying Cheese","title":"fryingcheese","image":"https://cheese.com/media/img/cheese/1_39.JPG","url":"https://cheese.com/frying-cheese/"},{"displayTitle":"Bayley Hazen Blue","title":"bayleyhazenblue","image":"https://cheese.com/media/img/cheese/1154-bayley_hazen_blue.jpg","url":"https://cheese.com/bayley-hazen-blue/"},{"displayTitle":"Swiss cheese","title":"swisscheese","image":"https://cheese.com/media/img/cheese/wiki/swiss.jpg","url":"https://cheese.com/swiss/"},{"displayTitle":"Flor de Guia","title":"flordeguia","image":"https://cheese.com/media/img/cheese/Queso_de_flor_1.jpg","url":"https://cheese.com/flor-de-guia/"},{"displayTitle":"Fromage de Montagne de Savoie","title":"fromagedemontagnedesavoie","image":"https://cheese.com/media/img/cheese/Fromage-de-Montagne-de-Savoie.jpg","url":"https://cheese.com/fromage-de-montagne-de-savoie/"},{"displayTitle":"Camembert de Normandie","title":"camembertdenormandie","image":"https://cheese.com/media/img/cheese/Camembert_normandie.jpg","url":"https://cheese.com/camembert-de-normandie/"},{"displayTitle":"Camembert","title":"camembert","image":"https://cheese.com/media/img/cheese/Camembert.jpg","url":"https://cheese.com/camembert/"},{"displayTitle":"Graddost","title":"graddost","image":"https://cheese.com/media/img/cheese/graddost.jpg","url":"https://cheese.com/graddost/"},{"displayTitle":"Boulette d'Avesnes","title":"boulettedavesnes","image":"https://cheese.com/media/img/cheese/Boulette_dAvesnes.jpg","url":"https://cheese.com/boulette-davesnes/"},{"displayTitle":"Fourme de Montbrison","title":"fourmedemontbrison","image":"https://cheese.com/media/img/cheese/Fourme_montbrison.jpg","url":"https://cheese.com/fourme-de-montbrison/"},{"displayTitle":"Charolais","title":"charolais","image":"https://cheese.com/media/img/cheese/Charolais.jpg","url":"https://cheese.com/charolais/"},{"displayTitle":"Crottin de Chavignol","title":"crottindechavignol","image":"https://cheese.com/media/img/cheese/Crottin_de_Chavignol.jpg","url":"https://cheese.com/crottin-de-chavignol/"},{"displayTitle":"Chaumes","title":"chaumes","image":"https://cheese.com/media/img/cheese/Chaumes.jpg","url":"https://cheese.com/chaumes/"},{"displayTitle":"Cure Nantais","title":"curenantais","image":"https://cheese.com/media/img/cheese/1_21.JPG","url":"https://cheese.com/cure-nantais/"},{"displayTitle":"Chavroux","title":"chavroux","image":"https://cheese.com/media/img/cheese/Chavroux.jpg","url":"https://cheese.com/chavroux/"},{"displayTitle":"Gorgonzola Cremificato","title":"gorgonzolacremificato","image":"https://cheese.com/media/img/cheese/1_13.JPG","url":"https://cheese.com/gorgonzola-cremificato/"},{"displayTitle":"Gorgonzola","title":"gorgonzola","image":"https://cheese.com/media/img/cheese/Gorgonzola_niUHULx.jpg","url":"https://cheese.com/gorgonzola/"},{"displayTitle":"Reggianito","title":"reggianito","image":"https://cheese.com/media/img/cheese/Reggianito.jpg","url":"https://cheese.com/reggianito/"},{"displayTitle":"Cambozola Grand Noir","title":"cambozolagrandnoir","image":"https://cheese.com/media/img/cheese/Cambozola_Grand_Noir.jpg","url":"https://cheese.com/cambozola-grand-noir/"},{"displayTitle":"Scamorza","title":"scamorza","image":"https://cheese.com/media/img/cheese/Scamorza_1.jpg","url":"https://cheese.com/scamorza/"},{"displayTitle":"Calenzana (Calinzanincu)","title":"calenzana(calinzanincu)","image":"https://cheese.com/media/img/cheese/1_3.jpg","url":"https://cheese.com/calenzana/"},{"displayTitle":"Cahill's Irish Porter Cheddar","title":"cahillsirishportercheddar","image":"https://cheese.com/media/img/cheese/05-cahills-irish-porter-cheddar-shutterstock_1563775300.jpg","url":"https://cheese.com/cahills-irish-porter-cheddar/"},{"displayTitle":"Caciotta","title":"caciotta","image":"https://cheese.com/media/img/cheese/22-Caciotta-shutterstock_632211605.jpg","url":"https://cheese.com/caciotta/"},{"displayTitle":"Caerphilly","title":"caerphilly","image":"https://cheese.com/media/img/cheese/1719-caerphilly.jpg","url":"https://cheese.com/caerphilly/"},{"displayTitle":"Caciotta Al Tartufo","title":"caciottaaltartufo","image":"https://cheese.com/media/img/cheese/Caciotta-al-Tartufo.jpg","url":"https://cheese.com/caciotta-al-tartufo/"},{"displayTitle":"Cacio De Roma®","title":"cacioderoma","image":"https://cheese.com/media/img/cheese/Cacio_de_Roma.jpg","url":"https://cheese.com/cacio-de-roma/"},{"displayTitle":"Caciocavallo di Bufala","title":"caciocavallodibufala","image":"https://cheese.com/media/img/cheese/Caciocavallo_di_Bufala_GswzFEK.jpg","url":"https://cheese.com/caciocavallo-di-bufala/"},{"displayTitle":"Caciocavallo","title":"caciocavallo","image":"https://cheese.com/media/img/cheese/Caciocavallo.jpg","url":"https://cheese.com/caciocavallo/"},{"displayTitle":"Crescenza","title":"crescenza","image":"https://cheese.com/media/img/cheese/Crescenza.jpg","url":"https://cheese.com/crescenza/"},{"displayTitle":"Caprice des Dieux","title":"capricedesdieux","image":"https://cheese.com/media/img/cheese/1819-caprice_des_dieux.jpg","url":"https://cheese.com/caprice-des-dieux/"},{"displayTitle":"Goya","title":"goya","image":"https://cheese.com/media/img/cheese/34-goya-shutterstock_1383826232.jpg","url":"https://cheese.com/goya/"},{"displayTitle":"Gorgonzola Piccante DOP","title":"gorgonzolapiccantedop","image":"https://cheese.com/media/img/cheese/Gorgonzola_Piccante_DOP.jpg","url":"https://cheese.com/gorgonzola-piccante-dop/"},{"displayTitle":"Castelo Branco","title":"castelobranco","image":"https://cheese.com/media/img/cheese/Queijo_de_Castelo_Branco.jpg","url":"https://cheese.com/castelo-branco/"},{"displayTitle":"Casatica","title":"casatica","image":"https://cheese.com/media/img/cheese/Casatica.jpg","url":"https://cheese.com/casatica/"},{"displayTitle":"Gorwydd Caerphilly","title":"gorwyddcaerphilly","image":"https://cheese.com/media/img/cheese/Gorwydd-Caerphilly.jpg","url":"https://cheese.com/gorwydd-caerphilly/"},{"displayTitle":"Fresh Chevre","title":"freshchevre","image":"https://cheese.com/media/img/cheese/1578-fresh_chevre.jpg","url":"https://cheese.com/fresh-chevre/"},{"displayTitle":"Kefalotyri","title":"kefalotyri","image":"https://cheese.com/media/img/cheese/Kefalotyri.jpg","url":"https://cheese.com/kefalotyri/"},{"displayTitle":"Geitost","title":"geitost","image":"https://cheese.com/media/img/cheese/Geitost.jpg","url":"https://cheese.com/geitost/"},{"displayTitle":"Garrotxa","title":"garrotxa","image":"https://cheese.com/media/img/cheese/Garrotxa.jpg","url":"https://cheese.com/garrotxa/"},{"displayTitle":"La Peral","title":"laperal","image":"https://cheese.com/media/img/cheese/1455-la_peral.jpg","url":"https://cheese.com/la-peral/"},{"displayTitle":"Lacy Swiss","title":"lacyswiss","image":"https://cheese.com/media/img/cheese/23-Lacy-Swiss--shutterstock_1086462719.jpg","url":"https://cheese.com/lacy-swiss/"},{"displayTitle":"President Camembert","title":"presidentcamembert","image":"https://cheese.com/media/img/cheese/President_Camembert.jpg","url":"https://cheese.com/president-camembert/"},{"displayTitle":"Cheddar with Irish Porter","title":"cheddarwithirishporter","image":"https://cheese.com/media/img/cheese/610-cheddar_with_irish_porter.jpg","url":"https://cheese.com/cheddar-with-irish-porter/"},{"displayTitle":"Beaufort","title":"beaufort","image":"https://cheese.com/media/img/cheese/24-beaufort-shutterstock_447054049.jpg","url":"https://cheese.com/beaufort/"},{"displayTitle":"Cheddar","title":"cheddar","image":"https://cheese.com/media/img/cheese/wiki/cheddar.jpg","url":"https://cheese.com/cheddar/"},{"displayTitle":"Farm Chanco","title":"farmchanco","image":"https://cheese.com/media/img/cheese/Quesochancojpeg.jpg","url":"https://cheese.com/farm-chanco/"},{"displayTitle":"Cheese Curds","title":"cheesecurds","image":"https://cheese.com/media/img/cheese/Cheese-Curds.jpg","url":"https://cheese.com/cheese-curds/"},{"displayTitle":"Farmer cheese","title":"farmercheese","image":"https://cheese.com/media/img/cheese/Farmer_Cheese_.jpg","url":"https://cheese.com/farmer/"},{"displayTitle":"Gamonéu","title":"gamonéu","image":"https://cheese.com/media/img/cheese/Gamonedo.JPG","url":"https://cheese.com/gamoneu/"},{"displayTitle":"Gammelost","title":"gammelost","image":"https://cheese.com/media/img/cheese/644-gammelost.jpg","url":"https://cheese.com/gammelost/"},{"displayTitle":"Blue Castello","title":"bluecastello","image":"https://cheese.com/media/img/cheese/CastelloBlueCheese.jpg","url":"https://cheese.com/blue-castello/"},{"displayTitle":"Bleu Bénédictin","title":"bleubénédictin","image":"https://cheese.com/media/img/cheese/689-bleu_benedictin.jpg","url":"https://cheese.com/bleu-benedictin/"},{"displayTitle":"Galbani","title":"galbani","image":"https://cheese.com/media/img/cheese/Galbani.jpg","url":"https://cheese.com/galbani/"},{"displayTitle":"Bocconcini","title":"bocconcini","image":"https://cheese.com/media/img/cheese/Bocconcini_gobeirne_V0API9t.jpg","url":"https://cheese.com/bocconcini/"},{"displayTitle":"Bleu Des Causses","title":"bleudescausses","image":"https://cheese.com/media/img/cheese/Bleu_des_Causses.JPG","url":"https://cheese.com/bleu-des-causses/"},{"displayTitle":"Blythedale Camembert","title":"blythedalecamembert","image":"https://cheese.com/media/img/cheese/782-blythedale_camembert.jpg","url":"https://cheese.com/blythedale-camembert/"},{"displayTitle":"Berkswell","title":"berkswell","image":"https://cheese.com/media/img/cheese/543-berkswell.jpg","url":"https://cheese.com/berkswell/"},{"displayTitle":"Bleu d'Auvergne","title":"bleudauvergne","image":"https://cheese.com/media/img/cheese/Bleu_auvergne.jpg","url":"https://cheese.com/bleu-dauvergne/"},{"displayTitle":"Blue Vein Cheese","title":"blueveincheese","image":"https://cheese.com/media/img/cheese/blue.jpg","url":"https://cheese.com/blue-vein-cheese/"},{"displayTitle":"Blue Vein (Australian)","title":"bluevein(australian)","image":"https://cheese.com/media/img/cheese/Roaring_Forties_Blue_Cheese.jpg","url":"https://cheese.com/blue-vein-australian/"},{"displayTitle":"Boeren-Leidse met sleutels","title":"boeren-leidsemetsleutels","image":"https://cheese.com/media/img/cheese/Leyden_cheese.jpg","url":"https://cheese.com/boeren-leidse-met-sleutels/"},{"displayTitle":"Brânză de Burduf","title":"brânzădeburduf","image":"https://cheese.com/media/img/cheese/cheese_wrapped_in_fir_bark.jpg","url":"https://cheese.com/branza-de-burduf/"},{"displayTitle":"Briquette de Brebis","title":"briquettedebrebis","image":"https://cheese.com/media/img/cheese/1_19.JPG","url":"https://cheese.com/briquette-de-brebis/"},{"displayTitle":"Brie de Meaux","title":"briedemeaux","image":"https://cheese.com/media/img/cheese/Brie_de_Meaux_1.jpg","url":"https://cheese.com/brie-de-meaux/"},{"displayTitle":"Brousse du Rove","title":"broussedurove","image":"https://cheese.com/media/img/cheese/Brousse_du_Rove.jpg","url":"https://cheese.com/brousse-du-rove/"},{"displayTitle":"Buche de Chevre","title":"buchedechevre","image":"https://cheese.com/media/img/cheese/1815-buche_de_chevre.jpg","url":"https://cheese.com/buche-de-chevre/"},{"displayTitle":"Burgos","title":"burgos","image":"https://cheese.com/media/img/cheese/Queso_De_Burgos.JPG","url":"https://cheese.com/burgos/"},{"displayTitle":"Danbo","title":"danbo","image":"https://cheese.com/media/img/cheese/625-danbo.jpg","url":"https://cheese.com/danbo/"},{"displayTitle":"Danablu (Danish Blue)","title":"danablu(danishblue)","image":"https://cheese.com/media/img/cheese/Danablu-Danish-Blue.jpg","url":"https://cheese.com/danablu-danish-blue/"},{"displayTitle":"Danish Feta","title":"danishfeta","image":"https://cheese.com/media/img/cheese/1061-danish_feta.jpg","url":"https://cheese.com/danish-feta/"},{"displayTitle":"Crotonese","title":"crotonese","image":"https://cheese.com/media/img/cheese/Pecorino_Crotonese.jpg","url":"https://cheese.com/crotonese/"},{"displayTitle":"Danish Fontina","title":"danishfontina","image":"https://cheese.com/media/img/cheese/danish_fontina.jpg","url":"https://cheese.com/danish-fontina/"},{"displayTitle":"Cuajada","title":"cuajada","image":"https://cheese.com/media/img/cheese/Cuajada.jpg","url":"https://cheese.com/cuajada/"},{"displayTitle":"Gubbeen","title":"gubbeen","image":"https://cheese.com/media/img/cheese/GubbeenCheeseWeb.jpg","url":"https://cheese.com/gubbeen/"},{"displayTitle":"Chabichou du Poitou","title":"chabichoudupoitou","image":"https://cheese.com/media/img/cheese/chabichou.jpg","url":"https://cheese.com/chabichou-du-poitou/"},{"displayTitle":"Cendre d'Olivet","title":"cendredolivet","image":"https://cheese.com/media/img/cheese/Olivet_cendre_2.jpg","url":"https://cheese.com/cendre-dolivet/"},{"displayTitle":"Catupiry","title":"catupiry","image":"https://cheese.com/media/img/cheese/606-catupiry.jpg","url":"https://cheese.com/catupiry/"},{"displayTitle":"Caveman Blue","title":"cavemanblue","image":"https://cheese.com/media/img/cheese/544-caveman_blue.jpg","url":"https://cheese.com/caveman-blue/"},{"displayTitle":"Casu marzu","title":"casumarzu","image":"https://cheese.com/media/img/cheese/Casu_Marzu_cheese.jpg","url":"https://cheese.com/casu-marzu/"},{"displayTitle":"Cotija","title":"cotija","image":"https://cheese.com/media/img/cheese/08-cotija-shutterstock_171554048.jpg","url":"https://cheese.com/cotija/"},{"displayTitle":"Cana de Cabra","title":"canadecabra","image":"https://cheese.com/media/img/cheese/Cana-de-Cabra-Low.jpg","url":"https://cheese.com/cana-de-cabra/"},{"displayTitle":"Coulommiers","title":"coulommiers","image":"https://cheese.com/media/img/cheese/wiki/coulommiers.jpg","url":"https://cheese.com/coulommiers/"},{"displayTitle":"Canastra cheese","title":"canastracheese","image":"https://cheese.com/media/img/cheese/1822-canastra_cheese.jpg","url":"https://cheese.com/canastra-cheese/"},{"displayTitle":"Coalho","title":"coalho","image":"https://cheese.com/media/img/cheese/Queijo_coalho.jpg","url":"https://cheese.com/coalho/"},{"displayTitle":"Cougar Gold","title":"cougargold","image":"https://cheese.com/media/img/cheese/1763_cougar_gold.jpg","url":"https://cheese.com/cougar-gold/"},{"displayTitle":"Cabrales","title":"cabrales","image":"https://cheese.com/media/img/cheese/cabrales.jpg","url":"https://cheese.com/cabrales/"},{"displayTitle":"Caboc","title":"caboc","image":"https://cheese.com/media/img/cheese/26-caboc-shutterstock_1329224714.jpg","url":"https://cheese.com/caboc/"},{"displayTitle":"Cachaille","title":"cachaille","image":"https://cheese.com/media/img/cheese/1_20.JPG","url":"https://cheese.com/cachaille/"},{"displayTitle":"Cabecou","title":"cabecou","image":"https://cheese.com/media/img/cheese/Cabecou.jpg","url":"https://cheese.com/cabecou/"},{"displayTitle":"Colby-Jack","title":"colby-jack","image":"https://cheese.com/media/img/cheese/wiki/colby-jack.jpg","url":"https://cheese.com/colby-jack/"},{"displayTitle":"Colby","title":"colby","image":"https://cheese.com/media/img/cheese/wiki/colby.jpg","url":"https://cheese.com/colby/"},{"displayTitle":"Crema Mexicana Agria","title":"cremamexicanaagria","image":"https://cheese.com/media/img/cheese/crema-mexicana-agria.jpg","url":"https://cheese.com/crema-agria/"},{"displayTitle":"Cardo","title":"cardo","image":"https://cheese.com/media/img/cheese/Cardo.jpg","url":"https://cheese.com/cardo/"},{"displayTitle":"Fior Di Latte","title":"fiordilatte","image":"https://cheese.com/media/img/cheese/mozzarella.jpg","url":"https://cheese.com/fior-di-latte/"},{"displayTitle":"Fiscalini Bandaged Cheddar","title":"fiscalinibandagedcheddar","image":"https://cheese.com/media/img/cheese/1032-fiscalini_bandaged_cheddar.jpg","url":"https://cheese.com/fiscalini-bandaged-cheddar/"},{"displayTitle":"Cottage Cheese (Australian)","title":"cottagecheese(australian)","image":"https://cheese.com/media/img/cheese/Cottagecheese.jpg","url":"https://cheese.com/cottage-cheese-australian/"},{"displayTitle":"Cornish Yarg","title":"cornishyarg","image":"https://cheese.com/media/img/cheese/624-cornish_yarg.jpg","url":"https://cheese.com/cornish-yarg/"},{"displayTitle":"Cotherstone","title":"cotherstone","image":"https://cheese.com/media/img/cheese/cotherstone.jpg","url":"https://cheese.com/cotherstone/"},{"displayTitle":"Cottage Cheese","title":"cottagecheese","image":"https://cheese.com/media/img/cheese/514_cottage_cheese.jpg","url":"https://cheese.com/cottage-cheese/"},{"displayTitle":"Cotswold","title":"cotswold","image":"https://cheese.com/media/img/cheese/19-cotswold-shutterstock_55436554.jpg","url":"https://cheese.com/cotswold/"},{"displayTitle":"Coolea","title":"coolea","image":"https://cheese.com/media/img/cheese/595-coolea.jpg","url":"https://cheese.com/coolea/"},{"displayTitle":"Cornish Brie","title":"cornishbrie","image":"https://cheese.com/media/img/cheese/598-cornish_brie.jpg","url":"https://cheese.com/cornish-brie/"},{"displayTitle":"ColoRouge","title":"colorouge","image":"https://cheese.com/media/img/cheese/ColoRouge.jpg","url":"https://cheese.com/colorouge/"},{"displayTitle":"Condio","title":"condio","image":"https://cheese.com/media/img/cheese/Condio.jpg","url":"https://cheese.com/condio/"},{"displayTitle":"Comte","title":"comte","image":"https://cheese.com/media/img/cheese/600-comte.jpg","url":"https://cheese.com/comte/"},{"displayTitle":"Esrom","title":"esrom","image":"https://cheese.com/media/img/cheese/Esrom.jpg","url":"https://cheese.com/esrom/"},{"displayTitle":"Etorki","title":"etorki","image":"https://cheese.com/media/img/cheese/Fromage_Etorki.jpg","url":"https://cheese.com/etorki/"},{"displayTitle":"Edelpilz","title":"edelpilz","image":"https://cheese.com/media/img/cheese/Edelpilz.jpg","url":"https://cheese.com/edelpilz/"},{"displayTitle":"Dolcelatte","title":"dolcelatte","image":"https://cheese.com/media/img/cheese/532_dolcelatte.jpg","url":"https://cheese.com/dolcelatte/"},{"displayTitle":"Delice de Bourgogne","title":"delicedebourgogne","image":"https://cheese.com/media/img/cheese/1052-delice_de_bourgogne.jpg","url":"https://cheese.com/delice-de-bourgogne/"},{"displayTitle":"Colony cheese","title":"colonycheese","image":"https://cheese.com/media/img/cheese/Colony_cheese.jpg","url":"https://cheese.com/colony-cheese/"},{"displayTitle":"Edam","title":"edam","image":"https://cheese.com/media/img/cheese/EdamCheese.jpg","url":"https://cheese.com/edam/"},{"displayTitle":"Colston Bassett Stilton","title":"colstonbassettstilton","image":"https://cheese.com/media/img/cheese/Colston_Bassett_Stilton.JPG","url":"https://cheese.com/colston-bassett-stilton/"},{"displayTitle":"Durrus","title":"durrus","image":"https://cheese.com/media/img/cheese/38-durrus-shutterstock_375008764.jpg","url":"https://cheese.com/durrus/"},{"displayTitle":"Dunlop","title":"dunlop","image":"https://cheese.com/media/img/cheese/955-dunlop.jpg","url":"https://cheese.com/dunlop/"},{"displayTitle":"Dragons Breath Blue","title":"dragonsbreathblue","image":"https://cheese.com/media/img/cheese/Dragons_Breath.jpg","url":"https://cheese.com/dragons-breath-blue/"},{"displayTitle":"Dorset Blue Vinny","title":"dorsetbluevinny","image":"https://cheese.com/media/img/cheese/Dorset_Blue_Vinney_cheese.jpg","url":"https://cheese.com/dorset-blue-vinny/"},{"displayTitle":"Dry Jack","title":"dryjack","image":"https://cheese.com/media/img/cheese/427px-Sonoma_Dry_Jack.jpg","url":"https://cheese.com/dry-jack/"},{"displayTitle":"Dorblu","title":"dorblu","image":"https://cheese.com/media/img/cheese/1168-dorblu.jpg","url":"https://cheese.com/dorblu/"},{"displayTitle":"Dorstone","title":"dorstone","image":"https://cheese.com/media/img/cheese/dorstone.JPG","url":"https://cheese.com/dorstone/"},{"displayTitle":"Don Olivo","title":"donolivo","image":"https://cheese.com/media/img/cheese/1200-don_olivo.jpg","url":"https://cheese.com/don-olivo/"},{"displayTitle":"Derby","title":"derby","image":"https://cheese.com/media/img/cheese/Sage_derby_cheese_EekCJQe.jpg","url":"https://cheese.com/derby/"},{"displayTitle":"Barricato al Pepe","title":"barricatoalpepe","image":"https://cheese.com/media/img/cheese/Barricato_al_Pepe.jpg","url":"https://cheese.com/barricato-al-pepe/"},{"displayTitle":"Beyaz Peynir","title":"beyazpeynir","image":"https://cheese.com/media/img/cheese/Beyaz-Peynir.jpg","url":"https://cheese.com/beyaz-peynir/"},{"displayTitle":"Bavarian Bergkase","title":"bavarianbergkase","image":"https://cheese.com/media/img/cheese/Bavarian_Bergkase.jpg","url":"https://cheese.com/bavarian-bergkase/"},{"displayTitle":"Beemster Extra Aged (XO)","title":"beemsterextraaged(xo)","image":"https://cheese.com/media/img/cheese/757-beemster_extra_aged.jpg","url":"https://cheese.com/beemster-extra-aged/"},{"displayTitle":"Bel Paese","title":"belpaese","image":"https://cheese.com/media/img/cheese/604-bel_paese.jpg","url":"https://cheese.com/bel-paese/"},{"displayTitle":"Beemster Classic","title":"beemsterclassic","image":"https://cheese.com/media/img/cheese/30-beemster-classic-shutterstock_168147977.jpg","url":"https://cheese.com/beemster-classic/"},{"displayTitle":"Bierkase","title":"bierkase","image":"https://cheese.com/media/img/cheese/Bierkase.jpg","url":"https://cheese.com/bierkase/"},{"displayTitle":"Bethmale des Pyrenees","title":"bethmaledespyrenees","image":"https://cheese.com/media/img/cheese/Bethmale.jpg","url":"https://cheese.com/bethmale-des-pyrenees/"},{"displayTitle":"Blacksticks Blue","title":"blacksticksblue","image":"https://cheese.com/media/img/cheese/13-blacksticks-blue-shutterstock_108187130.jpg","url":"https://cheese.com/blacksticks-blue/"},{"displayTitle":"Butterkase","title":"butterkase","image":"https://cheese.com/media/img/cheese/DeutschButterkase.jpg","url":"https://cheese.com/butterkase/"},{"displayTitle":"Burrata","title":"burrata","image":"https://cheese.com/media/img/cheese/587-burrata.jpg","url":"https://cheese.com/burrata/"},{"displayTitle":"Feta","title":"feta","image":"https://cheese.com/media/img/cheese/504_feta.jpg","url":"https://cheese.com/feta/"},{"displayTitle":"Filetta","title":"filetta","image":"https://cheese.com/media/img/cheese/685-filetta.jpg","url":"https://cheese.com/filetta/"},{"displayTitle":"Cream Havarti","title":"creamhavarti","image":"https://cheese.com/media/img/cheese/Havarathi.jpg","url":"https://cheese.com/cream-havarti/"},{"displayTitle":"Fiore Sardo","title":"fioresardo","image":"https://cheese.com/media/img/cheese/Fiore_Sardo.jpg","url":"https://cheese.com/fiore-sardo/"},{"displayTitle":"Finn","title":"finn","image":"https://cheese.com/media/img/cheese/finn.jpg","url":"https://cheese.com/finn/"},{"displayTitle":"Chhurpi","title":"chhurpi","image":"https://cheese.com/media/img/cheese/800px-Chhurpi.jpg","url":"https://cheese.com/chhurpi/"},{"displayTitle":"Cheshire","title":"cheshire","image":"https://cheese.com/media/img/cheese/Cheshire_Cheese.jpg","url":"https://cheese.com/cheshire/"},{"displayTitle":"Cream Cheese","title":"creamcheese","image":"https://cheese.com/media/img/cheese/cream_cheese_bagel.jpg","url":"https://cheese.com/cream-cheese/"}] --------------------------------------------------------------------------------