Browse Source

implemented working file struct & functions

sandbox
- 3 months ago
parent
commit
7169761d74
  1. 23
      Makefile
  2. 344
      include/peertube.hpp
  3. 72
      main.cpp

23
Makefile

@ -1,10 +1,8 @@ @@ -1,10 +1,8 @@
OPENAPI_GENERATOR=/home/user/Programs/openapi-generator-cli.jar
PEERTUBE_API=./deps/peertube/
# https://github.com/arvidn/libtorrent/pull/4123
# using submodule b/c it has to be the master branch
CFLAGS=-I"./include/" -I"./deps/libtorrent/include/"
CFLAGS=-I"./include/" -I"./deps/libtorrent/include/" -I"./deps/"
# -I"./deps/libtorrent/include/libtorrent/"
LDFLAGS= -Dwebtorrent=ON -DTORRENT_USE_OPENSSL -lpthread -lcurl -lcurlpp -lcurses
# -lboost_system -ltorrent-rasterbar
@ -12,14 +10,25 @@ LDFLAGS= -Dwebtorrent=ON -DTORRENT_USE_OPENSSL -lpthread -lcurl -lcurlpp -lcurs @@ -12,14 +10,25 @@ LDFLAGS= -Dwebtorrent=ON -DTORRENT_USE_OPENSSL -lpthread -lcurl -lcurlpp -lcurs
# building libtorrent with webtorrent support
# git submodule init --recursive
# cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 -Dwebtorrent=ON -G Ninja ..
LIBTORRENT=./deps/libtorrent/build/libtorrent-rasterbar.so.2.0.5
LD_LIBRARY_PATH=./deps/libtorrent/build/
LIBTORRENT= ./deps/libtorrent/build/libtorrent-rasterbar.so.2.0.5
# -Wl,-soname
all:
g++ $(LIBTORRENT) main.cpp $(CFLAGS) $(LDFLAGS) -std=c++17
LD_LIBRARY_PATH=./deps/libtorrent/build/
all: | main
# something to avoid prepending LD_LIBRARY_PATH=./deps/... every time.
# better if compilted to just search in relative path to begin with
patchelf --remove-needed libtorrent-rasterbar.so.2.0 cppia
patchelf --add-needed ./deps/libtorrent/build/libtorrent-rasterbar.so.2.0 cppia
main:
g++ main.cpp $(CFLAGS) $(LDFLAGS) $(LIBTORRENT) -std=c++17 -o cppia
video:
g++ ./deps/peertube/model/video.c -std=c++17
ncurses:
g++ demo_window.cpp -lcurses -o window
OPENAPI_GENERATOR=/home/user/Programs/openapi-generator-cli.jar
PEERTUBE_API=./deps/peertube/
openapi:
java -jar $(OPENAPI_GENERATOR) generate -i peertube.yaml -g c -o $(PEERTUBE_API)

344
include/peertube.hpp

