youtube/cli: add TSV option and -u option, remove channel2tsv - frontends - fro… | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit eec1de3aa027fd3e75101a4829658c2af844fb25 | |
parent b407559e2ea372a5d16bd0b08c9088762fa9ce75 | |
Author: Hiltjo Posthuma <[email protected]> | |
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(-) | |
--- | |
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… | |
-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… | |
-youtube/channel2tsv: ${LIB} youtube/youtube.o youtube/channel2tsv.o | |
- ${CC} -o $@ youtube/channel2tsv.o youtube/youtube.o ${LIB} ${LDFLAGS} … | |
- | |
youtube/cli: ${LIB} youtube/youtube.o youtube/cli.o | |
${CC} -o $@ youtube/cli.o youtube/youtube.o ${LIB} ${LDFLAGS} ${LIBTLS… | |
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; | |
-} | |
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", … | |
+ fprintf(stderr, "usage: %s [-t] <keyword> | <-c channelid> | <-u user>… | |
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; | |
} |