URI: 
       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) {