#include "videolist.h"
#include "devicelist.h"
#include "text.h"
#include <unordered_map>
#include <string>
#include <QKeyEvent>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
using KeyValuePairs = std::unordered_map<std::string, std::string>;
using Json = QJsonDocument;
class Response
{
public:
Response() {}
Response(QByteArray _ba) : ba(_ba) {}
Response(const Response& other) : ba(other.ba) {}
Json json() {
return QJsonDocument::fromJson(ba);
}
private:
QByteArray ba;
};
class Requests : public QObject
{
public:
Requests()
{
manager = new QNetworkAccessManager();
QObject::connect(manager, &QNetworkAccessManager::finished,
this, [=](QNetworkReply* reply)
{
if (reply->error()) {
qDebug() << reply->errorString();
return;
}
if (continuationMap.count(reply))
{
Response resp(reply->readAll());
continuationMap[reply](resp);
}
});
}
~Requests()
{
delete manager;
}
// sessions?
void get(const std::string& url, const KeyValuePairs& headers, std::function<void(Response&)> continuation)
{
QNetworkRequest request;
request.setUrl(QUrl(url.c_str()));
auto resp = manager->get(request);
continuationMap[resp] = continuation;
}
private:
QNetworkAccessManager* manager;
std::unordered_map<QNetworkReply*, std::function<void(Response&)>> continuationMap;
};
class MovieAggregator : public QObject
{
};
class JustWatch : public MovieAggregator
{
static std::string api_base_template;
public:
JustWatch(const char* _country = "US")//, bool _use_sessions = true)
{
requests = new Requests;
// self.kwargs = kwargs
country = _country;
//self.kwargs_cinema = []
setupLocale();
}
~JustWatch()
{
delete requests;
}
void setupLocale();
void searchForItem(std::string query, KeyValuePairs kwargs);
void getProviders();
void getGenres();
void getTitle(std::string title_id, std::string content_type = "movie");
void searchTitleId(std::string query);
void getSeason(std::string season_id);
void getCinemaTimes(std::string title_id, std::string content_type = "movie", KeyValuePairs kwargs = {});
void getCinemaDetails(KeyValuePairs kwargs);
void getUpcomingCinema(int weeks_offset, bool nationwide_cinema_releases_only = true);
void getCertifications(std::string content_type = "movie");
void getPersonCetail(std::string person_id);
private:
Requests* requests;
std::string country;
std::string locale;
};
void JustWatch::setupLocale()
{
std::string default_locale = "en_AU";
std::string api_url = api_base_template + "locales/state";
KeyValuePairs headers = { { "User - Agent", "JustWatch client(github.com / dawoudt / JustWatchAPI)" } };
requests->get(api_url, headers, [=](Response& resp)
{
std::string str = resp.json().toJson(QJsonDocument::Indented).toStdString();
qDebug() << str.c_str();
locale = default_locale;
auto results = resp.json();
//QJsonArray arr;
for (auto result : results.array())
if ((result.toObject()["iso_3166_2"].toString().toStdString() == country)
|| (result.toObject()["country"].toString().toStdString() == country))
locale = result.toObject()["full_locale"].toString().toStdString();
});
// warn = '\nWARN: Unable to locale for {}! Defaulting to en_AU\n'
//sys.stderr.write(warn.format(self.country))
//return default_locale;
}
std::string JustWatch::api_base_template = "http://apis.justwatch.com/content/";// {path}";
class VideoManager : public QObject
{
public:
VideoManager();
~VideoManager() {}
void getList();
private:
JustWatch justWatch;
};
VideoManager::VideoManager()
{
}
void VideoManager::getList()
{
}
VideoList::VideoList(QWidget *parent) : QWidget(parent)
{
resize(800,480);
devices = new DeviceList(this, QT_TRANSLATE_NOOP("DPF","Videos"), "videos");
connect(devices, SIGNAL(setStage(int)), this, SIGNAL(setStage(int)));
connect(devices, SIGNAL(switchFocus()), this, SLOT(switchFocus()));
setFocusProxy(devices);
devices->setFocusPolicy(Qt::StrongFocus);
devices->setFocus();
new Text(this, 380+2, 230+2, "Not Implemented", 20, QColor(0,0,0,128));
new Text(this, 380, 230, "Not Implemented", 20);
manager = new VideoManager;
}
VideoList::~VideoList()
{
delete manager;
}
void VideoList::switchFocus()
{
//focusNextPrevChild(true);
devices->setFocus();
}
#if 0
JustWatch API
from datetime import datetime
from datetime import timedelta
import requests
import sys
HEADER = { 'User-Agent':'JustWatch client (github.com/dawoudt/JustWatchAPI)' }
class JustWatch :
api_base_template = "https://apis.justwatch.com/content/{path}"
def __init__(self, country = 'AU', use_sessions = True, **kwargs) :
self.kwargs = kwargs
self.country = country
self.kwargs_cinema = []
self.requests = requests.Session() if use_sessions else requests
self.locale = self.set_locale()
def __del__(self) :
''' Should really use context manager
but this should do without changing functionality.
'''
if isinstance(self.requests, requests.Session) :
self.requests.close()
def set_locale(self) :
warn = '\nWARN: Unable to locale for {}! Defaulting to en_AU\n'
default_locale = 'en_AU'
path = 'locales/state'
api_url = self.api_base_template.format(path = path)
r = self.requests.get(api_url, headers = HEADER)
try :
r.raise_for_status()
except requests.exceptions.HTTPError :
sys.stderr.write(warn.format(self.country))
return default_locale
else:
results = r.json()
for result in results :
if result['iso_3166_2'] == self.country or \
result['country'] == self.country:
return result['full_locale']
sys.stderr.write(warn.format(self.country))
return default_locale
def search_for_item(self, query = None, **kwargs) :
path = 'titles/{}/popular'.format(self.locale)
api_url = self.api_base_template.format(path = path)
if kwargs :
self.kwargs = kwargs
if query :
self.kwargs.update({ 'query': query })
null = None
payload = {
"age_certifications":null,
"content_types" : null,
"presentation_types" : null,
"providers" : null,
"genres" : null,
"languages" : null,
"release_year_from" : null,
"release_year_until" : null,
"monetization_types" : null,
"min_price" : null,
"max_price" : null,
"nationwide_cinema_releases_only" : null,
"scoring_filter_types" : null,
"cinema_release" : null,
"query" : null,
"page" : null,
"page_size" : null,
"timeline_type" : null,
"person_id" : null
}
for key, value in self.kwargs.items() :
if key in payload.keys() :
payload[key] = value
else :
print('{} is not a valid keyword'.format(key))
r = self.requests.post(api_url, json = payload, headers = HEADER)
# Client should deal with rate - limiting.JustWatch may send a 429 Too Many Requests response.
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def get_providers(self) :
path = 'providers/locale/{}'.format(self.locale)
api_url = self.api_base_template.format(path = path)
r = self.requests.get(api_url, headers = HEADER)
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def get_genres(self) :
path = 'genres/locale/{}'.format(self.locale)
api_url = self.api_base_template.format(path = path)
r = self.requests.get(api_url, headers = HEADER)
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def get_title(self, title_id, content_type = 'movie') :
path = 'titles/{content_type}/{title_id}/locale/{locale}'.format(content_type = content_type,
title_id = title_id,
locale = self.locale)
api_url = self.api_base_template.format(path = path)
r = self.requests.get(api_url, headers = HEADER)
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def search_title_id(self, query) :
''' Returns a dictionary of titles returned
from search and their respective ID's
>> > ...
>> > just_watch.get_title_id('The Matrix')
{
'The Matrix': 10, ...
}
'''
results = self.search_for_item(query)
return { item['id']: item['title'] for item in results['items'] }
def get_season(self, season_id) :
header = HEADER
api_url = 'https://apis.justwatch.com/content/titles/show_season/{}/locale/{}'.format(season_id, self.locale)
r = self.requests.get(api_url, headers = header)
# Client should deal with rate - limiting.JustWatch may send a 429 Too Many Requests response.
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def get_cinema_times(self, title_id, content_type = 'movie', **kwargs) :
if kwargs :
self.kwargs_cinema = kwargs
null = None
payload = {
"date":null,
"latitude" : null,
"longitude" : null,
"radius" : 20000
}
for key, value in self.kwargs_cinema.items() :
if key in payload.keys() :
payload[key] = value
else :
print('{} is not a valid keyword'.format(key))
header = HEADER
api_url = 'https://apis.justwatch.com/content/titles/{}/{}/showtimes'.format(content_type, title_id)
r = self.requests.get(api_url, params = payload, headers = header)
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def get_cinema_details(self, **kwargs) :
if kwargs :
self.kwargs_cinema = kwargs
null = None
payload = {
"latitude":null,
"longitude" : null,
"radius" : 20000
}
for key, value in self.kwargs_cinema.items() :
if key in payload.keys() :
payload[key] = value
elif key == 'date' :
#ignore the date value if passed
pass
else:
print('{} is not a valid keyword'.format(key))
header = HEADER
api_url = 'https://apis.justwatch.com/content/cinemas/{}'.format(self.locale)
r = self.requests.get(api_url, params = payload, headers = header)
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def get_upcoming_cinema(self, weeks_offset, nationwide_cinema_releases_only = True) :
header = HEADER
payload = { 'nationwide_cinema_releases_only': nationwide_cinema_releases_only,
'body' : {} }
now_date = datetime.now()
td = timedelta(weeks = weeks_offset)
year_month_day = (now_date + td).isocalendar()
api_url = 'https://apis.justwatch.com/content/titles/movie/upcoming/{}/{}/locale/{}'
api_url = api_url.format(year_month_day[0], year_month_day[1], self.locale)
#this throws an error if you go too many weeks forward, so return a blank payload if we hit an error
try :
r = self.requests.get(api_url, params = payload, headers = header)
# Client should deal with rate - limiting.JustWatch may send a 429 Too Many Requests response.
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
except:
return { 'page': 0, 'page_size' : 0, 'total_pages' : 1, 'total_results' : 0, 'items' : [] }
def get_certifications(self, content_type = 'movie') :
header = HEADER
payload = { 'country': self.country, 'object_type' : content_type }
api_url = 'https://apis.justwatch.com/content/age_certifications'
r = self.requests.get(api_url, params = payload, headers = header)
# Client should deal with rate - limiting.JustWatch may send a 429 Too Many Requests response.
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
def get_person_detail(self, person_id) :
path = 'titles/person/{person_id}/locale/{locale}'.format(person_id = person_id, locale = self.locale)
api_url = self.api_base_template.format(path = path)
r = self.requests.get(api_url, headers = HEADER)
r.raise_for_status() # Raises requests.exceptions.HTTPError if r.status_code != 200
return r.json()
#endif