youtube/cgi: add page with basic video information - frontends - front-ends for some sites (experiment)
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 2237f8c69f34d8f48a37e34d1462d327b9ddc40d
 (DIR) parent d8464a0a1169fc7b1ff0cea3a907b879a7230b47
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       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(-)
       ---
 (DIR) 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], userid[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; charset=UTF-8\" />\n"
       -                "<title>Search: \"");
       +                "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n");
       +
       +        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/css\" media=\"screen\" />\n"
                        "<link rel=\"icon\" type=\"image/png\" href=\"/favicon.png\" />\n"
       @@ -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(buf))
       +                        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?channel_id=");
       +                        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;
        }