youtube: some cleanups, add option to list user videos - frontends - front-ends… | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit b407559e2ea372a5d16bd0b08c9088762fa9ce75 | |
parent 1752940aca51413222b22939b7c6ce5947960967 | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Tue, 21 Feb 2023 20:31:42 +0100 | |
youtube: some cleanups, add option to list user videos | |
Diffstat: | |
M json.c | 2 +- | |
M xml.c | 2 +- | |
M youtube/cli.c | 6 +++++- | |
M youtube/youtube.c | 69 ++++++++++++++++++-----------… | |
M youtube/youtube.h | 3 +++ | |
5 files changed, 50 insertions(+), 32 deletions(-) | |
--- | |
diff --git a/json.c b/json.c | |
@@ -28,7 +28,7 @@ setjsondata(const char *s, size_t len) | |
{ | |
json_data_off = 0; | |
json_data_size = len; | |
- json_data = s; | |
+ json_data = (unsigned char *)s; | |
} | |
static int | |
diff --git a/xml.c b/xml.c | |
@@ -18,7 +18,7 @@ setxmldata(const char *s, size_t len) | |
{ | |
xml_data_off = 0; | |
xml_data_size = len; | |
- xml_data_buf = s; | |
+ xml_data_buf = (unsigned char *)s; | |
} | |
static int | |
diff --git a/youtube/cli.c b/youtube/cli.c | |
@@ -114,7 +114,7 @@ render(struct search_response *r) | |
static void | |
usage(const char *argv0) | |
{ | |
- fprintf(stderr, "usage: %s <keyword> | <-c channelid>\n", argv0); | |
+ fprintf(stderr, "usage: %s <keyword> | <-c channelid> | <-u user>\n", … | |
exit(1); | |
} | |
@@ -143,6 +143,10 @@ main(int argc, char *argv[]) | |
if (argc < 3) | |
usage(argv[0]); | |
r = youtube_channel_videos(argv[2]); | |
+ } else if (!strcmp(argv[1], "-u")) { | |
+ if (argc < 3) | |
+ usage(argv[0]); | |
+ r = youtube_user_videos(argv[2]); | |
} else { | |
if (!uriencode(argv[1], search, sizeof(search))) | |
usage(argv[0]); | |
diff --git a/youtube/youtube.c b/youtube/youtube.c | |
@@ -36,6 +36,20 @@ request_channel_videos(const char *channelid) | |
} | |
static char * | |
+request_user_videos(const char *user) | |
+{ | |
+ char path[4096]; | |
+ int r; | |
+ | |
+ r = snprintf(path, sizeof(path), "/user/%s/videos", user); | |
+ /* check if request is too long (truncation) */ | |
+ if (r < 0 || (size_t)r >= sizeof(path)) | |
+ return NULL; | |
+ | |
+ return youtube_request(path); | |
+} | |
+ | |
+static char * | |
request_search(const char *s, const char *page, const char *order) | |
{ | |
char path[4096]; | |
@@ -66,8 +80,8 @@ request_search(const char *s, const char *page, const char *o… | |
return youtube_request(path); | |
} | |
-int | |
-extractjson(const char *s, char **start, char **end) | |
+static int | |
+extractjson(const char *s, const char **start, const char **end) | |
{ | |
*start = strstr(s, "window[\"ytInitialData\"] = "); | |
if (*start) { | |
@@ -91,7 +105,7 @@ extractjson(const char *s, char **start, char **end) | |
return 0; | |
} | |
-void | |
+static void | |
processnode(struct json_node *nodes, size_t depth, const char *value, | |
void *pp) | |
{ | |
@@ -191,16 +205,13 @@ processnode(struct json_node *nodes, size_t depth, const … | |
} | |
} | |
-struct search_response * | |
-youtube_search(const char *rawsearch, const char *page, const char *order) | |
+static struct search_response * | |
+parse_search_response(const char *data) | |
{ | |
struct search_response *r; | |
- char *data, *s, *start, *end; | |
+ const char *s, *start, *end; | |
int ret; | |
- if (!(data = request_search(rawsearch, page, order))) | |
- return NULL; | |
- | |
if (!(s = strstr(data, "\r\n\r\n"))) | |
return NULL; /* invalid response */ | |
/* skip header */ | |
@@ -219,38 +230,38 @@ youtube_search(const char *rawsearch, const char *page, c… | |
free(r); | |
return NULL; | |
} | |
- | |
return r; | |
} | |
struct search_response * | |
-youtube_channel_videos(const char *channelid) | |
+youtube_search(const char *rawsearch, const char *page, const char *order) | |
{ | |
- struct search_response *r; | |
- char *data, *s, *start, *end; | |
- int ret; | |
+ const char *data; | |
- if (!(data = request_channel_videos(channelid))) | |
+ if (!(data = request_search(rawsearch, page, order))) | |
return NULL; | |
- if (!(s = strstr(data, "\r\n\r\n"))) | |
- return NULL; /* invalid response */ | |
- /* skip header */ | |
- s += strlen("\r\n\r\n"); | |
+ return parse_search_response(data); | |
+} | |
- if (!(r = calloc(1, sizeof(*r)))) | |
- return NULL; | |
+struct search_response * | |
+youtube_channel_videos(const char *channelid) | |
+{ | |
+ const char *data; | |
- if (extractjson(s, &start, &end) == -1) { | |
- free(r); | |
+ if (!(data = request_channel_videos(channelid))) | |
return NULL; | |
- } | |
- ret = parsejson(start, end - start, processnode, r); | |
- if (ret < 0) { | |
- free(r); | |
+ return parse_search_response(data); | |
+} | |
+ | |
+struct search_response * | |
+youtube_user_videos(const char *user) | |
+{ | |
+ const char *data; | |
+ | |
+ if (!(data = request_user_videos(user))) | |
return NULL; | |
- } | |
- return r; | |
+ return parse_search_response(data); | |
} | |
diff --git a/youtube/youtube.h b/youtube/youtube.h | |
@@ -22,3 +22,6 @@ youtube_search(const char *rawsearch, const char *page, const… | |
struct search_response * | |
youtube_channel_videos(const char *channelid); | |
+ | |
+struct search_response * | |
+youtube_user_videos(const char *user); |