@ -2,24 +2,6 @@ @@ -2,24 +2,6 @@
#ifndef PEERTUBE_HTP
#define PEERTUBE_HPP
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
std::string request(const std::string& url) {
curlpp::options::Url source (url);
curlpp::Easy request;
request.setOpt(source);
std::ostringstream response;
try {
response << request;
} catch (curlpp::LibcurlRuntimeError e) {
std::cout << e.what() << std::endl;
} catch (std::exception const& e) {
std::cout << e.what() << std::endl;
}
return response.str();
}
int interpret(const std::string &user_input, std::string &host, std::string &id) {
// what did the user link?
char *token = new char[user_input.length() + 1];
@ -51,8 +33,7 @@ int interpret(const std::string &user_input, std::string &host, std::string &id) @@ -51,8 +33,7 @@ int interpret(const std::string &user_input, std::string &host, std::string &id)
state++;
} else {
id = std::string(token);
}
break;
} break;
case 4: // playlist id
id = std::string(token);
break;
@ -65,8 +46,7 @@ int interpret(const std::string &user_input, std::string &host, std::string &id) @@ -65,8 +46,7 @@ int interpret(const std::string &user_input, std::string &host, std::string &id)
} else if (strcmp(token,"video-playlists") == 0) {
is_playlist = true;
state++;
}
break;
} break;
case 'c':
id = std::string(token);
break;
@ -83,21 +63,23 @@ int interpret(const std::string &user_input, std::string &host, std::string &id) @@ -83,21 +63,23 @@ int interpret(const std::string &user_input, std::string &host, std::string &id)
// https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo
// https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideoPlaylistVideos
void peertube (const std::string &user_input) {
std::string get_endpoint(const std::string &user_input, bool &is_playlist) {
std::string host;
std::string id;
int what = 0;
what = interpret(user_input, host, id);
std::string url, api;
std::string url = std::string("");
std::string api;
std::stringstream ss;
switch (what) {
default:
std::cout << "???" << std::endl;
std::cout << what << std::endl;
case 0:
case 1:
std::cout << "URL not recognized." << std::endl;
return;
break;
case 3:
std::cout << "This was a regular video" << std::endl;
std::cout << "video page" << std::endl;
api = "/api/v1/videos/"; //(host, id)
ss << "https://" << host << api << id;
url = ss.str();
@ -111,67 +93,181 @@ void peertube (const std::string &user_input) { @@ -111,67 +93,181 @@ void peertube (const std::string &user_input) {
url = user_input;
break;
case 4:
std::cout << "this was a playlist" << std::endl;
std::cout << "playlist page" << std::endl;
api = "/api/v1/video-playlists/";
ss << "https://" << host << api << id << "/videos";
url = ss.str();
break;
}
std::cout << url << std::endl;
// std::string response = request(url);
return url;
}
// #include "peertube/model/video.h" <- model does not compile
// https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo
// salvage the stuff that didn't compile.'
std::string get_video(std::string user_input) {
std::string url;
std::string id, host;
// did the user link a video page or api endpoint?
char *token = new char[user_input.length() + 1];
strcpy(token, user_input.c_str());
token = strtok(token, "/");
#define FILE_T_STR_COUNT 6
enum {
MAGNET_URI,
TORRENT_URL,
TORRENTDOWNLOAD_URL,
FILE_URL,
FILEDOWNNLOAD_URL,
METADATA_URL
} file_t_attribs;
struct file_t {
// char *magnetUri;
int resolution; // ignore label
int size;
// char *torrentUrl;
// char *torrentDownloadUrl;
// char *fileUrl;
// char *fileDownloadUrl;
int fps;
// char *metadataurl;
char *attribs[FILE_T_STR_COUNT]; // B)
};
struct file_t* file_init (int resolution,
int size,
int fps,
unsigned int len_data,
const char **data) {
struct file_t *f = (file_t*)malloc(sizeof(file_t));
f -> size = size;
f -> fps = fps;
if (len_data != FILE_T_STR_COUNT) {
return NULL;
}
// not going to take any cues
// on how to initialize a struct from openapigenerator
unsigned int len;
unsigned int i = 0;
bool is_api = false;
while (token != NULL) {
if (strcmp(token, "https:") == 0 || strcmp(token, "http:") == 0) {
; // ignore - no need.
} else if (strcmp(token, "api") == 0) {
; // url given was the api - make direct request
is_api = true;
url = user_input;
break;
} else if (strcmp(token, "w") == 0) {
; // url given was the video page - must generate api url
} else if (token != NULL) {
switch (i) {
case 0: // http(s)
break;
case 1: // domain
host = std::string(token);
break;
case 3:
id = std::string(token);
break;
default:
printf("%s : %u", token, i);
break;
}
for (i; i < FILE_T_STR_COUNT; ++i) {
if (data[i] == NULL) {
return NULL;
}
token = strtok(NULL, "/");
i++;
len = strlen(data[i]) * sizeof(char);
f -> attribs[i] = (char*)malloc(len);
strcpy(f -> attribs[i], data[i]);
}
if (!is_api) {
std::stringstream ss;
std::string api = "/api/v1/videos/"; //(host, id)
ss << "https://" << host << api << id;
url = ss.str();
return f;
}
void file_print(const struct file_t * const f) {
unsigned int i = 0;
for (i; i < FILE_T_STR_COUNT; ++i) {
fprintf(stdout, "%s\n", f -> attribs[i]);
}
delete [] token;
return request(url);
}
void file_free(struct file_t* f) {
unsigned int i = 0;
for (i; i < FILE_T_STR_COUNT; ++i) {
free(f -> attribs[i]);
}
free(f);
}
struct video_t {
int id;
char *uuid;
char *short_uuid;
// int is_live;
// char *created_at; //date time
// char *published_at; //date time
// char *updated_at; //date time
// char *originally_published_at; //date time
// skip other models
char *description; // string
int duration; //numeric
// int is_local; //boolean
char *name; // string
int views; //numeric
int likes; //numeric
int dislikes; //numeric
int nsfw; //boolean
// skip other models again
int file_count;
struct file_t* files;
};
struct video_t *video_init(int id,
char *uuid,
char *short_uuid,
char *description,
int duration,
char *name,
int views,
int likes,
int dislikes,
int nsfw,
int file_count,
struct file_t* files) {
struct video_t *v = (video_t*)malloc(sizeof(video_t));
if (!v) {
return NULL;
}
v -> id = id;
v -> duration = duration;
v -> views = views;
v -> likes = likes;
v -> dislikes = dislikes;
v -> nsfw = nsfw;
unsigned int len;
if (uuid != NULL) {
len = strlen(uuid) * sizeof(char);
v -> uuid = (char *)malloc(len);
strcpy(v -> uuid, uuid);
}
if (short_uuid != NULL) {
len = strlen(short_uuid) * sizeof(char);
v -> short_uuid = (char*)malloc(len);
strcpy(v -> short_uuid, short_uuid);
}
if (description != NULL) {
len = strlen(description) * sizeof(char);
v -> description = (char*)malloc(len);
strcpy(v -> description, description);
}
if (name != NULL) {
len = strlen(name) * sizeof(char);
v -> name = (char*)malloc(len);
strcpy(v -> name, name);
}
v -> file_count = file_count;
if (files != NULL) {
v -> files = files;
}
return v;
}
void video_free(struct video_t *v) {
if (v -> uuid != NULL) {
free(v -> uuid);
}
if (v -> short_uuid != NULL) {
free(v -> short_uuid);
}
if (v -> description != NULL) {
free(v -> description);
}
if (v -> name != NULL) {
free(v -> name);
}
unsigned int i = 0;
for (i; i < v-> file_count; ++i) {
file_free(&v -> files[i]);
}
free(v);
}
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
static rapidjson::Value& get_video_files(rapidjson::Document& root) {
rapidjson::Value& out = root["files"];
assert(out.IsArray());
@ -197,6 +293,112 @@ static rapidjson::Value& get_video_files(rapidjson::Document& root) { @@ -197,6 +293,112 @@ static rapidjson::Value& get_video_files(rapidjson::Document& root) {
return out;
}
// look into rapidjson::Value vs rapidjson::Document
void bulk (std::string str[], rapidjson::Value src) {
;
}
struct file_t *init_from_json(const rapidjson::Value& file) {
const char *elem_ints[] = {
// "resolution", // id is nested inside resolution
"size",
"fps"
};
int ints[2];
// keep order -see enum above struct file_t definition
const char *elem_strs[FILE_T_STR_COUNT] = {
"magnetUri",
"torrentUrl",
"torrentDownloadUrl",
"fileUrl",
"fileDownloadUrl",
"metadataUrl"
};
const char *strs[FILE_T_STR_COUNT];
int resolution;
if (!file["resolution"]["id"].IsInt()) {
return NULL;
}
resolution = file["resolution"]["id"].GetInt();
unsigned int i = 0;
for (i; i < 2; ++i) {
const char *element = elem_ints[i];
const rapidjson::Value &v = file[element];
if (!v.IsInt()) {
return NULL;
}
ints[i] = v.GetInt();
}
i = 0;
for (i; i < FILE_T_STR_COUNT; ++i) {
const char *element = elem_strs[i];
const rapidjson::Value &v = file[element];
if (!v.IsString()) {
return NULL;
}
strs[i] = v.GetString();
}
struct file_t *foo = file_init(resolution,
ints[0],
ints[1],
FILE_T_STR_COUNT,
strs);
return foo;
}
struct video_t *init_from_json(rapidjson::Document& root) {
#define INT_ATTRIB_COUNT 5
const char *ints[INT_ATTRIB_COUNT] = {
"id",
"duration",
"views",
"likes",
"dislikes",
};
int actual_ints[INT_ATTRIB_COUNT];
#define STR_ATTRIB_COUNT 4
const char *strs[STR_ATTRIB_COUNT] = {
"uuid",
"short_uuid",
"description",
"name"
};
std::string actual_strs[STR_ATTRIB_COUNT];
unsigned int i = 0;
for (i; i < INT_ATTRIB_COUNT; ++i) {
const char *element = ints[i];
rapidjson::Value& v = root[element];
if (!v.IsInt()) {
return NULL;
}
actual_ints[i] = v.GetInt();
}
i = 0;
for (i; i < STR_ATTRIB_COUNT; ++i) {
const char *element = strs[i];
rapidjson::Value& v = root[element];
if (!v.IsString()) {
return NULL;
}
actual_strs[i] = v.GetString();
}
rapidjson::Value &v = root["nsfw"];
if (!v.IsBool()) {
return NULL;
}
bool is_nsfw = v.GetBool();
int nsfw = (is_nsfw) ? 1 : 0;
const rapidjson::Value& vf = get_video_files(root);
for (rapidjson::SizeType i = 0; i < vf.Size(); ++i) {
}
}
std::string get_magnet_link(const rapidjson::Value& files) {
unsigned int highest = 0;
std::string best_video;

72
main.cpp

@ -175,14 +175,41 @@ void seedbox (std::string &torrentfiles) { @@ -175,14 +175,41 @@ void seedbox (std::string &torrentfiles) {
}
}
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
std::string request(const std::string& url) {
curlpp::options::Url source (url);
curlpp::Easy request;
request.setOpt(source);
std::ostringstream response;
try {
response << request;
} catch (curlpp::LibcurlRuntimeError e) {
std::cout << e.what() << std::endl;
} catch (std::exception const& e) {
std::cout << e.what() << std::endl;
}
return response.str();
}
#include "libtorrent/create_torrent.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "peertube.hpp" // also includes rapidjson
// watch a video given a URL
void watch(std::string video_url) {
//turn peertube video url into api request
std::string got = get_video(video_url);
bool is_playlist = false;
std::string api = get_endpoint(video_url, is_playlist);
std::string got = request(api);
std::cout << got.length() << std::endl;
rapidjson::Document root;
root.Parse(got.c_str());
// figure something out with playlists.
// video downloads can either be in "files"
// or under "streamingPlaylists" if HLS is enabled on the server
const rapidjson::Value& vf = get_video_files(root);
@ -201,21 +228,50 @@ void watch(std::string video_url) { @@ -201,21 +228,50 @@ void watch(std::string video_url) {
std::this_thread::sleep_for(std::chrono::seconds(1));
} while (!ts.is_seeding && !ts.is_finished);
std::cout << std::endl;
// prompt user to save torrent file?
// reference:
// https://github.com/steeve/libtorrent/blob/master/examples/client_test.cpp#L880
}
void test (std::string video_url) {
bool is_playlist;
std::string api = get_endpoint(video_url, is_playlist);
std::string got = request(api);
std::cout << got.length() << std::endl;
rapidjson::Document root;
root.Parse(got.c_str());
const rapidjson::Value& vf = get_video_files(root);
for (rapidjson::SizeType i = 0; i < vf.Size(); ++i) {
struct file_t *test = init_from_json(vf[i]);
if (test != NULL) {
file_print(test);
file_free(test);
}
}
}
int main(int argc, char const* argv[]) {
std::cout << "This is cppia (unreleased)." << std::endl;
if (argc != 2) {
if (argc != 3) {
fprintf(stderr, "usage: %s <.txt list of torrents>\n", argv[0]);
return 1;
}
// std::cout << "Press 'q' to quit and 'h' for more options." << std::endl;
std::string s(argv[1]);
watch(s);
// seedbox(s);
std::string s(argv[2]);
// add real argument parsing later.
int option = atoi(argv[1]);
switch (option) {
case 0:
seedbox(s);
break;
case 1:
watch(s);
break;
case 2:
// peertube(s);
test(s);
break;
}
// API generated by openapi doesn't compile.'
// apiClient_t* peertube = apiClient_create();

Loading…
Cancel
Save