summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api.txt31
-rw-r--r--audio/linear.php20
-rw-r--r--audio/sc.php223
-rw-r--r--audio/seekable.php20
-rw-r--r--audio/spotify.php214
-rwxr-xr-xcaptcha.php126
-rw-r--r--data/config.php27
-rw-r--r--images.php5
-rw-r--r--lib/bot_protection.php (renamed from lib/captcha_gen.php)145
-rw-r--r--lib/classic.pngbin358 -> 0 bytes
-rw-r--r--lib/frontend.php13
-rw-r--r--lib/fuckhtml.php25
-rw-r--r--music.php47
-rw-r--r--news.php5
-rw-r--r--opensearch.php2
-rw-r--r--scraper/mojeek.php27
-rw-r--r--scraper/sc.php11
-rw-r--r--scraper/spotify.json1
-rw-r--r--scraper/spotify.php726
-rw-r--r--settings.php2
-rw-r--r--static/style.css43
-rw-r--r--template/header.html5
-rw-r--r--template/home.html2
-rw-r--r--template/images.html1
-rw-r--r--template/search.html1
-rw-r--r--videos.php5
-rw-r--r--web.php7
27 files changed, 1520 insertions, 214 deletions
diff --git a/api.txt b/api.txt
index bc8ed05..a64873e 100644
--- a/api.txt
+++ b/api.txt
@@ -267,20 +267,23 @@
Each entry under "song" contains a array index called "stream" that
looks like this ::
- endpoint: audio_sc
+ endpoint: sc
url: https://api-v2.soundcloud <...>
- When the endpoint is "audio_sc", you MUST use 4get's audio_sc
- endpoint, for example, if you want an audio stream back. Otherwise,
- you are free to handle the json+m3u8 crap yourself. If the endpoint
- is equal to "audio", that URL SHOULD return a valid HTTP audio
- stream, and using the "audio" endpoint becomes optional again.
+ When the endpoint is something else than "linear", you MUST use
+ the specified endpoint. Otherwise, you are free to handle that
+ json+m3u8 crap yourself. If the endpoint is equal to "linear", the
+ URL should return a valid HTTP audio stream. To access the endpoint,
+ you must add the following prefix in your request, like so:
+
+ https://4get.ca/audio/<endpoint>?s=<url>
+ /favicon
Get the favicon for a website. The only parameter is "s", and must
- include the protocol.
+ include the protocol for fetching in case the favicon is not cached
+ yet.
Example ::
@@ -313,14 +316,14 @@
is set.
-+ /audio
++ /audio/linear
Get a proxied audio file. Does not support "Range" headers, as it's
- only used to proxy small files.
+ only used to proxy small files (hence why it's called linear DUH)
The parameter is "s" for the audio link.
-+ /audio_sc
++ /audio/sc
Get a proxied audio file for SoundCloud. Does not support downloads
trough WGET or CURL, since it returns 30kb~160kb "206 Partial
Content" parts, due to technical limitations that comes with
@@ -334,6 +337,14 @@
does not support "normal" SoundCloud URLs at this time.
++ /audio/spotify
+ Get a proxied Spotify audio file. Accepts a track ID for the "s"
+ parameter. Will only allow you to fetch the 30 second preview since
+ I don't feel like fucking with cookies and accounts every fucking
+ living moment of my life. You must handle the initial 302 redirect
+ to the /audio/linear endpoint.
+
+
+ Appendix
If you have any questions or need clarifications, please send an
email my way to will at lolcat.ca
diff --git a/audio/linear.php b/audio/linear.php
new file mode 100644
index 0000000..b6a848f
--- /dev/null
+++ b/audio/linear.php
@@ -0,0 +1,20 @@
+<?php
+
+if(!isset($_GET["s"])){
+
+ http_response_code(404);
+ header("X-Error: No SOUND(s) provided!");
+ die();
+}
+
+include "../data/config.php";
+include "../lib/curlproxy.php";
+$proxy = new proxy();
+
+try{
+
+ $proxy->stream_linear_audio($_GET["s"]);
+}catch(Exception $error){
+
+ header("X-Error: " . $error->getMessage());
+}
diff --git a/audio/sc.php b/audio/sc.php
new file mode 100644
index 0000000..53d8164
--- /dev/null
+++ b/audio/sc.php
@@ -0,0 +1,223 @@
+<?php
+
+new sc_audio();
+
+class sc_audio{
+
+ public function __construct(){
+
+ include "../lib/curlproxy.php";
+ $this->proxy = new proxy();
+
+ if(isset($_GET["u"])){
+
+ /*
+ we're now proxying audio
+ */
+ $viewkey = $_GET["u"];
+
+ if(!isset($_GET["r"])){
+
+ $this->do404("Ranges(r) are missing");
+ }
+
+ $ranges = explode(",", $_GET["r"]);
+
+ // sanitize ranges
+ foreach($ranges as &$range){
+
+ if(!is_numeric($range)){
+
+ $this->do404("Invalid range specified");
+ }
+
+ $range = (int)$range;
+ }
+
+ // sort ranges (just to make sure)
+ sort($ranges);
+
+ // convert ranges to pairs
+ $last = -1;
+ foreach($ranges as &$r){
+
+ $tmp = $r;
+ $r = [$last + 1, $r];
+
+ $last = $tmp;
+ }
+
+ $browser_headers = getallheaders();
+
+ // get the requested range from client
+ $client_range = 0;
+ foreach($browser_headers as $key => $value){
+
+ if(strtolower($key) == "range"){
+
+ preg_match(
+ '/bytes=([0-9]+)/',
+ $value,
+ $client_regex
+ );
+
+ if(isset($client_regex[1])){
+
+ $client_range = (int)$client_regex[1];
+ }else{
+
+ $client_range = 0;
+ }
+ break;
+ }
+ }
+
+ if(
+ $client_range < 0 ||
+ $client_range > $ranges[count($ranges) - 1][1]
+ ){
+
+ // range is not satisfiable
+ http_response_code(416);
+ header("Content-Type: text/plain");
+ die();
+ }
+
+ $rng = null;
+ for($i=0; $i<count($ranges); $i++){
+
+ if($ranges[$i][0] <= $client_range){
+
+ $rng = $ranges[$i];
+ }
+ }
+
+ // proxy data!
+ http_response_code(206); // partial content
+ header("Accept-Ranges: bytes");
+ header("Content-Range: bytes {$rng[0]}-{$rng[1]}/" . ($ranges[count($ranges) - 1][1] + 1));
+
+ $viewkey =
+ preg_replace(
+ '/\/media\/([0-9]+)\/[0-9]+\/[0-9]+/',
+ '/media/$1/' . $rng[0] . '/' . $rng[1],
+ $viewkey
+ );
+
+ try{
+
+ $this->proxy->stream_linear_audio(
+ $viewkey
+ );
+ }catch(Exception $error){
+
+ $this->do404("Could not read stream");
+ }
+
+ die();
+ }
+
+ /*
+ redirect user to correct resource
+ we need to scrape and store the byte positions in the result URL
+ */
+ if(!isset($_GET["s"])){
+
+ $this->do404("The URL(s) parameter is missing");
+ }
+
+ $viewkey = $_GET["s"];
+
+ if(
+ preg_match(
+ '/soundcloud\.com$/',
+ parse_url($viewkey, PHP_URL_HOST)
+ ) === false
+ ){
+
+ $this->do404("This endpoint can only be used for soundcloud streams");
+ }
+
+ try{
+
+ $json = $this->proxy->get($viewkey)["body"];
+ }catch(Exception $error){
+
+ $this->do404("Curl error: " . $error->getMessage());
+ }
+
+ $json = json_decode($json, true);
+
+ if(!isset($json["url"])){
+
+ $this->do404("Could not get URL from JSON");
+ }
+
+ $viewkey = $json["url"];
+
+ $m3u8 = $this->proxy->get($viewkey)["body"];
+
+ $m3u8 = explode("\n", $m3u8);
+
+ $lineout = null;
+ $streampos_arr = [];
+ foreach($m3u8 as $line){
+
+ $line = trim($line);
+ if($line[0] == "#"){
+
+ continue;
+ }
+
+ if($lineout === null){
+ $lineout = $line;
+ }
+
+ preg_match(
+ '/\/media\/[0-9]+\/([0-9]+)\/([0-9]+)/',
+ $line,
+ $matches
+ );
+
+ if(isset($matches[0])){
+
+ $streampos_arr[] = [
+ (int)$matches[1],
+ (int)$matches[2]
+ ];
+ }
+ }
+
+ if($lineout === null){
+
+ $this->do404("Could not get stream URL");
+ }
+
+ $lineout =
+ preg_replace(
+ '/\/media\/([0-9]+)\/[0-9]+\/[0-9]+/',
+ '/media/$1/0/0',
+ $lineout
+ );
+
+ $streampos = [];
+
+ foreach($streampos_arr as $pos){
+
+ $streampos[] = $pos[1];
+ }
+
+ $streampos = implode(",", $streampos);
+
+ header("Location: /audio/sc?u=" . urlencode($lineout) . "&r=$streampos");
+ header("Accept-Ranges: bytes");
+ }
+
+ private function do404($error){
+
+ http_response_code(404);
+ header("Content-Type: text/plain");
+ header("X-Error: $error");
+ die();
+ }
+}
diff --git a/audio/seekable.php b/audio/seekable.php
new file mode 100644
index 0000000..b6a848f
--- /dev/null
+++ b/audio/seekable.php
@@ -0,0 +1,20 @@
+<?php
+
+if(!isset($_GET["s"])){
+
+ http_response_code(404);
+ header("X-Error: No SOUND(s) provided!");
+ die();
+}
+
+include "../data/config.php";
+include "../lib/curlproxy.php";
+$proxy = new proxy();
+
+try{
+
+ $proxy->stream_linear_audio($_GET["s"]);
+}catch(Exception $error){
+
+ header("X-Error: " . $error->getMessage());
+}
diff --git a/audio/spotify.php b/audio/spotify.php
new file mode 100644
index 0000000..dc8fae6
--- /dev/null
+++ b/audio/spotify.php
@@ -0,0 +1,214 @@
+<?php
+
+include "../data/config.php";
+new spotify();
+
+class spotify{
+
+ public function __construct(){
+
+ include "../lib/fuckhtml.php";
+ $this->fuckhtml = new fuckhtml();
+
+ if(
+ !isset($_GET["s"]) ||
+ !preg_match(
+ '/^(track|episode)\.([A-Za-z0-9]{22})$/',
+ $_GET["s"],
+ $matches
+ )
+ ){
+
+ $this->do404("The track ID(s) parameter is missing or invalid");
+ }
+
+ try{
+
+ if($matches[1] == "episode"){
+
+ $uri = "show";
+ }else{
+
+ $uri = $matches[1];
+ }
+
+ $embed =
+ $this->get("https://embed.spotify.com/{$uri}/" . $matches[2]);
+ }catch(Exception $error){
+
+ $this->do404("Failed to fetch embed data");
+ }
+
+ $this->fuckhtml->load($embed);
+
+ $json =
+ $this->fuckhtml
+ ->getElementById(
+ "__NEXT_DATA__",
+ "script"
+ );
+
+ if($json === null){
+
+ $this->do404("Failed to extract JSON");
+ }
+
+ $json =
+ json_decode($json["innerHTML"], true);
+
+ if($json === null){
+
+ $this->do404("Failed to decode JSON");
+ }
+
+ switch($matches[1]){
+
+ case "track":
+ if(
+ isset(
+ $json
+ ["props"]
+ ["pageProps"]
+ ["state"]
+ ["data"]
+ ["entity"]
+ ["audioPreview"]
+ ["url"]
+ )
+ ){
+
+ header("Content-type: audio/mpeg");
+ header(
+ "Location: /audio/linear?s=" .
+ urlencode(
+ $json
+ ["props"]
+ ["pageProps"]
+ ["state"]
+ ["data"]
+ ["entity"]
+ ["audioPreview"]
+ ["url"]
+ )
+ );
+ }else{
+
+ $this->do404("Could not extract playback URL");
+ }
+ break;
+
+ case "episode":
+ if(
+ isset(
+ $json
+ ["props"]
+ ["pageProps"]
+ ["state"]
+ ["data"]
+ ["entity"]
+ ["id"]
+ )
+ ){
+
+ try{
+ $json =
+ $this->get(
+ "https://spclient.wg.spotify.com/soundfinder/v1/unauth/episode/" .
+ $json
+ ["props"]
+ ["pageProps"]
+ ["state"]
+ ["data"]
+ ["entity"]
+ ["id"] .
+ "/com.widevine.alpha"
+ );
+ }catch(Exception $error){
+
+ $this->do404("Failed to fetch audio resource");
+ }
+
+ $json = json_decode($json, true);
+
+ if($json === null){
+
+ $this->do404("Failed to decode audio resource JSON");
+ }
+
+ if(
+ isset($json["passthrough"]) &&
+ $json["passthrough"] == "ALLOWED" &&
+ isset($json["passthroughUrl"])
+ ){
+
+ header(
+ "Location:" .
+ "/audio/linear.php?s=" .
+ urlencode(
+ str_replace(
+ "http://",
+ "https://",
+ $json["passthroughUrl"]
+ )
+ )
+ );
+ }else{
+
+ $this->do404("Failed to find passthroughUrl");
+ }
+
+ }else{
+
+ $this->do404("Failed to find episode ID");
+ }
+ break;
+ }
+ }
+
+ private function get($url){
+
+ $headers = [
+ "User-Agent: " . config::USER_AGENT,
+ "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"
+ ];
+
+ $curlproc = curl_init();
+
+ curl_setopt($curlproc, CURLOPT_URL, $url);
+
+ curl_setopt($curlproc, CURLOPT_ENCODING, ""); // default encoding
+ curl_setopt($curlproc, CURLOPT_HTTPHEADER, $headers);
+
+ 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;
+ }
+
+ private function do404($error){
+
+ http_response_code(404);
+ header("Content-Type: text/plain");
+ header("X-Error: $error");
+ die();
+ }
+}
diff --git a/captcha.php b/captcha.php
index 21da034..a92b0ee 100755
--- a/captcha.php
+++ b/captcha.php
@@ -1,47 +1,104 @@
<?php
if(
- !isset($_GET["k"]) ||
+ isset($_GET["v"]) === false ||
+ is_array($_GET["v"]) === true ||
preg_match(
- '/^c\.[0-9]+$/',
- $_GET["k"]
- )
+ '/^c[0-9]+\.[A-Za-z0-9_]{20}$/',
+ $_GET["v"]
+ ) === 0
){
+ http_response_code(401);
header("Content-Type: text/plain");
- echo "Fuck you";
+ echo "Fuck my feathered cloaca";
die();
}
-header("Content-Type: image/jpeg");
+//header("Content-Type: image/jpeg");
+include "data/config.php";
+
+if(config::BOT_PROTECTION !== 1){
+
+ header("Content-Type: text/plain");
+ echo "The IQ test is disabled";
+ die();
+}
-$grid = apcu_fetch($_GET["k"]);
+$grid = apcu_fetch($_GET["v"]);
-if(
- $grid === false ||
- $grid[3] === true // has already been generated
-){
+if($grid !== false){
+ // captcha already generated
http_response_code(304); // not modified
die();
}
+header("Content-Type: image/jpeg");
header("Last-Modified: Thu, 01 Oct 1970 00:00:00 GMT");
-// only generate one captcha with this config
+// ** generate captcha data
+// 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);
+
+$picks = random_int(3, 6);
+
+for($i=0; $i<$picks; $i++){
+
+ $answer_pos_tmp =
+ array_splice(
+ $range,
+ random_int(
+ 0,
+ 14 - $i
+ ),
+ 1
+ );
+
+ $answer_pos[] = $answer_pos_tmp[0];
+}
+
+// choose a dataset
+$c = count(config::CAPTCHA_DATASET);
+$choosen = config::CAPTCHA_DATASET[random_int(0, $c - 1)];
+$choices = [];
+
+for($i=0; $i<$c; $i++){
+
+ if(config::CAPTCHA_DATASET[$i][0] == $choosen[0]){
+
+ continue;
+ }
+
+ $choices[] = config::CAPTCHA_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)];
+ }
+}
+
+// store grid data for form validation on captcha_gen.php
apcu_store(
- $_GET["k"],
- [
- $grid[0],
- $grid[1],
- $grid[2],
- true // has captcha been generated?
- ],
- 120 // we give user another 2 minutes to solve
+ $_GET["v"],
+ $answer_pos,
+ 60 // we give user 1 minute to solve
);
// generate image
-
if(random_int(0,1) === 0){
$theme = [
@@ -57,7 +114,7 @@ if(random_int(0,1) === 0){
}
$im = new Imagick();
-$im->newImage(400, 400, $theme["bg"]);
+$im->newImage(400, 427, $theme["bg"]);
$im->setImageBackgroundColor($theme["bg"]);
$im->setImageFormat("jpg");
@@ -76,12 +133,18 @@ 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");
+ $tmp = new Imagick("./data/captcha/" . $grid[$i][0] . "/" . random_int(1, $grid[$i][1]) . ".png");
// convert transparency correctly
$tmp->setImageBackgroundColor("black");
$tmp->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
-
+
+ // randomly mirror
+ if(random_int(0,1) === 1){
+
+ $tmp->flopImage();
+ }
+
// distort $tmp
$tmp->distortImage(
$distort[random_int(0,1)],
@@ -101,21 +164,15 @@ for($y=0; $y<4; $y++){
false
);
+ $tmp->addNoiseImage($noise[random_int(0, 1)]);
+
// append image
- $im->compositeImage($tmp->getImage(), Imagick::COMPOSITE_DEFAULT, $x * 100, $y * 100);
+ $im->compositeImage($tmp->getImage(), Imagick::COMPOSITE_DEFAULT, $x * 100, ($y * 100) + 27);
$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);
@@ -123,7 +180,7 @@ $draw->setFillColor($theme["fg"]);
//$draw->setTextAntialias(false);
$draw->setFont("./data/captcha/font.ttf");
-$text = "Pick " . $grid[1] . " images of " . str_replace("_", " ", $grid[2]);
+$text = "Pick " . $picks . " images of " . str_replace("_", " ", $choosen[0]);
$pos = 200 - ($im->queryFontMetrics($draw, $text)["textWidth"] / 2);
@@ -143,5 +200,4 @@ for($i=0; $i<strlen($text); $i++){
$im->setFormat("jpeg");
$im->setImageCompressionQuality(90);
-$im->setImageCompression(Imagick::COMPRESSION_JPEG2000);
echo $im->getImageBlob();
diff --git a/data/config.php b/data/config.php
index dd0f3a7..6327ba9 100644
--- a/data/config.php
+++ b/data/config.php
@@ -5,7 +5,7 @@ class config{
// any parameters.
// 4get version. Please keep this updated
- const VERSION = 6;
+ const VERSION = 7;
// Will be shown pretty much everywhere.
const SERVER_NAME = "4get";
@@ -24,10 +24,10 @@ class config{
const API_ENABLED = true;
// Bot protection
- // 4get.ca has been hit with 250k bot reqs every single day for months
+ // 4get.ca has been hit with 500k bot reqs every single day for months
// you probably want to enable this if your instance is public...
// 0 = disabled
- // 1 = ask for image captcha (requires image dataset & imagick 6.9.11-60)
+ // 1 = ask for image captcha (requires imagemagick v6 or higher)
// @TODO: 2 = invite only (users needs a pass)
const BOT_PROTECTION = 0;
@@ -62,20 +62,27 @@ class config{
"https://4get.zzls.xyz",
"https://4getus.zzls.xyz",
"https://4get.silly.computer",
- "https://4g.opnxng.com",
"https://4get.konakona.moe",
"https://4get.lvkaszus.pl",
"https://4g.ggtyler.dev",
"https://4get.perennialte.ch",
- "https://4get.sihj.net",
+ "https://4get.sijh.net",
"https://4get.hbubli.cc",
"https://4get.plunked.party",
- "https://4get.seitan-ayoub.lol"
+ "https://4get.seitan-ayoub.lol",
+ "https://4get.etenie.pl",
+ "https://4get.lunar.icu",
+ "https://4get.dcs0.hu",
+ "https://4get.kizuki.lol",
+ "https://4get.psily.garden",
+ "https://search.milivojevic.in.rs",
+ "https://4get.snine.nl",
+ "https://4get.datura.network"
];
// Default user agent to use for scraper requests. Sometimes ignored to get specific webpages
// Changing this might break things.
- const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/120.0";
+ const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0";
// Proxy pool assignments for each scraper
// false = Use server's raw IP
@@ -94,6 +101,8 @@ class config{
const PROXY_YT = false; // youtube
const PROXY_YEP = false;
const PROXY_PINTEREST = false;
+ const PROXY_SEZNAM = false;
+ const PROXY_NAVER = false;
const PROXY_FTM = false; // findthatmeme
const PROXY_IMGUR = false;
const PROXY_YANDEX_W = false; // yandex web
@@ -107,8 +116,8 @@ class config{
// SOUNDCLOUD
// Get these parameters by making a search on soundcloud with network
// tab open, then filter URLs using "search?q=". (No need to login)
- const SC_USER_ID = "361066-632137-891392-693457";
- const SC_CLIENT_TOKEN = "nUB9ZvnjRiqKF43CkKf3iu69D8bboyKY";
+ const SC_USER_ID = "59333-426459-717969-168008";
+ const SC_CLIENT_TOKEN = "8BBZpqUP1KSN4W6YB64xog2PX4Dw98b1";
// MARGINALIA
// Get an API key by contacting the Marginalia.nu maintainer. The "public" key
diff --git a/images.php b/images.php
index d9dbecf..3c4df15 100644
--- a/images.php
+++ b/images.php
@@ -15,10 +15,11 @@ $get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
-include "lib/captcha_gen.php";
-new captcha($frontend, $get, $filters, "images", true);
+include "lib/bot_protection.php";
+new bot_protection($frontend, $get, $filters, "images", true);
$payload = [
+ "timetaken" => microtime(true),
"images" => "",
"nextpage" => ""
];
diff --git a/lib/captcha_gen.php b/lib/bot_protection.php
index abcab7a..82de54c 100644
--- a/lib/captcha_gen.php
+++ b/lib/bot_protection.php
@@ -1,6 +1,6 @@
<?php
-class captcha{
+class bot_protection{
public function __construct($frontend, $get, $filters, $page, $output){
@@ -26,7 +26,7 @@ class captcha{
if(
// check if key is not malformed
preg_match(
- '/^c[0-9]+\.[A-Za-z0-9]{20}$/',
+ '/^k[0-9]+\.[A-Za-z0-9_]{20}$/',
$_COOKIE["pass"]
) &&
// does key exist
@@ -39,7 +39,7 @@ class captcha{
// we start counting from 1
// when it has been incremented to 102, it has reached
// 100 reqs
- if($inc >= 102){
+ if($inc >= config::MAX_SEARCHES + 2){
// reached limit, delete and give captcha
apcu_delete($_COOKIE["pass"]);
@@ -62,7 +62,7 @@ class captcha{
if($output === false){
- http_response_code(429); // too many reqs
+ http_response_code(401); // forbidden
echo json_encode([
"status" => "The \"pass\" token in your cookies is missing or has expired!!"
]);
@@ -104,10 +104,13 @@ class captcha{
!isset($regex[0][1])
){
- // check if its k
+ // check if its the v key
if(
- $line[0] == "k" &&
- strpos($line[1], "c.") === 0
+ $line[0] == "v" &&
+ preg_match(
+ '/^c[0-9]+\.[A-Za-z0-9_]{20}$/',
+ $line[1]
+ )
){
$key = apcu_fetch($line[1]);
@@ -129,27 +132,21 @@ class captcha{
$answers[] = $regex;
}
-
+
if(
!$invalid &&
- $key !== false
+ $key !== false // has captcha been gen'd?
){
- $check = $key[1];
+ $check = count($key);
// validate answer
- for($i=0; $i<count($key[0]); $i++){
-
- if(!in_array($i, $answers)){
-
- continue;
- }
+ for($i=0; $i<count($answers); $i++){
- if($key[0][$i][0] == $key[2]){
+ if(in_array($answers[$i], $key)){
$check--;
}else{
- // got a wrong answer
$check = -1;
break;
}
@@ -160,21 +157,8 @@ class captcha{
// 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)];
- }
+ $key = "k" . $inc . "." . $this->randomchars();
apcu_inc($key, 1, $stupid, 86400);
@@ -203,84 +187,23 @@ class captcha{
}
}
- // 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
- $c = count(config::CAPTCHA_DATASET);
- $choosen = config::CAPTCHA_DATASET[random_int(0, $c - 1)];
- $choices = [];
-
- for($i=0; $i<$c; $i++){
-
- if(config::CAPTCHA_DATASET[$i][0] == $choosen[0]){
-
- continue;
- }
-
- $choices[] = config::CAPTCHA_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
- );
+ $key = "c" . apcu_inc("captcha_gen", 1) . "." . $this->randomchars();
$payload = [
+ "timetaken" => microtime(true),
"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!!' .
+ 'IQ test has been enabled due to bot abuse on the network.<br>' .
+ 'Solving this IQ test will let you make 100 searches today. I will add an invite system to bypass this soon...' .
$error .
'<form method="POST" enctype="text/plain" autocomplete="off">' .
'<div class="captcha-wrapper">' .
'<div class="captcha">' .
- '<img src="captcha?k=' . $key . '" alt="Captcha image">' .
+ '<img src="captcha.php?v=' . $key . '" alt="Captcha image">' .
'<div class="captcha-controls">' .
'<input type="checkbox" name="c[0]" id="c0">' .
'<label for="c0"></label>' .
@@ -317,13 +240,12 @@ class captcha{
'</div>' .
'</div>' .
'</div>' .
- '<input type="hidden" name="k" value="' . $key . '">' .
+ '<input type="hidden" name="v" value="' . $key . '">' .
'<input type="submit" value="Check IQ" class="captcha-submit">' .
'</form>' .
'</div>'
];
- http_response_code(429); // too many reqs
$frontend->loadheader(
$get,
$filters,
@@ -333,4 +255,27 @@ class captcha{
echo $frontend->load("search.html", $payload);
die();
}
+
+ private function randomchars(){
+
+ $chars =
+ array_merge(
+ range("A", "Z"),
+ range("a", "z"),
+ range(0, 9)
+ );
+
+ $chars[] = "_";
+
+ $c = count($chars) - 1;
+
+ $key = "";
+
+ for($i=0; $i<20; $i++){
+
+ $key .= $chars[random_int(0, $c)];
+ }
+
+ return $key;
+ }
}
diff --git a/lib/classic.png b/lib/classic.png
deleted file mode 100644
index d2c9609..0000000
--- a/lib/classic.png
+++ /dev/null
Binary files differ
diff --git a/lib/frontend.php b/lib/frontend.php
index b002ee9..738ad83 100644
--- a/lib/frontend.php
+++ b/lib/frontend.php
@@ -39,6 +39,14 @@ class frontend{
$replacements["ac"] = '';
}
+ if(
+ isset($replacements["timetaken"]) &&
+ $replacements["timetaken"] !== null
+ ){
+
+ $replacements["timetaken"] = '<div class="timetaken">Took ' . substr(microtime(true) - $replacements["timetaken"], 0, 4) . 's</div>';
+ }
+
$handle = fopen("template/{$template}", "r");
$data = fread($handle, filesize("template/{$template}"));
fclose($handle);
@@ -68,7 +76,7 @@ class frontend{
echo
$this->load("header.html", [
- "title" => trim($get["s"] . " ({$page})"),
+ "title" => trim(htmlspecialchars($get["s"]) . " ({$page})"),
"description" => ucfirst($page) . ' search results for &quot;' . htmlspecialchars($get["s"]) . '&quot;',
"index" => "no",
"search" => htmlspecialchars($get["s"]),
@@ -88,7 +96,7 @@ class frontend{
$this->drawerror(
"Tshh, blocked!",
- 'You were blocked from viewing this page. If you wish to scrape data from 4get, please consider running <a href="https://git.lolcat.ca/lolcat/4get" rel="noreferrer nofollow">your own 4get instance</a> or using <a href="/api.txt">the API</a>.',
+ 'You were blocked from viewing this page. If you wish to scrape data from 4get, please consider running <a href="https://git.lolcat.ca/lolcat/4get" rel="noreferrer nofollow">your own 4get instance</a>.',
);
die();
}
@@ -98,6 +106,7 @@ class frontend{
echo
$this->load("search.html", [
+ "timetaken" => null,
"class" => "",
"right-left" => "",
"right-right" => "",
diff --git a/lib/fuckhtml.php b/lib/fuckhtml.php
index 2f9d3aa..ed1252c 100644
--- a/lib/fuckhtml.php
+++ b/lib/fuckhtml.php
@@ -466,19 +466,26 @@ class fuckhtml{
return
preg_replace_callback(
- '/\\\u[A-Fa-f0-9]{4}|\\\x[A-Fa-f0-9]{2}/',
+ '/\\\u[A-Fa-f0-9]{4}|\\\x[A-Fa-f0-9]{2}|\\\n|\\\r/',
function($match){
- if($match[0][1] == "u"){
+ switch($match[0][1]){
- return json_decode('"' . $match[0] . '"');
- }else{
+ case "u":
+ return json_decode('"' . $match[0] . '"');
+ break;
- return mb_convert_encoding(
- stripcslashes($match[0]),
- "utf-8",
- "windows-1252"
- );
+ case "x":
+ return mb_convert_encoding(
+ stripcslashes($match[0]),
+ "utf-8",
+ "windows-1252"
+ );
+ break;
+
+ default:
+ return " ";
+ break;
}
},
$string
diff --git a/music.php b/music.php
index 5bc3e5f..0162d4c 100644
--- a/music.php
+++ b/music.php
@@ -15,10 +15,11 @@ $get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
-include "lib/captcha_gen.php";
-new captcha($frontend, $get, $filters, "music", true);
+include "lib/bot_protection.php";
+new bot_protection($frontend, $get, $filters, "music", true);
$payload = [
+ "timetaken" => microtime(true),
"class" => "",
"right-left" => "",
"right-right" => "",
@@ -36,7 +37,10 @@ try{
$categories = [
"song" => "",
"author" => "",
- "playlist" => ""
+ "playlist" => "",
+ "album" => "",
+ "podcast" => "",
+ "user" => ""
];
/*
@@ -48,14 +52,26 @@ if(count($results["song"]) !== 0){
$main = "song";
-}elseif(count($results["author"]) !== 0){
+}elseif(count($results["album"]) !== 0){
- $main = "author";
+ $main = "album";
}elseif(count($results["playlist"]) !== 0){
$main = "playlist";
+}elseif(count($results["podcast"]) !== 0){
+
+ $main = "podcast";
+
+}elseif(count($results["author"]) !== 0){
+
+ $main = "author";
+
+}elseif(count($results["user"]) !== 0){
+
+ $main = "user";
+
}else{
// No results found!
@@ -133,12 +149,15 @@ foreach($categories as $name => $data){
$customhtml = null;
if(
- $name == "song" &&
+ (
+ $name == "song" ||
+ $name == "podcast"
+ ) &&
$item["stream"]["endpoint"] !== null
){
$customhtml =
- '<audio src="' . $item["stream"]["endpoint"] . '?s=' . urlencode($item["stream"]["url"]) . '" controls autostart="false" preload="none">';
+ '<audio src="/audio/' . $item["stream"]["endpoint"] . '?s=' . urlencode($item["stream"]["url"]) . '" controls autostart="false" preload="none">';
}
$categories[$name] .= $frontend->drawtextresult($item, $greentext, $duration, $get["s"], $tabindex, $customhtml);
@@ -177,18 +196,8 @@ foreach($categories as $name => $value){
'<div class="answer-title">' .
'<a class="answer-title" href="?s=' . urlencode($get["s"]);
- switch($name){
-
- case "playlist":
- $payload[$write] .=
- '&type=playlist"><h2>Playlists</h2></a>';
- break;
-
- case "author":
- $payload[$write] .=
- '&type=people"><h2>Authors</h2></a>';
- break;
- }
+ $payload[$write] .=
+ '&type=' . $name . '"><h2>' . ucfirst($name) . 's</h2></a>';
$payload[$write] .=
'</div>' .
diff --git a/news.php b/news.php
index 9a237a4..3d5030a 100644
--- a/news.php
+++ b/news.php
@@ -15,10 +15,11 @@ $get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
-include "lib/captcha_gen.php";
-new captcha($frontend, $get, $filters, "news", true);
+include "lib/bot_protection.php";
+new bot_protection($frontend, $get, $filters, "news", true);
$payload = [
+ "timetaken" => microtime(true),
"class" => "",
"right-left" => "",
"right-right" => "",
diff --git a/opensearch.php b/opensearch.php
index 632a533..fb51430 100644
--- a/opensearch.php
+++ b/opensearch.php
@@ -5,7 +5,7 @@ include "data/config.php";
$domain =
htmlspecialchars(
- (strpos(strtolower($_SERVER['SERVER_PROTOCOL']), 'https') === false ? 'http' : 'https') .
+ ((isset($_SERVER["HTTPS"]) && ($_SERVER["HTTPS"] == "on" || $_SERVER["HTTPS"] === 1)) ? "https" : "http") .
'://' . $_SERVER["HTTP_HOST"]
);
diff --git a/scraper/mojeek.php b/scraper/mojeek.php
index d17158b..934e455 100644
--- a/scraper/mojeek.php
+++ b/scraper/mojeek.php
@@ -602,20 +602,23 @@ class mojeek{
);
}
- $data["date"] =
- explode(
- " - ",
- $this->fuckhtml
- ->getTextContent(
- $this->fuckhtml
- ->getElementsByClassName("i", "p")[0]
- )
+ $date =
+ $this->fuckhtml
+ ->getElementsByClassName(
+ "mdate",
+ "span"
);
- $data["date"] =
- strtotime(
- $data["date"][count($data["date"]) - 1]
- );
+ if(count($date) !== 0){
+
+ $data["date"] =
+ strtotime(
+ $this->fuckhtml
+ ->getTextContent(
+ $date[0]
+ )
+ );
+ }
$out["web"][] = $data;
}
diff --git a/scraper/sc.php b/scraper/sc.php
index 02cf087..23742f1 100644
--- a/scraper/sc.php
+++ b/scraper/sc.php
@@ -16,7 +16,7 @@ class sc{
"option" => [
"any" => "Any type",
"track" => "Tracks",
- "people" => "People",
+ "author" => "People",
"album" => "Albums",
"playlist" => "Playlists",
"goplus" => "Go+ Tracks"
@@ -143,7 +143,7 @@ class sc{
];
break;
- case "people":
+ case "author":
$url = "https://api-v2.soundcloud.com/search/users";
$params = [
"q" => $search,
@@ -237,7 +237,10 @@ class sc{
"npt" => null,
"song" => [],
"playlist" => [],
- "author" => []
+ "album" => [],
+ "podcast" => [],
+ "author" => [],
+ "user" => []
];
/*
@@ -346,7 +349,7 @@ class sc{
if(stripos($item["monetization_model"], "TIER") === false){
$stream = [
- "endpoint" => "audio_sc",
+ "endpoint" => "sc",
"url" =>
$item["media"]["transcodings"][0]["url"] .
"?client_id=" . config::SC_CLIENT_TOKEN .
diff --git a/scraper/spotify.json b/scraper/spotify.json
new file mode 100644
index 0000000..ad0590e
--- /dev/null
+++ b/scraper/spotify.json
@@ -0,0 +1 @@
+{"data":{"searchV2":{"albums":{"totalCount":1000,"items":[{"data":{"__typename":"Album","uri":"spotify:album:43uErencdmuTRFZPG3zXL1","name":"Piñata","artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}},{"uri":"spotify:artist:5LhTec3c7dcqBvpLRWbMcf","profile":{"name":"Madlib"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e02d844f6b7311a69b9a08e7a0f","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d00004851d844f6b7311a69b9a08e7a0f","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b273d844f6b7311a69b9a08e7a0f","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#777777","isFallback":false}}},"date":{"year":2014}}},{"data":{"__typename":"Album","uri":"spotify:album:2ll6KONxe4F87GJku1ZZrl","name":"Freddie's Inferno","artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0269b381d574b329409bd806e6","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485169b381d574b329409bd806e6","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27369b381d574b329409bd806e6","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#283840","isFallback":false}}},"date":{"year":2022}}},{"data":{"__typename":"Album","uri":"spotify:album:3znl1qe13kyjQv7KcR685N","name":"Alfredo","artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}},{"uri":"spotify:artist:0eVyjRhzZKke2KFYTcDkeu","profile":{"name":"The Alchemist"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0252c24049a16d59e98a638651","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485152c24049a16d59e98a638651","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27352c24049a16d59e98a638651","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#7A7A1C","isFallback":false}}},"date":{"year":2020}}},{"data":{"__typename":"Album","uri":"spotify:album:07YX7oCO5D6zr1NVDEeSAd","name":"Freddie's Inferno (Deluxe)","artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e025472702e288ab0e6d9d94355","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048515472702e288ab0e6d9d94355","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2735472702e288ab0e6d9d94355","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#C435CB","isFallback":false}}},"date":{"year":2023}}},{"data":{"__typename":"Album","uri":"spotify:album:3PZx4Vntcp5T7UgdfjnFDa","name":"$oul $old $eparately","artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e029f301e3a4d5f25d1888585b1","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048519f301e3a4d5f25d1888585b1","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2739f301e3a4d5f25d1888585b1","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#CA4F0E","isFallback":false}}},"date":{"year":2022}}},{"data":{"__typename":"Album","uri":"spotify:album:6JaEv20qGvSgIHQbxwtjUu","name":"Freddie","artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e02fa55faa1d9c494e37317734c","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d00004851fa55faa1d9c494e37317734c","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b273fa55faa1d9c494e37317734c","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#DC3351","isFallback":false}}},"date":{"year":2018}}},{"data":{"__typename":"Album","uri":"spotify:album:4Sc3qZCPGp2QXFcxYA8Mn2","name":"Freddie's Inferno - Ghost Slowed","artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0279de01fd3be27fdd3a120e2b","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485179de01fd3be27fdd3a120e2b","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27379de01fd3be27fdd3a120e2b","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#148A0D","isFallback":false}}},"date":{"year":2022}}},{"data":{"__typename":"Album","uri":"spotify:album:31KbO7WnDp2AjPdmRTJzdf","name":"Bandana","artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}},{"uri":"spotify:artist:5LhTec3c7dcqBvpLRWbMcf","profile":{"name":"Madlib"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e023bf3b1061f9f703b0f6bf532","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048513bf3b1061f9f703b0f6bf532","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2733bf3b1061f9f703b0f6bf532","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#104860","isFallback":false}}},"date":{"year":2019}}},{"data":{"__typename":"Album","uri":"spotify:album:4WLWbEhOq5kphrWF5oEEou","name":"Suffer","artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e02ab400f73482c4eff6121adfb","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d00004851ab400f73482c4eff6121adfb","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b273ab400f73482c4eff6121adfb","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#E02018","isFallback":false}}},"date":{"year":2020}}},{"data":{"__typename":"Album","uri":"spotify:album:6sX8jSeSVOZrcoC8NecJOe","name":"$oul $old $eparately (Bonus Edition)","artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e029314b7f522d7ee55b3a9af96","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048519314b7f522d7ee55b3a9af96","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2739314b7f522d7ee55b3a9af96","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#406068","isFallback":false}}},"date":{"year":2022}}}]},"artists":{"totalCount":646,"items":[{"data":{"__typename":"Artist","uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/ab6761610000e5eb9d100e5a9cf34beab8e75750","width":640,"height":640},{"url":"https://i.scdn.co/image/ab6761610000f1789d100e5a9cf34beab8e75750","width":160,"height":160},{"url":"https://i.scdn.co/image/ab676161000051749d100e5a9cf34beab8e75750","width":320,"height":320}],"extractedColors":{"colorDark":{"hex":"#505048","isFallback":false}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/ab6761610000e5eb7594ccfeb000227bf7b1f0c0","width":640,"height":640},{"url":"https://i.scdn.co/image/ab6761610000f1787594ccfeb000227bf7b1f0c0","width":160,"height":160},{"url":"https://i.scdn.co/image/ab676161000051747594ccfeb000227bf7b1f0c0","width":320,"height":320}],"extractedColors":{"colorDark":{"hex":"#304030","isFallback":false}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:4M1FpEWs2PeYfJe7xxJfhH","profile":{"name":"Freddie Mercury","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/ab6761610000e5eb1052b77abd7f89485562d797","width":640,"height":640},{"url":"https://i.scdn.co/image/ab6761610000f1781052b77abd7f89485562d797","width":160,"height":160},{"url":"https://i.scdn.co/image/ab676161000051741052b77abd7f89485562d797","width":320,"height":320}],"extractedColors":{"colorDark":{"hex":"#B83840","isFallback":false}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:5dCuFngSPyOOnTAvrC7v2s","profile":{"name":"Freddie King","verified":false},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/6c1f3c786fbc542e29df368b40d6ad888fe010be","width":588,"height":672},{"url":"https://i.scdn.co/image/59853b8df8e0a851e28ed82b176fcd2f4304b3de","width":64,"height":73},{"url":"https://i.scdn.co/image/f5659df5e8bd559c3cb7deebf8732b04da238083","width":200,"height":229}],"extractedColors":{"colorDark":{"hex":"#535353","isFallback":true}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:2yaixhgm3yXxjhJAH8SZy3","profile":{"name":"Freddie Jackson","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/88949e0ae99ef6fd8723647b1e3b0281cfb5eca1","width":640,"height":758},{"url":"https://i.scdn.co/image/7ed1fc37bfffe2f60e764e6691375231f65fa54c","width":64,"height":76},{"url":"https://i.scdn.co/image/64b462573e770b5e4d27ffb6267c752499ee84fd","width":200,"height":237},{"url":"https://i.scdn.co/image/2c343dee11668ef91feea2866500b03cd8ca001d","width":1000,"height":1184}],"extractedColors":{"colorDark":{"hex":"#535353","isFallback":true}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:7fihhreD4v29FQsWykhCJm","profile":{"name":"Freddie Aguilar","verified":false},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/ab67616d0000b2734572306a60e5b780ba1adc9a","width":640,"height":640},{"url":"https://i.scdn.co/image/ab67616d000048514572306a60e5b780ba1adc9a","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d00001e024572306a60e5b780ba1adc9a","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#B06058","isFallback":false}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:30R9paG1c5BGtNGle59VPq","profile":{"name":"Freddie McGregor","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/d33fad34754acbf79f0047381e7e4554657c96a3","width":640,"height":674},{"url":"https://i.scdn.co/image/4d54fd18bf87d82623e176b474f54fd73ce967d2","width":64,"height":67},{"url":"https://i.scdn.co/image/c45b6109209f2693372bd14113ef9004f622a5fc","width":200,"height":211},{"url":"https://i.scdn.co/image/a1f805632eb1a01039c7c7e35523c49e2cb51da6","width":714,"height":752}],"extractedColors":{"colorDark":{"hex":"#535353","isFallback":true}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:7sP4SQ0WY6jfps1I19Ot7i","profile":{"name":"Fridayy","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/ab6761610000e5ebff065dd457b7c2ada6f13236","width":640,"height":640},{"url":"https://i.scdn.co/image/ab6761610000f178ff065dd457b7c2ada6f13236","width":160,"height":160},{"url":"https://i.scdn.co/image/ab67616100005174ff065dd457b7c2ada6f13236","width":320,"height":320}],"extractedColors":{"colorDark":{"hex":"#307088","isFallback":false}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:0fTHKjepK5HWOrb2rkS5Em","profile":{"name":"Freddie Hubbard","verified":false},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/26e32b5ccf23535b99174af74eb7b8cb6ae7724f","width":500,"height":500},{"url":"https://i.scdn.co/image/de1efbb1e478f4456d74eb1682d362711f61ef04","width":64,"height":64},{"url":"https://i.scdn.co/image/3a20ec726d127e05b4a5112a6b69244ac826c09f","width":200,"height":200}],"extractedColors":{"colorDark":{"hex":"#203038","isFallback":false}}}}}},{"data":{"__typename":"Artist","uri":"spotify:artist:6vclJnUiJ9D7IW0OP54MFT","profile":{"name":"Fredz","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/ab6761610000e5eb22b0855322eea8198db079af","width":640,"height":640},{"url":"https://i.scdn.co/image/ab6761610000f17822b0855322eea8198db079af","width":160,"height":160},{"url":"https://i.scdn.co/image/ab6761610000517422b0855322eea8198db079af","width":320,"height":320}],"extractedColors":{"colorDark":{"hex":"#535353","isFallback":true}}}}}}]},"episodes":{"totalCount":1000,"items":[{"data":{"__typename":"Episode","uri":"spotify:episode:0ATaVVbXaCDyIWVT85RNqN","name":"Freddy Fazbear's Theme","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d7005aedbf02ac3ef4d8f0ee2","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f7005aedbf02ac3ef4d8f0ee2","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a7005aedbf02ac3ef4d8f0ee2","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#304030","isFallback":false}}},"duration":{"totalMilliseconds":67547},"releaseDate":{"isoString":"2022-02-28T22:18:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:3ldqTpE8sEIZ714x6ocisz","name":"Where Was I?","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68da5c6d7ed7d865d6c709d97b7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fa5c6d7ed7d865d6c709d97b7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8aa5c6d7ed7d865d6c709d97b7","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"Seagull Productions"}}},"description":"Powers out. And glowing blue eyes stare at you through the doorway. A familiar tune plays. Thanks for listening! abbiezmusic: https://open.spotify.com/show/0sbu6rzkowk8FOqkLN2IBd?si=5671c64d32e14aae --- Send in a voice message: https://podcasters.spotify.com/pod/show/kris-silva1/message","contentRating":{"label":"NONE"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:01NeuNGRcArz00Vbe6Wivv","name":"A Wild Visitor | 1","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#506878","isFallback":false}}},"duration":{"totalMilliseconds":2228480},"releaseDate":{"isoString":"2023-09-18T23:01:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:0UpRHsb3a73uOYLlOVPSRE","name":"Hooked on Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"Wondery"}}},"description":"When a wild dolphin called Freddie appears in the harbour of a tired English fishing town and forms a deep friendship with Alan, a devastating rumour emerges.See Privacy Policy at https://art19.com/privacy and California Privacy Notice at https://art19.com/privacy#do-not-sell-my-info.","contentRating":{"label":"EXPLICIT"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:35lO9qRW3Sz8mJqsTthhp9","name":"Flippin' Crazy | 2","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#506878","isFallback":false}}},"duration":{"totalMilliseconds":2258991},"releaseDate":{"isoString":"2023-09-18T23:02:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:0UpRHsb3a73uOYLlOVPSRE","name":"Hooked on Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"Wondery"}}},"description":"Alan continues to swim with Freddie despite the salacious allegation against him. Surely no-one will take it seriously. Or will they?See Privacy Policy at https://art19.com/privacy and California Privacy Notice at https://art19.com/privacy#do-not-sell-my-info.","contentRating":{"label":"EXPLICIT"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:19nLWZSUUSij0KYU6xwFmh","name":"#1611 - Freddie Gibbs & Brian Moses","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d9a3a5ca9e3ea1a6912a4bbfc","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f9a3a5ca9e3ea1a6912a4bbfc","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a9a3a5ca9e3ea1a6912a4bbfc","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#C25800","isFallback":false}}},"duration":{"totalMilliseconds":15220288},"releaseDate":{"isoString":"2021-02-23T19:15:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["VIDEO","AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:4rOoJ6Egrf8K2IrywzwOMk","name":"The Joe Rogan Experience","coverArt":{"sources":[{"url":"https://i.scdn.co/image/97d6fdf3e55a3a1c10662d132232ccbd53740bc3","width":64,"height":64},{"url":"https://i.scdn.co/image/d3ae59a048dff7e95109aec18803f22bebe82d2f","width":300,"height":300},{"url":"https://i.scdn.co/image/9af79fd06e34dea3cd27c4e1cd6ec7343ce20af4","width":640,"height":640}]},"mediaType":"MIXED","publisher":{"name":"Joe Rogan"}}},"description":"Brian Moses is a comedian, writer, producer, and co-creator of Roast Battle. Freddie Gibbs is a rapper, founder of the ESGN music label, and 2020 Grammy Award Nominee. Check out \"Moses's Traveling Cocaine Circus\" on February 23 at Vulcan Gas Co in Austin, TX.","contentRating":{"label":"EXPLICIT"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:4pNx3gJgkjSEPCCCBR8p3o","name":"MNF Special | Freddie Ljungberg looks back on the Arsenal Invincibles","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d0ed9e875e89772954833e672","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f0ed9e875e89772954833e672","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a0ed9e875e89772954833e672","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#EE0008","isFallback":false}}},"duration":{"totalMilliseconds":933766},"releaseDate":{"isoString":"2023-11-28T12:00:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:4qJ5vj67gQcp0ACR5rYWPp","name":"The Sky Sports Football Podcast","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d0ed9e875e89772954833e672","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f0ed9e875e89772954833e672","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a0ed9e875e89772954833e672","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"Sky Sports"}}},"description":"Arsenal legend, Freddie Ljungberg joins Dave Jones and Jamie Carragher in the Monday Night Football studio to look back on Arsenal's famous 'Invincibles' season in 2003/04.","contentRating":{"label":"NONE"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:20faSH30pfYG1bdwzzjpsr","name":"#1786 - Freddie Gibbs & Brian Moses","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d428b380993fab668235ba031","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f428b380993fab668235ba031","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a428b380993fab668235ba031","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#C25800","isFallback":false}}},"duration":{"totalMilliseconds":13046740},"releaseDate":{"isoString":"2022-03-01T18:00:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["VIDEO","AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:4rOoJ6Egrf8K2IrywzwOMk","name":"The Joe Rogan Experience","coverArt":{"sources":[{"url":"https://i.scdn.co/image/97d6fdf3e55a3a1c10662d132232ccbd53740bc3","width":64,"height":64},{"url":"https://i.scdn.co/image/d3ae59a048dff7e95109aec18803f22bebe82d2f","width":300,"height":300},{"url":"https://i.scdn.co/image/9af79fd06e34dea3cd27c4e1cd6ec7343ce20af4","width":640,"height":640}]},"mediaType":"MIXED","publisher":{"name":"Joe Rogan"}}},"description":"Freddie Gibbs is a rapper, founder of the ESGN music label, and 2020 Grammy Award Nominee. Brian Moses is a comedian, writer, creator, producer and host of Roast Battle.","contentRating":{"label":"EXPLICIT"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:0VIGsUP71GLrw2TNTSzgdo","name":"Deep Trouble | 3","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#506878","isFallback":false}}},"duration":{"totalMilliseconds":1817991},"releaseDate":{"isoString":"2023-09-20T23:01:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:0UpRHsb3a73uOYLlOVPSRE","name":"Hooked on Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"Wondery"}}},"description":"Alan is caught in a tabloid frenzy. The whole country is laughing at him. But there’s nothing funny about the death threats he receives.See Privacy Policy at https://art19.com/privacy and California Privacy Notice at https://art19.com/privacy#do-not-sell-my-info.","contentRating":{"label":"EXPLICIT"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:3Hvi29RiSXhSnh7CANpNOc","name":"#548 - JOE ROGAN + FREDDIE GIBBS + BRIAN MOSES","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68da865ea62edea632339964ab9","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fa865ea62edea632339964ab9","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8aa865ea62edea632339964ab9","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#B80808","isFallback":false}}},"duration":{"totalMilliseconds":6040046},"releaseDate":{"isoString":"2022-03-12T01:50:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:77iUVnajPyEWPhY6LxjpzM","name":"KILL TONY","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68da865ea62edea632339964ab9","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fa865ea62edea632339964ab9","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8aa865ea62edea632339964ab9","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"DEATHSQUAD.TV"}}},"description":"Joe Rogan, Freddie Gibbs, Brian Moses, William Montgomery, Ellis Aych, Hans Kim, Matthew Muehling, John Deas, D Madness, Michael A. Gonzales, Jules Durel, Yoni, Joe White, Tony Hinchcliffe, Brian Redban – 02/28/2022–THIS EPISODE IS SPONSORED BY:BOX OF AWESOME! – From style and grooming goods, tobarware, cooking tools, and outdoor gear, Box of Awesome hascollections for every part of your life. – Get 20% off your first monthly box when you sign upat BOXOFAWESOME.COM and enter the code “KILLTONY” at checkout.—EXPRESSVPN.COM – GET 3 FREE MONTHS BY GOING TO: EXPRESSVPN.COM/KILLTONY—Created by and starring Jak Knight, Langston Kerman, Sam Jay and Chris Redd, Bust Down isinspired by the crew’s real-life chemistry, conversations, and friendship. The result is anirreverent, offbeat, unpredictable swirl of hijinks and absurdity. Bust Down is streaming now, only on Peacock.","contentRating":{"label":"EXPLICIT"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:4Qb2tBH5tB8MnP02RfN96s","name":"Sink or Swim | 6","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#506878","isFallback":false}}},"duration":{"totalMilliseconds":3029655},"releaseDate":{"isoString":"2023-10-09T23:01:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:0UpRHsb3a73uOYLlOVPSRE","name":"Hooked on Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"Wondery"}}},"description":"The most beautiful experience of Alan’s life has left a devastating legacy. Right now, he needs Freddie more than ever. But where is he?See Privacy Policy at https://art19.com/privacy and California Privacy Notice at https://art19.com/privacy#do-not-sell-my-info.","contentRating":{"label":"EXPLICIT"}}},{"data":{"__typename":"Episode","uri":"spotify:episode:79hXkQpF0UXOZHNRdhl895","name":"The Freddie Wong Exclusive","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d7030162c1e15aaf5318cb63d","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f7030162c1e15aaf5318cb63d","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a7030162c1e15aaf5318cb63d","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#682820","isFallback":false}}},"duration":{"totalMilliseconds":5523800},"releaseDate":{"isoString":"2022-03-06T21:08:00Z","precision":"MINUTE"},"playedState":{"playPositionMilliseconds":0,"state":"NOT_STARTED"},"mediaTypes":["AUDIO"],"podcastV2":{"data":{"__typename":"Podcast","uri":"spotify:show:78PyQphowySboNLN1tb9mP","name":"Chuckle Sandwich","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d7030162c1e15aaf5318cb63d","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f7030162c1e15aaf5318cb63d","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a7030162c1e15aaf5318cb63d","width":640,"height":640}]},"mediaType":"AUDIO","publisher":{"name":"Chuckle Sandwich"}}},"description":"On this episode of Chuckle Sandwich, we have our greatest hero in the history of online video, Freddie Wong. This is a great episode spanning a multitude of topics, we think you'll like it, you'll have a chuckle. You know you will.Advertising Inquiries: https://redcircle.com/brandsPrivacy & Opt-Out: https://redcircle.com/privacy","contentRating":{"label":"NONE"}}}]},"genres":{"totalCount":0,"items":[]},"playlists":{"totalCount":160,"items":[{"data":{"__typename":"Playlist","uri":"spotify:playlist:668OCL2fvuRaDhVA2xX0PH","name":"Freddie aguilar — Hits Songs","description":"","images":{"items":[{"sources":[{"url":"https://mosaic.scdn.co/640/ab67616d00001e021638e57af45902802bb211d9ab67616d00001e0224e8467f64a087779f8f1aa7ab67616d00001e0281777c54a751d1523fbf4124ab67616d00001e02eb51743b370d5c5e7a1a526f","width":640,"height":640},{"url":"https://mosaic.scdn.co/300/ab67616d00001e021638e57af45902802bb211d9ab67616d00001e0224e8467f64a087779f8f1aa7ab67616d00001e0281777c54a751d1523fbf4124ab67616d00001e02eb51743b370d5c5e7a1a526f","width":300,"height":300},{"url":"https://mosaic.scdn.co/60/ab67616d00001e021638e57af45902802bb211d9ab67616d00001e0224e8467f64a087779f8f1aa7ab67616d00001e0281777c54a751d1523fbf4124ab67616d00001e02eb51743b370d5c5e7a1a526f","width":60,"height":60}],"extractedColors":{"colorDark":{"hex":"#701818","isFallback":false}}}]},"format":"","attributes":[],"ownerV2":{"data":{"__typename":"User","name":"Cyndie Delos Reyes","uri":"spotify:user:22grb72kgwpcm37omtez4zx6a","username":"22grb72kgwpcm37omtez4zx6a","avatar":{"sources":[{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=796169773740679&height=50&width=50&ext=1704180808&hash=AfqkUSlS5lPgspPd-3GZ0C23X80K9TR1008qx1QK4LYskA","width":64,"height":64},{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=796169773740679&height=300&width=300&ext=1704180808&hash=AfopDAzT-vUx6WbwQL24Ntw-JbXfk5NhkDbAqS9UXHl1Qg","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1EIVMpJ61f3xiA","name":"Freddie Dredd Mix","description":"<a href=spotify:playlist:37i9dQZF1EIWqQgloIJcif>PlayaPhonk</a>, <a href=spotify:playlist:37i9dQZF1EIXHsrYuIrdd8>Kaito Shoma</a> and <a href=spotify:playlist:37i9dQZF1EIXamqlCyayjn>MUPP</a>","images":{"items":[{"sources":[{"url":"https://seed-mix-image.spotifycdn.com/v6/img/artist/0dlDsD7y6ccmDm8tuWCU6F/en/default","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#8A7074","isFallback":false}}}]},"format":"artist-mix-reader","attributes":[{"key":"mediaListConfig","value":"spotify:medialistconfig:artist-seed-mix:default_v22"},{"key":"request_id","value":"ssp|060b9623eb9e0156829a229f93f258e4691c"},{"key":"correlation-id","value":"ssp|060b9623eb9e0156829a229f93f258e4691c"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1DZ06evO0vFpVC","name":"This Is Freddie Gibbs","description":"This is Freddie Gibbs. The essential tracks, all in one playlist.","images":{"items":[{"sources":[{"url":"https://thisis-images.spotifycdn.com/37i9dQZF1DZ06evO0vFpVC-default.jpg","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#D83E46","isFallback":false}}}]},"format":"artistsets","attributes":[{"key":"artistGid","value":"1fd56c2e0ed1410582bec5e16404ee93"},{"key":"translatedArtistName","value":"Freddie Gibbs"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:3z4bdOZVA6FOY0VeX07urU","name":"Freddie Dredd Gym ☠️","description":"","images":{"items":[{"sources":[{"url":"https://i.scdn.co/image/ab67706c0000da84322a01d966bb617653a25c96","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#607070","isFallback":false}}}]},"format":"","attributes":[],"ownerV2":{"data":{"__typename":"User","name":"Ilan Pino","uri":"spotify:user:31pfgevx6ierndvdp2wc76nsafyy","username":"31pfgevx6ierndvdp2wc76nsafyy","avatar":{"sources":[{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=122834662143986&height=50&width=50&ext=1704176391&hash=AfqHs1Fb4EiDR3GjQ8aNwtCxEO0qw_MFxAw0YxcTtpoBeQ","width":64,"height":64},{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=122834662143986&height=300&width=300&ext=1704176391&hash=AfpxksYXJee4jnzHPZtxs4_HREYboKAJInvUoxikCnAWaQ","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1DZ06evO03yOTR","name":"This Is Freddie Dredd","description":"This is Freddie Dredd. The essential tracks, all in one playlist.","images":{"items":[{"sources":[{"url":"https://thisis-images.spotifycdn.com/37i9dQZF1DZ06evO03yOTR-default.jpg","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#697A71","isFallback":false}}}]},"format":"artistsets","attributes":[{"key":"artistGid","value":"07130403d3054b4e9479800d4ea7966d"},{"key":"translatedArtistName","value":"Freddie Dredd"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1EIY628PDoPlfM","name":"Freddie Aguilar Mix","description":"<a href=spotify:playlist:37i9dQZF1EIZOfily1ygVx>Coritha</a>, <a href=spotify:playlist:37i9dQZF1EIYprgZBaemPn>Sampaguita</a> and <a href=spotify:playlist:37i9dQZF1EIW2dxiRdSGIi>Roel Cortez</a>","images":{"items":[{"sources":[{"url":"https://seed-mix-image.spotifycdn.com/v6/img/artist/7fihhreD4v29FQsWykhCJm/en/default","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#B45D4F","isFallback":false}}}]},"format":"artist-mix-reader","attributes":[{"key":"mediaListConfig","value":"spotify:medialistconfig:artist-seed-mix:default_v22"},{"key":"request_id","value":"ssp|060b9623eb9e0156829a229f93f258e4691c"},{"key":"correlation-id","value":"ssp|060b9623eb9e0156829a229f93f258e4691c"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1DZ06evO2NEgTc","name":"This Is Freddie Mercury","description":"This is Freddie Mercury. The essential tracks, all in one playlist.","images":{"items":[{"sources":[{"url":"https://thisis-images.spotifycdn.com/37i9dQZF1DZ06evO2NEgTc-default.jpg","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#977036","isFallback":false}}}]},"format":"artistsets","attributes":[{"key":"artistGid","value":"9ce11638a14e42f4b36f291ac6069ecd"},{"key":"translatedArtistName","value":"Freddie Mercury"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:0fOUdz9gv1fAEozh8sct9E","name":"Freddie Mercury Best of ","description":"","images":{"items":[{"sources":[{"url":"https://mosaic.scdn.co/640/ab67616d00001e0207744e2ed983efa3e6620a47ab67616d00001e0223fa8e36a5b814e428e13478ab67616d00001e02a12daf02bea0c11ac2be610aab67616d00001e02ce4f1737bc8a646c8c4bd25a","width":640,"height":640},{"url":"https://mosaic.scdn.co/300/ab67616d00001e0207744e2ed983efa3e6620a47ab67616d00001e0223fa8e36a5b814e428e13478ab67616d00001e02a12daf02bea0c11ac2be610aab67616d00001e02ce4f1737bc8a646c8c4bd25a","width":300,"height":300},{"url":"https://mosaic.scdn.co/60/ab67616d00001e0207744e2ed983efa3e6620a47ab67616d00001e0223fa8e36a5b814e428e13478ab67616d00001e02a12daf02bea0c11ac2be610aab67616d00001e02ce4f1737bc8a646c8c4bd25a","width":60,"height":60}],"extractedColors":{"colorDark":{"hex":"#767676","isFallback":false}}}]},"format":"","attributes":[],"ownerV2":{"data":{"__typename":"User","name":"michaela.floeck","uri":"spotify:user:michaela.floeck","username":"michaela.floeck","avatar":null}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1E4q02Sea3ruPg","name":"Freddie Dredd Radio","description":"With HAARPER, Lil Darkie, Ramirez and more","images":{"items":[{"sources":[{"url":"https://seeded-session-images.scdn.co/v2/img/122/secondary/artist/0dlDsD7y6ccmDm8tuWCU6F/en","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#7B7676","isFallback":false}}}]},"format":"inspiredby-mix","attributes":[{"key":"mediaListConfig","value":"spotify:medialistconfig:artist-radio-inspiredby:default_v29"},{"key":"request_id","value":"ssp|060b9623eb9e865682a4229fadd95dc075f6"},{"key":"correlation-id","value":"ssp|060b9623eb9e865682a4229fadd95dc075f6"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1DZ06evO3Q87Cg","name":"This Is Fredz","description":"This is Fredz. The essential tracks, all in one playlist.","images":{"items":[{"sources":[{"url":"https://thisis-images.spotifycdn.com/37i9dQZF1DZ06evO3Q87Cg-default.jpg","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#881010","isFallback":false}}}]},"format":"artistsets","attributes":[{"key":"artistGid","value":"d5acd53ab3de452fa9cb6a9fd5d49735"},{"key":"translatedArtistName","value":"Fredz"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}}]},"podcasts":{"totalCount":567,"items":[{"data":{"__typename":"Podcast","uri":"spotify:show:0UpRHsb3a73uOYLlOVPSRE","name":"Hooked on Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#506878","isFallback":false}}},"publisher":{"name":"Wondery"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Documentary","uri":"spotify:genre:0JQ5DAqbMKFCWOPjGCVIq4"},{"__typename":"PodcastTopic","title":"True crime","uri":"spotify:genre:0JQ5DAqbMKFJxB6x6hfvv0"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:1FZDpAfv4pHM243JfCh5lu","name":"Wrestling with Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68dbb7767bb83b2ba19e50ad89c","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fbb7767bb83b2ba19e50ad89c","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8abb7767bb83b2ba19e50ad89c","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#777777","isFallback":false}}},"publisher":{"name":"My Cultura and iHeartPodcasts"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Sports","uri":"spotify:genre:0JQ5DAqbMKFLhhtGqqgAsz"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:13ZOVT9rEh2EvcsikrdPIq","name":"UnHerd with Freddie Sayers","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68dcd3ae26b25df5aab6ae9f81d","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fcd3ae26b25df5aab6ae9f81d","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8acd3ae26b25df5aab6ae9f81d","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#084048","isFallback":false}}},"publisher":{"name":"UnHerd"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Science","uri":"spotify:genre:0JQ5IMCbQBLzqj7yQzZb03"},{"__typename":"PodcastTopic","title":"Philosophy","uri":"spotify:genre:0JQ5IMCbQBLjLJlIwYDak9"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:73C3ccJ0To0LTZ5SHlGVpy","name":"five night’s at freddy’s tunes.","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68ddc50e33dc4e3a0b95a770958","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fdc50e33dc4e3a0b95a770958","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8adc50e33dc4e3a0b95a770958","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#886820","isFallback":false}}},"publisher":{"name":"keryn malcolm"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Games","uri":"spotify:genre:0JQ5DAqbMKFHAsyQVXtkEA"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:0OPj9ZYSAuxHs3AfnTmbwY","name":"Freddie and Harry","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d3166ec9b4336ab672745eb6a","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f3166ec9b4336ab672745eb6a","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a3166ec9b4336ab672745eb6a","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#E12D34","isFallback":false}}},"publisher":{"name":"ESPN Radio, Freddie Coleman, Harry Douglas"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Sports","uri":"spotify:genre:0JQ5DAqbMKFLhhtGqqgAsz"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:1a65iwRRAQylxb9EtRWmsd","name":"Freddy Fazbear Pizza Podcast","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68da64550e7e6b86c9aae1ffb20","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fa64550e7e6b86c9aae1ffb20","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8aa64550e7e6b86c9aae1ffb20","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#697A83","isFallback":false}}},"publisher":{"name":"RyeToast"},"mediaType":"MIXED","topics":{"items":[{"__typename":"PodcastTopic","title":"Video games","uri":"spotify:genre:0JQ5IMCbQBLtqWiaa5oQu8"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:2fYiV28elCbBGoz5mC4eBt","name":"De Grote Verkiezingsshow - met Rudi en Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d99be28820dee7b60c8c8672a","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f99be28820dee7b60c8c8672a","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a99be28820dee7b60c8c8672a","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#9B6E32","isFallback":false}}},"publisher":{"name":"De Correspondent"},"mediaType":"MIXED","topics":{"items":[]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:5cyN0aDOTiUgo0io54wX5E","name":"Freddie's One Man Show","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68ddb1f53dda98d1b290b8e0e01","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1fdb1f53dda98d1b290b8e0e01","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8adb1f53dda98d1b290b8e0e01","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#535353","isFallback":true}}},"publisher":{"name":"superfreddie"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Video games","uri":"spotify:genre:0JQ5IMCbQBLtqWiaa5oQu8"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:2J6pJn4pugImVWhU07A8T5","name":"Story Break","coverArt":{"sources":[{"url":"https://i.scdn.co/image/f70c80d871d5c8f90e6fcbae09adb4f2c46a98db","width":64,"height":64},{"url":"https://i.scdn.co/image/28e50901e709cf2e1e6fb0c50ff3152393f150ba","width":300,"height":300},{"url":"https://i.scdn.co/image/d239cc12fdf13aaf212bd13984269d38fc0d8722","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#984040","isFallback":false}}},"publisher":{"name":"RocketJump"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Film","uri":"spotify:genre:0JQ5IMCbQBLBylyI0RX5u8"},{"__typename":"PodcastTopic","title":"TV","uri":"spotify:genre:0JQ5IMCbQBLo64OouK01L3"}]}}},{"data":{"__typename":"Podcast","uri":"spotify:show:18QRX8fBL32S09fEhiVolM","name":"Mercury Mysteries","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d338d028fc254d8e2c6d5650f","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f338d028fc254d8e2c6d5650f","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a338d028fc254d8e2c6d5650f","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#AB6711","isFallback":false}}},"publisher":{"name":"Nostalgie Vlaanderen"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Music history","uri":"spotify:genre:0JQ5IMCbQBLubyEn3NCJAz"}]}}}]},"audiobooks":{"totalCount":370,"items":[{"data":{"__typename":"Audiobook","uri":"spotify:show:2sQueNGKAVFt6yxlNyHspG","name":"Daisy Jones & The Six (TV Tie-in Edition): A Novel","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703b266d40f1896129df2e1e74c7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5b266d40f1896129df2e1e74c7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a8266d40f1896129df2e1e74c7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#481810","isFallback":false}}},"authors":[{"name":"Taylor Jenkins Reid"}],"publishDate":{"isoString":"2019-03-05T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:5IH4EtibwbcFmoi1ThYaAP","name":"Freddy and the Dragon","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703b685a2bf770cda4b0bd82484b","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5b685a2bf770cda4b0bd82484b","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a8685a2bf770cda4b0bd82484b","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#A81828","isFallback":false}}},"authors":[{"name":"Walter R. Brooks"}],"publishDate":{"isoString":"2009-09-25T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:1FcMRk9fKxKCoxeXeQZic1","name":"Freddie Farrell: Excuse Me While I Burst Into Flames","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703b1be8e1aca6a223d89cf6a10c","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5b1be8e1aca6a223d89cf6a10c","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a81be8e1aca6a223d89cf6a10c","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#D83E36","isFallback":false}}},"authors":[{"name":"Freddie Farrell"}],"publishDate":{"isoString":"2017-07-21T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:0LgAbzYC2xsPVE4hrwvqNs","name":"Freddie Vs. The Family Curse","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703b4698f847446c88068b0d6864","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5b4698f847446c88068b0d6864","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a84698f847446c88068b0d6864","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#0880AE","isFallback":false}}},"authors":[{"name":"Tracy Badua"}],"publishDate":{"isoString":"2022-05-03T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:7vnE3lQG6jWblvQagPPi01","name":"Freddie Mercury: The Definitive Biography: The Definitive Biography","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703bae27c581ca811533f8824e62","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5bae27c581ca811533f8824e62","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a8ae27c581ca811533f8824e62","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#777777","isFallback":false}}},"authors":[{"name":"Lesley-Ann Jones"}],"publishDate":{"isoString":"2012-06-07T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:3QBffaAKSA2fkbfHl0dTq8","name":"Freddy Goes to Florida","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703bed7c73922c8bf80181c27d0f","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5bed7c73922c8bf80181c27d0f","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a8ed7c73922c8bf80181c27d0f","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#A81828","isFallback":false}}},"authors":[{"name":"Walter Brooks"}],"publishDate":{"isoString":"2009-09-25T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:5Rwjoy3LcxBYG6sprPRAdN","name":"Freddie Steinmark: Faith, Family, Football","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703b0465263dd1903809cb68baf7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5b0465263dd1903809cb68baf7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a80465263dd1903809cb68baf7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#686858","isFallback":false}}},"authors":[{"name":"Bower Yousse"},{"name":"Thomas J. Cryan"}],"publishDate":{"isoString":"2023-08-29T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:2s32IGc2CS6aRkgbit9hWH","name":"Freddy the Pilot","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703b0e6e150418bf306dd77c0060","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5b0e6e150418bf306dd77c0060","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a80e6e150418bf306dd77c0060","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#A01828","isFallback":false}}},"authors":[{"name":"Walter R. Brooks"}],"publishDate":{"isoString":"2009-11-06T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:6Frwq64gXCu8LLDobxtppw","name":"Freddie Ramos and the Meteorite","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703b7ae2a7ba3de9b388a10feae8","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5b7ae2a7ba3de9b388a10feae8","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a87ae2a7ba3de9b388a10feae8","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#B56124","isFallback":false}}},"authors":[{"name":"Jacqueline Jules"}],"publishDate":{"isoString":"2021-04-01T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}},{"data":{"__typename":"Audiobook","uri":"spotify:show:2Fisy2HOFktMAzEYv5LMwr","name":"Freddy Goes to the North Pole","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6766630000703bc16900d316512b884c9117f1","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6766630000db5bc16900d316512b884c9117f1","width":300,"height":300},{"url":"https://i.scdn.co/image/ab676663000022a8c16900d316512b884c9117f1","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#982038","isFallback":false}}},"authors":[{"name":"Walter R. Brooks"}],"publishDate":{"isoString":"2009-09-25T00:00:00Z"},"topics":{"items":[]},"mediaType":"AUDIO","accessInfo":null}}]},"tracksV2":{"totalCount":1000,"items":[{"matchedFields":[],"item":{"data":{"__typename":"Track","uri":"spotify:track:3uDUPK6GJZ3jv76hAOSIay","id":"3uDUPK6GJZ3jv76hAOSIay","name":"Freddie's Warmup","albumOfTrack":{"uri":"spotify:album:00igoxLQ6l5h5fXz00No8m","name":"Freddie's Warmup","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e023a774dadc88171de69817c3c","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048513a774dadc88171de69817c3c","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2733a774dadc88171de69817c3c","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#4870A0","isFallback":false}}},"id":"00igoxLQ6l5h5fXz00No8m"},"artists":{"items":[{"uri":"spotify:artist:3OcPdn7YP6TgPT4wqoDOfi","profile":{"name":"Vlado"}}]},"contentRating":{"label":"NONE"},"duration":{"totalMilliseconds":120930},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":["NAME"],"item":{"data":{"__typename":"Track","uri":"spotify:track:37F7E7BKEw2E4O2L7u0IEp","id":"37F7E7BKEw2E4O2L7u0IEp","name":"Limbo","albumOfTrack":{"uri":"spotify:album:2ll6KONxe4F87GJku1ZZrl","name":"Freddie's Inferno","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0269b381d574b329409bd806e6","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485169b381d574b329409bd806e6","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27369b381d574b329409bd806e6","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#283840","isFallback":false}}},"id":"2ll6KONxe4F87GJku1ZZrl"},"artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"contentRating":{"label":"EXPLICIT"},"duration":{"totalMilliseconds":169946},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":["NAME"],"item":{"data":{"__typename":"Track","uri":"spotify:track:46M2hXnaQpueG7vSvgVtVH","id":"46M2hXnaQpueG7vSvgVtVH","name":"GTG","albumOfTrack":{"uri":"spotify:album:4KvTJJPmcAd1XJaO3UrARG","name":"GTG","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e02f67a8d19b2c7130f0437887b","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d00004851f67a8d19b2c7130f0437887b","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b273f67a8d19b2c7130f0437887b","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#084010","isFallback":false}}},"id":"4KvTJJPmcAd1XJaO3UrARG"},"artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"contentRating":{"label":"EXPLICIT"},"duration":{"totalMilliseconds":93893},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":[],"item":{"data":{"__typename":"Track","uri":"spotify:track:5OkYfk72CNL8XLqa3gp9q7","id":"5OkYfk72CNL8XLqa3gp9q7","name":"Something to Rap About (feat. Tyler, The Creator)","albumOfTrack":{"uri":"spotify:album:3znl1qe13kyjQv7KcR685N","name":"Alfredo","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0252c24049a16d59e98a638651","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485152c24049a16d59e98a638651","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27352c24049a16d59e98a638651","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#7A7A1C","isFallback":false}}},"id":"3znl1qe13kyjQv7KcR685N"},"artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}},{"uri":"spotify:artist:0eVyjRhzZKke2KFYTcDkeu","profile":{"name":"The Alchemist"}},{"uri":"spotify:artist:4V8LLVI7PbaPR0K2TGSxFF","profile":{"name":"Tyler, The Creator"}}]},"contentRating":{"label":"EXPLICIT"},"duration":{"totalMilliseconds":282560},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":[],"item":{"data":{"__typename":"Track","uri":"spotify:track:1vvBUZseJ7fwYPX1NedOLd","id":"1vvBUZseJ7fwYPX1NedOLd","name":"Cha Cha","albumOfTrack":{"uri":"spotify:album:2SUBknzxng0iqBpKT9vzns","name":"Cha Cha","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0242ffc7773e7f4ea48e5606a8","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485142ffc7773e7f4ea48e5606a8","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27342ffc7773e7f4ea48e5606a8","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#D93C3C","isFallback":false}}},"id":"2SUBknzxng0iqBpKT9vzns"},"artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"contentRating":{"label":"EXPLICIT"},"duration":{"totalMilliseconds":173937},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":["NAME"],"item":{"data":{"__typename":"Track","uri":"spotify:track:4ysmfC5JyEaBuLQt5OiGZU","id":"4ysmfC5JyEaBuLQt5OiGZU","name":"Freddie Mercury","albumOfTrack":{"uri":"spotify:album:2F6fL177vAARDz0nSWdoNe","name":"Grandeur mature","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e020abb308765ae8782712d7ec6","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048510abb308765ae8782712d7ec6","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2730abb308765ae8782712d7ec6","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#D74015","isFallback":false}}},"id":"2F6fL177vAARDz0nSWdoNe"},"artists":{"items":[{"uri":"spotify:artist:0q9gV5iFHokttrI4WBuRQu","profile":{"name":"Émile Bilodeau"}},{"uri":"spotify:artist:7vYe47XsRmlUuaA9ZSC9fi","profile":{"name":"Klô Pelgag"}}]},"contentRating":{"label":"NONE"},"duration":{"totalMilliseconds":235773},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":[],"item":{"data":{"__typename":"Track","uri":"spotify:track:1p1b9LdLJ0REuFJX9mYtFX","id":"1p1b9LdLJ0REuFJX9mYtFX","name":"1985","albumOfTrack":{"uri":"spotify:album:3znl1qe13kyjQv7KcR685N","name":"Alfredo","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0252c24049a16d59e98a638651","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485152c24049a16d59e98a638651","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27352c24049a16d59e98a638651","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#7A7A1C","isFallback":false}}},"id":"3znl1qe13kyjQv7KcR685N"},"artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}},{"uri":"spotify:artist:0eVyjRhzZKke2KFYTcDkeu","profile":{"name":"The Alchemist"}}]},"contentRating":{"label":"EXPLICIT"},"duration":{"totalMilliseconds":152546},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":["NAME"],"item":{"data":{"__typename":"Track","uri":"spotify:track:3omcH1HGghFtzaFGgazoy8","id":"3omcH1HGghFtzaFGgazoy8","name":"Devil's Work","albumOfTrack":{"uri":"spotify:album:4WLWbEhOq5kphrWF5oEEou","name":"Suffer","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e02ab400f73482c4eff6121adfb","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d00004851ab400f73482c4eff6121adfb","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b273ab400f73482c4eff6121adfb","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#E02018","isFallback":false}}},"id":"4WLWbEhOq5kphrWF5oEEou"},"artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"contentRating":{"label":"NONE"},"duration":{"totalMilliseconds":125608},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":["NAME"],"item":{"data":{"__typename":"Track","uri":"spotify:track:2x91iJc0UkFcjRMEZ2CoWB","id":"2x91iJc0UkFcjRMEZ2CoWB","name":"Freddie Freeloader (feat. John Coltrane, Cannonball Adderley, Wynton Kelly & Paul Chambers)","albumOfTrack":{"uri":"spotify:album:4sb0eMpDn3upAFfyi4q2rw","name":"Kind Of Blue (Legacy Edition)","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e020ebc17239b6b18ba88cfb8ca","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048510ebc17239b6b18ba88cfb8ca","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2730ebc17239b6b18ba88cfb8ca","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#303848","isFallback":false}}},"id":"4sb0eMpDn3upAFfyi4q2rw"},"artists":{"items":[{"uri":"spotify:artist:0kbYTNQb4Pb1rPbbaF0pT4","profile":{"name":"Miles Davis"}},{"uri":"spotify:artist:2hGh5VOeeqimQFxqXvfCUf","profile":{"name":"John Coltrane"}},{"uri":"spotify:artist:5v74mT11KGJqadf9sLw4dA","profile":{"name":"Cannonball Adderley"}},{"uri":"spotify:artist:5ncBRFyyylFng7kQJaRXN0","profile":{"name":"Wynton Kelly"}},{"uri":"spotify:artist:0M1UOBJZ9tcKJbrbnVlHZG","profile":{"name":"Paul Chambers"}}]},"contentRating":{"label":"NONE"},"duration":{"totalMilliseconds":586400},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":["NAME"],"item":{"data":{"__typename":"Track","uri":"spotify:track:5WbKBMz6y0FbUdZl18XlJO","id":"5WbKBMz6y0FbUdZl18XlJO","name":"Wrath","albumOfTrack":{"uri":"spotify:album:2ll6KONxe4F87GJku1ZZrl","name":"Freddie's Inferno","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e0269b381d574b329409bd806e6","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d0000485169b381d574b329409bd806e6","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b27369b381d574b329409bd806e6","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#283840","isFallback":false}}},"id":"2ll6KONxe4F87GJku1ZZrl"},"artists":{"items":[{"uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd"}}]},"contentRating":{"label":"EXPLICIT"},"duration":{"totalMilliseconds":113546},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}}]},"users":{"totalCount":10,"items":[{"data":{"__typename":"User","uri":"spotify:user:archbonkers","id":"archbonkers","displayName":"Freddie Gibbs","username":"archbonkers","avatar":null}},{"data":{"__typename":"User","uri":"spotify:user:freddielore","id":"freddielore","displayName":"Freddie Lore","username":"freddielore","avatar":{"sources":[{"url":"https://scontent-iad3-2.xx.fbcdn.net/v/t39.30808-1/339576326_521266213307501_6468102634403870173_n.jpg?stp=cp0_dst-jpg_p50x50&_nc_cat=105&ccb=1-7&_nc_sid=4da83f&_nc_ohc=v7Udtu4XwZMAX-mVvAC&_nc_ht=scontent-iad3-2.xx&edm=AP4hL3IEAAAA&oh=00_AfA-CEJBszwxAom4LfdyJb9dTZH-C9hrltL7LrFHIveWWg&oe=65709E97","width":64,"height":64},{"url":"https://scontent-iad3-2.xx.fbcdn.net/v/t39.30808-1/339576326_521266213307501_6468102634403870173_n.jpg?stp=dst-jpg_p320x320&_nc_cat=105&ccb=1-7&_nc_sid=9e7101&_nc_ohc=v7Udtu4XwZMAX-mVvAC&_nc_ht=scontent-iad3-2.xx&edm=AP4hL3IEAAAA&oh=00_AfCQYTcOPSpw7q_2e9VMtL8-afJTihtjjoLFmPgBuC6mcg&oe=65709E97","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#7F7F7F","isFallback":true}}}}},{"data":{"__typename":"User","uri":"spotify:user:winger","id":"winger","displayName":"Freddie Tanzi Winger","username":"winger","avatar":{"sources":[{"url":"https://scontent-iad3-1.xx.fbcdn.net/v/t1.6435-1/117577894_10157564190306717_1583458534180709848_n.jpg?stp=cp0_dst-jpg_p50x50&_nc_cat=110&ccb=1-7&_nc_sid=db1b99&_nc_ohc=qOoO7dXcYZUAX9woOM4&_nc_ht=scontent-iad3-1.xx&edm=AP4hL3IEAAAA&oh=00_AfDtxtJF7nD748dscUsmFuRrCV_StQVN0pWhNvwYJ5lxUQ&oe=65931029","width":64,"height":64},{"url":"https://scontent-iad3-1.xx.fbcdn.net/v/t1.6435-1/117577894_10157564190306717_1583458534180709848_n.jpg?stp=dst-jpg_p320x320&_nc_cat=110&ccb=1-7&_nc_sid=0be577&_nc_ohc=qOoO7dXcYZUAX9woOM4&_nc_ht=scontent-iad3-1.xx&edm=AP4hL3IEAAAA&oh=00_AfBDmOJ9S3tJz6MAZL7TJb8L3LIVaPn2bQVqYQOUkZ5Wtg&oe=65931029","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#7F7F7F","isFallback":true}}}}},{"data":{"__typename":"User","uri":"spotify:user:yhmqhnjpjnvw4pi1iy9ijty8z","id":"yhmqhnjpjnvw4pi1iy9ijty8z","displayName":"Freddie Dredd","username":"yhmqhnjpjnvw4pi1iy9ijty8z","avatar":null}},{"data":{"__typename":"User","uri":"spotify:user:freddiemercuryofficial","id":"freddiemercuryofficial","displayName":"Freddie Mercury","username":"freddiemercuryofficial","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8217e92a04193b7921355b6c6c","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8517e92a04193b7921355b6c6c","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#D14361","isFallback":false}}}}},{"data":{"__typename":"User","uri":"spotify:user:31lhgb7qhgkvdvpzwc3br47uyaom","id":"31lhgb7qhgkvdvpzwc3br47uyaom","displayName":"Freddie","username":"31lhgb7qhgkvdvpzwc3br47uyaom","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b824087851cc094302687a01be8","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee854087851cc094302687a01be8","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#381818","isFallback":false}}}}},{"data":{"__typename":"User","uri":"spotify:user:fw0ng","id":"fw0ng","displayName":"Freddie Wong","username":"fw0ng","avatar":{"sources":[{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=10102262577228925&height=50&width=50&ext=1704162248&hash=Afot9sTfOc2vr3WIxCOIJ5nra1PV0mESLdQrhpeR6x32mA","width":64,"height":64},{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=10102262577228925&height=300&width=300&ext=1704162248&hash=AfpS8wIN8vKTYuUTvP4-uPEAnxyECNPNPzjxjzbFcT3KMQ","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#7F7F7F","isFallback":true}}}}},{"data":{"__typename":"User","uri":"spotify:user:tmtylblog","id":"tmtylblog","displayName":"Freddie Laker","username":"tmtylblog","avatar":{"sources":[{"url":"https://scontent-iad3-2.xx.fbcdn.net/v/t39.30808-1/287759827_10159908940012118_6161228018076305417_n.jpg?stp=cp0_dst-jpg_p50x50&_nc_cat=106&ccb=1-7&_nc_sid=4da83f&_nc_ohc=9uh39yK0_UYAX8WCj1S&_nc_ht=scontent-iad3-2.xx&edm=AP4hL3IEAAAA&oh=00_AfCiWnTG8n1kocdcgO8Ea8FU_YtMmk5CqApNBjU1Bc0KQw&oe=65712892","width":64,"height":64},{"url":"https://scontent-iad3-2.xx.fbcdn.net/v/t39.30808-1/287759827_10159908940012118_6161228018076305417_n.jpg?stp=dst-jpg_p320x320&_nc_cat=106&ccb=1-7&_nc_sid=9e7101&_nc_ohc=9uh39yK0_UYAX8WCj1S&_nc_ht=scontent-iad3-2.xx&edm=AP4hL3IEAAAA&oh=00_AfBYfFQIGhQdrffbIp8AqKirpIUS8543Ff_9RBMaPGN5PA&oe=65712892","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#7F7F7F","isFallback":true}}}}},{"data":{"__typename":"User","uri":"spotify:user:freddieblad","id":"freddieblad","displayName":"Freddie Baker","username":"freddieblad","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b825f9ceb04432862041aa12467","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee855f9ceb04432862041aa12467","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#535353","isFallback":true}}}}},{"data":{"__typename":"User","uri":"spotify:user:fred19hki","id":"fred19hki","displayName":"Freddie McPex","username":"fred19hki","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b82735ef4b36ce78104a5803950","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee85735ef4b36ce78104a5803950","width":300,"height":300}],"extractedColors":{"colorDark":{"hex":"#981050","isFallback":false}}}}}]},"topResults":{"itemsV2":[{"matchedFields":[],"item":{"data":{"__typename":"Artist","uri":"spotify:artist:0dlDsD7y6ccmDm8tuWCU6F","profile":{"name":"Freddie Dredd","verified":true},"visuals":{"avatarImage":{"sources":[{"url":"https://i.scdn.co/image/ab6761610000e5eb9d100e5a9cf34beab8e75750","width":640,"height":640},{"url":"https://i.scdn.co/image/ab6761610000f1789d100e5a9cf34beab8e75750","width":160,"height":160},{"url":"https://i.scdn.co/image/ab676161000051749d100e5a9cf34beab8e75750","width":320,"height":320}],"extractedColors":{"colorDark":{"hex":"#505048","isFallback":false}}}}}}},{"matchedFields":[],"item":{"data":{"__typename":"Track","uri":"spotify:track:3uDUPK6GJZ3jv76hAOSIay","id":"3uDUPK6GJZ3jv76hAOSIay","name":"Freddie's Warmup","albumOfTrack":{"uri":"spotify:album:00igoxLQ6l5h5fXz00No8m","name":"Freddie's Warmup","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e023a774dadc88171de69817c3c","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d000048513a774dadc88171de69817c3c","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b2733a774dadc88171de69817c3c","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#4870A0","isFallback":false}}},"id":"00igoxLQ6l5h5fXz00No8m"},"artists":{"items":[{"uri":"spotify:artist:3OcPdn7YP6TgPT4wqoDOfi","profile":{"name":"Vlado"}}]},"contentRating":{"label":"NONE"},"duration":{"totalMilliseconds":120930},"playability":{"playable":true},"associations":{"associatedVideos":{"totalCount":0}}}}},{"matchedFields":[],"item":{"data":{"__typename":"Playlist","uri":"spotify:playlist:668OCL2fvuRaDhVA2xX0PH","name":"Freddie aguilar — Hits Songs","description":"","images":{"items":[{"sources":[{"url":"https://mosaic.scdn.co/640/ab67616d00001e021638e57af45902802bb211d9ab67616d00001e0224e8467f64a087779f8f1aa7ab67616d00001e0281777c54a751d1523fbf4124ab67616d00001e02eb51743b370d5c5e7a1a526f","width":640,"height":640},{"url":"https://mosaic.scdn.co/300/ab67616d00001e021638e57af45902802bb211d9ab67616d00001e0224e8467f64a087779f8f1aa7ab67616d00001e0281777c54a751d1523fbf4124ab67616d00001e02eb51743b370d5c5e7a1a526f","width":300,"height":300},{"url":"https://mosaic.scdn.co/60/ab67616d00001e021638e57af45902802bb211d9ab67616d00001e0224e8467f64a087779f8f1aa7ab67616d00001e0281777c54a751d1523fbf4124ab67616d00001e02eb51743b370d5c5e7a1a526f","width":60,"height":60}],"extractedColors":{"colorDark":{"hex":"#701818","isFallback":false}}}]},"format":"","attributes":[],"ownerV2":{"data":{"__typename":"User","name":"Cyndie Delos Reyes","uri":"spotify:user:22grb72kgwpcm37omtez4zx6a","username":"22grb72kgwpcm37omtez4zx6a","avatar":{"sources":[{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=796169773740679&height=50&width=50&ext=1704180808&hash=AfqkUSlS5lPgspPd-3GZ0C23X80K9TR1008qx1QK4LYskA","width":64,"height":64},{"url":"https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=796169773740679&height=300&width=300&ext=1704180808&hash=AfopDAzT-vUx6WbwQL24Ntw-JbXfk5NhkDbAqS9UXHl1Qg","width":300,"height":300}]}}}}}},{"matchedFields":[],"item":{"data":{"__typename":"Album","uri":"spotify:album:43uErencdmuTRFZPG3zXL1","name":"Piñata","artists":{"items":[{"uri":"spotify:artist:0Y4inQK6OespitzD6ijMwb","profile":{"name":"Freddie Gibbs"}},{"uri":"spotify:artist:5LhTec3c7dcqBvpLRWbMcf","profile":{"name":"Madlib"}}]},"coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab67616d00001e02d844f6b7311a69b9a08e7a0f","width":300,"height":300},{"url":"https://i.scdn.co/image/ab67616d00004851d844f6b7311a69b9a08e7a0f","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67616d0000b273d844f6b7311a69b9a08e7a0f","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#777777","isFallback":false}}},"date":{"year":2014}}}},{"matchedFields":[],"item":{"data":{"__typename":"Podcast","uri":"spotify:show:0UpRHsb3a73uOYLlOVPSRE","name":"Hooked on Freddie","coverArt":{"sources":[{"url":"https://i.scdn.co/image/ab6765630000f68d39264359c565e389be9a0bc7","width":64,"height":64},{"url":"https://i.scdn.co/image/ab67656300005f1f39264359c565e389be9a0bc7","width":300,"height":300},{"url":"https://i.scdn.co/image/ab6765630000ba8a39264359c565e389be9a0bc7","width":640,"height":640}],"extractedColors":{"colorDark":{"hex":"#506878","isFallback":false}}},"publisher":{"name":"Wondery"},"mediaType":"AUDIO","topics":{"items":[{"__typename":"PodcastTopic","title":"Documentary","uri":"spotify:genre:0JQ5DAqbMKFCWOPjGCVIq4"},{"__typename":"PodcastTopic","title":"True crime","uri":"spotify:genre:0JQ5DAqbMKFJxB6x6hfvv0"}]}}}}],"featured":[{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1DZ06evO03yOTR","name":"This Is Freddie Dredd","description":"This is Freddie Dredd. The essential tracks, all in one playlist.","images":{"items":[{"sources":[{"url":"https://thisis-images.spotifycdn.com/37i9dQZF1DZ06evO03yOTR-default.jpg","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#697A71","isFallback":false}}}]},"format":"artistsets","attributes":[{"key":"artistGid","value":"07130403d3054b4e9479800d4ea7966d"},{"key":"translatedArtistName","value":"Freddie Dredd"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1E4q02Sea3ruPg","name":"Freddie Dredd Radio","description":"With HAARPER, Lil Darkie, Ramirez and more","images":{"items":[{"sources":[{"url":"https://seeded-session-images.scdn.co/v2/img/122/secondary/artist/0dlDsD7y6ccmDm8tuWCU6F/en","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#7B7676","isFallback":false}}}]},"format":"inspiredby-mix","attributes":[{"key":"mediaListConfig","value":"spotify:medialistconfig:artist-radio-inspiredby:default_v29"},{"key":"request_id","value":"ssp|060b9623eba4853e754ad63d1916cbc6db98"},{"key":"correlation-id","value":"ssp|060b9623eba4853e754ad63d1916cbc6db98"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}},{"data":{"__typename":"Playlist","uri":"spotify:playlist:37i9dQZF1DX89EkrAT8Z6U","name":"shōnen","description":"A mixtape for the perfect anime fight scene.","images":{"items":[{"sources":[{"url":"https://i.scdn.co/image/ab67706f00000002f11d2a4483ba53adf4ee6c55","width":null,"height":null}],"extractedColors":{"colorDark":{"hex":"#E02E3E","isFallback":false}}}]},"format":"format-shows-shuffle","attributes":[{"key":"mediaListConfig","value":"spotify:medialistconfig:editorial:default_v38"},{"key":"request_id","value":"ssp|060b9596bca8322894bd517d4bfa48fe4039"},{"key":"uri","value":"spotify:user:spotify:playlist:37i9dQZF1DX89EkrAT8Z6U"},{"key":"status","value":"PUBLISHED"},{"key":"isAlgotorial","value":"true"},{"key":"moveFollowersJobId","value":"8e9ce39f-4a24-44c3-9a6e-0d9d201d5ef5"},{"key":"primary_color","value":"#ffffff"},{"key":"header_image_url_desktop","value":"https://i.scdn.co/image/ab6768640000fe896e4dfcc0d3f3622653ba5f68"},{"key":"image_url","value":"https://i.scdn.co/image/ab67686d00003ae0a36d0a9421b77e6d3cf571c4"},{"key":"episode_description","value":"A mixtape for the perfect anime fight scene."},{"key":"correlation-id","value":"ssp|060b9596bca8322894bd517d4bfa48fe4039"}],"ownerV2":{"data":{"__typename":"User","name":"Spotify","uri":"spotify:user:spotify","username":"spotify","avatar":{"sources":[{"url":"https://i.scdn.co/image/ab67757000003b8255c25988a6ac314394d3fbf5","width":64,"height":64},{"url":"https://i.scdn.co/image/ab6775700000ee8555c25988a6ac314394d3fbf5","width":300,"height":300}]}}}}}]},"chipOrder":{"items":[{"typeName":"TOP_RESULTS"},{"typeName":"AUDIOBOOKS"},{"typeName":"ARTISTS"},{"typeName":"TRACKS"},{"typeName":"PLAYLISTS"},{"typeName":"ALBUMS"},{"typeName":"PODCASTS"},{"typeName":"EPISODES"},{"typeName":"USERS"},{"typeName":"GENRES"}]}}},"extensions":{"requestIds":{"/searchV2":{"search-api":"145870a2-b232-4f4e-810a-99cdf2a6a9f3/VHGk"},"/searchV2/topResults":{"search-api":"145870a2-b232-4f4e-810a-99cdf2a6a9f3/VV96"}}}}
diff --git a/scraper/spotify.php b/scraper/spotify.php
new file mode 100644
index 0000000..79f61a6
--- /dev/null
+++ b/scraper/spotify.php
@@ -0,0 +1,726 @@
+<?php
+
+class spotify{
+
+ private const req_web = 0;
+ private const req_api = 1;
+ private const req_clientid = 2;
+
+ public function __construct(){
+
+ include "lib/backend.php";
+ $this->backend = new backend("spotify");
+
+ include "lib/fuckhtml.php";
+ $this->fuckhtml = new fuckhtml();
+ }
+
+ public function getfilters($page){
+
+ return [
+ "category" => [
+ "display" => "Category",
+ "option" => [
+ "any" => "All (no pagination)",
+ "audiobooks" => "Audiobooks",
+ "tracks" => "Songs",
+ "artists" => "Artists",
+ "playlists" => "Playlists",
+ "albums" => "Albums",
+ "podcastAndEpisodes" => "Podcasts & Shows (no pagination)",
+ "episodes" => "Episodes",
+ "users" => "Profiles"
+ ]
+ ]
+ ];
+ }
+
+ private function get($proxy, $url, $get = [], $reqtype = self::req_web, $bearer = null, $token = null){
+
+ $curlproc = curl_init();
+
+ switch($reqtype){
+
+ case self::req_api:
+ $headers = [
+ "User-Agent: " . config::USER_AGENT,
+ "Accept: application/json",
+ "Accept-Language: en",
+ "app-platform: WebPlayer",
+ "authorization: Bearer {$bearer}",
+ "client-token: {$token}",
+ "content-type: application/json;charset=UTF-8",
+ "Origin: https://open.spotify.com",
+ "Referer: https://open.spotify.com/",
+ "DNT: 1",
+ "Connection: keep-alive",
+ "Sec-Fetch-Dest: empty",
+ "Sec-Fetch-Mode: cors",
+ "Sec-Fetch-Site: same-site",
+ "spotify-app-version: 1.2.27.93.g7aee53d4",
+ "TE: trailers"
+ ];
+ break;
+
+ case self::req_web:
+ $headers = [
+ "User-Agent: " . config::USER_AGENT,
+ "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",
+ "Sec-GPC: 1",
+ "Connection: keep-alive",
+ "Upgrade-Insecure-Requests: 1",
+ "Sec-Fetch-Dest: document",
+ "Sec-Fetch-Mode: navigate",
+ "Sec-Fetch-Site: cross-site"
+ ];
+ break;
+
+ case self::req_clientid:
+ $get = json_encode($get);
+
+ curl_setopt($curlproc, CURLOPT_POST, true);
+ curl_setopt($curlproc, CURLOPT_POSTFIELDS, $get);
+
+ $headers = [
+ "User-Agent:" . config::USER_AGENT,
+ "Accept: application/json",
+ "Accept-Language: en-US,en;q=0.5",
+ "Accept-Encoding: gzip, deflate, br",
+ "Referer: https://open.spotify.com/",
+ "content-type: application/json",
+ "Content-Length: " . strlen($get),
+ "Origin: https://open.spotify.com",
+ "DNT: 1",
+ "Sec-GPC: 1",
+ "Connection: keep-alive",
+ "Sec-Fetch-Dest: empty",
+ "Sec-Fetch-Mode: cors",
+ "Sec-Fetch-Site: same-site",
+ "TE: trailers"
+ ];
+ break;
+ }
+
+ if($reqtype !== self::req_clientid){
+ 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, $headers);
+
+ 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);
+
+ $this->backend->assign_proxy($curlproc, $proxy);
+
+ $data = curl_exec($curlproc);
+
+ if(curl_errno($curlproc)){
+ throw new Exception(curl_error($curlproc));
+ }
+
+ curl_close($curlproc);
+ return $data;
+ }
+
+ public function music($get){
+
+ $search = $get["s"];
+ $ip = $this->backend->get_ip();
+ $category = $get["category"];
+
+ /*
+ audiobooks first and second page decoded
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchAudiobooks&variables={"searchTerm":"freddie+dredd","offset":0,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"8758e540afdba5afa3c5246817f6bd31d86a15b3f5666c363dd017030f35d785"}}
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchAudiobooks&variables={"searchTerm":"freddie+dredd","offset":30,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"8758e540afdba5afa3c5246817f6bd31d86a15b3f5666c363dd017030f35d785"}}
+ */
+
+ /*
+ songs
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchTracks&variables={"searchTerm":"asmr","offset":0,"limit":100,"numberOfTopResults":20,"includeAudiobooks":false}&extensions={"persistedQuery":{"version":1,"sha256Hash":"16c02d6304f5f721fc2eb39dacf2361a4543815112506a9c05c9e0bc9733a679"}}
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchTracks&variables={"searchTerm":"asmr","offset":100,"limit":100,"numberOfTopResults":20,"includeAudiobooks":false}&extensions={"persistedQuery":{"version":1,"sha256Hash":"16c02d6304f5f721fc2eb39dacf2361a4543815112506a9c05c9e0bc9733a679"}}
+ */
+
+ /*
+ artists
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchArtists&variables={"searchTerm":"asmr","offset":0,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"b8840daafdda9a9ceadb7c5774731f63f9eca100445d2d94665f2dc58b45e2b9"}}
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchArtists&variables={"searchTerm":"asmr","offset":30,"limit":23,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"b8840daafdda9a9ceadb7c5774731f63f9eca100445d2d94665f2dc58b45e2b9"}}
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchArtists&variables={"searchTerm":"asmr","offset":53,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"b8840daafdda9a9ceadb7c5774731f63f9eca100445d2d94665f2dc58b45e2b9"}}
+ */
+
+ /*
+ playlists
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchPlaylists&variables={"searchTerm":"asmr","offset":0,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"19b4143a0500ccec189ca0f4a0316bc2c615ecb51ce993ba4d7d08afd1d87aa4"}}
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchPlaylists&variables={"searchTerm":"asmr","offset":30,"limit":3,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"19b4143a0500ccec189ca0f4a0316bc2c615ecb51ce993ba4d7d08afd1d87aa4"}}
+ */
+
+ /*
+ albums
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchAlbums&variables={"searchTerm":"asmr","offset":33,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"e93b13cda461482da2940467eb2beed9368e9bb2fff37df3fb6633fc61271a27"}}
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchAlbums&variables={"searchTerm":"asmr","offset":33,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"e93b13cda461482da2940467eb2beed9368e9bb2fff37df3fb6633fc61271a27"}}
+ */
+
+ /*
+ podcasts & shows (contains authors, no pagination)
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchFullEpisodes&variables={"searchTerm":"asmr","offset":0,"limit":30}&extensions={"persistedQuery":{"version":1,"sha256Hash":"9f996251c9781fabce63f1a9980b5287ea33bc5e8c8953d0c4689b09936067a1"}}
+ */
+
+ /*
+ episodes
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchDesktop&variables={"searchTerm":"asmr","offset":0,"limit":10,"numberOfTopResults":5,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"da03293d92a2cfc5e24597dcdc652c0ad135e1c64a78fddbf1478a7e096bea44"}}
+ ??? https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchFullEpisodes&variables={"searchTerm":"asmr","offset":60,"limit":30}&extensions={"persistedQuery":{"version":1,"sha256Hash":"9f996251c9781fabce63f1a9980b5287ea33bc5e8c8953d0c4689b09936067a1"}}
+ */
+
+ /*
+ profiles
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchUsers&variables={"searchTerm":"asmr","offset":0,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"02026f48ab5001894e598904079b620ebc64f2d53b55ca20c3858abd3a46c5fb"}}
+ https://api-partner.spotify.com/pathfinder/v1/query?operationName=searchUsers&variables={"searchTerm":"asmr","offset":30,"limit":30,"numberOfTopResults":20,"includeAudiobooks":true}&extensions={"persistedQuery":{"version":1,"sha256Hash":"02026f48ab5001894e598904079b620ebc64f2d53b55ca20c3858abd3a46c5fb"}}
+ */
+
+ // get HTML
+ try{
+
+ $html =
+ $this->get(
+ $ip,
+ "https://open.spotify.com/search/" .
+ rawurlencode($search) .
+ ($category != "any" ? "/" . $category : ""),
+ []
+ );
+ }catch(Exception $error){
+
+ throw new Exception("Failed to get initial search page");
+ }
+
+ // grep bearer and client ID
+ $this->fuckhtml->load($html);
+
+ $script =
+ $this->fuckhtml
+ ->getElementById(
+ "session",
+ "script"
+ );
+
+ if($script === null){
+
+ throw new Exception("Failed to grep bearer token");
+ }
+
+ $script =
+ json_decode(
+ $script["innerHTML"],
+ true
+ );
+
+ $bearer = $script["accessToken"];
+ $client_id = $script["clientId"];
+
+ // hit client ID endpoint
+ try{
+
+ $token =
+ json_decode(
+ $this->get(
+ $ip,
+ "https://clienttoken.spotify.com/v1/clienttoken",
+ [ // !! that shit must be sent as json data
+ "client_data" => [
+ "client_id" => $client_id,
+ "client_version" => "1.2.27.93.g7aee53d4",
+ "js_sdk_data" => [
+ "device_brand" => "unknown",
+ "device_id" => "4c7ca20117ca12288ea8fc7118a9118c",
+ "device_model" => "unknown",
+ "device_name" => "computer",
+ "os" => "windows",
+ "os_version" => "NT 10.0"
+ ]
+ ]
+ ],
+ self::req_clientid
+ ),
+ true
+ );
+ }catch(Exception $error){
+
+ throw new Exception("Failed to fetch token");
+ }
+
+ if($token === null){
+
+ throw new Exception("Failed to decode token");
+ }
+
+ $token = $token["granted_token"]["token"];
+
+ try{
+
+ switch($get["option"]){
+
+ case "any":
+ $variables = [
+ "searchTerm" => $search,
+ "offset" => 0,
+ "limit" => 10,
+ "numberOfTopResults" => 5,
+ "includeAudiobooks" => true
+ ];
+ break;
+
+ case "audiobooks":
+
+ break;
+ }
+
+ $payload =
+ $this->get(
+ $ip,
+ "https://api-partner.spotify.com/pathfinder/v1/query",
+ [
+ "operationName" => "searchDesktop",
+ "variables" =>
+ json_encode(
+ [
+ "searchTerm" => $search,
+ "offset" => 0,
+ "limit" => 10,
+ "numberOfTopResults" => 5,
+ "includeAudiobooks" => true
+ ]
+ ),
+ "extensions" =>
+ json_encode(
+ [
+ "persistedQuery" => [
+ "version" => 1,
+ "sha256Hash" => "21969b655b795601fb2d2204a4243188e75fdc6d3520e7b9cd3f4db2aff9591e" // ?
+ ]
+ ]
+ )
+ ],
+ self::req_api,
+ $bearer,
+ $token
+ );
+
+ }catch(Exception $error){
+
+ throw new Exception("Failed to fetch JSON results");
+ }
+
+ if($payload == "Token expired"){
+
+ throw new Exception("Grepped spotify token has expired");
+ }
+
+ $payload = json_decode($payload, true);
+
+ if($payload === null){
+
+ throw new Exception("Failed to decode JSON results");
+ }
+
+ //$payload = json_decode(file_get_contents("scraper/spotify.json"), true);
+
+ $out = [
+ "status" => "ok",
+ "npt" => null,
+ "song" => [],
+ "playlist" => [],
+ "album" => [],
+ "podcast" => [],
+ "author" => [],
+ "user" => []
+ ];
+
+ // get songs
+ foreach($payload["data"]["searchV2"]["tracksV2"]["items"] as $result){
+
+ if(isset($result["item"])){
+
+ $result = $result["item"];
+ }
+
+ if(isset($result["data"])){
+
+ $result = $result["data"];
+ }
+
+ [$artist, $artist_link] = $this->get_artists($result["artists"]);
+
+ $out["song"][] = [
+ "title" => $result["name"],
+ "description" => null,
+ "url" => "https://open.spotify.com/track/" . $result["id"],
+ "views" => null,
+ "author" => [
+ "name" => $artist,
+ "url" => $artist_link,
+ "avatar" => null
+ ],
+ "thumb" => $this->get_thumb($result["albumOfTrack"]["coverArt"]),
+ "date" => null,
+ "duration" => $result["duration"]["totalMilliseconds"] / 1000,
+ "stream" => [
+ "endpoint" => "spotify",
+ "url" => "track." . $result["id"]
+ ]
+ ];
+ }
+
+ // get playlists
+ foreach($payload["data"]["searchV2"]["playlists"]["items"] as $playlist){
+
+ if(isset($playlist["data"])){
+
+ $playlist = $playlist["data"];
+ }
+
+ $avatar = $this->get_thumb($playlist["ownerV2"]["data"]["avatar"]);
+
+ $out["playlist"][] = [
+ "title" => $playlist["name"],
+ "description" => null,
+ "author" => [
+ "name" => $playlist["ownerV2"]["data"]["name"],
+ "url" =>
+ "https://open.spotify.com/user/" .
+ explode(
+ ":",
+ $playlist["ownerV2"]["data"]["uri"],
+ 3
+ )[2],
+ "avatar" => $avatar["url"]
+ ],
+ "thumb" => $this->get_thumb($playlist["images"]["items"][0]),
+ "date" => null,
+ "duration" => null,
+ "url" =>
+ "https://open.spotify.com/playlist/" .
+ explode(
+ ":",
+ $playlist["uri"],
+ 3
+ )[2]
+ ];
+ }
+
+ // get albums
+ foreach($payload["data"]["searchV2"]["albums"]["items"] as $album){
+
+ if(isset($album["data"])){
+
+ $album = $album["data"];
+ }
+
+ [$artist, $artist_link] = $this->get_artists($album["artists"]);
+
+ $out["album"][] = [
+ "title" => $album["name"],
+ "description" => null,
+ "author" => [
+ "name" => $artist,
+ "url" => $artist_link,
+ "avatar" => null
+ ],
+ "thumb" => $this->get_thumb($album["coverArt"]),
+ "date" => mktime(0, 0, 0, 0, 32, $album["date"]["year"]),
+ "duration" => null,
+ "url" =>
+ "https://open.spotify.com/album/" .
+ explode(
+ ":",
+ $album["uri"],
+ 3
+ )[2]
+ ];
+ }
+
+ // get podcasts
+ foreach($payload["data"]["searchV2"]["podcasts"]["items"] as $podcast){
+
+ if(isset($podcast["data"])){
+
+ $podcast = $podcast["data"];
+ }
+
+ $description = [];
+ foreach($podcast["topics"]["items"] as $subject){
+
+ $description[] = $subject["title"];
+ }
+
+ $description = implode(", ", $description);
+
+ if($description == ""){
+
+ $description = null;
+ }
+
+ $out["podcast"][] = [
+ "title" => $podcast["name"],
+ "description" => $description,
+ "author" => [
+ "name" => $podcast["publisher"]["name"],
+ "url" => null,
+ "avatar" => null
+ ],
+ "thumb" => $this->get_thumb($podcast["coverArt"]),
+ "date" => null,
+ "duration" => null,
+ "url" =>
+ "https://open.spotify.com/show/" .
+ explode(
+ ":",
+ $podcast["uri"],
+ 3
+ )[2],
+ "stream" => [
+ "endpoint" => null,
+ "url" => null
+ ]
+ ];
+ }
+
+ // get audio books (put in podcasts)
+ foreach($payload["data"]["searchV2"]["audiobooks"]["items"] as $podcast){
+
+ if(isset($podcast["data"])){
+
+ $podcast = $podcast["data"];
+ }
+
+ $description = [];
+ foreach($podcast["topics"]["items"] as $subject){
+
+ $description[] = $subject["title"];
+ }
+
+ $description = implode(", ", $description);
+
+ if($description == ""){
+
+ $description = null;
+ }
+
+ $authors = [];
+ foreach($podcast["authors"] as $author){
+
+ $authors[] = $author["name"];
+ }
+
+ $authors = implode(", ", $authors);
+
+ if($authors == ""){
+
+ $authors = null;
+ }
+
+ $uri =
+ explode(
+ ":",
+ $podcast["uri"],
+ 3
+ )[2];
+
+ $out["podcast"][] = [
+ "title" => $podcast["name"],
+ "description" => $description,
+ "author" => [
+ "name" => $authors,
+ "url" => null,
+ "avatar" => null
+ ],
+ "thumb" => $this->get_thumb($podcast["coverArt"]),
+ "date" => strtotime($podcast["publishDate"]["isoString"]),
+ "duration" => null,
+ "url" => "https://open.spotify.com/show/" . $uri,
+ "stream" => [
+ "endpoint" => "spotify",
+ "url" => "episode." . $uri
+ ]
+ ];
+ }
+
+ // get episodes (and place them in podcasts)
+ foreach($payload["data"]["searchV2"]["episodes"]["items"] as $podcast){
+
+ if(isset($podcast["data"])){
+
+ $podcast = $podcast["data"];
+ }
+
+ $out["podcast"][] = [
+ "title" => $podcast["name"],
+ "description" => $this->limitstrlen($podcast["description"]),
+ "author" => [
+ "name" =>
+ isset(
+ $podcast["podcastV2"]["data"]["publisher"]["name"]
+ ) ?
+ $podcast["podcastV2"]["data"]["publisher"]["name"]
+ : null,
+ "url" => null,
+ "avatar" => null
+ ],
+ "thumb" => $this->get_thumb($podcast["coverArt"]),
+ "date" => strtotime($podcast["releaseDate"]["isoString"]),
+ "duration" => $podcast["duration"]["totalMilliseconds"] / 1000,
+ "url" =>
+ "https://open.spotify.com/show/" .
+ explode(
+ ":",
+ $podcast["uri"],
+ 3
+ )[2],
+ "stream" => [
+ "endpoint" => null,
+ "url" => null
+ ]
+ ];
+ }
+
+ // get authors
+ foreach($payload["data"]["searchV2"]["artists"]["items"] as $user){
+
+ if(isset($user["data"])){
+
+ $user = $user["data"];
+ }
+
+ $avatar = $this->get_thumb($user["visuals"]["avatarImage"]);
+
+ $out["author"][] = [
+ "title" =>
+ (
+ $user["profile"]["verified"] === true ?
+ "✓ " : ""
+ ) .
+ $user["profile"]["name"],
+ "followers" => null,
+ "description" => null,
+ "thumb" => $avatar,
+ "url" =>
+ "https://open.spotify.com/artist/" .
+ explode(
+ ":",
+ $user["uri"],
+ 3
+ )[2]
+ ];
+ }
+
+ // get users
+ foreach($payload["data"]["searchV2"]["users"]["items"] as $user){
+
+ if(isset($user["data"])){
+
+ $user = $user["data"];
+ }
+
+ $avatar = $this->get_thumb($user["avatar"]);
+
+ $out["user"][] = [
+ "title" => $user["displayName"] . " (@{$user["id"]})",
+ "followers" => null,
+ "description" => null,
+ "thumb" => $avatar,
+ "url" => "https://open.spotify.com/user/" . $user["id"]
+ ];
+ }
+
+ return $out;
+ }
+
+ private function get_artists($artists){
+
+ $artist_out = [];
+
+ foreach($artists["items"] as $artist){
+
+ $artist_out[] = $artist["profile"]["name"];
+ }
+
+ $artist_out =
+ implode(", ", $artist_out);
+
+ if($artist_out == ""){
+
+ return [null, null];
+ }
+
+ $artist_link =
+ $artist === null ?
+ null :
+ "https://open.spotify.com/artist/" .
+ explode(
+ ":",
+ $artists["items"][0]["uri"]
+ )[2];
+
+ return [$artist_out, $artist_link];
+ }
+
+ private function get_thumb($cover){
+
+ $thumb_out = null;
+
+ if($cover !== null){
+ foreach($cover["sources"] as $thumb){
+
+ if(
+ $thumb_out === null ||
+ (int)$thumb["width"] > $thumb_out["width"]
+ ){
+
+ $thumb_out = $thumb;
+ }
+ }
+ }
+
+ if($thumb_out === null){
+
+ return [
+ "url" => null,
+ "ratio" => null
+ ];
+ }else{
+
+ return [
+ "url" => $thumb_out["url"],
+ "ratio" => "1:1"
+ ];
+ }
+ }
+
+ private function limitstrlen($text){
+
+ return
+ explode(
+ "\n",
+ wordwrap(
+ str_replace(
+ ["\n\r", "\r\n", "\n", "\r"],
+ " ",
+ $text
+ ),
+ 300,
+ "\n"
+ ),
+ 2
+ )[0];
+ }
+}
diff --git a/settings.php b/settings.php
index 3cd59f4..5572b19 100644
--- a/settings.php
+++ b/settings.php
@@ -274,7 +274,6 @@ foreach($themes as $theme){
/*
Set cookies
*/
-
if($_POST){
$loop = &$_POST;
@@ -473,6 +472,7 @@ if(count($_GET) === 0){
$frontend->load(
"search.html",
[
+ "timetaken" => null,
"class" => "",
"right-left" =>
'<div class="infobox"><h2>Preference link</h2>Following this link will re-apply all cookies configured here and will redirect you to the front page. Useful if your browser clears out cookies after a browsing session.<br><br>' .
diff --git a/static/style.css b/static/style.css
index 0c1d475..9e04c11 100644
--- a/static/style.css
+++ b/static/style.css
@@ -48,10 +48,35 @@ body{
font-size:16px;
box-sizing:border-box;
font-family:sans-serif;
- padding:15px 7% 45px;
+ margin:15px 7% 45px;
word-wrap:anywhere;
line-height:22px;
max-width:2000px;
+ position:relative;
+}
+
+.navigation{
+ position:absolute;
+ top:0;
+ right:0;
+ font-size:14px;
+ line-height:40px;
+}
+
+.navigation a{
+ color:var(--bdae93);
+ text-decoration:none;
+}
+
+.navigation a:hover{
+ text-decoration:underline;
+}
+
+.navigation a:not(:last-child)::after{
+ content:"|";
+ padding:0 7px;
+ display:inline-block;
+ color:var(--504945);
}
h1,h2,h3,h4,h5,h6{
@@ -176,7 +201,6 @@ h3,h4,h5,h6{
/* Filters */
.filters{
- padding-bottom:15px;
margin-bottom:7px;
}
@@ -203,6 +227,12 @@ h3,h4,h5,h6{
height:24px;
}
+.timetaken{
+ font-size:14px;
+ font-weight:bold;
+ margin-bottom:10px;
+}
+
/*
HOME
@@ -1288,6 +1318,15 @@ table tr a:last-child{
}
@media only screen and (max-width: 1000px){
+ form{
+ padding-top:27px;
+ }
+
+ .navigation{
+ left:0;
+ right:unset;
+ line-height:22px;
+ }
.nextpage.img{
width:initial;
diff --git a/template/header.html b/template/header.html
index fcdbb13..accd4cd 100644
--- a/template/header.html
+++ b/template/header.html
@@ -12,6 +12,11 @@
<meta name="description" content="{%server_name%}: {%description%}">
</head>
<body>
+ <div class="navigation">
+ <a href="/">Home</a>
+ <a href="/settings">Settings</a>
+ <a href="https://git.lolcat.ca/lolcat/4get_news" target="_BLANK">News</a>
+ </div>
<form method="GET" autocomplete="off">
<div class="searchbox">
<input type="submit" value="Search" tabindex="-1">
diff --git a/template/home.html b/template/home.html
index b4f0735..28799f2 100644
--- a/template/home.html
+++ b/template/home.html
@@ -28,7 +28,7 @@
<div class="autocomplete"></div>
</div>
</form>
- <a href="settings">Settings</a> • <a href="instances">Instances</a> • <a href="api.txt">API</a> • <a href="about">About</a> • <a href="https://git.lolcat.ca/lolcat/4get">Source</a> • <a href="https://ko-fi.com/lolcat" rel="noreferrer" target="BLANK">Donate</a>
+ <a href="settings">Settings</a> • <a href="instances">Instances</a> • <a href="https://git.lolcat.ca/lolcat/4get_news">News</a> • <a href="api.txt">API</a> • <a href="about">About</a> • <a href="https://git.lolcat.ca/lolcat/4get">Source</a> • <a href="https://ko-fi.com/lolcat" rel="noreferrer" target="BLANK">Donate</a>
<div class="subtext">
<a href="https://4get.ca">Clearnet</a> • <a href="http://4getwebfrq5zr4sxugk6htxvawqehxtdgjrbcn2oslllcol2vepa23yd.onion">Tor</a> • <a href="https://lolcat.ca">Report a problem</a><br>
Running on <b>v{%version%}</b>!!
diff --git a/template/images.html b/template/images.html
index a19ddeb..6007e44 100644
--- a/template/images.html
+++ b/template/images.html
@@ -1,3 +1,4 @@
+ <div class="timetaken">Took {%timetaken%}s</div>
<div id="images">
{%images%}
</div>
diff --git a/template/search.html b/template/search.html
index d7f73a5..e1c979c 100644
--- a/template/search.html
+++ b/template/search.html
@@ -1,3 +1,4 @@
+ {%timetaken%}
<div id="overflow" class="web{%class%}">
<div class="right-wrapper">
<div class="right-right">
diff --git a/videos.php b/videos.php
index cf48aac..868e530 100644
--- a/videos.php
+++ b/videos.php
@@ -15,10 +15,11 @@ $get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
-include "lib/captcha_gen.php";
-new captcha($frontend, $get, $filters, "videos", true);
+include "lib/bot_protection.php";
+new bot_protection($frontend, $get, $filters, "videos", true);
$payload = [
+ "timetaken" => microtime(true),
"class" => "",
"right-left" => "",
"right-right" => "",
diff --git a/web.php b/web.php
index 5511392..42675d9 100644
--- a/web.php
+++ b/web.php
@@ -15,10 +15,11 @@ $get = $frontend->parsegetfilters($_GET, $filters);
/*
Captcha
*/
-include "lib/captcha_gen.php";
-new captcha($frontend, $get, $filters, "web", true);
+include "lib/bot_protection.php";
+new bot_protection($frontend, $get, $filters, "web", true);
$payload = [
+ "timetaken" => microtime(true),
"class" => "",
"right-left" => "",
"right-right" => "",
@@ -359,7 +360,7 @@ if(count($results["answer"]) !== 0){
case "audio":
$right["answer"] .=
- '<audio src="/audio?s=' . urlencode($description["url"]) . '" controls><a href="/audio.php?s=' . urlencode($description["url"]) . '">Listen to the pronunciation audio</a></audio>';
+ '<audio src="/audio/linear?s=' . urlencode($description["url"]) . '" controls><a href="/audio/linear?s=' . urlencode($description["url"]) . '">Listen to the pronunciation audio</a></audio>';
break;
}
}