summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md20
-rw-r--r--admin.php0
-rw-r--r--api.txt18
-rw-r--r--api/v1/ac.php4
-rw-r--r--api/v1/images.php6
-rw-r--r--api/v1/music.php7
-rw-r--r--api/v1/news.php6
-rw-r--r--api/v1/videos.php6
-rw-r--r--api/v1/web.php6
-rwxr-xr-xcaptcha.php147
-rw-r--r--data/captcha/font.ttfbin0 -> 125972 bytes
-rw-r--r--images.php10
-rw-r--r--lib/captcha_gen.php325
-rw-r--r--lib/curlproxy.php5
-rw-r--r--lib/frontend.php26
-rw-r--r--lib/nextpage.php2
-rw-r--r--music.php10
-rw-r--r--news.php10
-rw-r--r--scraper/ftm.php148
-rw-r--r--scraper/imgur.php249
-rw-r--r--scraper/pinterest.php224
-rw-r--r--scraper/yep.php370
-rw-r--r--settings.php21
-rw-r--r--static/style.css75
-rw-r--r--videos.php10
-rw-r--r--web.php68
26 files changed, 1710 insertions, 63 deletions
diff --git a/README.md b/README.md
index 651944a..70c475e 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,9 @@ https://4get.ca
- Yandex
- Google
- Brave
+ - Yep
+ - Imgur
+ - FindThatMeme
3. Videos
- YouTube
@@ -39,6 +42,17 @@ https://4get.ca
5. Music
- SoundCloud
+6. Autocompleter
+ - Brave
+ - DuckDuckGo
+ - Yandex
+ - Google
+ - Qwant
+ - Yep
+ - Marginalia
+ - YouTube
+ - SoundCloud
+
More scrapers are coming soon. I currently want to add Google web/video/news search, HackerNews (durr orange site!!) and Qwant. A shopping and files tab is also in my todo list.
# Setup
@@ -166,7 +180,11 @@ certbot --nginx --key-type ecdsa -d www.yourdomain.com -d yourdomain.com
After doing that certbot should deploy the certificate automatically into your 4get nginx config file. It should be ready to use at that point.
-Ok bye!!!
+## Captcha
+
+Right now the setup for this shit is absolutely awful.
+
+Edit line 190 in `lib/captcha_gen.php` and specify your image sets. You can't disable the captcha right now lol. Just use a previous commit if you want to do that. Call me a shitcoder all you want I've had no energy lately. Images must be stored in `data/captcha`. Create a folder for each category. All files in there should be named from `1.png` to `321839.png`, for example.
## Tor Setup
diff --git a/admin.php b/admin.php
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/admin.php
diff --git a/api.txt b/api.txt
index 40b0ed3..f3c8b17 100644
--- a/api.txt
+++ b/api.txt
@@ -30,12 +30,25 @@
under your own terms. Please respect the terms of use listed here so
that this website may be available to all in the far future.
+ P.s fuck whoever botted my site for months on end, choke on my dick
+ lol!!!!
+
Get your instance running here ::
https://git.lolcat.ca/lolcat/4get
Thanks!
++ Passes
+ Depending of the instance, you may need to provide a "pass" token
+ in the cookies of your request. These can be obtained from solving
+ a captcha which will allow you to make 100 requests in the next 24
+ hours. In the future, you will be able to ask the serber maintainer
+ for a "pass" which will allow you to bypass the captcha requirement.
+
+ The captcha doesn't need javascript to work.
+
+
+ Decode the data
All payloads returned by the API are encoded in the JSON format. If
you don't know how to tackle the problem, maybe programming is not
@@ -47,8 +60,11 @@
+ Check if an API call was successful
All API responses come with an array index named "status". If the
status is something else than the string "ok", something went wrong.
+ You can supply the content of the "status" string back to your
+ application to inform the user of what went wrong.
- The HTTP code will always be 200 as to not cause issues with CORS.
+ The HTTP code will be 429 if your pass is invalid. It is set to 200
+ otherwise.
+ Get the next page of results
diff --git a/api/v1/ac.php b/api/v1/ac.php
index 0964fd9..3ee1481 100644
--- a/api/v1/ac.php
+++ b/api/v1/ac.php
@@ -17,7 +17,7 @@ class autocomplete{
"yep" => "https://api.yep.com/ac/?query={searchTerms}",
"marginalia" => "https://search.marginalia.nu/suggest/?partial={searchTerms}",
"yt" => "https://suggestqueries-clients6.youtube.com/complete/search?client=youtube&q={searchTerms}",
- "sc" => "https://api-v2.soundcloud.com/search/queries?q={searchTerms}&client_id=iMxZgT5mfGstBj8GWJbYMvpzelS8ne0E&limit=10&offset=0&linked_partitioning=1&app_version=1693487844&app_locale=en"
+ "sc" => "https://api-v2.soundcloud.com/search/queries?q={searchTerms}&client_id=ArYppSEotE3YiXCO4Nsgid2LLqJutiww&limit=10&offset=0&linked_partitioning=1&app_version=1693487844&app_locale=en"
];
/*
@@ -100,7 +100,7 @@ class autocomplete{
foreach($js[1] as $item){
- $json[] = strip_tags($item[0]);
+ $json[] = htmlspecialchars_decode(strip_tags($item[0]));
}
echo json_encode(
diff --git a/api/v1/images.php b/api/v1/images.php
index 694658e..474e2dd 100644
--- a/api/v1/images.php
+++ b/api/v1/images.php
@@ -7,6 +7,12 @@ chdir("../../");
include "lib/frontend.php";
$frontend = new frontend();
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, false);
+
[$scraper, $filters] = $frontend->getscraperfilters(
"images",
isset($_GET["scraper"]) ? $_GET["scraper"] : null
diff --git a/api/v1/music.php b/api/v1/music.php
index faf2d96..7512ac0 100644
--- a/api/v1/music.php
+++ b/api/v1/music.php
@@ -7,6 +7,13 @@ chdir("../../");
include "lib/frontend.php";
$frontend = new frontend();
+/*
+ Captcha
+*/
+$null = null;
+include "lib/captcha_gen.php";
+new captcha($null, $null, $null, $null, false);
+
[$scraper, $filters] = $frontend->getscraperfilters(
"music",
isset($_GET["scraper"]) ? $_GET["scraper"] : null
diff --git a/api/v1/news.php b/api/v1/news.php
index 775ef94..97738fc 100644
--- a/api/v1/news.php
+++ b/api/v1/news.php
@@ -7,6 +7,12 @@ chdir("../../");
include "lib/frontend.php";
$frontend = new frontend();
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, false);
+
[$scraper, $filters] = $frontend->getscraperfilters(
"news",
isset($_GET["scraper"]) ? $_GET["scraper"] : null
diff --git a/api/v1/videos.php b/api/v1/videos.php
index 225611a..9277792 100644
--- a/api/v1/videos.php
+++ b/api/v1/videos.php
@@ -7,6 +7,12 @@ chdir("../../");
include "lib/frontend.php";
$frontend = new frontend();
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, false);
+
[$scraper, $filters] = $frontend->getscraperfilters(
"videos",
isset($_GET["scraper"]) ? $_GET["scraper"] : null
diff --git a/api/v1/web.php b/api/v1/web.php
index 7f6d769..c479149 100644
--- a/api/v1/web.php
+++ b/api/v1/web.php
@@ -7,6 +7,12 @@ chdir("../../");
include "lib/frontend.php";
$frontend = new frontend();
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, false);
+
[$scraper, $filters] = $frontend->getscraperfilters(
"web",
isset($_GET["scraper"]) ? $_GET["scraper"] : null
diff --git a/captcha.php b/captcha.php
new file mode 100755
index 0000000..21da034
--- /dev/null
+++ b/captcha.php
@@ -0,0 +1,147 @@
+<?php
+
+if(
+ !isset($_GET["k"]) ||
+ preg_match(
+ '/^c\.[0-9]+$/',
+ $_GET["k"]
+ )
+){
+
+ header("Content-Type: text/plain");
+ echo "Fuck you";
+ die();
+}
+
+header("Content-Type: image/jpeg");
+
+$grid = apcu_fetch($_GET["k"]);
+
+if(
+ $grid === false ||
+ $grid[3] === true // has already been generated
+){
+
+ http_response_code(304); // not modified
+ die();
+}
+
+header("Last-Modified: Thu, 01 Oct 1970 00:00:00 GMT");
+
+// only generate one captcha with this config
+apcu_store(
+ $_GET["k"],
+ [
+ $grid[0],
+ $grid[1],
+ $grid[2],
+ true // has captcha been generated?
+ ],
+ 120 // we give user another 2 minutes to solve
+);
+
+// generate image
+
+if(random_int(0,1) === 0){
+
+ $theme = [
+ "bg" => "#ebdbb2",
+ "fg" => "#1d2021"
+ ];
+}else{
+
+ $theme = [
+ "bg" => "#1d2021",
+ "fg" => "#ebdbb2"
+ ];
+}
+
+$im = new Imagick();
+$im->newImage(400, 400, $theme["bg"]);
+$im->setImageBackgroundColor($theme["bg"]);
+$im->setImageFormat("jpg");
+
+$noise = [
+ imagick::NOISE_GAUSSIAN,
+ imagick::NOISE_LAPLACIAN
+];
+
+$distort = [
+ imagick::DISTORTION_AFFINE,
+ imagick::DISTORTION_SHEPARDS
+];
+
+$i = 0;
+for($y=0; $y<4; $y++){
+
+ for($x=0; $x<4; $x++){
+
+ $tmp = new Imagick("./data/captcha/" . $grid[0][$i][0] . "/" . random_int(1, $grid[0][$i][1]) . ".png");
+
+ // convert transparency correctly
+ $tmp->setImageBackgroundColor("black");
+ $tmp->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
+
+ // distort $tmp
+ $tmp->distortImage(
+ $distort[random_int(0,1)],
+ [
+ 0, 0,
+ random_int(-15, 15), random_int(-15, 15),
+
+ 100, 0,
+ random_int(80, 120), random_int(-15, 15),
+
+ 100, 100,
+ random_int(80, 120), random_int(80, 120),
+
+ 0, 100,
+ random_int(-15, 15), random_int(80, 120)
+ ],
+ false
+ );
+
+ // append image
+ $im->compositeImage($tmp->getImage(), Imagick::COMPOSITE_DEFAULT, $x * 100, $y * 100);
+
+ $i++;
+ }
+}
+
+// add noise
+$im->addNoiseImage($noise[random_int(0, 1)]);
+
+// expand top of image
+$im->setImageGravity(Imagick::GRAVITY_SOUTH);
+$im->chopImage(0, -27, 400, 400);
+$im->extentImage(0, 0, 0, -27);
+
+// add text
+$draw = new ImagickDraw();
+$draw->setFontSize(20);
+$draw->setFillColor($theme["fg"]);
+//$draw->setTextAntialias(false);
+$draw->setFont("./data/captcha/font.ttf");
+
+$text = "Pick " . $grid[1] . " images of " . str_replace("_", " ", $grid[2]);
+
+$pos = 200 - ($im->queryFontMetrics($draw, $text)["textWidth"] / 2);
+
+for($i=0; $i<strlen($text); $i++){
+
+ $im->annotateImage(
+ $draw,
+ $pos,
+ 20,
+ random_int(-15, 15),
+ $text[$i]
+ );
+
+ $pos += $im->queryFontMetrics($draw, $text[$i])["textWidth"];
+
+}
+
+$im->setFormat("jpeg");
+$im->setImageCompressionQuality(90);
+$im->setImageCompression(Imagick::COMPRESSION_JPEG2000);
+echo $im->getImageBlob();
diff --git a/data/captcha/font.ttf b/data/captcha/font.ttf
new file mode 100644
index 0000000..13f5dc7
--- /dev/null
+++ b/data/captcha/font.ttf
Binary files differ
diff --git a/images.php b/images.php
index ff420c9..5be8de4 100644
--- a/images.php
+++ b/images.php
@@ -10,11 +10,11 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
-$frontend->loadheader(
- $get,
- $filters,
- "images"
-);
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, $get, $filters, "images", true);
$payload = [
"images" => "",
diff --git a/lib/captcha_gen.php b/lib/captcha_gen.php
new file mode 100644
index 0000000..2ae824b
--- /dev/null
+++ b/lib/captcha_gen.php
@@ -0,0 +1,325 @@
+<?php
+
+class captcha{
+
+ public function __construct($frontend, $get, $filters, $page, $output){
+
+ /*
+ Validate cookie, if it exists
+ */
+ if(isset($_COOKIE["pass"])){
+
+ if(
+ // check if key is not malformed
+ preg_match(
+ '/^c[0-9]+\.[A-Za-z0-9]{20}$/',
+ $_COOKIE["pass"]
+ ) &&
+ // does key exist
+ apcu_exists($_COOKIE["pass"])
+ ){
+
+ // exists, increment counter
+ $inc = apcu_inc($_COOKIE["pass"]);
+
+ // we start counting from 1
+ // when it has been incremented to 102, it has reached
+ // 100 reqs
+ if($inc >= 102){
+
+ // reached limit, delete and give captcha
+ apcu_delete($_COOKIE["pass"]);
+ }else{
+
+ // the cookie is OK! dont die() and give results
+ if($output === true){
+ $frontend->loadheader(
+ $get,
+ $filters,
+ $page
+ );
+ }
+ return;
+ }
+ }
+ }
+
+ if($output === false){
+
+ echo json_encode([
+ "status" => "The \"pass\" token in your cookies is missing or has expired!!"
+ ]);
+ die();
+ }
+
+ /*
+ Validate form data
+ */
+ $lines =
+ explode(
+ "\r\n",
+ file_get_contents("php://input")
+ );
+
+ $invalid = false;
+ $answers = [];
+ $key = false;
+ $error = "";
+
+ foreach($lines as $line){
+
+ $line = explode("=", $line, 2);
+
+ if(count($line) !== 2){
+
+ $invalid = true;
+ break;
+ }
+
+ preg_match(
+ '/^c\[([0-9]+)\]$/',
+ $line[0],
+ $regex
+ );
+
+ if(
+ $line[1] != "on" ||
+ !isset($regex[0][1])
+ ){
+
+ // check if its k
+ if(
+ $line[0] == "k" &&
+ strpos($line[1], "c.") === 0
+ ){
+
+ $key = apcu_fetch($line[1]);
+ apcu_delete($line[1]);
+ }
+ break;
+ }
+
+ $regex = (int)$regex[1];
+
+ if(
+ $regex >= 16 ||
+ $regex <= -1
+ ){
+
+ $invalid = true;
+ break;
+ }
+
+ $answers[] = $regex;
+ }
+
+ if(
+ !$invalid &&
+ $key !== false
+ ){
+ $check = $key[1];
+
+ // validate answer
+ for($i=0; $i<count($key[0]); $i++){
+
+ if(!in_array($i, $answers)){
+
+ continue;
+ }
+
+ if($key[0][$i][0] == $key[2]){
+
+ $check--;
+ }else{
+
+ // got a wrong answer
+ $check = -1;
+ break;
+ }
+ }
+
+ if($check === 0){
+
+ // we passed the captcha
+ // set cookie
+ $inc = apcu_inc("cookie");
+ $chars =
+ array_merge(
+ range("A", "Z"),
+ range("a", "z"),
+ range(0, 9)
+ );
+
+ $c = count($chars) - 1;
+
+ $key = "c" . $inc . ".";
+
+ for($i=0; $i<20; $i++){
+
+ $key .= $chars[random_int(0, $c)];
+ }
+
+ apcu_inc($key, 1, $stupid, 86400);
+
+ setcookie(
+ "pass",
+ $key,
+ [
+ "expires" => time() + 86400, // expires in 24 hours
+ "samesite" => "Strict",
+ "path" => "/"
+ ]
+ );
+
+ $frontend->loadheader(
+ $get,
+ $filters,
+ $page
+ );
+ return;
+
+ }else{
+
+ $error = "<div class=\"quote\">You were <a href=\"https://www.youtube.com/watch?v=e1d7fkQx2rk\" target=\"_BLANK\" rel=\"noreferrer nofollow\">kicked out of Mensa.</a> Please try again.</div>";
+ }
+ }
+
+ /*
+ Generate random grid data to pass to captcha.php
+ */
+ $dataset = [
+ ["birds", 2263],
+ ["fumo_plushies", 1006],
+ ["minecraft", 848]
+ ];
+
+ // get the positions for the answers
+ // will return between 3 and 6 answer positions
+ $range = range(0, 15);
+ $answer_pos = [];
+
+ array_splice($range, 0, 1);
+
+ for($i=0; $i<random_int(3, 6); $i++){
+
+ $answer_pos_tmp =
+ array_splice(
+ $range,
+ random_int(
+ 0,
+ 14 - $i
+ ),
+ 1
+ );
+
+ $answer_pos[] = $answer_pos_tmp[0];
+ }
+
+ // choose a dataset
+ $choosen = &$dataset[random_int(0, count($dataset) - 1)];
+ $choices = [];
+
+ for($i=0; $i<count($dataset); $i++){
+
+ if($dataset[$i][0] == $choosen[0]){
+
+ continue;
+ }
+
+ $choices[] = $dataset[$i];
+ }
+
+ // generate grid data
+ $grid = [];
+
+ for($i=0; $i<16; $i++){
+
+ if(in_array($i, $answer_pos)){
+
+ $grid[] = $choosen;
+ }else{
+
+ $grid[] = $choices[random_int(0, count($choices) - 1)];
+ }
+ }
+
+ $key = "c." . apcu_inc("captcha_gen", 1) . "." . random_int(0, 100000000);
+
+ apcu_store(
+ $key,
+ [
+ $grid,
+ count($answer_pos),
+ $choosen[0],
+ false // has captcha been generated?
+ ],
+ 120 // we give user 2 minutes to get captcha, in case of network error
+ );
+
+ $payload = [
+ "class" => "",
+ "right-left" => "",
+ "right-right" => "",
+ "left" =>
+ '<div class="infobox">' .
+ '<h1>IQ test</h1>' .
+ 'Due to getting hit with 20,000 bot requests per day, I had to put this up. Sorry.<br><br>' .
+ 'Solving this captcha will allow you to make 100 searches today. I will add a way for legit users to bypass the captcha later. Sorry /g/tards!!' .
+ $error .
+ '<form method="POST" enctype="text/plain" autocomplete="off">' .
+ '<div class="captcha-wrapper">' .
+ '<div class="captcha">' .
+ '<img src="captcha.php?k=' . $key . '" alt="Captcha image">' .
+ '<div class="captcha-controls">' .
+ '<input type="checkbox" name="c[0]" id="c0">' .
+ '<label for="c0"></label>' .
+ '<input type="checkbox" name="c[1]" id="c1">' .
+ '<label for="c1"></label>' .
+ '<input type="checkbox" name="c[2]" id="c2">' .
+ '<label for="c2"></label>' .
+ '<input type="checkbox" name="c[3]" id="c3">' .
+ '<label for="c3"></label>' .
+ '<input type="checkbox" name="c[4]" id="c4">' .
+ '<label for="c4"></label>' .
+ '<input type="checkbox" name="c[5]" id="c5">' .
+ '<label for="c5"></label>' .
+ '<input type="checkbox" name="c[6]" id="c6">' .
+ '<label for="c6"></label>' .
+ '<input type="checkbox" name="c[7]" id="c7">' .
+ '<label for="c7"></label>' .
+ '<input type="checkbox" name="c[8]" id="c8">' .
+ '<label for="c8"></label>' .
+ '<input type="checkbox" name="c[9]" id="c9">' .
+ '<label for="c9"></label>' .
+ '<input type="checkbox" name="c[10]" id="c10">' .
+ '<label for="c10"></label>' .
+ '<input type="checkbox" name="c[11]" id="c11">' .
+ '<label for="c11"></label>' .
+ '<input type="checkbox" name="c[12]" id="c12">' .
+ '<label for="c12"></label>' .
+ '<input type="checkbox" name="c[13]" id="c13">' .
+ '<label for="c13"></label>' .
+ '<input type="checkbox" name="c[14]" id="c14">' .
+ '<label for="c14"></label>' .
+ '<input type="checkbox" name="c[15]" id="c15">' .
+ '<label for="c15"></label>' .
+ '</div>' .
+ '</div>' .
+ '</div>' .
+ '<input type="hidden" name="k" value="' . $key . '">' .
+ '<input type="submit" value="Check IQ" class="captcha-submit">' .
+ '</form>' .
+ '</div>'
+ ];
+
+ http_response_code(429); // too many reqs
+ $frontend->loadheader(
+ $get,
+ $filters,
+ "web"
+ );
+
+ echo $frontend->load("search.html", $payload);
+ die();
+ }
+}
diff --git a/lib/curlproxy.php b/lib/curlproxy.php
index 93cdbdc..ef9085b 100644
--- a/lib/curlproxy.php
+++ b/lib/curlproxy.php
@@ -127,6 +127,11 @@ class proxy{
throw new Exception("Too many redirects");
}
+ if($url == "https://i.imgur.com/removed.png"){
+
+ throw new Exception("Encountered imgur 404");
+ }
+
// sanitize URL
if($this->validateurl($url) === false){
diff --git a/lib/frontend.php b/lib/frontend.php
index 4c5e232..97c8c5b 100644
--- a/lib/frontend.php
+++ b/lib/frontend.php
@@ -901,7 +901,11 @@ class frontend{
"ddg" => "DuckDuckGo",
"yandex" => "Yandex",
"brave" => "Brave",
- "google" => "Google"
+ "google" => "Google",
+ "yep" => "Yep",
+ //"pinterest" => "Pinterest",
+ "imgur" => "Imgur",
+ "ftm" => "FindThatMeme"
]
];
break;
@@ -1011,10 +1015,30 @@ class frontend{
$lib = new wiby();
break;
+ case "yep":
+ include "scraper/yep.php";
+ $lib = new yep();
+ break;
+
case "sc":
include "scraper/sc.php";
$lib = new sc();
break;
+
+ case "pinterest":
+ include "scraper/pinterest.php";
+ $lib = new pinterest();
+ break;
+
+ case "imgur":
+ include "scraper/imgur.php";
+ $lib = new imgur();
+ break;
+
+ case "ftm":
+ include "scraper/ftm.php";
+ $lib = new ftm();
+ break;
}
// set scraper on $_GET
diff --git a/lib/nextpage.php b/lib/nextpage.php
index 3fab855..7516667 100644
--- a/lib/nextpage.php
+++ b/lib/nextpage.php
@@ -26,7 +26,7 @@ class nextpage{
apcu_store(
$page . "." .
$this->scraper .
- (string)($key),
+ (string)$key,
gzdeflate($salt.$iv.$out.$tag),
900 // cache information for 15 minutes blaze it
);
diff --git a/music.php b/music.php
index 61078b9..c95fb4c 100644
--- a/music.php
+++ b/music.php
@@ -10,11 +10,11 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
-$frontend->loadheader(
- $get,
- $filters,
- "music"
-);
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, $get, $filters, "music", true);
$payload = [
"class" => "",
diff --git a/news.php b/news.php
index eb5817f..ff37489 100644
--- a/news.php
+++ b/news.php
@@ -10,11 +10,11 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
-$frontend->loadheader(
- $get,
- $filters,
- "news"
-);
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, $get, $filters, "news", true);
$payload = [
"class" => "",
diff --git a/scraper/ftm.php b/scraper/ftm.php
new file mode 100644
index 0000000..af39c12
--- /dev/null
+++ b/scraper/ftm.php
@@ -0,0 +1,148 @@
+<?php
+
+class ftm{
+
+ public function __construct(){
+
+ include "lib/nextpage.php";
+ $this->nextpage = new nextpage("ftm");
+ }
+
+ public function getfilters($page){
+
+ return [];
+ }
+
+ private function get($url, $search, $offset){
+
+ $curlproc = curl_init();
+
+ curl_setopt($curlproc, CURLOPT_URL, $url);
+
+ $payload =
+ json_encode(
+ [
+ "search" => $search,
+ "offset" => $offset
+ ]
+ );
+
+ curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
+ curl_setopt($curlproc, CURLOPT_HTTPHEADER,
+ ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/110.0",
+ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
+ "Accept-Language: en-US,en;q=0.5",
+ "Accept-Encoding: gzip",
+ "Content-Length: " . strlen($payload),
+ "Content-Type: application/json",
+ "DNT: 1",
+ "Connection: keep-alive",
+ "Origin: https://findthatmeme.com",
+ "Referer: https://findthatmeme.com/?search=" . urlencode($search),
+ "Upgrade-Insecure-Requests: 1",
+ "Sec-Fetch-Dest: document",
+ "Sec-Fetch-Mode: navigate",
+ "Sec-Fetch-Site: none",
+ "Sec-Fetch-User: ?1",
+ "X-Auth-Key: undefined",
+ "X-CSRF-Validation-Header: true"]
+ );
+
+ curl_setopt($curlproc, CURLOPT_POST, true);
+ curl_setopt($curlproc, CURLOPT_POSTFIELDS, $payload);
+
+ curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
+ curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
+
+ $data = curl_exec($curlproc);
+
+ if(curl_errno($curlproc)){
+
+ throw new Exception(curl_error($curlproc));
+ }
+
+ curl_close($curlproc);
+ return $data;
+ }
+
+ public function image($get){
+
+ $search = $get["s"];
+
+ $out = [
+ "status" => "ok",
+ "npt" => null,
+ "image" => []
+ ];
+
+ if($get["npt"]){
+
+ $count = (int)$this->nextpage->get($get["npt"], "images");
+ }else{
+
+ $count = 0;
+ }
+
+ try{
+ $json =
+ json_decode(
+ $this->get(
+ "https://findthatmeme.com/api/v1/search",
+ $search,
+ $count
+ ),
+ true
+ );
+
+ }catch(Exception $error){
+
+ throw new Exception("Failed to fetch JSON");
+ }
+
+ if($json === null){
+
+ throw new Exception("Failed to decode JSON");
+ }
+
+ foreach($json as $item){
+
+ $count++;
+
+ if($item["type"] == "VIDEO"){
+
+ $thumb = "thumb/" . $item["thumbnail"];
+ }else{
+
+ $thumb = $item["image_path"];
+ }
+
+ $out["image"][] = [
+ "title" => date("jS \of F Y @ g:ia", strtotime($item["created_at"])),
+ "source" => [
+ [
+ "url" =>
+ "https://findthatmeme.us-southeast-1.linodeobjects.com/" .
+ $thumb,
+ "width" => null,
+ "height" => null
+ ]
+ ],
+ "url" => $item["source_page_url"]
+ ];
+ }
+
+ if($count === 50){
+
+ $out["npt"] =
+ $this->nextpage->store(
+ $count,
+ "images"
+ );
+ }
+
+ return $out;
+ }
+}
diff --git a/scraper/imgur.php b/scraper/imgur.php
new file mode 100644
index 0000000..4a16de7
--- /dev/null
+++ b/scraper/imgur.php
@@ -0,0 +1,249 @@
+<?php
+
+class imgur{
+
+ public function __construct(){
+
+ include "lib/nextpage.php";
+ $this->nextpage = new nextpage("imgur");
+
+ include "lib/fuckhtml.php";
+ $this->fuckhtml = new fuckhtml();
+ }
+
+ public function getfilters($page){
+
+ return [
+ "sort" => [ // /score/
+ "display" => "Sort by",
+ "option" => [
+ "score" => "Highest scoring",
+ "relevance" => "Most relevant",
+ "time" => "Newest first"
+ ]
+ ],
+ "time" => [ // /score/day/
+ "display" => "Time posted",
+ "option" => [
+ "all" => "All time",
+ "day" => "Today",
+ "week" => "This week",
+ "month" => "This month",
+ "year" => "This year"
+ ]
+ ],
+ "format" => [ // q_type
+ "display" => "Format",
+ "option" => [
+ "any" => "Any format",
+ "jpg" => "JPG",
+ "png" => "PNG",
+ "gif" => "GIF",
+ "anigif" => "Animated GIF",
+ "album" => "Albums"
+ ]
+ ],
+ "size" => [ // q_size_px
+ "display" => "Size",
+ "option" => [
+ "any" => "Any size",
+ "small" => "Small (500px or less)",
+ "med" => "Medium (500px to 2000px)",
+ "big" => "Big (2000px to 5000px)",
+ "lrg" => "Large (5000px to 10000px)",
+ "huge" => "Huge (10000px and above)"
+ ]
+ ]
+ ];
+ }
+
+ private function get($url, $get = []){
+
+ $curlproc = curl_init();
+
+ if($get !== []){
+ $get = http_build_query($get);
+ $url .= "?scrolled&" . $get;
+ }
+
+ curl_setopt($curlproc, CURLOPT_URL, $url);
+
+ curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
+ curl_setopt($curlproc, CURLOPT_HTTPHEADER,
+ ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/110.0",
+ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
+ "Accept-Language: en-US,en;q=0.5",
+ "Accept-Encoding: gzip",
+ "DNT: 1",
+ "Referer: https://imgur.com/search/",
+ "Connection: keep-alive",
+ "Sec-Fetch-Dest: empty",
+ "Sec-Fetch-Mode: cors",
+ "Sec-Fetch-Site: same-origin",
+ "TE: trailers",
+ "X-Requested-With: XMLHttpRequest"]
+ );
+
+ curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
+ curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
+
+ $data = curl_exec($curlproc);
+
+ if(curl_errno($curlproc)){
+
+ throw new Exception(curl_error($curlproc));
+ }
+
+ curl_close($curlproc);
+ return $data;
+ }
+
+ public function image($get){
+
+ if($get["npt"]){
+
+ $filter =
+ json_decode(
+ $this->nextpage->get(
+ $get["npt"],
+ "images"
+ ),
+ true
+ );
+
+ $search = $filter["s"];
+ unset($filter["s"]);
+
+ $sort = $filter["sort"];
+ unset($filter["sort"]);
+
+ $time = $filter["time"];
+ unset($filter["time"]);
+
+ $format = $filter["format"];
+ unset($filter["format"]);
+
+ $size = $filter["size"];
+ unset($filter["size"]);
+
+ $page = $filter["page"];
+ unset($filter["page"]);
+ }else{
+
+ $search = $get["s"];
+ $sort = $get["sort"];
+ $time = $get["time"];
+ $format = $get["format"];
+ $size = $get["size"];
+ $page = 0;
+
+ $filter = [
+ "q" => $search
+ ];
+
+ if($format != "any"){
+
+ $filter["q_type"] = $format;
+ }
+
+ if($size != "any"){
+
+ $filter["q_size_px"] = $size;
+ $filter["q_size_is_mpx"] = "off";
+ }
+ }
+
+ $out = [
+ "status" => "ok",
+ "npt" => null,
+ "image" => []
+ ];
+
+ try{
+ $html =
+ $this->get(
+ "https://imgur.com/search/$sort/$time/page/$page",
+ $filter
+ );
+
+ }catch(Exception $error){
+
+ throw new Exception("Failed to fetch HTML");
+ }
+
+ $this->fuckhtml->load($html);
+
+ $posts =
+ $this->fuckhtml
+ ->getElementsByClassName(
+ "post",
+ "div"
+ );
+
+ foreach($posts as $post){
+
+ $this->fuckhtml->load($post);
+
+ $image =
+ $this->fuckhtml
+ ->getElementsByTagName("img")[0];
+
+ $image_url = "https:" . substr($this->fuckhtml->getTextContent($image["attributes"]["src"]), 0, -5);
+
+ $out["image"][] = [
+ "title" =>
+ $this->fuckhtml
+ ->getTextContent(
+ $image["attributes"]["alt"]
+ ),
+ "source" => [
+ [
+ "url" => $image_url . ".jpg",
+ "width" => null,
+ "height" => null
+ ],
+ [
+ "url" => $image_url . "m.jpg",
+ "width" => null,
+ "height" => null
+ ]
+ ],
+ "url" =>
+ "https://imgur.com" .
+ $this->fuckhtml
+ ->getTextContent(
+ $this->fuckhtml
+ ->getElementsByClassName(
+ "image-list-link",
+ "a"
+ )
+ [0]
+ ["attributes"]
+ ["href"]
+ )
+ ];
+ }
+
+ if(isset($out["image"][0])){
+
+ // store nextpage
+ $filter["s"] = $search;
+ $filter["sort"] = $sort;
+ $filter["time"] = $time;
+ $filter["format"] = $format;
+ $filter["size"] = $size;
+ $filter["page"] = $page + 1;
+
+ $out["npt"] =
+ $this->nextpage->store(
+ json_encode($filter),
+ "images"
+ );
+ }
+
+ return $out;
+ }
+}
diff --git a/scraper/pinterest.php b/scraper/pinterest.php
new file mode 100644
index 0000000..2bb5b71
--- /dev/null
+++ b/scraper/pinterest.php
@@ -0,0 +1,224 @@
+<?php
+
+class pinterest{
+
+ public function __construct(){
+
+ include "lib/nextpage.php";
+ $this->nextpage = new nextpage("pinterest");
+ }
+
+ public function getfilters($page){
+
+ return [];
+ }
+
+ private function get($url, $get = []){
+
+ $curlproc = curl_init();
+
+ if($get !== []){
+ $get = http_build_query($get);
+ $url .= "?" . $get;
+ }
+
+ curl_setopt($curlproc, CURLOPT_URL, $url);
+
+ curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
+ curl_setopt($curlproc, CURLOPT_HTTPHEADER,
+ ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/110.0",
+ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
+ "Accept-Language: en-US,en;q=0.5",
+ "Accept-Encoding: gzip",
+ "DNT: 1",
+ "Connection: keep-alive",
+ "Upgrade-Insecure-Requests: 1",
+ "Sec-Fetch-Dest: document",
+ "Sec-Fetch-Mode: navigate",
+ "Sec-Fetch-Site: none",
+ "Sec-Fetch-User: ?1"]
+ );
+
+ curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
+ curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
+
+ $data = curl_exec($curlproc);
+
+ if(curl_errno($curlproc)){
+
+ throw new Exception(curl_error($curlproc));
+ }
+
+ curl_close($curlproc);
+ return $data;
+ }
+
+ public function image($get){
+
+ $search = $get["s"];
+
+ $out = [
+ "status" => "ok",
+ "npt" => null,
+ "image" => []
+ ];
+
+ $filter = [
+ "source_url" => "/search/pins/?q=" . urlencode($search),
+ "rs" => "typed",
+ "data" =>
+ json_encode(
+ [
+ "options" => [
+ "article" => null,
+ "applied_filters" => null,
+ "appliedProductFilters" => "---",
+ "auto_correction_disabled" => false,
+ "corpus" => null,
+ "customized_rerank_type" => null,
+ "filters" => null,
+ "query" => $search,
+ "query_pin_sigs" => null,
+ "redux_normalize_feed" => true,
+ "rs" => "typed",
+ "scope" => "pins", // pins, boards, videos,
+ "source_id" => null
+ ],
+ "context" => []
+ ]
+ ),
+ "_" => substr(str_replace(".", "", (string)microtime(true)), 0, -1)
+ ];
+
+ try{
+ $json =
+ json_decode(
+ $this->get(
+ "https://www.pinterest.ca/resource/BaseSearchResource/get/",
+ $filter
+ ),
+ true
+ );
+
+ }catch(Exception $error){
+
+ throw new Exception("Failed to fetch JSON");
+ }
+
+ if($json === null){
+
+ throw new Exception("Failed to decode JSON");
+ }
+
+ //print_r($json);
+
+ foreach(
+ $json
+ ["resource_response"]
+ ["data"]
+ ["results"]
+ as $item
+ ){
+
+ switch($item["type"]){
+
+ case "pin":
+
+ /*
+ Handle image object
+ */
+ $images = array_values($item["images"]);
+ $image = &$images[count($images) - 1]; // original
+ $thumb = &$images[1]; // 236x
+
+ $title = [];
+
+ if(
+ isset($item["grid_title"]) &&
+ trim($item["grid_title"]) != ""
+ ){
+
+ $title[] = $item["grid_title"];
+ }
+
+ if(
+ isset($item["description"]) &&
+ trim($item["description"]) != ""
+ ){
+
+ $title[] = $item["description"];
+ }
+
+ $title = implode(": ", $title);
+
+ if(
+ $title == "" &&
+ isset($item["board"]["name"]) &&
+ trim($item["board"]["name"]) != ""
+ ){
+
+ $title = $item["board"]["name"];
+ }
+
+ if($title == ""){
+
+ $title = null;
+ }
+
+ $out["image"][] = [
+ "title" => $title,
+ "source" => [
+ [
+ "url" => $image["url"],
+ "width" => (int)$image["width"],
+ "height" => (int)$image["height"]
+ ],
+ [
+ "url" => $thumb["url"],
+ "width" => (int)$thumb["width"],
+ "height" => (int)$thumb["height"]
+ ]
+ ],
+ "url" => "https://www.pinterest.com/pin/" . $item["id"]
+ ];
+ break;
+
+ case "board":
+
+ if(isset($item["cover_pin"]["image_url"])){
+
+ $image = [
+ "url" => $item["cover_pin"]["image_url"],
+ "width" => (int)$item["cover_pin"]["size"][0],
+ "height" => (int)$item["cover_pin"]["size"][1]
+ ];
+ }elseif(isset($item["image_cover_url_hd"])){
+ /*
+ $image = [
+ "url" =>
+ "width" => null,
+ "height" => null
+ ];*/
+ }
+ break;
+ }
+ }
+
+ return $out;
+ }
+
+ private function getfullresimage($image, $has_og){
+
+ $has_og = $has_og ? "1200x" : "originals";
+
+ return
+ preg_replace(
+ '/https:\/\/i\.pinimg\.com\/[^\/]+\//',
+ "https://i.pinimg.com/" . $has_og . "/",
+ $image
+ );
+ }
+}
diff --git a/scraper/yep.php b/scraper/yep.php
new file mode 100644
index 0000000..8ff4a57
--- /dev/null
+++ b/scraper/yep.php
@@ -0,0 +1,370 @@
+<?php
+
+class yep{
+
+ public function __construct(){
+
+ include "lib/nextpage.php";
+ $this->nextpage = new nextpage("yep");
+ }
+
+ public function getfilters($page){
+
+ return [
+ "country" => [
+ "display" => "Country",
+ "option" => [
+ "all" => "All regions",
+ "af" => "Afghanistan",
+ "al" => "Albania",
+ "dz" => "Algeria",
+ "as" => "American Samoa",
+ "ad" => "Andorra",
+ "ao" => "Angola",
+ "ai" => "Anguilla",
+ "ag" => "Antigua and Barbuda",
+ "ar" => "Argentina",
+ "am" => "Armenia",
+ "aw" => "Aruba",
+ "au" => "Australia",
+ "at" => "Austria",
+ "az" => "Azerbaijan",
+ "bs" => "Bahamas",
+ "bh" => "Bahrain",
+ "bd" => "Bangladesh",
+ "bb" => "Barbados",
+ "by" => "Belarus",
+ "be" => "Belgium",
+ "bz" => "Belize",
+ "bj" => "Benin",
+ "bt" => "Bhutan",
+ "bo" => "Bolivia",
+ "ba" => "Bosnia and Herzegovina",
+ "bw" => "Botswana",
+ "br" => "Brazil",
+ "bn" => "Brunei Darussalam",
+ "bg" => "Bulgaria",
+ "bf" => "Burkina Faso",
+ "bi" => "Burundi",
+ "cv" => "Cabo Verde",
+ "kh" => "Cambodia",
+ "cm" => "Cameroon",
+ "ca" => "Canada",
+ "ky" => "Cayman Islands",
+ "cf" => "Central African Republic",
+ "td" => "Chad",
+ "cl" => "Chile",
+ "cn" => "China",
+ "co" => "Colombia",
+ "cg" => "Congo",
+ "cd" => "Congo, Democratic Republic",
+ "ck" => "Cook Islands",
+ "cr" => "Costa Rica",
+ "hr" => "Croatia",
+ "cu" => "Cuba",
+ "cy" => "Cyprus",
+ "cz" => "Czechia",
+ "ci" => "Côte d'Ivoire",
+ "dk" => "Denmark",
+ "dj" => "Djibouti",
+ "dm" => "Dominica",
+ "do" => "Dominican Republic",
+ "ec" => "Ecuador",
+ "eg" => "Egypt",
+ "sv" => "El Salvador",
+ "gq" => "Equatorial Guinea",
+ "ee" => "Estonia",
+ "et" => "Ethiopia",
+ "fo" => "Faroe Islands",
+ "fj" => "Fiji",
+ "fi" => "Finland",
+ "fr" => "France",
+ "gf" => "French Guiana",
+ "pf" => "French Polynesia",
+ "ga" => "Gabon",
+ "gm" => "Gambia",
+ "ge" => "Georgia",
+ "de" => "Germany",
+ "gh" => "Ghana",
+ "gi" => "Gibraltar",
+ "gr" => "Greece",
+ "gl" => "Greenland",
+ "gd" => "Grenada",
+ "gp" => "Guadeloupe",
+ "gu" => "Guam",
+ "gt" => "Guatemala",
+ "gg" => "Guernsey",
+ "gn" => "Guinea",
+ "gy" => "Guyana",
+ "ht" => "Haiti",
+ "hn" => "Honduras",
+ "hk" => "Hong Kong",
+ "hu" => "Hungary",
+ "is" => "Iceland",
+ "in" => "India",
+ "id" => "Indonesia",
+ "iq" => "Iraq",
+ "ie" => "Ireland",
+ "im" => "Isle of Man",
+ "il" => "Israel",
+ "it" => "Italy",
+ "jm" => "Jamaica",
+ "jp" => "Japan",
+ "je" => "Jersey",
+ "jo" => "Jordan",
+ "kz" => "Kazakhstan",
+ "ke" => "Kenya",
+ "ki" => "Kiribati",
+ "kw" => "Kuwait",
+ "kg" => "Kyrgyzstan",
+ "la" => "Lao People's Democratic Republic",
+ "lv" => "Latvia",
+ "lb" => "Lebanon",
+ "ls" => "Lesotho",
+ "ly" => "Libya",
+ "li" => "Liechtenstein",
+ "lt" => "Lithuania",
+ "lu" => "Luxembourg",
+ "mk" => "Macedonia",
+ "mg" => "Madagascar",
+ "mw" => "Malawi",
+ "my" => "Malaysia",
+ "mv" => "Maldives",
+ "ml" => "Mali",
+ "mt" => "Malta",
+ "mq" => "Martinique",
+ "mr" => "Mauritania",
+ "mu" => "Mauritius",
+ "yt" => "Mayotte",
+ "mx" => "Mexico",
+ "fm" => "Micronesia, Federated States of",
+ "md" => "Moldova",
+ "mc" => "Monaco",
+ "mn" => "Mongolia",
+ "me" => "Montenegro",
+ "ms" => "Montserrat",
+ "ma" => "Morocco",
+ "mz" => "Mozambique",
+ "mm" => "Myanmar",
+ "na" => "Namibia",
+ "nr" => "Nauru",
+ "np" => "Nepal",
+ "nl" => "Netherlands",
+ "nc" => "New Caledonia",
+ "nz" => "New Zealand",
+ "ni" => "Nicaragua",
+ "ne" => "Niger",
+ "ng" => "Nigeria",
+ "nu" => "Niue",
+ "no" => "Norway",
+ "om" => "Oman",
+ "pk" => "Pakistan",
+ "ps" => "Palestine, State of",
+ "pa" => "Panama",
+ "pg" => "Papua New Guinea",
+ "py" => "Paraguay",
+ "pe" => "Peru",
+ "ph" => "Philippines",
+ "pn" => "Pitcairn",
+ "pl" => "Poland",
+ "pt" => "Portugal",
+ "pr" => "Puerto Rico",
+ "qa" => "Qatar",
+ "ro" => "Romania",
+ "ru" => "Russian Federation",
+ "rw" => "Rwanda",
+ "re" => "Réunion",
+ "sh" => "Saint Helena",
+ "kn" => "Saint Kitts and Nevis",
+ "lc" => "Saint Lucia",
+ "vc" => "Saint Vincent and the Grenadines",
+ "ws" => "Samoa",
+ "sm" => "San Marino",
+ "st" => "Sao Tome and Principe",
+ "sa" => "Saudi Arabia",
+ "sn" => "Senegal",
+ "rs" => "Serbia",
+ "sc" => "Seychelles",
+ "sl" => "Sierra Leone",
+ "sg" => "Singapore",
+ "sk" => "Slovakia",
+ "si" => "Slovenia",
+ "sb" => "Solomon Islands",
+ "so" => "Somalia",
+ "kr" => "Sourth Korea",
+ "za" => "South Africa",
+ "es" => "Spain",
+ "lk" => "Sri Lanka",
+ "sr" => "Suriname",
+ "se" => "Sweden",
+ "ch" => "Switzerland",
+ "tw" => "Taiwan",
+ "tj" => "Tajikistan",
+ "tz" => "Tanzania",
+ "th" => "Thailand",
+ "tl" => "Timor-Leste",
+ "tg" => "Togo",
+ "tk" => "Tokelau",
+ "to" => "Tonga",
+ "tt" => "Trinidad and Tobago",
+ "tn" => "Tunisia",
+ "tr" => "Turkey",
+ "tm" => "Turkmenistan",
+ "ug" => "Uganda",
+ "ua" => "Ukraine",
+ "ae" => "United Arab Emirates",
+ "gb" => "United Kingdom",
+ "us" => "United States",
+ "uy" => "Uruguay",
+ "uz" => "Uzbekistan",
+ "vu" => "Vanuatu",
+ "ve" => "Venezuela",
+ "vn" => "Vietnam",
+ "vg" => "Virgin Islands, British",
+ "vi" => "Virgin Islands, U.S.",
+ "ye" => "Yemen",
+ "zm" => "Zambia",
+ "zw" => "Zimbabwe"
+ ]
+ ],
+ "nsfw" => [
+ "display" => "NSFW",
+ "option" => [
+ "yes" => "Yes",
+ "maybe" => "Maybe",
+ "no" => "No"
+ ]
+ ]
+ ];
+ }
+
+ private function get($url, $get = []){
+
+ $curlproc = curl_init();
+
+ if($get !== []){
+ $get = http_build_query($get);
+ $url .= "?" . $get;
+ }
+
+ curl_setopt($curlproc, CURLOPT_URL, $url);
+
+ curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
+ curl_setopt($curlproc, CURLOPT_HTTPHEADER,
+ ["User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/110.0",
+ "Accept: */*",
+ "Accept-Language: en-US,en;q=0.5",
+ "Accept-Encoding: gzip",
+ "DNT: 1",
+ "Origin: https://yep.com",
+ "Referer: https://yep.com/",
+ "Connection: keep-alive",
+ "Sec-Fetch-Dest: empty",
+ "Sec-Fetch-Mode: cors",
+ "Sec-Fetch-Site: same-site"]
+ );
+
+ curl_setopt($curlproc, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($curlproc, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curlproc, CURLOPT_CONNECTTIMEOUT, 30);
+ curl_setopt($curlproc, CURLOPT_TIMEOUT, 30);
+
+ $data = curl_exec($curlproc);
+
+ if(curl_errno($curlproc)){
+
+ throw new Exception(curl_error($curlproc));
+ }
+
+ curl_close($curlproc);
+ return $data;
+ }
+
+ public function image($get){
+
+ $search = $get["s"];
+ $country = $get["country"];
+ $nsfw = $get["nsfw"];
+
+ switch($nsfw){
+
+ case "yes": $nsfw = "off"; break;
+ case "maybe": $nsfw = "moderate"; break;
+ case "no": $nsfw = "strict"; break;
+ }
+
+ $out = [
+ "status" => "ok",
+ "npt" => null,
+ "image" => []
+ ];
+
+ try{
+
+ $json =
+ json_decode(
+ $this->get(
+ "https://api.yep.com/fs/2/search",
+ [
+ "client" => "web",
+ "gl" => $country == "all" ? $country : strtoupper($country),
+ "no_correct" => "false",
+ "q" => $search,
+ "safeSearch" => $nsfw,
+ "type" => "images"
+ ]
+ ),
+ true
+ );
+ }catch(Exception $error){
+
+ throw new Exception("Failed to fetch JSON");
+ }
+
+ if($json === null){
+
+ throw new Exception("Failed to decode JSON");
+ }
+
+ foreach($json[1]["results"] as $item){
+
+ if(
+ $item["width"] !== 0 &&
+ $item["height"] !== 0
+ ){
+
+ $thumb_width = $item["width"] >= 260 ? 260 : $item["width"];
+ $thumb_height = ceil($item["height"] * ($thumb_width / $item["width"]));
+
+ $width = $item["width"];
+ $height = $item["height"];
+ }else{
+
+ $thumb_width = null;
+ $thumb_height = null;
+ $width = null;
+ $height = null;
+ }
+
+ $out["image"][] = [
+ "title" => $item["title"],
+ "source" => [
+ [
+ "url" => $item["image_id"],
+ "width" => $width,
+ "height" => $height
+ ],
+ [
+ "url" => $item["src"],
+ "width" => $thumb_width,
+ "height" => $thumb_height
+ ]
+ ],
+ "url" => $item["host_page"]
+ ];
+ }
+
+ return $out;
+ }
+}
diff --git a/settings.php b/settings.php
index bce3af0..98e6b49 100644
--- a/settings.php
+++ b/settings.php
@@ -161,6 +161,22 @@ $settings = [
[
"value" => "google",
"text" => "Google"
+ ],
+ [
+ "value" => "yep",
+ "text" => "Yep"
+ ],
+ /*[
+ "value" => "pinterest",
+ "text" => "Pinterest"
+ ],*/
+ [
+ "value" => "imgur",
+ "text" => "Imgur"
+ ],
+ [
+ "value" => "ftm",
+ "text" => "FindThatMeme"
]
]
],
@@ -243,7 +259,7 @@ if($_POST){
// refresh cookie dates
$loop = &$_COOKIE;
}
-
+
foreach($loop as $key => $value){
foreach($settings as $title){
@@ -262,7 +278,8 @@ foreach($loop as $key => $value){
"",
[
"expires" => -1, // removes cookie
- "samesite" => "Strict"
+ "samesite" => "Strict",
+ "path" => "/"
]
);
diff --git a/static/style.css b/static/style.css
index ec55624..fdb4951 100644
--- a/static/style.css
+++ b/static/style.css
@@ -283,7 +283,79 @@ h3,h4,h5,h6{
WEB
*/
-/* Left wrapper */
+/* Captcha */
+.captcha-wrapper{
+ position:relative;
+ max-width:400px;
+ margin:17px auto 0;
+ border:1px solid var(--928374);
+}
+
+.captcha{
+ padding-bottom:100%;
+ padding-top:6.2%;
+}
+
+.captcha-wrapper img{
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+}
+
+.captcha-controls{
+ position:absolute;
+ top:0;
+ left:0;
+ bottom:0;
+ right:0;
+ top:6.3%;
+}
+
+.captcha-wrapper img{
+ display:block;
+ background:#282828;
+}
+
+.captcha-wrapper input{
+ display:none;
+}
+
+.captcha-wrapper label{
+ float:left;
+ width:25%;
+ height:25%;
+ position:relative;
+ cursor:pointer;
+}
+
+.captcha-wrapper label:hover{
+ background:rgba(255,255,255,0.2);
+}
+
+.captcha-wrapper input:checked + label{
+ background:rgba(0,0,0,0.5);
+}
+
+.captcha-wrapper input:checked + label:after{
+ content:"";
+ position:absolute;
+ left:39%;
+ top:29%;
+ width:20%;
+ height:30%;
+ transform:rotate(45deg);
+ border-right:7px solid var(--ebdbb2);
+ border-bottom:7px solid var(--ebdbb2);
+ box-sizing:border-box;
+}
+
+.captcha-submit{
+ float:right;
+ margin:12px 0 4px;
+}
+
.web .left{
width:40%;
float:left;
@@ -294,6 +366,7 @@ h3,h4,h5,h6{
border:1px dashed var(--504945);
padding:10px;
margin-bottom:17px;
+ overflow:hidden;
}
.infobox .code{
diff --git a/videos.php b/videos.php
index 2842703..ddc281c 100644
--- a/videos.php
+++ b/videos.php
@@ -10,11 +10,11 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
-$frontend->loadheader(
- $get,
- $filters,
- "videos"
-);
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, $get, $filters, "videos", true);
$payload = [
"class" => "",
diff --git a/web.php b/web.php
index e34672d..4df2609 100644
--- a/web.php
+++ b/web.php
@@ -10,11 +10,11 @@ $frontend = new frontend();
$get = $frontend->parsegetfilters($_GET, $filters);
-$frontend->loadheader(
- $get,
- $filters,
- "web"
-);
+/*
+ Captcha
+*/
+include "lib/captcha_gen.php";
+new captcha($frontend, $get, $filters, true);
$payload = [
"class" => "",
@@ -44,6 +44,35 @@ try{
die();
}
+/*
+ Prepend Oracle output, if applicable
+*/
+include("oracles/encoder.php");
+include("oracles/calc.php");
+include("oracles/time.php");
+include("oracles/numerics.php");
+$oracles = [new calculator(), new encoder(), new time(), new numerics()];
+$fortune = "";
+foreach ($oracles as $oracle) {
+ if ($oracle->check_query($_GET["s"])) {
+ $resp = $oracle->generate_response($_GET["s"]);
+ if ($resp != "") {
+ $fortune .= "<div class=\"infobox\">";
+ foreach ($resp as $title => $r) {
+ if ($title) {
+ $fortune .= "<h3>".htmlspecialchars($title)."</h3><div class=\"code\">".htmlspecialchars($r)."</div>";
+ }
+ else {
+ $fortune .= "<i>".$r."</i><br>";
+ }
+ }
+ $fortune .= "<small>Answer provided by oracle: ".$oracle->info["name"]."</small></div>";
+ }
+ break;
+ }
+}
+$payload["left"] = $fortune;
+
$answerlen = 0;
/*
@@ -476,35 +505,6 @@ if($c !== 0){
}
/*
- Prepend Oracle output, if applicable
-*/
-include_once("oracles/encoder.php");
-include_once("oracles/calc.php");
-include_once("oracles/time.php");
-include_once("oracles/numerics.php");
-$oracles = [new calculator(), new encoder(), new time(), new numerics()];
-$fortune = "";
-foreach ($oracles as $oracle) {
- if ($oracle->check_query($_GET["s"])) {
- $resp = $oracle->generate_response($_GET["s"]);
- if ($resp != "") {
- $fortune .= "<div class=\"infobox\">";
- foreach ($resp as $title => $r) {
- if ($title) {
- $fortune .= "<h3>".htmlspecialchars($title)."</h3><div class=\"code\">".htmlspecialchars($r)."</div>";
- }
- else {
- $fortune .= "<i>".$r."</i><br>";
- }
- }
- $fortune .= "<small>Answer provided by oracle: ".$oracle->info["name"]."</small></div>";
- }
- break;
- }
-}
-$payload["left"] = $fortune . $payload["left"];
-
-/*
Load next page
*/
if($results["npt"] !== null){