youtube/cgi: add page with basic video information - frontends - front-ends for… | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 2237f8c69f34d8f48a37e34d1462d327b9ddc40d | |
parent d8464a0a1169fc7b1ff0cea3a907b879a7230b47 | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Sat, 25 Feb 2023 20:14:18 +0100 | |
youtube/cgi: add page with basic video information | |
Diffstat: | |
M youtube/cgi.c | 161 +++++++++++++++++++++++++++--… | |
1 file changed, 140 insertions(+), 21 deletions(-) | |
--- | |
diff --git a/youtube/cgi.c b/youtube/cgi.c | |
@@ -21,7 +21,9 @@ extern char **environ; | |
static int curpage = 1; | |
/* CGI parameters */ | |
-static char rawsearch[4096], search[4096], order[16], page[64], channelid[256]… | |
+static char rawsearch[4096], search[4096], order[16], page[64]; | |
+static char videoid[256]; | |
+static char channelid[256], userid[256]; | |
void | |
parsecgi(void) | |
@@ -81,28 +83,32 @@ parsecgi(void) | |
if (decodeparam(userid, sizeof(userid), p) == -1) | |
userid[0] = '\0'; | |
} | |
-} | |
-int | |
-render(struct search_response *r) | |
-{ | |
- struct item *v; | |
- char tmp[64]; | |
- size_t i; | |
- | |
- if (pledge("stdio", NULL) == -1) { | |
- OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
- exit(1); | |
+ /* video ID */ | |
+ if ((p = getparam(query, "v"))) { | |
+ if (decodeparam(videoid, sizeof(videoid), p) == -1) | |
+ videoid[0] = '\0'; | |
} | |
+} | |
+void | |
+header(void) | |
+{ | |
OUT( | |
"Content-Type: text/html; charset=utf-8\r\n\r\n" | |
"<!DOCTYPE html>\n<html>\n<head>\n" | |
"<meta name=\"referrer\" content=\"no-referrer\" />\n" | |
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charse… | |
- "<title>Search: \""); | |
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charse… | |
+ | |
+ if (videoid[0]) { | |
+ OUT("<title>Video: "); | |
+ xmlencode(videoid); | |
+ OUT("</title>"); | |
+ } else { | |
+ OUT("<title>Search: \""); | |
xmlencode(search); | |
printf("\" sorted by %s</title>\n", order); | |
+ } | |
OUT( | |
"<link rel=\"stylesheet\" href=\"css/style.css\" type=\"text/c… | |
"<link rel=\"icon\" type=\"image/png\" href=\"/favicon.png\" /… | |
@@ -133,6 +139,27 @@ render(struct search_response *r) | |
"</tr>\n" | |
"</table>\n" | |
"</form>\n"); | |
+} | |
+ | |
+void | |
+footer(void) | |
+{ | |
+ OUT("</body>\n</html>\n"); | |
+} | |
+ | |
+int | |
+render_search(struct search_response *r) | |
+{ | |
+ struct item *v; | |
+ char tmp[64]; | |
+ size_t i; | |
+ | |
+ if (pledge("stdio", NULL) == -1) { | |
+ OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
+ exit(1); | |
+ } | |
+ | |
+ header(); | |
if (r && r->nitems) { | |
OUT( | |
@@ -163,7 +190,13 @@ render(struct search_response *r) | |
if (v->id[0]) { | |
OUT("<a href=\"https://www.youtube.com/embed/"… | |
xmlencode(v->id); | |
- printf("\" accesskey=\"%zu\">", i); | |
+ printf("\" accesskey=\"%zu\"", i); | |
+/* if (v->shortdescription[0]) { | |
+ OUT(" title=\""); | |
+ xmlencode(v->shortdescription); | |
+ OUT("\""); | |
+ }*/ | |
+ OUT(">"); | |
} | |
switch (v->linktype) { | |
@@ -187,6 +220,13 @@ render(struct search_response *r) | |
if (v->id[0]) | |
OUT("</a>"); | |
+ /* link to video information */ | |
+ if (v->id[0]) { | |
+ OUT(" <a href=\"?v="); | |
+ xmlencode(v->id); | |
+ OUT("\">[I]</a>"); | |
+ } | |
+ | |
OUT( | |
"</span><br/>\n" | |
"\t\t<span class=\"channel\">"); | |
@@ -277,7 +317,76 @@ render(struct search_response *r) | |
"</table>\n"); | |
} | |
- OUT("</body>\n</html>\n"); | |
+ footer(); | |
+ | |
+ return 0; | |
+} | |
+ | |
+int | |
+render_video(struct video_response *r) | |
+{ | |
+ char buf[256]; | |
+ | |
+ if (pledge("stdio", NULL) == -1) { | |
+ OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
+ exit(1); | |
+ } | |
+ | |
+ header(); | |
+ | |
+ OUT("<pre>"); | |
+ | |
+ OUT("URL: "); | |
+ OUT("https://www.youtube.com/embed/"); | |
+ xmlencode(r->id); | |
+ OUT("\n"); | |
+ | |
+ OUT("Title: "); | |
+ xmlencode(r->title); | |
+ OUT("\n"); | |
+ | |
+ if (r->lengthseconds > 0) { | |
+ OUT("Length: "); | |
+ if (durationstr(r->lengthseconds, buf, sizeof(buf)) < sizeof(b… | |
+ xmlencode(buf); | |
+ OUT("\n"); | |
+ } | |
+ | |
+ OUT("Views: "); | |
+ printf("%ld", r->viewcount); | |
+ OUT("\n"); | |
+ | |
+ if (r->publishdate[0]) { | |
+ OUT("Published: "); | |
+ xmlencode(r->publishdate); | |
+ OUT("\n"); | |
+ } | |
+ | |
+ if (r->uploaddate[0]) { | |
+ OUT("Uploaded: "); | |
+ xmlencode(r->uploaddate); | |
+ OUT("\n"); | |
+ } | |
+ | |
+ if (r->author[0]) { | |
+ OUT("Channel: "); | |
+ xmlencode(r->author); | |
+ if (r->channelid[0]) { | |
+ OUT(": https://www.youtube.com/feeds/videos.xml?channe… | |
+ xmlencode(r->channelid); | |
+ } | |
+ OUT("\n"); | |
+ } | |
+ | |
+ if (r->shortdescription[0]) { | |
+ OUT("Description:\n\n"); | |
+ xmlencode(r->shortdescription); | |
+ OUT("\n"); | |
+ } | |
+ | |
+ OUT("</pre>"); | |
+ | |
+ footer(); | |
return 0; | |
} | |
@@ -286,6 +395,7 @@ int | |
main(void) | |
{ | |
struct search_response *r = NULL; | |
+ struct video_response *vr = NULL; | |
if (pledge("stdio dns inet rpath unveil", NULL) == -1 || | |
unveil(TLS_CA_CERT_FILE, "r") == -1 || | |
@@ -296,21 +406,30 @@ main(void) | |
parsecgi(); | |
- if (rawsearch[0]) | |
+ if (rawsearch[0]) { | |
r = youtube_search(rawsearch, page, order); | |
- else if (channelid[0]) | |
+ } else if (channelid[0]) { | |
r = youtube_channel_videos(channelid); | |
- else if (userid[0]) | |
+ } else if (userid[0]) { | |
r = youtube_user_videos(userid); | |
- else | |
+ } else if (videoid[0]) { | |
+ vr = youtube_video(videoid); | |
+ if (!vr || vr->isfound == 0) { | |
+ OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
+ exit(1); | |
+ } | |
+ render_video(vr); | |
+ return 0; | |
+ } else { | |
goto show; | |
+ } | |
if (!r || r->nitems == 0) { | |
OUT("Status: 500 Internal Server Error\r\n\r\n"); | |
exit(1); | |
} | |
show: | |
- render(r); | |
+ render_search(r); | |
return 0; | |
} |