From dc8f78256944885108f1d52b822c8677bf9d964c Mon Sep 17 00:00:00 2001 From: Minteck Date: Sun, 12 Dec 2021 11:19:38 +0100 Subject: Initial commit --- .gitignore | 4 + .gitlab-ci.yml | 15 ++ .idea/.gitignore | 8 + .idea/MinteckSearch.iml | 8 + .idea/deployment.xml | 14 ++ .idea/modules.xml | 8 + .idea/php.xml | 4 + .idea/sshConfigs.xml | 8 + .idea/vcs.xml | 6 + .idea/webServers.xml | 14 ++ TODO | 3 + assets/default.png | Bin 0 -> 1478 bytes assets/instant.js | 50 +++++ assets/main.css | 200 +++++++++++++++++++ assets/relevant.svg | 1 + assets/search.svg | 1 + assets/verified.svg | 1 + icon/index.php | 46 +++++ index.php | 16 ++ logo.old.svg | 217 +++++++++++++++++++++ logo.svg | 490 +++++++++++++++++++++++++++++++++++++++++++++++ out/index.php | 42 ++++ private/instants/kartik | 34 ++++ private/instants/minteck | 34 ++++ ratelimited/instant.php | 82 ++++++++ search/index.php | 270 ++++++++++++++++++++++++++ 26 files changed, 1576 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .idea/.gitignore create mode 100644 .idea/MinteckSearch.iml create mode 100644 .idea/deployment.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/php.xml create mode 100644 .idea/sshConfigs.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/webServers.xml create mode 100644 TODO create mode 100644 assets/default.png create mode 100644 assets/instant.js create mode 100644 assets/main.css create mode 100644 assets/relevant.svg create mode 100644 assets/search.svg create mode 100644 assets/verified.svg create mode 100644 icon/index.php create mode 100644 index.php create mode 100644 logo.old.svg create mode 100644 logo.svg create mode 100644 out/index.php create mode 100644 private/instants/kartik create mode 100644 private/instants/minteck create mode 100644 ratelimited/instant.php create mode 100644 search/index.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..668dbbd --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +private/ratelimiting/* +private/cache/* +private/db.json +private/dictionary.json \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..4402674 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,15 @@ +# Generic Minteck GitLab CI/CD Checks +# PHP applications +image: php:zts-buster + +cache: + paths: + - vendor/ + +before_script: + - apt-get update + - apt-get install -y git + +test: + script: + - bash -c '[[ $(find . -name \*.php -exec php -l {} \; | grep -v "No syntax errors") ]] && exit 2 || exit 0' diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/MinteckSearch.iml b/.idea/MinteckSearch.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/MinteckSearch.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..22d9ade --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b0cb0c4 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..7341688 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/sshConfigs.xml b/.idea/sshConfigs.xml new file mode 100644 index 0000000..66ef29d --- /dev/null +++ b/.idea/sshConfigs.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/webServers.xml b/.idea/webServers.xml new file mode 100644 index 0000000..e9b027b --- /dev/null +++ b/.idea/webServers.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/TODO b/TODO new file mode 100644 index 0000000..bd9ed29 --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +Integration with Stack Overflow for development questions +Integration with Wolfram Alpha for general questions +Integration with DeepL for translation \ No newline at end of file diff --git a/assets/default.png b/assets/default.png new file mode 100644 index 0000000..b018b02 Binary files /dev/null and b/assets/default.png differ diff --git a/assets/instant.js b/assets/instant.js new file mode 100644 index 0000000..439daab --- /dev/null +++ b/assets/instant.js @@ -0,0 +1,50 @@ +(async () => { + instant = JSON.parse( + (await ( + await ( + await window.fetch("/ratelimited/instant.php?q=" + query) + ).blob() + ).text() + )); + + document.getElementById("details").innerHTML = "from DuckDuckGo:

" + instant.Abstract + "

" + instant.AbstractSource + "

"; + if (instant.Abstract.trim() !== "") document.getElementById("details").style.display = "block"; + if (instant.Abstract.trim() !== "") document.getElementById("results").classList.add("with-details"); + if (instant.Abstract.trim() !== "") try {document.getElementsByClassName("dym-section")[0].outerHTML = ""; } catch (e) {} + + if (!instant._WolfEye_External) { + try { document.getElementById("details-source").innerHTML = " " } catch (e) {} + try { document.getElementById("details-data-link").target = "" } catch (e) {} + } + + if (instant.Results[0]) { + if (!document.getElementsByClassName("result-official")[0]) { + document.getElementById("results").innerHTML = '
Example
https://example.com/
' + document.getElementById("results").innerHTML; + } + + document.getElementsByClassName("result-official")[0].classList.add("result-verified"); + document.getElementsByClassName("result-official")[0].children[0].href = instant.Results[0].FirstURL; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[2].src = "/assets/verified.svg"; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[2].title = "Verified Website"; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[0].src = "https://duckduckgo.com" + instant.Results[0].Icon.URL; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[1].innerText = instant.Heading; + document.getElementsByClassName("result-official")[0].children[0].children[1].children[0].innerText = instant.Results[0].FirstURL; + } + + if (query === "wolfeye" || query === "wolf eye") { + document.getElementById("details").innerHTML = "

Hold tight! Let's go home...

You are already using WolfEye; but you seem lost. Use the search bar at the top of this page to search for something on the Web.

" + document.getElementById("details").style.display = "block"; + + if (!document.getElementsByClassName("result-official")[0]) { + document.getElementById("results").innerHTML = '
Example
https://example.com/
' + document.getElementById("results").innerHTML; + } + + document.getElementsByClassName("result-official")[0].classList.add("result-verified"); + document.getElementsByClassName("result-official")[0].children[0].href = "https://wolfeye.minteck.org"; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[2].src = "/assets/verified.svg"; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[2].title = "Verified Website"; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[0].src = "/logo.svg"; + document.getElementsByClassName("result-official")[0].children[0].children[0].children[1].innerText = "WolfEye"; + document.getElementsByClassName("result-official")[0].children[0].children[1].children[0].innerText = "https://wolfeye.minteck.org"; + } +})() \ No newline at end of file diff --git a/assets/main.css b/assets/main.css new file mode 100644 index 0000000..107521f --- /dev/null +++ b/assets/main.css @@ -0,0 +1,200 @@ +body, html { + background: #222; + color: white; + margin: 0; + font-family: arial,sans-serif; +} + +.result-url, .result-name { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.result { + color: white; + text-decoration: none; + padding: 8px; + margin-bottom: 5px; + border-radius: 5px; + border: 2px solid transparent; +} + +.result:hover { + background: #333; +} + +.result:active, .result:focus { + background: #444; +} + +.result a { + text-decoration: inherit; + color: inherit; +} + +.result.result-official { + border-color: rgba(255, 255, 0, 0.3); +} + +.result.result-verified { + border-color: rgba(0, 255, 21, 0.3); +} + +.result-relevant { + vertical-align: middle; +} + +#results-intro-logo, #results-intro-bar { + display: inline-block; + margin: 0; +} + +#results-intro { + background: #111; + padding: 0 50px; + margin-bottom: 20px; + position: fixed; + top: 0; + left: 0; + right: 0; + border-bottom: 1px solid #252525; +} + +#results-intro-bar-input { + background: #171717; + color: white; + border: 1px solid #222; + padding: 10px; + outline: none; + height: 8px; + border-radius: 5px; + width: calc(100vw - 230px); + margin: 8px 10px; +} + +#results-intro-bar-input:hover { + border-color: #333; +} + +#results-intro-bar-input:active, #results-intro-bar-input:focus { + border-color: #444; +} + +#intro-results-separator { + margin-top: 43px; +} + +@media (max-width: 1200px) { + #results, #details, #results-debug { + padding: 50px 200px !important; + } +} + +@media (max-width: 1000px) { + #results, #details, #results-debug { + padding: 50px 150px !important; + } +} + +@media (max-width: 700px) { + #results, #details, #results-debug { + padding: 50px 100px !important; + } +} + +@media (max-width: 500px) { + #results, #details, #results-debug { + padding: 50px 50px !important; + } +} + +@media (max-width: 450px) { + #results, #details, #results-debug { + padding: 50px 10px !important; + } +} + +#results, #details, #results-debug { + padding: 50px 250px; +} + +.dym-link { + color: lightgray; +} + +.dym-section { + padding: 10px; + background: #333; + border-bottom: 1px solid #353535; +} + +.result-icon { + width: 24px; + height: 24px; + vertical-align: middle; +} + +#results-intro-logo-img { + width: 32px; + height: 32px; + vertical-align: middle; +} + +#details { + padding-top: 10px !important; + padding-bottom: 10px !important; + display: none; +} + +#results-intro-bar-submit { + background-color: transparent; + color: transparent; + border: transparent; + cursor: pointer; + background-image: url("/assets/search.svg"); + background-repeat: no-repeat; + background-position: center; + background-size: contain; + width: 24px; + height: 24px; + padding: 4px; +} + +@media (max-width: 50px) { + #results-intro { + padding: 0 50px; + } + #results-intro-bar-input { + width: calc(100vw - 152px); + margin: 8px 5px; + } +} + +#results-debug { + margin: 0; + padding-top: 10px !important; + padding-bottom: 0 !important; +} + +#results.with-details { + padding-top: 10px !important; +} + +#results-debug-inner-details { + opacity: 0; + font-family: monospace; +} + +#results-debug-inner-details:hover { + opacity: 1; +} + +#details-source { + display: inline-block; + opacity: .5; +} + +#details-source-link, #details-data-link { + color: white; +} \ No newline at end of file diff --git a/assets/relevant.svg b/assets/relevant.svg new file mode 100644 index 0000000..dc6a14c --- /dev/null +++ b/assets/relevant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/search.svg b/assets/search.svg new file mode 100644 index 0000000..06a261d --- /dev/null +++ b/assets/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/verified.svg b/assets/verified.svg new file mode 100644 index 0000000..ada4600 --- /dev/null +++ b/assets/verified.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon/index.php b/icon/index.php new file mode 100644 index 0000000..97bf068 --- /dev/null +++ b/icon/index.php @@ -0,0 +1,46 @@ + $entry) { + $domain = explode("/", $entry["url"])[2]; + $sim = similar_text($domain, $_GET['q'], $perc); + if (substr($domain, 0, 4) === "www.") { + $domainstr = substr($domain, 4); + } else { + $domainstr = $domain; + } + $domains[] = [ + "id" => $id, + "url" => "https://" . $domain . "/", + "domain" => $domainstr, + "relevance" => $perc / 50 - 1 + ]; + } + + usort($domains, function($a, $b) { + return $a['relevance'] <=> $b['relevance']; + }); + + $domains = array_reverse($domains); + $icdom = $domains[0]['domain']; +} + +header("Location: https://external-content.duckduckgo.com/ip3/" . $icdom . ".ico"); +die(); \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..4bc8815 --- /dev/null +++ b/index.php @@ -0,0 +1,16 @@ + + + + + WolfEye + + +

WolfEye

+
+ + + + +
+ + diff --git a/logo.old.svg b/logo.old.svg new file mode 100644 index 0000000..4f397a4 --- /dev/null +++ b/logo.old.svg @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000..c631fcf --- /dev/null +++ b/logo.svg @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/out/index.php b/out/index.php new file mode 100644 index 0000000..cefe36b --- /dev/null +++ b/out/index.php @@ -0,0 +1,42 @@ + $entry) { + $domain = explode("/", $entry["url"])[2]; + $sim = similar_text($domain, $_GET['q'], $perc); + if (substr($domain, 0, 4) === "www.") { + $domainstr = substr($domain, 4); + } else { + $domainstr = $domain; + } + $domains[] = [ + "id" => $id, + "url" => "https://" . $domain . "/", + "domain" => $domainstr, + "relevance" => $perc / 50 - 1 + ]; + } + + usort($domains, function($a, $b) { + return $a['relevance'] <=> $b['relevance']; + }); + + $domains = array_reverse($domains); + header("Location: " . $domains[0]['url']); + die(); +} \ No newline at end of file diff --git a/private/instants/kartik b/private/instants/kartik new file mode 100644 index 0000000..5f52c0f --- /dev/null +++ b/private/instants/kartik @@ -0,0 +1,34 @@ +{ + "Abstract" : "Kartik is an online car racing game developed by Minteck in early 2021. The game is made of its own engine based on GitHub's Electron; which use have caused major problems during the development; Minteck said on her blog that she doesn't even know how to properly use Electron. The game releases on June 12th 2021, and with bug fixing updates until October 1st 2021. Kartik was originally supposed to be released under a proprietary license, but was made open source later in the development as per the JetBrains License Agreement.", + "AbstractSource" : "Minteck", + "AbstractText" : "", + "AbstractURL" : "/search?q=minteck", + "Answer" : "", + "AnswerType" : "", + "Definition" : "", + "DefinitionSource" : "", + "DefinitionURL" : "", + "Entity" : "infobox", + "Heading" : "Kartik", + "Image" : "/i/kartik.minteck.org.ico", + "ImageHeight" : 0, + "ImageIsLogo" : 1, + "ImageWidth" : 0, + "Infobox" : {}, + "Redirect" : "", + "RelatedTopics" : [], + "Results" : [ + { + "FirstURL" : "https://kartik.minteck.org/home/", + "Icon" : { + "Height" : 0, + "URL" : "/i/kartik.minteck.org.ico", + "Width" : 0 + }, + "Result" : null, + "Text" : "Official site" + } + ], + "Type" : "A", + "meta" : {} +} diff --git a/private/instants/minteck b/private/instants/minteck new file mode 100644 index 0000000..bdf23d1 --- /dev/null +++ b/private/instants/minteck @@ -0,0 +1,34 @@ +{ + "Abstract" : "Mia (also known as Minteck) is a French Web developer; developing her own software since 2018 and contributing to open source projects since 2019. She is mainly known for games like Kartik or Foxperson, and for the content management system Neutron. Since 2021, all software she makes is free libre and open source as per her JetBrains License Agreement.", + "AbstractSource" : "Minteck", + "AbstractText" : "", + "AbstractURL" : "/search?q=minteck", + "Answer" : "", + "AnswerType" : "", + "Definition" : "", + "DefinitionSource" : "", + "DefinitionURL" : "", + "Entity" : "infobox", + "Heading" : "Minteck", + "Image" : "/i/staging.minteck.org.ico", + "ImageHeight" : 0, + "ImageIsLogo" : 1, + "ImageWidth" : 0, + "Infobox" : {}, + "Redirect" : "", + "RelatedTopics" : [], + "Results" : [ + { + "FirstURL" : "https://minteck.org/", + "Icon" : { + "Height" : 0, + "URL" : "/i/staging.minteck.org.ico", + "Width" : 0 + }, + "Result" : null, + "Text" : "Official site" + } + ], + "Type" : "A", + "meta" : {} +} diff --git a/ratelimited/instant.php b/ratelimited/instant.php new file mode 100644 index 0000000..bfbb56f --- /dev/null +++ b/ratelimited/instant.php @@ -0,0 +1,82 @@ + -1, + "global" => -1, + "blocked" => false +]; + +if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/" . $addr)) { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/" . $addr, "1|" . date('YmdHi')); +} else { + $requests = (int)explode("|", file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/" . $addr))[0]; + $date = explode("|", file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/" . $addr))[1]; + if ($date === date('YmdHi')) { + $requests++; + if ($requests > 3) { + $cacheOnly = true; + $rl["blocked"] = true; + } + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/" . $addr, $requests . "|" . date('YmdHi')); + } else { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/" . $addr, "1|" . date('YmdHi')); + } + + $rl["local"] = $requests; +} + +if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/_global")) { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/_global", "1|" . date('YmdHi')); +} else { + $requests = (int)explode("|", file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/_global"))[0]; + $date = explode("|", file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/_global"))[1]; + if ($date === date('YmdHi')) { + $requests++; + if ($requests >= 20) { + $cacheOnly = true; + $rl["blocked"] = true; + } + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/_global", $requests . "|" . date('YmdHi')); + } else { + file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/private/ratelimiting/_global", "1|" . date('YmdHi')); + } + + $rl["global"] = $requests; +} + +header("Content-Type: application/json"); + +if (file_exists($_SERVER["DOCUMENT_ROOT"] . "/private/instants/" . str_replace(" ", "_", $query))) { + $ds = "local"; + $data = file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/private/instants/" . str_replace(" ", "_", $query)); +} else if (file_exists($_SERVER["DOCUMENT_ROOT"] . "/private/cache/instant_" . str_replace(" ", "_", $query))) { + $ds = "cache"; + $data = file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/private/cache/instant_" . str_replace(" ", "_", $query)); +} else { + if ($cacheOnly) { + die(); + } else { + $ds = "online"; + $data = file_get_contents("https://api.duckduckgo.com/?q=" . $query . "&format=json&pretty=1&t=Minteck-WolfEye_https://minteck.org&skip_disambig=1&no_redirect=1&no_html=1"); + file_put_contents($_SERVER["DOCUMENT_ROOT"] . "/private/cache/instant_" . str_replace(" ", "_", $query), $data); + } +} + +$parsed = json_decode($data, true); +$parsed = array_reverse($parsed); +$parsed["_WolfEye_DataSource"] = $ds; +$parsed["_WolfEye_RateLimiting"] = $rl; +$parsed["_WolfEye_External"] = $ds !== "local"; +$parsed = array_reverse($parsed); + +die(json_encode($parsed, JSON_PRETTY_PRINT)); \ No newline at end of file diff --git a/search/index.php b/search/index.php new file mode 100644 index 0000000..709a239 --- /dev/null +++ b/search/index.php @@ -0,0 +1,270 @@ + + + + + + <?= ucfirst($query) ?> on WolfEye + + + + +
+ +
+ + +
+
+ +
$closest", $query); + } + + if ($query === "google") { + $fixed = true; + $fixes[] = str_replace($item, "duckduckgo", $query); + $fixesd[] = str_replace($item, "duckduckgo", $query); + } + + if ($query === "microsoft") { + $fixed = true; + $fixes[] = str_replace($item, "redhat", $query); + $fixesd[] = str_replace($item, "redhat", $query); + } + + if ($query === "windows") { + $fixed = true; + $fixes[] = str_replace($item, "linux", $query); + $fixesd[] = str_replace($item, "linux", $query); + } + + if ($query === "apple") { + $fixed = true; + $fixes[] = str_replace($item, "raspberry", $query); + $fixesd[] = str_replace($item, "raspberry", $query); + } + + if ($query === "france") { + $fixed = true; + $fixes[] = str_replace($item, "hell", $query); + $fixesd[] = str_replace($item, "hell", $query); + } + } + + if ($fixed) { + echo("
"); + if (count($fixes) > 1) { + echo("Showing results for \"$query\", did you mean:"); + } else { + echo("Showing results for \"$query\", did you mean \"$fixesd[0]\"?"); + } + echo("
"); + } + $elapsed_correct = microtime(true) - $start_correct; + + // Actual Search + $start_search = microtime(true); + $matches = []; + foreach ($data["entries"] as $id => $item) { + $avg = -1; + $aavg = []; + $iparsed = strtolower(substr($item["title"], 0, 200)); + $iparsed = preg_replace("/[^A-Za-z0-9 ]/", '', preg_replace("/[\.]/", ' ', $iparsed)); + $qwords = explode(" ", $query); + + if (trim($iparsed) !== "") { + foreach ($qwords as $qword) { + $sim = similar_text($iparsed, $qword, $perc); + if ($perc > 0) { + $aavg[] = $perc; + } + } + + if (count($aavg) > 0) { + $aavg = array_filter($aavg); + $avg = (array_sum($aavg) / count($aavg)) / 50 - 1; + $matches[] = [ + "id" => $id, + "relevance" => $avg + ]; + } + } + + $avg = -1; + $aavg = []; + $iparsed = strtolower(substr($item["url"], 0, 200)); + $iparsed = preg_replace("/[^A-Za-z0-9 ]/", '', preg_replace("/[\.]/", ' ', $iparsed)); + $qwords = explode(" ", $query); + + if (trim($iparsed) !== "") { + foreach ($qwords as $qword) { + $sim = similar_text($iparsed, $qword, $perc); + if ($perc > 0) { + $aavg[] = $perc; + } + } + + if (count($aavg) > 0) { + $aavg = array_filter($aavg); + $avg = (array_sum($aavg) / count($aavg)) / 50 - 1; + $matches[] = [ + "id" => $id, + "relevance" => $avg + ]; + } + } + } + + usort($matches, function($a, $b) { + return $a['relevance'] <=> $b['relevance']; + }); + + $matches = array_reverse($matches); + + $matches2 = []; + $prel = []; + + foreach($matches as $match) { + if (!isset($prel[(string)$match["relevance"]])) { + $prel[(string)$match["relevance"]] = [$match]; + } else { + $prel[(string)$match["relevance"]][] = $match; + } + } + + $elapsed_search = microtime(true) - $start_search; + $start_parse = microtime(true); + $entriesdom = []; + foreach($prel as $item => $items) { + $shortest = -1; + + foreach ($items as $word) { + $lev = levenshtein($query, $data["entries"][$word["id"]]["title"]); + + if ($lev == 0) { + $closest = $word["id"]; + $shortest = 0; + break; + } + + if ($lev <= $shortest || $shortest < 0) { + $closest = $word["id"]; + $shortest = $lev; + } + } + + $entriesdom[] = [ + "link" => "/out?q=" . $query . "&u=" . uniqid() . "&i=" . $closest, + "title" => $data["entries"][$closest]["title"], + "url" => $data["entries"][$closest]["url"], + "icon" => "/icon?q=" . $query . "&i=" . $closest, + ]; + } + $elapsed_parse = microtime(true) - $start_parse; + ?> +

results

+ +
+ + + +
+ $entry): ?> + $id, + "url" => "https://" . $domain . "/", + "domain" => $domainstr, + "relevance" => $perc / 50 - 1 + ]; + ?> + $b['relevance']; + }); + + $domains = array_reverse($domains); if ($domains[0]["relevance"] > 0): ?> + + + + + +
+ + + + + -- cgit