I’m a huge fan of Trakt, but I know people who are tempted by VIP solely for the widgets. Now that’s great, but those widgets probably aren’t worth your $5. If supporting websites is important to you, this is probably not the post for you. It’s likely that this method could break in the future, keep that in mind!

We’re going to use our server as a bit of a proxy.

Here’s a couple of examples of what we’ll be creating (they’re live).

eliottrobson

eliottrobson

Pretty slick huh? Let’s get yours up and running now!

First, ssh into your server. Now, let’s edit the nginx config.

sudo nano /etc/nginx/sites-available/default

Place the following above any other location blocks.

if ($request_uri ~* "/trakt/") {
    set $skip_cache 1;
}
location ~* ^/trakt/.*$ {
    rewrite ^ /wp-content/uploads/trakt/request.php?uri=$uri last;
}

Here we are creating a virtual directory “trakt” which is deferred to our php handler file.

Install the file once you’ve saved the changes.

sudo systemctl reload nginx

So, at the moment we are redirecting all requests to /trakt/… to our php file, let’s build that.

mkdir /var/www/html/wp-content/uploads/trakt
mkdir /var/www/html/wp-content/uploads/trakt/cache

Create a file in this folder called request.php

<?php
// Hardcode to avoid this server being exploited as a proxy
$user = '1e3820057d9da91d1b9b8cc6db3e8826';

// 60 minutes
$cachetime = 60 * 60;

$start = 'trakt/';
$uri = $_GET['uri'];

$request = substr($uri, strpos($uri, $start) + strlen($start));

// Some quick validation
$validation = explode('/', $request);

$valid = [
	'watched' => [
		'thin@2x.jpg',
		'banner@2x.jpg',
		'fanart2@2x.jpg',
		'fanart@2x.jpg',
		'thumb@2x.jpg',
		'poster@2x.jpg',
		'thin@1x.jpg',
		'banner@1x.jpg',
		'fanart2@1x.jpg',
		'fanart@1x.jpg',
		'thumb@1x.jpg',
		'poster@1x.jpg'
	],
	'collected' => [
		'thin@2x.jpg',
		'banner@2x.jpg',
		'fanart2@2x.jpg',
		'fanart@2x.jpg',
		'thumb@2x.jpg',
		'poster@2x.jpg',
		'thin@1x.jpg',
		'banner@1x.jpg',
		'fanart2@1x.jpg',
		'fanart@1x.jpg',
		'thumb@1x.jpg',
		'poster@1x.jpg'
	],
	'profile.jpg'
];

$options = [
	'image_only' => [
		'1'
	],
	'type' => [
		'episode',
		'movie'
	],
];

// Throw 404 if not valid
if (!isset($valid[$validation[0]]) || !in_array($validation[1], $valid[$validation[0]])) {
	header("HTTP/1.0 404 Not Found");
	exit();
}

$query = [];
// Validate the query parameters too
foreach ($options as $key => $option) {		
	if (isset($_GET[$key]) && in_array($_GET[$key], $options[$key])) {
		$query[] = $key . '=' . $_GET[$key];
	}
}

// Build the query string
if (count($query) > 0) {
	$request .= '?' . implode('&', $query);
}

$cache = 'cache/' . md5($request) . '.jpg';
$has_cache = file_exists($cache);

if (!$has_cache || time() - filemtime($cache) > $cachetime) {
	$url = 'https://widgets.trakt.tv/users/' . $user . '/' . $request;
	$filename = pathinfo(parse_url($url)['path'])['filename'];
	
	$stream = stream_context_create([
		'http' => [
			'method' => 'GET',
			'header' => 'Referer: https://trakt.tv/widgets/'
		]
	]);
	
	copy($url, $cache, $stream);
}

header('Content-Type: ' . mime_content_type($cache));
header('Content-Length: ' . filesize($cache));
readfile($cache);

You’ll need to change the user variable to point to your id. You can extract this from the examples at this url:

https://trakt.tv/widgets/watched

This file accepts the request, runs a bit of validation (adjust as necessary), then proxy the request (with a bit of caching) with the referer header. Tricking the Trakt server to give us the correct image 

At current this doesn’t support the card type, but I’ve had moderate success with it. You would need to capture the card request and then cache each of the images too (cloudflare hotlinking protection) and replace those in the page.

Boom! 

You should probably sponsor Trakt if you like the system, alternatively – here you go!

  • iAmSaugata

    Hi,
    I am not on nginx, I am on simple apache with php and mysql running on linode, and not that expert, what configuration do I have to make to work this?