youtube/feed: split modifier for items found/matched and shorts - frontends - front-ends for some sites (experiment)
HTML git clone git://git.codemadness.org/frontends
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
DIR commit ea245985375df1599b6807ea079ac99d40d665ae
DIR parent 0e6fd5d3df8b9fc67ed53d587f10f22d28de24eb
HTML Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Sun, 17 May 2026 23:02:44 +0200
youtube/feed: split modifier for items found/matched and shorts
- Modifiers: +shorts, -shorts or +found, -found. The default is now to show all
items, but not show shorts.
- Unify/reuse the logic to allow to show an item in the current item context.
Diffstat:
M youtube/feed.c | 103 +++++++++++++++++++------------
1 file changed, 64 insertions(+), 39 deletions(-)
---
DIR diff --git a/youtube/feed.c b/youtube/feed.c
@@ -159,8 +159,10 @@ static String attrrel, tmpstr;
static struct search_response *search_res = NULL;
static void (*printfields)(void) = sfeed_item; /* default: sfeed(5) format */
static int cgimode = 0, godmode = 0;
-/* allow items not found/matched on the channel with the feed (like shorts). */
-static int allownotfound = 0;
+/* only show items found/matched on the channel with the feed. */
+static int showfound = 0;
+/* show shorts ("/shorts/" in the URL) or not. */
+static int showshorts = 0;
static const char *server_name = "127.0.0.1", *server_port = "70";
static int
@@ -443,6 +445,27 @@ atom_footer(void)
fputs("</feed>\n", stdout);
}
+static int
+iscurrentitemshort(void)
+{
+ return ctx.fields[FeedFieldLink].str.len &&
+ strstr(ctx.fields[FeedFieldLink].str.data, "/shorts/");
+}
+
+static int
+iscurrentitemallowed(struct item *found)
+{
+ /* Only print the video if it was found in the feed aswell. */
+ if (showfound && !found)
+ return 0;
+
+ /* Show shorts or not. */
+ if (!showshorts && iscurrentitemshort())
+ return 0;
+
+ return 1;
+}
+
static void
atom_item(void)
{
@@ -458,17 +481,16 @@ atom_item(void)
if (!strcmp(ctx.fields[FeedFieldYoutubeId].str.data, v->id))
found = v;
}
- /* Only print the video if it was found in the feed aswell.
- This way it filters away shorts too. */
- if (!allownotfound && !found)
+
+ if (!iscurrentitemallowed(found))
return;
fputs("<entry>\n\t<title>", stdout);
if (found && found->membersonly)
xmlencode(MEMBERS_ONLY);
xmlencode(ctx.fields[FeedFieldTitle].str.data);
- if (ctx.fields[FeedFieldLink].str.len &&
- strstr(ctx.fields[FeedFieldLink].str.data, "/shorts/"))
+
+ if (iscurrentitemshort())
fputs(YT_SHORTS_TITLE, stdout);
if (found && found->duration[0]) {
fputs(" [", stdout);
@@ -540,9 +562,8 @@ html_item(void)
if (!strcmp(ctx.fields[FeedFieldYoutubeId].str.data, v->id))
found = v;
}
- /* Only print the video if it was found in the feed aswell.
- This way it filters away shorts too. */
- if (!allownotfound && !found)
+
+ if (!iscurrentitemallowed(found))
return;
/* just print the original timestamp, it should conform */
@@ -558,8 +579,7 @@ html_item(void)
if (found && found->membersonly)
xmlencode(MEMBERS_ONLY);
xmlencode(ctx.fields[FeedFieldTitle].str.data);
- if (ctx.fields[FeedFieldLink].str.len &&
- strstr(ctx.fields[FeedFieldLink].str.data, "/shorts/"))
+ if (iscurrentitemshort())
fputs(YT_SHORTS_TITLE, stdout);
if (found && found->duration[0]) {
fputs(" [", stdout);
@@ -604,9 +624,8 @@ gph_item(void)
if (!strcmp(ctx.fields[FeedFieldYoutubeId].str.data, v->id))
found = v;
}
- /* Only print the video if it was found in the feed aswell.
- This way it filters away shorts too. */
- if (!allownotfound && !found)
+
+ if (!iscurrentitemallowed(found))
return;
fputs("h", stdout);
@@ -616,8 +635,7 @@ gph_item(void)
if (found && found->membersonly)
gphencode(MEMBERS_ONLY);
gphencode(ctx.fields[FeedFieldTitle].str.data);
- if (ctx.fields[FeedFieldLink].str.len &&
- strstr(ctx.fields[FeedFieldLink].str.data, "/shorts/"))
+ if (iscurrentitemshort())
gphencode(YT_SHORTS_TITLE);
if (found && found->duration[0]) {
fputs(" [", stdout);
@@ -678,9 +696,8 @@ json_item(void)
if (!strcmp(ctx.fields[FeedFieldYoutubeId].str.data, v->id))
found = v;
}
- /* Only print the video if it was found in the feed aswell.
- This way it filters away shorts too. */
- if (!allownotfound && !found)
+
+ if (!iscurrentitemallowed(found))
return;
if (!json_firstitem)
@@ -700,8 +717,7 @@ json_item(void)
if (found && found->membersonly)
json_printfield(MEMBERS_ONLY);
json_printfield(ctx.fields[FeedFieldTitle].str.data);
- if (ctx.fields[FeedFieldLink].str.len &&
- strstr(ctx.fields[FeedFieldLink].str.data, "/shorts/"))
+ if (iscurrentitemshort())
json_printfield(YT_SHORTS_TITLE);
if (found && found->duration[0]) {
fputs(" [", stdout);
@@ -742,9 +758,8 @@ sfeed_item(void)
if (!strcmp(ctx.fields[FeedFieldYoutubeId].str.data, v->id))
found = v;
}
- /* Only print the video if it was found in the feed aswell.
- This way it filters away shorts too. */
- if (!allownotfound && !found)
+
+ if (!iscurrentitemallowed(found))
return;
string_print_timestamp(&ctx.fields[FeedFieldTime].str);
@@ -752,8 +767,7 @@ sfeed_item(void)
if (found && found->membersonly)
fputs(MEMBERS_ONLY, stdout);
string_print(&ctx.fields[FeedFieldTitle].str);
- if (ctx.fields[FeedFieldLink].str.len &&
- strstr(ctx.fields[FeedFieldLink].str.data, "/shorts/"))
+ if (iscurrentitemshort())
fputs(YT_SHORTS_TITLE, stdout);
if (found && found->duration[0]) {
fputs(" [", stdout);
@@ -792,9 +806,8 @@ twtxt_item(void)
if (!strcmp(ctx.fields[FeedFieldYoutubeId].str.data, v->id))
found = v;
}
- /* Only print the video if it was found in the feed aswell.
- This way it filters away shorts too. */
- if (!allownotfound && !found)
+
+ if (!iscurrentitemallowed(found))
return;
string_print(&ctx.fields[FeedFieldTime].str);
@@ -802,8 +815,7 @@ twtxt_item(void)
if (found && found->membersonly)
fputs(MEMBERS_ONLY, stdout);
string_print(&ctx.fields[FeedFieldTitle].str);
- if (ctx.fields[FeedFieldLink].str.len &&
- strstr(ctx.fields[FeedFieldLink].str.data, "/shorts/"))
+ if (iscurrentitemshort())
fputs(YT_SHORTS_TITLE, stdout);
if (found && found->duration[0]) {
fputs(" [", stdout);
@@ -1072,7 +1084,7 @@ void
usage(void)
{
const char *line1 = "Bad Request, path should be the channel id + file extension, for example: UCrbvoMC0zUvPL8vjswhLOSw.json";
- const char *line2 = "Supported extensions are: [atom|gph|html|json|tsv|txt][+notfound]";
+ const char *line2 = "Supported extensions are: [atom|gph|html|json|tsv|txt][[+-]found|shorts]";
if (cgimode) {
if (godmode) {
@@ -1086,19 +1098,19 @@ usage(void)
}
exit(0);
} else {
- fputs("usage: feed <channelid> [atom|gph|html|json|tsv|txt][+notfound]\n", stderr);
+ fputs("usage: feed <channelid> [atom|gph|html|json|tsv|txt][[+-found|shorts]\n", stderr);
fputs("For example: feed UCrbvoMC0zUvPL8vjswhLOSw txt\n", stderr);
exit(1);
}
}
-/* check format, ignore specifier, like "+notfound" */
+/* check format, ignore modifier, like "+notfound" */
int
isformat(const char *input, const char *check)
{
size_t len;
- len = strcspn(input, "+");
+ len = strcspn(input, "+-");
if (!len)
return 0;
@@ -1108,6 +1120,21 @@ isformat(const char *input, const char *check)
return 0;
}
+void
+parseformatmodifier(const char *input)
+{
+ /* only show items found/matched on the channel with the feed. */
+ if (strstr(input, "+found"))
+ showfound = 1;
+ if (strstr(input, "-found"))
+ showfound = 0;
+ /* show shorts ("/shorts/" in the URL) or not. */
+ if (strstr(input, "+shorts"))
+ showshorts = 1;
+ if (strstr(input, "-shorts"))
+ showshorts = 0;
+}
+
int
main(int argc, char *argv[])
{
@@ -1172,9 +1199,7 @@ main(int argc, char *argv[])
else
usage();
- /* specifier to allow items to print items not matched (for shorts) */
- if (strstr(format, "+notfound"))
- allownotfound = 1;
+ parseformatmodifier(format);
search_res = youtube_channel_videos(channelid);
if (!search_res || search_res->nitems == 0) {