youtube/cli: add TSV option and -u option, remove channel2tsv - frontends - front-ends for some sites (experiment)
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit eec1de3aa027fd3e75101a4829658c2af844fb25
 (DIR) parent b407559e2ea372a5d16bd0b08c9088762fa9ce75
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Tue, 21 Feb 2023 20:46:42 +0100
       
       youtube/cli: add TSV option and -u option, remove channel2tsv
       
       Diffstat:
         M Makefile                            |       6 +-----
         D youtube/channel2tsv.c               |     108 -------------------------------
         M youtube/cli.c                       |     103 ++++++++++++++++++++++++++-----
       
       3 files changed, 89 insertions(+), 128 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       @@ -25,7 +25,6 @@ BIN = \
                reddit/cli \
                reddit/gopher \
                youtube/cgi \
       -        youtube/channel2tsv \
                youtube/cli \
                youtube/gopher
        
       @@ -98,14 +97,11 @@ twitch/cgi: ${LIB} twitch/twitch.o twitch/cgi.o
        twitch/gopher: ${LIB} twitch/twitch.o twitch/gopher.o
                ${CC} -o $@ twitch/gopher.o twitch/twitch.o ${LIB} ${LDFLAGS} ${LIBTLS_LDFLAGS_STATIC}
        
       -youtube: youtube/cgi youtube/channel2tsv youtube/cli youtube/gopher
       +youtube: youtube/cgi youtube/cli youtube/gopher
        
        youtube/cgi: ${LIB} youtube/youtube.o youtube/cgi.o
                ${CC} -o $@ youtube/cgi.o youtube/youtube.o ${LIB} ${LDFLAGS} ${LIBTLS_LDFLAGS_STATIC}
        
       -youtube/channel2tsv: ${LIB} youtube/youtube.o youtube/channel2tsv.o
       -        ${CC} -o $@ youtube/channel2tsv.o youtube/youtube.o ${LIB} ${LDFLAGS} ${LIBTLS_LDFLAGS}
       -
        youtube/cli: ${LIB} youtube/youtube.o youtube/cli.o
                ${CC} -o $@ youtube/cli.o youtube/youtube.o ${LIB} ${LDFLAGS} ${LIBTLS_LDFLAGS}
        
 (DIR) diff --git a/youtube/channel2tsv.c b/youtube/channel2tsv.c
       @@ -1,108 +0,0 @@
       -#include <sys/socket.h>
       -#include <sys/types.h>
       -
       -#include <ctype.h>
       -#include <errno.h>
       -#include <netdb.h>
       -#include <stdarg.h>
       -#include <stdio.h>
       -#include <stdlib.h>
       -#include <string.h>
       -#include <unistd.h>
       -
       -#include "https.h"
       -#include "util.h"
       -#include "youtube.h"
       -
       -#define OUT(s) fputs((s), stdout)
       -#define OUTESCAPE(s) printescape((s))
       -
       -/* print: ignore control-characters */
       -void
       -printescape(const char *s)
       -{
       -        for (; *s; ++s)
       -                if (!iscntrl((unsigned char)*s))
       -                        fputc(*s, stdout);
       -}
       -
       -int
       -render(struct search_response *r)
       -{
       -        struct item *videos = r->items;
       -        size_t i;
       -
       -        if (pledge("stdio", NULL) == -1) {
       -                fprintf(stderr, "pledge: %s\n", strerror(errno));
       -                exit(1);
       -        }
       -
       -        for (i = 0; i < r->nitems; i++) {
       -                switch (videos[i].linktype) {
       -                case Channel:
       -                case Movie:
       -                case Playlist:
       -                        continue;
       -                default:
       -                        break;
       -                }
       -
       -                OUTESCAPE(videos[i].id);
       -                OUT("\t");
       -                if (videos[i].id[0]) {
       -                        OUT("https://www.youtube.com/embed/");
       -                        OUTESCAPE(videos[i].id);
       -                }
       -                OUT("\t");
       -                OUTESCAPE(videos[i].title);
       -                OUT("\t");
       -                OUTESCAPE(videos[i].publishedat);
       -                OUT("\t");
       -                OUTESCAPE(videos[i].viewcount);
       -                OUT("\t");
       -                OUTESCAPE(videos[i].duration);
       -                OUT("\n");
       -        }
       -
       -        return 0;
       -}
       -
       -static void
       -usage(const char *argv0)
       -{
       -        fprintf(stderr, "usage: %s <channelid>\n", argv0);
       -        exit(1);
       -}
       -
       -int
       -main(int argc, char *argv[])
       -{
       -        struct search_response *r;
       -        char channelid[1024];
       -
       -        if (pledge("stdio dns inet rpath unveil", NULL) == -1) {
       -                fprintf(stderr, "pledge: %s\n", strerror(errno));
       -                exit(1);
       -        }
       -        if (unveil(TLS_CA_CERT_FILE, "r") == -1) {
       -                fprintf(stderr, "unveil: %s\n", strerror(errno));
       -                exit(1);
       -        }
       -        if (unveil(NULL, NULL) == -1) {
       -                fprintf(stderr, "unveil: %s\n", strerror(errno));
       -                exit(1);
       -        }
       -
       -        if (argc < 2 || !argv[1][0])
       -                usage(argv[0]);
       -        if (!uriencode(argv[1], channelid, sizeof(channelid)))
       -                usage(argv[0]);
       -
       -        r = youtube_channel_videos(channelid);
       -        if (!r || r->nitems == 0)
       -                exit(1);
       -
       -        render(r);
       -
       -        return 0;
       -}
 (DIR) diff --git a/youtube/cli.c b/youtube/cli.c
       @@ -27,7 +27,7 @@ printescape(const char *s)
        }
        
        int
       -render(struct search_response *r)
       +render_tsv(struct search_response *r)
        {
                struct item *videos = r->items;
                size_t i;
       @@ -38,7 +38,47 @@ render(struct search_response *r)
                }
        
                for (i = 0; i < r->nitems; i++) {
       -                /* TODO: better printing of other types */
       +                OUTESCAPE(videos[i].id);
       +                OUT("\t");
       +                if (videos[i].id[0]) {
       +                        OUT("https://www.youtube.com/embed/");
       +                        OUTESCAPE(videos[i].id);
       +                }
       +                OUT("\t");
       +                OUTESCAPE(videos[i].title);
       +                OUT("\t");
       +                OUTESCAPE(videos[i].publishedat);
       +                OUT("\t");
       +                OUTESCAPE(videos[i].viewcount);
       +                OUT("\t");
       +                OUTESCAPE(videos[i].duration);
       +                OUT("\t");
       +                switch (videos[i].linktype) {
       +                case Channel:  OUT("channel"); break;
       +                case Movie:    OUT("movie"); break;
       +                case Playlist: OUT("playlist"); break;
       +                default:       break;
       +                }
       +                OUT("\t");
       +                OUTESCAPE(videos[i].channelid);
       +                OUT("\t");
       +                OUTESCAPE(videos[i].channeltitle);
       +                OUT("\t");
       +                OUTESCAPE(videos[i].userid);
       +                OUT("\t");
       +                OUT("\n");
       +        }
       +
       +        return 0;
       +}
       +
       +int
       +render(struct search_response *r)
       +{
       +        struct item *videos = r->items;
       +        size_t i;
       +
       +        for (i = 0; i < r->nitems; i++) {
                        switch (videos[i].linktype) {
                        case Channel:
                                OUT("[Channel] ");
       @@ -114,20 +154,49 @@ render(struct search_response *r)
        static void
        usage(const char *argv0)
        {
       -        fprintf(stderr, "usage: %s <keyword> | <-c channelid> | <-u user>\n", argv0);
       +        fprintf(stderr, "usage: %s [-t] <keyword> | <-c channelid> | <-u user>\n", argv0);
                exit(1);
        }
        
        int
        main(int argc, char *argv[])
        {
       -        struct search_response *r;
       +        struct search_response *r = NULL;
                char search[1024];
       +        const char *keywords = NULL, *channelid = NULL, *user = NULL;
       +        int i, usetsv = 0;
        
                if (pledge("stdio dns inet rpath unveil", NULL) == -1) {
                        fprintf(stderr, "pledge: %s\n", strerror(errno));
                        exit(1);
                }
       +
       +        for (i = 1; i < argc; i++) {
       +                if (argv[i][0] == '-') {
       +                        switch (argv[i][1]) {
       +                        case 'c':
       +                                if (i + 1 >= argc)
       +                                        usage(argv[0]);
       +                                channelid = argv[i + 1];
       +                                i++;
       +                                break;
       +                        case 'u':
       +                                if (i + 1 >= argc)
       +                                        usage(argv[0]);
       +                                user = argv[i + 1];
       +                                i++;
       +                                break;
       +                        case 't':
       +                                usetsv = 1;
       +                                break;
       +                        default:
       +                                usage(argv[0]);
       +                        }
       +                        continue;
       +                }
       +                keywords = argv[i];
       +        }
       +
                if (unveil(TLS_CA_CERT_FILE, "r") == -1) {
                        fprintf(stderr, "unveil: %s\n", strerror(errno));
                        exit(1);
       @@ -139,16 +208,12 @@ main(int argc, char *argv[])
        
                if (argc < 2 || !argv[1][0])
                        usage(argv[0]);
       -        if (!strcmp(argv[1], "-c")) {
       -                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)))
       +        if (channelid) {
       +                r = youtube_channel_videos(channelid);
       +        } else if (user) {
       +                r = youtube_user_videos(user);
       +        } else if (keywords) {
       +                if (!uriencode(keywords, search, sizeof(search)))
                                usage(argv[0]);
                        r = youtube_search(search, "", "relevance");
                }
       @@ -157,7 +222,15 @@ main(int argc, char *argv[])
                        exit(1);
                }
        
       -        render(r);
       +        if (pledge("stdio", NULL) == -1) {
       +                fprintf(stderr, "pledge: %s\n", strerror(errno));
       +                exit(1);
       +        }
       +
       +        if (usetsv)
       +                render_tsv(r);
       +        else
       +                render(r);
        
                return 0;
        }