First version
Does not encode entry yet
This commit is contained in:
parent
054426a817
commit
55561b2a7f
2 changed files with 130 additions and 5 deletions
126
main.cpp
126
main.cpp
|
@ -1,6 +1,126 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
#include "config.hpp"
|
||||||
std::cout << "Hello, world!" << std::endl;
|
|
||||||
return 0;
|
/* check version */
|
||||||
|
#ifndef VERSION
|
||||||
|
#define VERSION "UNKNOWN"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp){
|
||||||
|
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* goal: ytsearch -h|-v|search-term
|
||||||
|
*
|
||||||
|
* @example ytsearch "rick astley"
|
||||||
|
* https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
std::cout << "ytsearch: a search term is needed, try 'ytsearch -h' for more information" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
std::string const video_url = { "https://www.youtube.com/watch?v=" };
|
||||||
|
std::string search_url = { "https://www.youtube.com/results?search_query=" };
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "hv")) != -1)
|
||||||
|
{
|
||||||
|
switch (opt)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
std::cout << "Usage: ytsearch [options...] search-term" << std::endl <<
|
||||||
|
" -h: show this help and quit" << std::endl <<
|
||||||
|
" -v: show version number and quit" << std::endl <<
|
||||||
|
std::endl <<
|
||||||
|
"Retrieve the url of a youtube video matching the searched terms" << std::endl;
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
case 'v':
|
||||||
|
std::cout << VERSION << std::endl;
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
default:
|
||||||
|
std::cout << "ytsearch: try 'ytsearch -h' for more information" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
search_url += argv[1];
|
||||||
|
|
||||||
|
CURL *curl;
|
||||||
|
std::string readBuffer;
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
|
||||||
|
if (!curl)
|
||||||
|
{
|
||||||
|
std::cout << "ytsearch: error in curl initialization" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, search_url.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||||
|
CURLcode res = { curl_easy_perform(curl) };
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
std::cout << "ytsearch: error when fetching results: " << res << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string paths[4] = {
|
||||||
|
"navigationEndpoint",
|
||||||
|
"commandMetadata",
|
||||||
|
"webCommandMetadata",
|
||||||
|
"url",
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t pos_start = readBuffer.find("ytInitialData");
|
||||||
|
std::string const error_api = "ytsearch: error, youtube's api changed: update ytsearch";
|
||||||
|
|
||||||
|
if (pos_start == std::string::npos or pos_start == 0)
|
||||||
|
{
|
||||||
|
std::cout << error_api << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t first_video = readBuffer.find("WEB_PAGE_TYPE_WATCH", pos_start);
|
||||||
|
|
||||||
|
if (first_video == std::string::npos or pos_start == 0)
|
||||||
|
{
|
||||||
|
std::cout << error_api << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (first_video > pos_start + 60) // type is defined a little after url, we want a video
|
||||||
|
{
|
||||||
|
for (std::string name : paths)
|
||||||
|
{
|
||||||
|
pos_start = { readBuffer.find(name, pos_start) };
|
||||||
|
|
||||||
|
if (pos_start == std::string::npos or pos_start == 0)
|
||||||
|
{
|
||||||
|
std::cout << error_api << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = { pos_start + 15 }; // size of " url":"/watch?v= ", last part of paths
|
||||||
|
|
||||||
|
size_t pos_end = { readBuffer.find('"', size) };
|
||||||
|
|
||||||
|
std::cout << video_url << readBuffer.substr(size, pos_end - size) << std::endl;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'ytsearch',
|
'ytsearch',
|
||||||
'cpp',
|
'cpp',
|
||||||
version : '1.0.0',
|
version : '0.1.0',
|
||||||
default_options : [
|
default_options : [
|
||||||
'buildtype=debug',
|
'buildtype=debug',
|
||||||
'optimization=0',
|
'optimization=0',
|
||||||
|
@ -10,8 +10,13 @@ project(
|
||||||
meson_version: '>= 0.60.0',
|
meson_version: '>= 0.60.0',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
conf_data = configuration_data()
|
||||||
|
conf_data.set('version', meson.project_version())
|
||||||
|
configure_file(input: 'config.hpp.in', output: 'config.hpp', configuration: conf_data)
|
||||||
|
|
||||||
|
|
||||||
executable('ytsearch',
|
executable('ytsearch',
|
||||||
'main.cpp'
|
'main.cpp',
|
||||||
|
dependencies : dependency('libcurl')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue