".implode(" - ", $meta)."
Not sure what went wrong? Learn more about hash."\">how to use Goosle.
diff --git a/assets/css/styles.css b/assets/css/styles.css index 4e77d07..987197c 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -9,8 +9,7 @@ * liability that might arise from its use. ------------------------------------------------------------------------------------ */ -html { font-size: 16px; } -body { position: relative; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; color: #222; background-color: #ffffff; line-height: 1.2; } +body { margin: 0; padding: 0; background-color: #fff; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: #222; line-height: 1.2; } div { margin: 0; padding: 0; border: 0; vertical-align: baseline; } article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block; } h2, h3, h4, h5, h6 { font-weight: normal; } @@ -22,110 +21,108 @@ p { font-size: 18px; color: #494949; } a { text-decoration: none; color: #4495d4; } small, sub, sup { padding: 5px 0; color: #666; font-size: 12px; } sub, sup { font-style: italic; } +pre, code { word-wrap: break-word; overflow-wrap: break-word; } a:hover { text-decoration: underline; } -input[type="text"]:invalid ~ input[type="submit"] { opacity: 0.5; pointer-events: none; } -input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; -webkit-mask-image: url("data:image/svg+xml;utf8,"); } +input[type="text"]: invalid ~ input[type="submit"] { opacity: 0.5; pointer-events: none; } +input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; -webkit-mask-image: url("data: image/svg+xml;utf8,"); } /* Page structure */ -.wrap { min-height: 100vh; overflow: hidden; } -.header-wrap { display: block; padding-top: 16px; width: 100%; } -.results-wrap { position: relative; display: flex; margin: 0 158px 50px 158px; } -.footer-wrap { position: absolute; bottom: 0; display: block; margin-top: 15px; padding: 0; width: 100%; } - -/* Main page */ -body.main { background-color: #1f242b; color: #f0f6fc; } -.search-box-main, .password-generator { text-align: center; margin-top: 10%; } -.search-box-main h1 { font-size: 4rem; } -.search-box-main .search, .password-generator .password { padding: 10px 20px; width: 600px; color: #f0f6fc; background-color: #333333; font-size: 2rem; font-family: sans-serif; border: 1px solid #3C4043; border-radius: 10px; } -.search-box-main .search[type="search"]::-webkit-search-cancel-button { background-size: 28px 28px; height: 28px; width: 28px; background-color: #f0f6fc; } -.search-box-buttons button { margin: 30px 20px 10px 20px; padding: 13px 10px 13px 10px; min-width: 130px; color: #f0f6fc; background-color: #333333; font-size: 0.8rem; border: 1px solid #3C4043; border-radius: 6px; } -.search-box-buttons button:hover { border: 1px solid #5f6368; } +body { min-height: 100vh; display: flex; flex-direction: column; } +.header { padding-top: 16px; width: 100%; } +.content { margin: 0 158px; padding: 15px 0; } +.footer { bottom: 0; margin-top: auto; padding: 0; width: 100%; } + +/* Start page */ +.startpage { background-color: #1f242b; color: #f0f6fc; } +.startpage-search, .password-generator { text-align: center; margin-top: 10%; } +.startpage-search h1 { font-size: 4rem; } +.startpage-search .search, .password-generator .password { padding: 10px 20px; width: 600px; color: #f0f6fc; background-color: #333333; font-size: 2rem; font-family: sans-serif; border: 1px solid #3C4043; border-radius: 10px; } +.startpage-search .search[type="search"]::-webkit-search-cancel-button { background-size: 28px 28px; height: 28px; width: 28px; background-color: #f0f6fc; } +.search-buttons button { margin: 30px 20px 10px 20px; padding: 13px 10px 13px 10px; min-width: 130px; color: #f0f6fc; background-color: #333333; font-size: 1rem; border: 1px solid #3C4043; border-radius: 6px; } +.startpage-search .search:focus, .password-generator .password:focus, .search-buttons button:hover { border: 1px solid #5f6368; } .password-generator { margin: 30px auto; padding: 0; } .password-generator .password { margin: 10px auto; width: 300px; text-align: center; font-size: 0.8rem; } -/* Search Results - Header */ -.header-wrap { background-color: #1f242b; color: #f0f6fc; border-bottom: 2px solid #1fa4d1; } -.header-wrap .search, .header-wrap .button { position: relative; height: 40px; color: #f0f6fc; font-size: 1rem; font-weight: 400; } -.header-wrap .search { margin: 28px 0 28px 158px; padding: 5px 5px 5px 15px; width: 580px; background-color: #1f242b; border: 1px solid #303842; border-radius: 10px 0 0 10px; } -.header-wrap .search[type="search"]::-webkit-search-cancel-button { background-size: 20px 20px; height: 20px; width: 20px; background-color: #f0f6fc; } -.header-wrap .button { margin: 28px 10px 28px 0; padding: 5px 20px 5px 15px; background-color: #1fa4d1; border: none; border-radius: 0 10px 10px 0; } - -/* Search results - Header Navigation */ -.navigation-header { margin-left: 165px; margin-bottom: 10px; } -.navigation-header img { margin-right: 5px; height: 16px; vertical-align: middle; } -.navigation-header a { margin-right: 20px; border: none; font-size: 1rem; cursor: pointer; text-decoration: none; } -.navigation-header a:hover { color: #ebf3fa; } -.navigation-header a:visited { color: #1fa4d1; } -.navigation-header .active { padding-bottom: 8px; border-bottom: 4px #1fa4d1 solid; } - -/* Search results */ -.main-column { width: 100%; } -.main-column ol .meta { margin: .75rem 0 .05rem 0; padding: .5rem 10px 0 10px; } -.main-column ol .sources { margin: .05rem 0 .75rem 0; padding: 0 10px .5rem 10px; font-size: 0.75rem; color: #666; } - -.main-column ol .special-result { margin: .75rem 0 .25rem 0; padding: .5rem 10px; } -.main-column ol .result { margin: .50rem 0 .50rem 0; padding: 0; } - -.main-column ol li article { padding: .5rem 10px; border: 1px solid #fefefe; border-radius: 8px; } -.main-column ol li article div.url:first-child, .main-column ol li.special-result article div.source:first-child { flex-grow: 0; } -.main-column ol li article div.url { display: inline-block; margin: 0; max-width: 100%; color: #666; font-size: 1rem; line-height: 1.6; letter-spacing: .2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } -.main-column ol li article div.url a { margin: 0; color: #3f6e35; cursor: pointer; text-decoration: none; } -.main-column ol li article div.title, .main-column ol li.special-result article div.title { margin-bottom: .29rem; } -.main-column ol li article div.title h2 { margin: 0; padding: 0; position: relative; font-size: 1.46rem; letter-spacing: -.01px; } -.main-column ol li article div.title h2:hover { text-decoration: underline; } -.main-column ol li article div.title a { margin: 0; display: block; cursor: pointer; } -.main-column ol li article div.title a:visited { color: #6d59a3; } -.main-column ol li article div.description { margin: 0; line-height: 1.4; font-size: 1rem; color: #494949; } -.main-column ol li article div.engine { padding: 2px 0; font: 12px italic; color: #666; } -.main-column ol li article div.description .seeders { color: #518257; } -.main-column ol li article div.description .leechers { color: #c00; } - -/* Image results */ -.main-column .image-wrapper { width: 100%; margin: .75rem 0 .75rem 0; } -@supports not (display: grid) { - .image-grid > * { max-width: 8rem; margin-left: auto; margin-right: auto; } - .image-grid li.result { display: inline-block; margin: .75rem; width: 12.5%; } - .image-grid > * + * { margin-top: 1rem; } -} +/* oAUTH page*/ +.oauthpage { background-color: #1f242b; color: #f0f6fc; } +.oauth-form { text-align: center; margin-top: 20px; } +.oauth-form h1 { font-size: 4rem; } +.oauth-form p, .oauth-form small { margin-bottom: 15px; color: #f0f6fc; } +.oauth-form .field { padding: 5px 10px; width: 300px; color: #f0f6fc; background-color: #333333; font-size: 1rem; font-family: sans-serif; border: 1px solid #3C4043; border-radius: 10px; } +.oauth-buttons button { margin: 30px 20px 10px 20px; padding: 13px 10px 13px 10px; min-width: 130px; color: #f0f6fc; background-color: #333333; font-size: 1rem; border: 1px solid #3C4043; border-radius: 6px; } +.oauth-buttons button:hover { border: 1px solid #5f6368; } + +/* Results page header */ +.header { background-color: #1f242b; color: #f0f6fc; border-bottom: 2px solid #1fa4d1; } +.header .search, .header .button { position: relative; height: 40px; color: #f0f6fc; font-size: 1rem; font-weight: 400; } +.header .search { margin: 28px 0 28px 158px; padding: 5px 5px 5px 15px; width: 580px; background-color: #1f242b; border: 1px solid #5f6368; border-radius: 10px 0 0 10px; } +.header .search[type="search"]::-webkit-search-cancel-button { background-size: 20px 20px; height: 20px; width: 20px; background-color: #f0f6fc; } +.header .button { margin: 28px 10px 28px 0; padding: 5px 20px 5px 15px; background-color: #1fa4d1; border: none; border-radius: 0 10px 10px 0; } + +.navigation { margin-left: 158px; margin-bottom: 10px; } +.navigation img { margin-right: 5px; height: 16px; vertical-align: middle; } +.navigation a { margin-right: 20px; border: none; font-size: 1rem; cursor: pointer; text-decoration: none; } +.navigation a:hover { color: #ebf3fa; } +.navigation a: visited { color: #1fa4d1; } +.navigation .active { padding-bottom: 8px; border-bottom: 4px solid #1fa4d1; } + +/* Search results spacing */ +.content .meta { padding: 10px 0 0 0; } +.content .sources { padding: 0 0 10px 0; font-size: 0.75rem; color: #666; } +.content .suggestion { padding: 15px 0; } +.content .result { margin: 0 0 25px 0; } +.content .result-special { margin: 15px 0 25px 0; padding: 10px; } +.content .result.image { margin: 0; } + +/* Search results (web, image and magnet) */ +.content .result { border: 1px solid #fefefe; border-radius: 8px; } +.content .result div.url, .content .result-special div.source { max-width: 100%; font-size: 1rem; line-height: 1.6; letter-spacing: .2px; white-space: nowrap; overflow: hidden; } +.content .result div.url a, .content .result-special div.source a { color: #3f6e35; cursor: pointer; text-decoration: none; } +.content .result div.title, .content .result-special div.title { margin-bottom: 5px; } +.content .result div.title h2 { padding: 0; position: relative; font-size: 1.46rem; letter-spacing: -.01px; } +.content .result div.title h2:hover { text-decoration: underline; } +.content .result div.title a { display: block; cursor: pointer; } +.content .result div.title a: visited { color: #6d59a3; } +.content .result div.description { line-height: 1.4; font-size: 1rem; color: #494949; } +.content .result div.engine { padding: 2px 0; font: 12px italic; color: #666; } +.content .result div.description .seeders { color: #518257; } +.content .result div.description .leechers { color: #c00; } + +.content .result-special { position: relative; background-color: #fefefe; overflow: hidden; border: 1px solid #aeaeae; border-radius: 8px; color: #222; } +.content .result-special div.title h2 { padding: 0; font-size: 1.5rem; font-weight: 600; word-wrap: break-word; color: #222; } +.content .result-special div.title h2:hover { text-decoration: none; } +.content .result-special div.title a { display: block; color: #6c00a2; cursor: pointer; } +.content .result-special div.title a: visited { color: #6d59a3; } +.content .result-special div.text, .content .result-special div.source { position: relative; font-style: normal; } + +/* Grids (image and magnet highlights) */ @supports (display: grid) { - .main-column ol.image-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); grid-gap: 1rem; } + .image-grid ol, .magnet-grid ol { display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); grid-gap: 1rem; } } -.main-column ol.image-grid .result .image-box { position: relative; } -.main-column ol.image-grid .result .image-box::after { display: block; padding-bottom: 100%; content: ""; } -.main-column ol.image-grid .result .image-box img { position: absolute; object-fit: cover; width: 100%; height: 100%; border-radius: 10px; } -.main-column ol.image-grid .result .image-box img:hover { outline: none; border-color: #3C4043; box-shadow: 0 0 10px #3C4043; } -.main-column ol.image-grid .result span { padding: 5px 0 0 0; color: #666; font-size: 0.75rem; } - -/* Special results - Main column */ -.main-column ol .special-result { background-color: #fefefe; } -.main-column ol li.special-result article { padding: .5rem 10px; position: relative; overflow: hidden; border: 1px solid #aeaeae; border-radius: 8px; color: #222; } -.main-column ol li.special-result article div.title h2 { margin: 0; padding: 0; font-size: 1.5rem; font-weight: 600; word-wrap: break-word; color: #222; } -.main-column ol li.special-result article div.title h2:hover { text-decoration: none; } -.main-column ol li.special-result article div.title a { margin: 0; display: block; color: #6c00a2; cursor: pointer; } -.main-column ol li.special-result article div.title a:visited { color: #6d59a3; } -.main-column ol li.special-result article div.text, .main-column ol li article div.source { position: relative; font-style: normal; } -.main-column ol li.special-result article div.text img { padding: 0 0 10px 10px; } -.main-column ol li.special-result article div.source { display: inline-block; margin: 0; max-width: 100%; color: #666; font-size: 1rem; line-height: 1.6; letter-spacing: .2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-decoration: inherit; } -.main-column ol li.special-result article div.source a { margin: 0; color: #3f6e35; text-decoration: none; } - -/* Magnet highlights */ -.main-column .magnet-wrapper { width: 100%; margin: .75rem 0 .75rem 0; } @supports not (display: grid) { - .magnet-grid > * { max-width: 8rem; margin-left: auto; margin-right: auto; } - .magnet-grid li.result { display: inline-block; margin: .75rem; width: 12.5%; } - .magnet-grid > * + * { margin-top: 1rem; } -} -@supports (display: grid) { - .main-column ol.magnet-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); grid-gap: 1rem; padding: .5rem 10px; } + .image-grid ol > *, .magnet-grid ol > * { max-width: 8rem; margin-left: auto; margin-right: auto; } + .image-grid ol .result, .magnet-grid ol .result { display: inline-block; margin: .75rem; width: 12.5%; } + .image-grid ol > * + *, .magnet-grid ol > * + * { margin-top: 1rem; } } -.main-column ol.magnet-grid .result .magnet-box { position: relative; } -.main-column ol.magnet-grid .result .magnet-box::after { display: block; content: ""; } -.main-column ol.magnet-grid .result .magnet-box img { width: 100%; height: 100%; border-radius: 10px; } -.main-column ol.magnet-grid .result .magnet-box p { visibility: hidden; opacity: 0; position: absolute; top: 0; bottom: 0; left: 0; right: 0; background: #1f242b; transition: opacity .1s, visibility .1s; padding: 10px; line-height: 1.4; text-align: center; font-size: 0.8rem; color: #f0f6fc; } -.main-column ol.magnet-grid .result .magnet-box a { display: block; position: relative; margin: 5px 0 5px 0; padding: 5px 20px; background-color: #1fa4d1; border: 1px solid #466f82; border-radius: 10px; color: #f0f6fc; font-weight: 800; text-align: center; } -.main-column ol.magnet-grid .result .magnet-box a:hover { text-decoration: none; } -.main-column ol.magnet-grid .result .magnet-box:hover p { visibility: visible; opacity: .90; outline: none; border-color: #3C4043; border-radius: 10px; box-shadow: 0 0 10px #3C4043; } + +/* Image results */ +.image-grid { width: 100%; margin: 25px 0; } +.image-grid ol .result .image-box { position: relative; } +.image-grid ol .result .image-box::after { display: block; padding-bottom: 100%; content: ""; } +.image-grid ol .result .image-box img { position: absolute; object-fit: cover; width: 100%; height: 100%; border-radius: 10px; } +.image-grid ol .result .image-box img:hover { outline: none; border-color: #3C4043; box-shadow: 0 0 10px #3C4043; } +.image-grid ol .result span { padding: 5px 0 0 0; color: #666; font-size: 0.75rem; } + +/* Magnet highlights */ +.magnet-grid { width: 100%; margin: 25px 0; } +.magnet-grid ol .result .magnet-box { position: relative; } +.magnet-grid ol .result .magnet-box::after { display: block; content: ""; } +.magnet-grid ol .result .magnet-box img { width: 100%; height: 100%; border-radius: 10px; } +.magnet-grid ol .result .magnet-box p { visibility: hidden; opacity: 0; position: absolute; top: 0; bottom: 0; left: 0; right: 0; background: #1f242b; transition: opacity .1s, visibility .1s; padding: 10px; line-height: 1.4; text-align: center; font-size: 0.8rem; color: #f0f6fc; } +.magnet-grid ol .result .magnet-box a { display: block; position: relative; margin: 5px 0 5px 0; padding: 5px 20px; background-color: #1fa4d1; border: 1px solid #466f82; border-radius: 10px; color: #f0f6fc; font-weight: 800; text-align: center; } +.magnet-grid ol .result .magnet-box a:hover { text-decoration: none; } +.magnet-grid ol .result .magnet-box:hover p { visibility: visible; opacity: .90; outline: none; border-color: #3C4043; border-radius: 10px; box-shadow: 0 0 10px #3C4043; } /* Misc */ .logo { position: absolute; margin: 28px 18px; } @@ -133,104 +130,104 @@ body.main { background-color: #1f242b; color: #f0f6fc; } .no-decoration, .no-decoration:hover { text-decoration: none; } .hide { display: none; } .G { color: #1fa4d1; } -.warning { position: relative; overflow: hidden; margin: 1rem 0 1rem 0; padding: .5rem 10px; color: #db9900; background-color: #ffffe0; border: 1px solid #e6db55; border-radius: 10px; } -.error { position: relative; overflow: hidden; margin: 1rem 0 1rem 0; padding: .5rem 10px; color: #c00; background-color: #ffebe8; border: 1px solid #c00; border-radius: 10px; } -.auth-error { margin-top: 15%; font-size: 2rem; text-align: center; color: #eaeaea; } +.warning { position: relative; overflow: hidden; margin: 20px 0; padding: 10px; color: #db9900; background-color: #ffffe0; border: 1px solid #e6db55; border-radius: 10px; } +.error { position: relative; overflow: hidden; margin: 20px 0; padding: 10px; color: #c00; background-color: #ffebe8; border: 1px solid #c00; border-radius: 10px; } +.auth-success { margin-top: 15%; font-size: 1rem; text-align: center; color: #f0f6fc; } +.auth-error { margin-top: 15%; font-size: 2rem; text-align: center; color: #f0f6fc; } +a.update { color: #c90; font-weight: bold; } -/* Footer bar */ -.footer-wrap { background-color: #161616; color: #f0f6fc; border-top: 2px solid #303134; } -.footer { padding: 10px; } +/* Footer */ +.footer { background-color: #161616; color: #f0f6fc; border-top: 1px solid #1fa4d1; } .footer a { color: #f0f6fc; } -a.update { color: #c90; font-weight: bold; } +.footer-left, .footer-right { display: inline-block; padding: 10px; } +.footer-right { float: right; } -@media only screen and (max-width:960px) { /* tablet, landscape iPad, lo-res laptops ands desktops */ +@media only screen and (max-width: 960px) { /* tablet, landscape iPad, lo-res/smaller laptops */ /* Page structure */ - .results-wrap { position: relative; display: flex; margin: 0 48px 20px 48px; } + .content { position: relative; margin: 0 48px; } + .footer-left, .footer-right { display: block; padding: 5px 5px 0 5px; text-align: center; } + .footer-right { float: none; padding: 0px 5px 5px 5px; } - /* Main page */ - .search-box-main { margin-top: 10%; } - .search-box-main input { width: 80%; } - .search-box-buttons button { display: table-row; margin: 30px 0px 0px 0px; width: 80%; } + /* Start page */ + .startpage-search { margin-top: 10%; } + .startpage-search .search { width: 80%; } + .search-buttons button { display: table-row; margin: 30px 0px 0px 0px; width: 80%; } /* Search Results - Header */ - .header-wrap { margin-left: auto; margin-right: auto; text-align: center; } - .header-wrap .search { margin: 10px 0px 28px 48px; width: 400px; } - .header-wrap .search, .header-wrap .button { margin: 10px 0px 28px 0px; } + .header { margin-left: auto; margin-right: auto; text-align: center; } + .header .search { margin: 10px 0px 28px 48px; width: 400px; } + .header .search, .header .button { margin: 10px 0px 28px 0px; } /* Search results - Header Navigation */ - .navigation-header { display: flex; margin: 0; padding: 0; align-items: baseline; } - .navigation-header a { margin: 0 auto; padding: 0; } + .navigation { margin: 0 auto 10px auto; padding: 0; align-items: baseline; } /* Misc */ .logo { position: relative; display: block;margin: 0 auto; float: none; padding: 10px; font-size: 1.75rem; } } -@media only screen and (max-width:640px) { /* portrait tablets, portrait iPad, landscape e-readers, landscape 800x480 or 854x480 phones */ +@media only screen and (max-width: 640px) { /* portrait tablets, portrait iPad, landscape e-readers, landscape 800x480 or 854x480 phones */ /* Page structure */ - .results-wrap { position: relative; display: flex; margin: 0 10px 10px 10px; } + .content { position: relative; margin: 0 10px; } + .footer-left, .footer-right { display: block; padding: 5px 5px 0 5px; text-align: center; } + .footer-right { float: none; padding: 0px 5px 5px 5px; } - /* Main page */ - .search-box-main { margin-top: 10%; } - .search-box-main input { width: 80%; } - .search-box-buttons button { display: table-row; margin: 30px 0px 0px 0px; width: 80%; } + /* Start page */ + .startpage-search { margin-top: 10%; } + .startpage-search .search { width: 80%; } + .search-buttons button { display: table-row; margin: 30px 0px 0px 0px; width: 80%; } /* Search Results - Header */ - .header-wrap { margin-left: auto; margin-right: auto; text-align: center; } - .header-wrap .search, .header-wrap .button { margin: 0px 0px 10px 0px; width: 80%; border-radius: 25px; } + .header { margin-left: auto; margin-right: auto; text-align: center; } + .header .search, .header .button { margin: 0px 0px 10px 0px; width: 80%; border-radius: 25px; } /* Search results - Header Navigation */ - .navigation-header { display: flex; margin: 0; padding: 0; align-items: baseline; } - .navigation-header a { margin: 0 auto; padding: 0; } + .navigation { margin: 0 auto 10px auto; padding: 0; align-items: baseline; } /* Misc */ .logo { position: relative; display: block; float: none; margin: 0 auto; padding: 10px; font-size: 1.75rem; } } -@media only screen and (max-width:480px) { /* portrait e-readers (Nook/Kindle), smaller tablets @ 600 or @ 640 wide. */ +@media only screen and (max-width: 480px) { /* portrait e-readers (Nook/Kindle), smaller tablets @ 600 or @ 640 wide. */ /* Page structure */ - .results-wrap { position: relative; display: flex; margin: 0 10px 10px 10px; } + .content { position: relative; margin: 0 10px; } + .footer-left, .footer-right { display: block; padding: 5px 5px 0 5px; text-align: center; } + .footer-right { float: none; padding: 0px 5px 5px 5px; } - /* Main page */ - .search-box-main { margin-top: 10%; } - .search-box-main input { width: 80%; } - .search-box-main h1 { font-size: 2.5rem; } - .search-box-buttons button { display: table-row; margin: 30px 0px 0px 0px; width: 80%; } + /* Start page */ + .startpage-search { margin-top: 10%; } + .startpage-search h1 { font-size: 2.5rem; } + .startpage-search .search { width: 80%; } + .search-buttons button { display: table-row; margin: 30px 0px 0px 0px; width: 80%; } /* Search Results - Header */ - .header-wrap { margin-left: auto; margin-right: auto; text-align: center; } - .header-wrap .search, .header-wrap .button { margin: 0px 0px 10px 0px; width: 80%; border-radius: 25px; } + .header { margin-left: auto; margin-right: auto; text-align: center; } + .header .search, .header .button { margin: 0px 0px 10px 0px; width: 80%; border-radius: 25px; } /* Search results - Header Navigation */ - .navigation-header { display: flex; margin: 0; padding: 0; align-items: baseline; } - .navigation-header a { margin: 0 auto; padding: 0; } - - /* Magnet highlights */ - .main-column .magnet-wrapper { display: none; } + .navigation { margin: 0 auto 10px auto; padding: 0; align-items: baseline; } /* Misc */ .logo { position: relative; display: block; float: none; margin: 0 auto; padding: 10px; font-size: 1.75rem; } } -@media only screen and (max-width:320px) { /* smartphones, iPhone, portrait 480x320 phones */ +@media only screen and (max-width: 320px) { /* smartphones, iPhone, portrait 480x320 phones, split screen devices */ /* Page structure */ - .results-wrap { position: relative; display: flex; margin: 0 10px 10px 10px; } + .content { position: relative; margin: 0 10px; } + .footer-left, .footer-right { display: block; padding: 5px 5px 0 5px; text-align: center; } + .footer-right { float: none; padding: 0px 5px 5px 5px; } - /* Main page */ - .search-box-main { margin-top: 40px; } - .search-box-main input { width: 80%; } - .search-box-main h1 { font-size: 2.5rem; } - .search-box-buttons button { display: table-row; margin: 20px 0px 0px 0px; width: 80%; } + /* Start page */ + .startpage-search { margin-top: 40px; } + .startpage-search h1 { font-size: 2.5rem; } + .startpage-search .search { width: 80%; } + .search-buttons button { display: table-row; margin: 20px 0px 0px 0px; width: 80%; } /* Search Results - Header */ - .header-wrap { margin-left: auto; margin-right: auto; text-align: center; } - .header-wrap .search, .header-wrap .button { margin: 0px 0px 10px 0px; width: 80%; border-radius: 25px; } + .header { margin-left: auto; margin-right: auto; text-align: center; } + .header .search, .header .button { margin: 0px 0px 10px 0px; width: 80%; border-radius: 25px; } /* Search results - Header Navigation */ - .navigation-header { display: flex; margin: 0; padding: 0; align-items: baseline; } - .navigation-header a { margin: 0 auto; padding: 0; } - - /* Magnet highlights */ - .main-column .magnet-wrapper { display: none; } + .navigation { margin: 0 auto 10px auto; padding: 0; align-items: baseline; } /* Misc */ .logo { position: relative; float: none; display: block; margin: 0 auto; padding: 10px; font-size: 1.75rem; } diff --git a/assets/images/goosle.webp b/assets/images/goosle.webp new file mode 100644 index 0000000..28aeef9 Binary files /dev/null and b/assets/images/goosle.webp differ diff --git a/config.default.php b/config.default.php index 2c1c920..ace119d 100644 --- a/config.default.php +++ b/config.default.php @@ -11,154 +11,106 @@ ------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------ +SITEURL: + Set the base domain name for your Goosle setup (ex. example.com, something.example.com, example.com/something/) so that internal links will work correctly. + HASH: - A simple lowercase passphrase (something simple like: j9fg-i2du-er6m or 1846) used for caching results. This helps to differentiate between instances on the same server. - You can also add it to your url/bookmark as a simple passphrase to keep unwanted users out. + A simple lowercase passphrase, something simple like: j9fg-i2du-er6m or 1846. + Used for caching results and optionally for accessing Goosle (See HASH_AUTH option). -HASH AUTH: +HASH_AUTH: Use the above hash as a simple passphrase. - Using it as a passphrase lets you host Goosle on a public server without providing a public service. + Using it as a passphrase lets you host Goosle on a public facing server without providing a public service. + This is useful for if just you and some friends or family should be able to use Goosle from anywhere. + + "off" Don't use the hash as a password. + "on" Use the hash as a password. Usage: https://example.com/?a=1234567890 - Disclaimer: This is not meant to 'hack proof' or truly secure the setup. Just a simple token to keep surface level prying eyes out. - -CACHE: - It is highly recommended to enable caching as it'll speed up repeat searches by a lot. + Disclaimer: This is not meant to 'hack proof' or truly secure the setup. Just a simple token to keep surface level prying eyes out. CACHE_TYPE: - Choose how to cache results. The cache is NOT unique per user but shared between all users. Different users searching for the exact same thing get the same results. - Default caching method is APCu. Alternatively, you can store the results in text files in the /cache/ folder. - Ignored if above 'cache' option is set to off. - "apcu" (Recommended) faster, utilize memory. - "file" Store results in text files. + It is highly recommended to enable caching as it will speed up repeat searches by a lot. + The cache is NOT unique per user but shared between all users. Different users searching for the exact same thing get the same results. + + Caching can be done in memory with APCu or as temporary files in the /cache/ folder. + + "off" No caching. + "file" Store results in text files (Default). + "apcu" Faster, utilizes memory. CACHE_TIME: Minutes the result should be cached. Accepts a numeric value between 1 and 720. - APCu stores in memory, using a longer time takes up more of it. It is recommended to not exceed 30 minutes for it. + APCu stores in memory, using a longer time takes up more of it. It is recommended to not exceed 30 minutes for APCu. The file cache is only limited by your hosting storage space and can safely be much much longer if you want. To not show outdated results the 'limit' is 720 minutes, which equals 12 hours. - Ignored if above 'cache' option is set to off. - - - -ENABLE IMAGE SEARCH: - Enable or disable image searches - Search results are provided by Yahoo! Images. - -ENABLE MAGNET SEARCH: - Enable or disable searching for magnet links on torrent websites. - -ENABLE SEARCH ENGINES: - Enable or disable search engines. - -ENABLE MAGNET CRAWLERS: - Enable or disable crawlers to pull magnet links from. - - - + Ignored if above 'CACHE_TYPE' option is set to off. +/* ------------------------------------------------------------------------------------ LANGUAGE: - DuckDuckGo, Google and Ecosia are language agnostic. But they DO profile you for your locale. - For example: Me searching with english terms has me seeing Spanish results because I live in Mexico. This setting should minimize that for supported engines. - - DuckDuckGo uses language regions as opposed to a simpler language choice. See if your region is available - https://duckduckgo.com/duckduckgo-help-pages/settings/params/. - Google's language option breaks reasonable results and other options like verbatim mode and some other settings. So you'll have to rely on Google picking up on the query language. + DuckDuckGo and Google are mostly language agnostic. + + To not fit the USA mold, Goosle defaults to the United Kingdom for english results. + + Google has no language setting because as soon as you specify it all 'anonymous' settings stop working. + DuckDuckGo uses language regions and defaults to the United Kingdom. To change it see if your region is available - https://duckduckgo.com/duckduckgo-help-pages/settings/params/. Wikipedia needs to be told which language you want. This changes the search url. Use any of their supported languages (en, es, fr, nl, etc.) + Qwant uses a locale similar to DuckDuckGo. Available locales are: bg_bg, br_fr, ca_ad, ca_es, ca_fr, co_fr, cs_cz, cy_gb, da_dk, de_at, de_ch, de_de, ec_ca, el_gr, en_au, en_ca, en_gb, en_ie, en_my, en_nz, en_us, es_ad, es_ar, es_cl, es_co, es_es, es_mx, es_pe, et_ee, eu_es, eu_fr, fc_ca, fi_fi, fr_ad, fr_be, fr_ca, fr_ch, fr_fr, gd_gb, he_il, hu_hu, it_ch, it_it, ko_kr, nb_no, nl_be, nl_nl, pl_pl, pt_ad, pt_pt, ro_ro, sv_se, th_th, zh_cn, zh_hk. SOCIAL MEDIA RELEVANCE: Show social media results lower in the combined results if you don't value such results. - Downranked results include: Facebook, Instagram, Twitter, Snapchat, TikTok, LinkedIn and Reddit. - !!CAREFUL!! This is a blanket setting, if what you're searching for primarily has social media links then less relevant results may show first. - Accepts a numeric value between 1 and 10. With 10 having *NO* effect on the rank, and 0 not ranking the link at all (shows very very low in the results) - -SHOW SEARCH SOURCE: - Show which search engine(s) came up with the result. - -SHOW SEARCH RANK: - When search source is enabled, show the rank Goosle gave the result. - -IMDB ID SEARCH: - Highlight imdb results if it's a tv-show or movie. - Handy for finding better results for specific tv-shows through EZTV and The Pirate Bay. - -PASSWORD GENERATOR - Show a password generator on the Goosle home page. - - - -SPECIAL: - Enable or disable special searches that show up before search results. - - - -SHOW ZERO SEEDERS: - Set to "on" to include results with 0 seeders (slow or stale downloads). Off to exclude these results. - -YTS HIGHLIGHT: - If you've enabled the YTS special search, you can also choose what it should show. The 8 most [insert choice] movies. - "date_added" = Newest movies (Default). - "rating" = Highest rated movies as per imdb. - "download_count" = Most downloaded movies. - -BLOCK 1337x CATEGORIES: - Add category IDs of 1337x categories, check /engines/magnet/1337x.php for a list of known categories. - Accepts a basic numeric array, comma separated. - -BLOCK PIRATEBAY CATEGORIES: - Add category IDs of Pirate Bay categories, check /engines/magnet/thepiratebay.php for a list of known categories. - Accepts a basic numeric array, comma separated. - -BLOCK YTS CATEGORIES: - Add category names as keywords, eg; "thriller", "war". - Movies can be in multiple categories, if a movie is in 5 categories it only has to match one to be filtered out. - Accepts a basic array of keywords, comma separated. - - - + Downranked results include websites like Facebook, Instagram, Twitter, Snapchat, TikTok, LinkedIn and Reddit. + !! CAREFUL !! This is a blanket setting, if what (or who) you're searching for primarily has social media links then less relevant results may show first. + Accepts a numeric value between 1 and 10. With 10 having *NO* effect on the rank, and 0 not ranking the link at all (shows very very low in the results). +/* ------------------------------------------------------------------------------------ USER AGENTS: - Add more or less user agents to the list. Keep at least one! + Add more or less user agents to the list but keep at least one! On every search Goosle picks one at random to identify as. Keep them generic to prevent profiling, but also so that the request comes off as a generic boring browser and not as a server/crawler. - Safari, Firefox and Internet Explorer/Edge should be safe to use. + Safari, Firefox and Internet Explorer (Yes that's old!) should be safe to use. Chrome may attract attention because of the lack of Chrome information (tracking) aside from the user agent. The search engine may know something is 'weird'. Opera/Edge/Brave and many others use Chrome under the hood and are not a good pick for that reason. - Mobile agents may work, but some services like Wikipedia are a bit picky when it comes to answering API calls. Mobile users generally do not use APIs, so they may block your search. + Mobile user agents may work, but some services like Wikipedia are a bit picky when it comes to answering API calls. + Mobile users generally do not use APIs, so they may block your search or show a trimmed version of results. MAGNET TRACKERS: - Only used for The Pirate Bay, LimeTorrents and YTS. + These are added to the magnet links Goosle creates by itself. Generally you do not need to change these. - These are added to the magnet links Goosle creates. You can add more or replace the existing ones if you know what you're doing. - Accepts a basic array of strings (tracker urls), comma separated. + Currently only The Pirate Bay, LimeTorrents and YTS use generated magnet links. + + You can add more or replace the existing ones if you know what you're doing. But keep at least one, preferably 3-5+. ------------------------------------------------------------------------------------ */ return (object) array( - "hash" => "j9fg-i2du-er6m", + // ALL OPTIONS ARE REQUIRED, EVEN IF YOU DO NOT USE THE FEATURE. EMPTY VALUES OR MISSING SETTINGS CAUSE ISSUES!!! + "siteurl" => "example.com", // Make sure this is accurate + "hash" => "j9fg-i2du-er6m", // Some kind of alphanumeric password-like string, used for caching and optionally for access to Goosle "hash_auth" => "off", // Default: off - "cache" => "off", // Default: off - "cache_type" => "apcu", // Default: apcu + "cache_type" => "file", // Default: file "cache_time" => 30, // Default: 30 (Minutes) - "enable_image_search" => "on", // Default: on - "enable_magnet_search" => "on", // Default: on "enable_duckduckgo" => "on", // Default: on "enable_google" => "on", // Default: on - "enable_reddit" => "on", // Default: on + "enable_qwantnews" => "on", // Default: on "enable_wikipedia" => "on", // Default: on - "enable_ecosia" => "off", // Default: on - // Site uses some kind of bot detector preventing crawler from working reliably since Feb 1, 2024, remove support in future release?) + "enable_image_search" => "on", // Default: on (Disables all image search regardless of settings for individual engines) + "enable_yahooimages" => "on", // Default: on + "enable_openverse" => "off", // Default: off (Requires API token, see readme for details) + "enable_qwant" => "on", // Default: on + + "enable_magnet_search" => "on", // Default: on (Disables all image search regardless of settings for individual engines) + "enable_eztv" => "on", // Default: on "enable_limetorrents" => "on", // Default: on + "enable_nyaa" => "on", // Default: on "enable_piratebay" => "on", // Default: on "enable_yts" => "on", // Default: on - "enable_magnetdl" => "on", // Default: on - "enable_nyaa" => "on", // Default: on - "enable_eztv" => "on", // Default: on - "enable_l33tx" => "off", // Default: off - // Site now uses cloudflare preventing crawler from working since Jan 20, 2024, remove support in future release?) "duckduckgo_language" => "uk-en", // Default: uk-en (United Kingdom) "wikipedia_language" => "en", // Default: en (English) + "qwant_language" => "en_gb", // Default: en_gb (United Kingdom) + "social_media_relevance" => 8, // Default: 8 - "show_reddit_nsfw" => "on", // Default: on "show_search_source" => "on", // Default: on "show_search_rank" => "off", // Default: off "imdb_id_search" => "off", // Default: off @@ -174,11 +126,15 @@ "show_zero_seeders" => "on", // Default: on "yts_highlight" => "date_added", // Default: "date_added" - "leetx_categories_blocked" => array(3, 7, 47), // Default: 3, 7, 47 "piratebay_categories_blocked" => array(206, 210), // Default: 206, 210 "yts_categories_blocked" => array("horror"), // Default: "horror" "user_agents" => array( + "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1", // Linux, Lynx browser 2.8.5 + "Lynx/2.8.9rel.1 libwww-FM/2.14 SSL-MM/1.4.1", // Linux, Lynx browser 2.8.9 + "Lynx/2.8.6rel.4 libwww-FM/2.14 SSL-MM/1.4.1", // Linux, Lynx browser 2.8.6 + "TinyBrowser/2.0 (TinyBrowser Comment; rv:1.9.1a2pre) Gecko/20201231", // Linux, Tinybrowser 2 + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) DuckDuckGo/7 Safari/605.1.15", // macOS 10.15, DuckDuckGo 7 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15) Gecko/20100101 Firefox/119.0", // macOS 10.15, Firefox 119 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/116.0", // Windows 10, Firefox 116 "Mozilla/5.0 (X11; Ubuntu; Linux x86_64) Gecko/20100101 Firefox/83.0", // Linux Ubuntu, Firefox 83 @@ -187,11 +143,26 @@ "magnet_trackers" => array( "http://nyaa.tracker.wf:7777/announce", - "http://tracker.openbittorrent.com:80/announce", - "udp://tracker.opentrackr.org:1337/announce", - "udp://exodus.desync.com:6969/announce", + "udp://tracker.opentrackr.org:1337/announce", + "udp://exodus.desync.com:6969/announce", "udp://tracker.torrent.eu.org:451/announce", "udp://opentracker.i2p.rocks:6969/announce", + "udp://open.demonii.com:1337/announce", + "udp://open.stealth.si:80/announce", + "udp://tracker.moeking.me:6969/announce", + "udp://explodie.org:6969/announce", + "udp://tracker1.bt.moack.co.kr:80/announce", + "udp://tracker.theoks.net:6969/announce", + "udp://tracker-udp.gbitt.info:80/announce", + "https://tracker.tamersunion.org:443/announce", + "https://tracker.gbitt.info:443/announce", + "udp://tracker.tiny-vps.com:6969/announce", + "udp://tracker.dump.cl:6969/announce", + "udp://tamas3.ynh.fr:6969/announce", + "udp://retracker01-msk-virt.corbina.net:80/announce", + "udp://open.free-tracker.ga:6969/announce", + "udp://epider.me:6969/announce", + "udp://bt2.archive.org:6969/announce", ) ); -?> +?> \ No newline at end of file diff --git a/engines/image/openverse.php b/engines/image/openverse.php new file mode 100644 index 0000000..6f5eb2f --- /dev/null +++ b/engines/image/openverse.php @@ -0,0 +1,111 @@ +query, 0, 200); + + // Safe search override + $safe = "0"; // No mature results + if(strpos($query_terms[0], "safe") !== false) { + $switch = explode(":", $query_terms[0]); + + if(!is_numeric($switch[1])) { + $safe = (strtolower($switch[1]) == "off") ? "1" : "0"; + $this->query = implode(" ", array_slice($query_terms, 1)); + } + } + + // q = query + // format = json + // mature = 1 / 0 + // page_size = 80 (int) + + $args = array("q" => $query_terms, "format" => "json", "mature" => $safe, "page_size" => 50); + $url = "https://api.openverse.org/v1/images/?".http_build_query($args); + + unset($query_terms, $switch, $safe, $max_results, $args); + + return $url; + } + + public function get_request_headers() { + $token_file = ABSPATH.'cache/token.data'; + $token = unserialize(file_get_contents($token_file)); + + return array( + 'Accept' => 'application/json, */*;q=0.8', + 'Content-type' => 'application/x-www-form-urlencoded', + 'Authorization' => 'Bearer '.$token['openverse']['access_token'], + 'Accept-Language' => null, + 'Accept-Encoding' => null, + 'Connection' => null, + 'Sec-Fetch-Dest' => null, + 'Sec-Fetch-Mode' => null, + 'Sec-Fetch-Site' => null + ); + } + + public function parse_results($response) { + $results = array(); + $json_response = json_decode($response, true); + + // No response + if(empty($json_response)) return $results; + + // Set base rank and result amound + $rank = $results['amount'] = count($json_response['results']); + + // Nothing found + if($results['amount'] == 0) return $results; + + // Use API result + foreach ($json_response['results'] as $result) { + // Deal with optional or missing data + $dimensions_w = (!empty($result['width'])) ? sanitize($result['width']) : ""; + $dimensions_h = (!empty($result['height'])) ? sanitize($result['height']) : ""; + $filesize = (!empty($result['filesize'])) ? sanitize($result['filesize']) : ""; + $link = (!empty($result['url'])) ? sanitize($result['url']) : ""; + + $image_full = (!empty($result['foreign_landing_url'])) ? sanitize($result['foreign_landing_url']) : ""; + $image_thumb = (!empty($result['thumbnail'])) ? sanitize($result['thumbnail']) : $image_full; + $alt = (!empty($result['title'])) ? sanitize($result['title']) : ""; + + // Add attribution to alt text? + $creator = (!empty($result['creator'])) ? " by ".sanitize($result['creator']) : ""; + $alt = (!empty($creator)) ? $alt.$creator : $alt; + + // Process result + $filesize = intval(preg_replace('/[^0-9]/', '', $filesize)); + + // filter duplicate IMAGE urls/results + if(!empty($results['search'])) { + if(in_array($image_full, array_column($results['search'], "image_full"))) continue; + } + + $results['search'][] = array ("id" => uniqid(rand(0, 9999)), "source" => "Openverse", "image_thumb" => $image_thumb, "alt" => $alt, "image_full" => $image_full, "width" => $dimensions_w, "height" => $dimensions_h, "filesize" => $filesize, "webpage_url" => $link, "engine_rank" => $rank); + $rank -= 1; + unset($url_data, $usable_data, $dimensions_w, $dimensions_h, $filesize, $link, $image_full, $alt, $image_thumb); + } + unset($json_response, $rank); + + // Add error if there are no search results + if(empty($results['search'])) { + $results['error'] = array( + "message" => "No results found. Please try with less or different keywords!" + ); + } + + return $results; + } +} +?> diff --git a/engines/image/qwant.php b/engines/image/qwant.php new file mode 100644 index 0000000..01c730e --- /dev/null +++ b/engines/image/qwant.php @@ -0,0 +1,106 @@ +query)); + + // Safe search override + $safe = "1"; // Moderate results + if(strpos($query_terms[0], "safe") !== false) { + $switch = explode(":", $query_terms[0]); + + if(!is_numeric($switch[1])) { + $safe = (strtolower($switch[1]) == "off") ? "0" : "2"; + $this->query = implode(" ", array_slice($query_terms, 1)); + } + } + + $language = (strlen($this->opts->qwant_language) > 0 && strlen($this->opts->qwant_language < 6)) ? $this->opts->qwant_language : "en_gb"; + + // q = query + // t = Type of search, Images + // count = Up-to how many images to return (Max 50) + // locale = In which language should the search be done + // device = What kind of device are we searching from? + // safesearch = Safe search filter (0 = off, 1 = normal, 2 = strict) + + $args = array("q" => $this->query, "t" => 'images', 'count' => 50, 'locale' => $language, 'device' => 'desktop', 'safesearch' => $safe); + $url = "https://api.qwant.com/v3/search/images?".http_build_query($args); + + unset($query_terms, $switch, $safe, $language, $args); + + return $url; + } + + public function get_request_headers() { + return array( + 'Accept' => 'application/json, */*;q=0.8', + 'Accept-Language' => null, + 'Accept-Encoding' => null, + 'Connection' => null, + 'Sec-Fetch-Dest' => null, + 'Sec-Fetch-Mode' => null, + 'Sec-Fetch-Site' => null + ); + } + + public function parse_results($response) { + $results = array(); + $json_response = json_decode($response, true); + + // No response + if(empty($json_response)) return $results; + + // Nothing found + if($json_response["status"] != "success") return $results; + + // Set base rank and result amound + $rank = $results['amount'] = $json_response["data"]["result"]["total"]; + + // Use API result + foreach ($json_response["data"]["result"]["items"] as $result) { + // Deal with optional or missing data + $dimensions_w = (!empty($result['width'])) ? sanitize($result['width']) : ""; + $dimensions_h = (!empty($result['height'])) ? sanitize($result['height']) : ""; + $filesize = (!empty($result['size'])) ? sanitize($result['size']) : ""; + $link = (!empty($result['url'])) ? sanitize($result['url']) : ""; + + $image_full = (!empty($result['media'])) ? sanitize($result['media']) : ""; + $image_thumb = (!empty($result['thumbnail'])) ? sanitize($result['thumbnail']) : $image_full; + $alt = (!empty($result['title'])) ? sanitize($result['title']) : ""; + + // Process result + $filesize = intval(preg_replace('/[^0-9]/', '', $filesize)); + + // filter duplicate IMAGE urls/results + if(!empty($results['search'])) { + if(in_array($image_full, array_column($results['search'], "image_full"))) continue; + } + + $results['search'][] = array ("id" => uniqid(rand(0, 9999)), "source" => "Qwant", "image_thumb" => $image_thumb, "alt" => $alt, "image_full" => $image_full, "width" => $dimensions_w, "height" => $dimensions_h, "filesize" => $filesize, "webpage_url" => $link, "engine_rank" => $rank); + $rank -= 1; + unset($url_data, $usable_data, $dimensions_w, $dimensions_h, $filesize, $link, $image_full, $alt, $image_thumb); + } + unset($json_response, $rank); + + // Add error if there are no search results + if(empty($results['search'])) { + $results['error'] = array( + "message" => "No results found. Please try with less or different keywords!" + ); + } + + return $results; + } +} +?> \ No newline at end of file diff --git a/engines/image/yahoo.php b/engines/image/yahoo.php index 64a43b8..3628fd9 100644 --- a/engines/image/yahoo.php +++ b/engines/image/yahoo.php @@ -38,11 +38,17 @@ public function get_request_url() { $args = array("p" => $this->query, "imgsz" => $size); $url = "https://images.search.yahoo.com/search/images?".http_build_query($args); - unset($query_terms, $switch, $args, $size); + unset($query_terms, $switch, $size, $args); return $url; } + public function get_request_headers() { + return array( + 'Accept' => 'text/html, application/xhtml+xml, application/xml;q=0.8, */*;q=0.7', + ); + } + public function parse_results($response) { $results = array(); $xpath = get_xpath($response); @@ -62,15 +68,19 @@ public function parse_results($response) { // Scrape the results // $scrape = $xpath->query("//li[contains(@class, 'ld') and not(contains(@class, 'slotting'))][position() < 101]"); $scrape = $xpath->query("//li[contains(@class, 'ld') and not(contains(@class, 'ignore'))][position() < 101]"); + + // Set base rank and result amound $rank = $results['amount'] = count($scrape); + // Nothing found + if($results['amount'] == 0) return $results; foreach($scrape as $result) { - $image = $xpath->evaluate(".//img/@src", $result)[0]; - if($image == null) continue; + $image_thumb = $xpath->evaluate(".//img/@src", $result)[0]; + if(is_null($image_thumb)) continue; $url_data = $xpath->evaluate(".//a/@href", $result)[0]; - if($url_data == null) continue; + if(is_null($url_data)) continue; // Get and prepare meta data // -- Relevant $url_data (there is more, but unused by Goosle) @@ -92,27 +102,25 @@ public function parse_results($response) { } // Deal with optional or missing data - $dimensions_w = (!array_key_exists('w', $usable_data)) ? "" : htmlspecialchars($usable_data['w']); - $dimensions_h = (!array_key_exists('h', $usable_data)) ? "" : htmlspecialchars($usable_data['h']); - $link = (!array_key_exists('imgurl', $usable_data)) ? "" : "//".htmlspecialchars($usable_data['imgurl']); - $url = (!array_key_exists('rurl', $usable_data)) ? "" : htmlspecialchars($usable_data['rurl']); - $filesize = (!array_key_exists('size', $usable_data)) ? "" : htmlspecialchars($usable_data['size']); - $alt = (!array_key_exists('tt', $usable_data)) ? "" : htmlspecialchars($usable_data['tt']); + $dimensions_w = (!array_key_exists('w', $usable_data)) ? "" : sanitize($usable_data['w']); + $dimensions_h = (!array_key_exists('h', $usable_data)) ? "" : sanitize($usable_data['h']); + $image_full = (!array_key_exists('imgurl', $usable_data)) ? "" : "//".sanitize($usable_data['imgurl']); + $link = (!array_key_exists('rurl', $usable_data)) ? "" : sanitize($usable_data['rurl']); + $filesize = (!array_key_exists('size', $usable_data)) ? "" : sanitize($usable_data['size']); + $alt = (!array_key_exists('tt', $usable_data)) ? "" : sanitize($usable_data['tt']); // Process result - $image = htmlspecialchars($image->textContent); + $image_thumb = sanitize($image_thumb->textContent); + $filesize = intval(preg_replace('/[^0-9.]/', '', $filesize) * 1000); - // filter duplicate urls/results + // filter duplicate IMAGE urls/results if(!empty($results['search'])) { - $result_urls = array_column($results['search'], "direct_link"); - if(in_array($link, $result_urls)) continue; + if(in_array($image_full, array_column($results['search'], "image_full"))) continue; } - $id = uniqid(rand(0, 9999)); - - $results['search'][] = array ("id" => $id, "source" => "Yahoo! Images", "image" => $image, "alt" => $alt, "url" => $url, "width" => $dimensions_w, "height" => $dimensions_h, "filesize" => $filesize, "direct_link" => $link, "engine_rank" => $rank); + $results['search'][] = array ("id" => uniqid(rand(0, 9999)), "source" => "Yahoo! Images", "image_thumb" => $image_thumb, "alt" => $alt, "image_full" => $image_full, "width" => $dimensions_w, "height" => $dimensions_h, "filesize" => $filesize, "webpage_url" => $link, "engine_rank" => $rank); $rank -= 1; - unset($url_data, $usable_data, $dimensions_w, $dimensions_h, $filesize, $link, $url, $alt, $image); + unset($url_data, $usable_data, $dimensions_w, $dimensions_h, $filesize, $link, $image_full, $alt, $image_thumb); } unset($response, $xpath, $scrape, $rank); diff --git a/engines/magnet/1337x.php b/engines/magnet/1337x.php deleted file mode 100644 index 1eebc8b..0000000 --- a/engines/magnet/1337x.php +++ /dev/null @@ -1,147 +0,0 @@ -query)."/1/"; - - return $url; - - } - - public function parse_results($response) { - $results = array(); - $xpath = get_xpath($response); - - // Failed to load page - if(!$xpath) return $results; - - $categories = array( - 1 => "DVD", - 2 => "Divx/Xvid", - 3 => "SVCD/VCD", - 4 => "Dubs/Dual Audio", - 5 => "DVD", - 6 => "Divx/Xvid", - 7 => "SVCD/VCD", - 9 => "Documentary", - - 10 => "PC Game", - 11 => "PS2", - 12 => "PSP", - 13 => "Xbox", - 14 => "Xbox360", - 15 => "PS1", - 16 => "Dreamcast", - 17 => "Other (Gaming)", - 18 => "PC Software", - 19 => "Mac Software", - - 20 => "Linux Software", - 21 => "Other (Software)", - 22 => "MP3", - 23 => "Lossless Audio", - 24 => "DVD (Music)", - 25 => "Music Video", - 26 => "Radio", - 27 => "Other (Audio)", - 28 => "Anime", - - 33 => "Emulation", - 34 => "Tutorials", - 35 => "Sounds", - 36 => "E-Books", - 37 => "Images", - 38 => "Mobile Phone", - 39 => "Comics", - - 40 => "Other", - 41 => "HD (Video)", - 42 => "HD (Video)", - 43 => "PS3", - 44 => "Wii", - 45 => "DS", - 46 => "GameCube", - 47 => "Nulled Script", - 48 => "Video", - 49 => "Picture", - - 50 => "Magazine", - 51 => "Hentai", - 52 => "Audiobook", - 53 => "Album (Music)", - 54 => "h.264/x264", - 55 => "Mp4", - 56 => "Android", - 57 => "iOS", - 58 => "Box Set (Music)", - 59 => "Discography", - - 60 => "Single (Music)", - 66 => "3D", - 67 => "Games", - 68 => "Concerts", - 69 => "AAC (Music)", - - 70 => "HEVC/x265", - 71 => "HEVC/x265", - 72 => "3DS", - 73 => "Bollywood", - 74 => "Cartoon", - 75 => "SD (Video)", - 76 => "UHD", - 77 => "PS4", - 78 => "Dual Audio (Video)", - 79 => "Dubbed (Video)", - - 80 => "Subbed", - 81 => "Raw", - 82 => "Switch", - ); - - // Scrape the page - foreach($xpath->query("//table/tbody/tr") as $result) { - $name = sanitize($xpath->evaluate(".//td[@class='coll-1 name']/a", $result)[1]->textContent); - $url = "https://1337x.to".sanitize($xpath->evaluate(".//td[@class='coll-1 name']/a/@href", $result)[1]->textContent); - $magnet = "./engines/magnet/magnetize_1337x.php?url=".$url; - $seeders = sanitize($xpath->evaluate(".//td[@class='coll-2 seeds']", $result)[0]->textContent); - $leechers = sanitize($xpath->evaluate(".//td[@class='coll-3 leeches']", $result)[0]->textContent); - $size_unformatted = explode(" ", sanitize($xpath->evaluate(".//td[contains(@class, 'coll-4 size')]", $result)[0]->textContent)); - $size = $size_unformatted[0] . " " . preg_replace("/[0-9]+/", "", $size_unformatted[1]); - - // Ignore results with 0 seeders? - if($this->opts->show_zero_seeders == "off" AND $seeders == 0) continue; - - // Get extra data - $category = explode("/", sanitize($xpath->evaluate(".//td[@class='coll-1 name']/a/@href", $result)[0]->textContent)); - $category = $category[2]; - - // Block these categories - if(in_array($category, $this->opts->leetx_categories_blocked)) continue; - - // Filter episodes - if(!is_season_or_episode($this->query, $name)) continue; - - $id = uniqid(rand(0, 9999)); - - $results[] = array ( - // Required - "id" => $id, "source" => "1337x.to", "name" => $name, "magnet" => $magnet, "hash" => null, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, - // Extra - "category" => $categories[$category], "url" => $url - ); - } - unset($response, $xpath); - - return $results; - } -} -?> \ No newline at end of file diff --git a/engines/magnet/eztv.php b/engines/magnet/eztv.php index 8ffe588..3546d79 100644 --- a/engines/magnet/eztv.php +++ b/engines/magnet/eztv.php @@ -23,6 +23,18 @@ public function get_request_url() { return $url; } + public function get_request_headers() { + return array( + 'Accept' => 'application/json, */*;q=0.8', + 'Accept-Language' => null, + 'Accept-Encoding' => null, + 'Connection' => null, + 'Sec-Fetch-Dest' => null, + 'Sec-Fetch-Mode' => null, + 'Sec-Fetch-Site' => null + ); + } + public function parse_results($response) { $results = array(); $json_response = json_decode($response, true); @@ -61,11 +73,9 @@ public function parse_results($response) { } } - $id = uniqid(rand(0, 9999)); - $results[] = array ( // Required - "id" => $id, "source" => "EZTV", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => human_filesize($size), + "id" => uniqid(rand(0, 9999)), "source" => "EZTV", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => human_filesize($size), // Extra "quality" => $quality, "codec" => $codec, "date_added" => $date_added ); diff --git a/engines/magnet/lime.php b/engines/magnet/lime.php index 9ff49c6..73d636c 100644 --- a/engines/magnet/lime.php +++ b/engines/magnet/lime.php @@ -17,6 +17,12 @@ public function get_request_url() { return $url; } + public function get_request_headers() { + return array( + 'Accept' => 'text/html, application/xhtml+xml, application/xml;q=0.8, */*;q=0.7', + ); + } + public function parse_results($response) { $results = array(); $xpath = get_xpath($response); @@ -46,11 +52,9 @@ public function parse_results($response) { // Filter episodes if(!is_season_or_episode($this->query, $name)) continue; - $id = uniqid(rand(0, 9999)); - $results[] = array ( // Required - "id" => $id, "source" => "limetorrents.lol", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, + "id" => uniqid(rand(0, 9999)), "source" => "limetorrents.lol", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, // Extra "category" => $category, "url" => $url ); diff --git a/engines/magnet/magnetdl.php b/engines/magnet/magnetdl.php deleted file mode 100644 index 18da7d2..0000000 --- a/engines/magnet/magnetdl.php +++ /dev/null @@ -1,64 +0,0 @@ -query, 0, 1)."/".str_replace(' ', '-', $this->query); - - return $url; - } - - public function parse_results($response) { - $results = array(); - $xpath = get_xpath($response); - - // Failed to load page - if(!$xpath) return $results; - - // Scrape the page - foreach($xpath->query("//table[@class='download']/tbody/tr") as $result) { - // Skip page navigation and incompatible rows - if(is_null($xpath->evaluate(".//td[2]", $result)[0])) continue; - - $name = sanitize($xpath->evaluate(".//td[2]/a/@title", $result)[0]->textContent); - $magnet = sanitize($xpath->evaluate(".//td[1]/a/@href", $result)[0]->textContent); - $hash = parse_url($magnet, PHP_URL_QUERY); - parse_str($hash, $hash_parameters); - $hash = strtolower(str_replace("urn:btih:", "", $hash_parameters['xt'])); - $seeders = sanitize($xpath->evaluate(".//td[7]", $result)[0]->textContent); - $leechers = sanitize($xpath->evaluate(".//td[8]", $result)[0]->textContent); - $size = sanitize($xpath->evaluate(".//td[6]", $result)[0]->textContent); - - // Ignore results with 0 seeders? - if($this->opts->show_zero_seeders == "off" AND $seeders == 0) continue; - - // Get extra data - $category = sanitize($xpath->evaluate(".//td[4]", $result)[0]->textContent); - $url = "https://www.magnetdl.com".sanitize($xpath->evaluate(".//td[2]//a/@href", $result)[0]->textContent); - - // Filter episodes - if(!is_season_or_episode($this->query, $name)) continue; - - $id = uniqid(rand(0, 9999)); - - $results[] = array ( - // Required - "id" => $id, "source" => "magnetdl.com", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, - // Extra - "category" => $category, "url" => $url - ); - } - unset($response, $xpath); - - return $results; - } -} -?> diff --git a/engines/magnet/magnetize_1337x.php b/engines/magnet/magnetize_1337x.php deleted file mode 100644 index 89a5a6e..0000000 --- a/engines/magnet/magnetize_1337x.php +++ /dev/null @@ -1,29 +0,0 @@ -user_agents); -$response = curl_exec($ch); -curl_close($ch); - -$xpath = get_xpath($response); - -// No results -if(!$xpath) die(); - -$magnet = trim($xpath->query("//main/div/div/div/div/div/ul/li/a/@href")[0]->textContent); - -header("Location: $magnet") -?> diff --git a/engines/magnet/nyaa.php b/engines/magnet/nyaa.php index dc1fd05..b2ff269 100644 --- a/engines/magnet/nyaa.php +++ b/engines/magnet/nyaa.php @@ -19,6 +19,12 @@ public function get_request_url() { return $url; } + public function get_request_headers() { + return array( + 'Accept' => 'text/html, application/xhtml+xml, application/xml;q=0.8, */*;q=0.7', + ); + } + public function parse_results($response) { $results = array(); $xpath = get_xpath($response); @@ -53,11 +59,9 @@ public function parse_results($response) { // Filter episodes if(!is_season_or_episode($this->query, $name)) continue; - $id = uniqid(rand(0, 9999)); - $results[] = array ( // Required - "id" => $id, "source" => "nyaa.si", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, + "id" => uniqid(rand(0, 9999)), "source" => "nyaa.si", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, // Extra "category" => $category, "url" => $url, "date_added" => $date_added ); diff --git a/engines/magnet/thepiratebay.php b/engines/magnet/thepiratebay.php index f064bb6..caff731 100644 --- a/engines/magnet/thepiratebay.php +++ b/engines/magnet/thepiratebay.php @@ -19,6 +19,18 @@ public function get_request_url() { return $url; } + public function get_request_headers() { + return array( + 'Accept' => 'application/json, */*;q=0.8', + 'Accept-Language' => null, + 'Accept-Encoding' => null, + 'Connection' => null, + 'Sec-Fetch-Dest' => null, + 'Sec-Fetch-Mode' => null, + 'Sec-Fetch-Site' => null + ); + } + public function parse_results($response) { $results = array(); $json_response = json_decode($response, true); @@ -89,24 +101,24 @@ public function parse_results($response) { ); // Use API result - foreach($json_response as $response) { + foreach($json_response as $result) { // Nothing found - if($response['name'] == "No results returned") break; + if($result['name'] == "No results returned") break; - $name = sanitize($response['name']); - $hash = strtolower(sanitize($response['info_hash'])); + $name = sanitize($result['name']); + $hash = strtolower(sanitize($result['info_hash'])); $magnet = "magnet:?xt=urn:btih:".$hash."&dn=".urlencode($name)."&tr=".implode("&tr=", $this->opts->magnet_trackers); - $seeders = sanitize($response['seeders']); - $leechers = sanitize($response['leechers']); - $size = sanitize($response['size']); + $seeders = sanitize($result['seeders']); + $leechers = sanitize($result['leechers']); + $size = sanitize($result['size']); // Ignore results with 0 seeders? if($this->opts->show_zero_seeders == "off" AND $seeders == 0) continue; // Get extra data - $category = sanitize($response['category']); - $url = "https://thepiratebay.org/description.php?id=".sanitize($response['id']); - $date_added = sanitize($response['added']); + $category = sanitize($result['category']); + $url = "https://thepiratebay.org/description.php?id=".sanitize($result['id']); + $date_added = sanitize($result['added']); // Block these categories if(in_array($category, $this->opts->piratebay_categories_blocked)) continue; @@ -114,11 +126,9 @@ public function parse_results($response) { // Filter episodes if(!is_season_or_episode($this->query, $name)) continue; - $id = uniqid(rand(0, 9999)); - $results[] = array( // Required - "id" => $id, "source" => "thepiratebay.org", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => human_filesize($size), + "id" => uniqid(rand(0, 9999)), "source" => "thepiratebay.org", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => human_filesize($size), // Extra "category" => $categories[$category], "url" => $url, "date_added" => $date_added, ); diff --git a/engines/magnet/yts.php b/engines/magnet/yts.php index 39adb3d..9657d61 100644 --- a/engines/magnet/yts.php +++ b/engines/magnet/yts.php @@ -16,9 +16,21 @@ public function get_request_url() { return $url; } + public function get_request_headers() { + return array( + 'Accept' => 'application/json, */*;q=0.8', + 'Accept-Language' => null, + 'Accept-Encoding' => null, + 'Connection' => null, + 'Sec-Fetch-Dest' => null, + 'Sec-Fetch-Mode' => null, + 'Sec-Fetch-Site' => null + ); + } + public function parse_results($response) { $results = array(); - $response = curl_multi_getcontent($this->ch); +// $response = curl_multi_getcontent($this->ch); $json_response = json_decode($response, true); // No response @@ -60,11 +72,10 @@ public function parse_results($response) { // Get extra data $quality = sanitize($download['quality']); $codec = sanitize($download['video_codec']); - $id = uniqid(rand(0, 9999)); $results[] = array ( // Required - "id" => $id, "source" => "yts.mx", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, + "id" => uniqid(rand(0, 9999)), "source" => "yts.mx", "name" => $name, "magnet" => $magnet, "hash" => $hash, "seeders" => $seeders, "leechers" => $leechers, "size" => $size, // Extra "quality" => $quality, "codec" => $codec, "year" => $year, "category" => $category, "runtime" => $runtime, "url" => $url, "date_added" => $date_added ); diff --git a/engines/search-image.php b/engines/search-image.php index 576ebc0..b85fb6c 100644 --- a/engines/search-image.php +++ b/engines/search-image.php @@ -13,17 +13,27 @@ class ImageSearch extends EngineRequest { protected $requests; public function __construct($opts, $mh) { - require ABSPATH."engines/image/yahoo.php"; + $this->requests = array(); - $this->requests = array( - new YahooImageRequest($opts, $mh), - ); + if($opts->enable_yahooimages == "on") { + require ABSPATH."engines/image/yahoo.php"; + $this->requests[] = new YahooImageRequest($opts, $mh); + } + + if($opts->enable_openverse == "on") { + require ABSPATH."engines/image/openverse.php"; + $this->requests[] = new OpenverseRequest($opts, $mh); + } + + if($opts->enable_qwant == "on") { + require ABSPATH."engines/image/qwant.php"; + $this->requests[] = new QwantImageRequest($opts, $mh); + } } public function parse_results($response) { $results = array(); - // Merge all results together foreach($this->requests as $request) { if($request->request_successful()) { $engine_result = $request->get_results(); @@ -41,26 +51,28 @@ public function parse_results($response) { // Merge duplicates and apply relevance scoring foreach($engine_result['search'] as $result) { if(array_key_exists('search', $results)) { - $result_urls = array_column($results['search'], "direct_link", "id"); - $found_key = array_search($result['direct_link'], $result_urls); + $result_urls = array_column($results['search'], "webpage_url", "id"); + $found_id = array_search($result['webpage_url'], $result_urls); } else { - $found_key = false; + $found_id = false; } - if($found_key !== false) { + if($found_id !== false) { // Duplicate result from another source, merge and rank accordingly - $results['search'][$found_key]['goosle_rank'] += $result['engine_rank']; + $results['search'][$found_id]['goosle_rank'] += $result['engine_rank']; } else { // First find, rank and add to results $query_terms = explode(" ", preg_replace("/[^a-z0-9 ]+/", "", strtolower($request->query))); $match_rank = match_count($result['alt'], $query_terms); +// $match_rank += match_count($result['url'], $query_terms); + $match_rank += match_count($result['webpage_url'], $query_terms); $result['goosle_rank'] = $result['engine_rank'] + $match_rank; $results['search'][$result['id']] = $result; } - unset($result, $result_urls, $found_key, $social_media_multiplier, $goosle_rank, $match_rank); + unset($result, $result_urls, $found_id, $social_media_multiplier, $goosle_rank, $match_rank); } } } @@ -115,35 +127,38 @@ public static function print_results($results, $opts) { echo "
Use this page to set up an authorization token for Openverse.
+ Fill in the relevant fields and click the button at the bottom to continue.