{"id":24876234,"url":"https://github.com/dotandimet/mojolicious-plugin-feedreader","last_synced_at":"2026-06-28T18:31:24.500Z","repository":{"id":137338450,"uuid":"17257258","full_name":"dotandimet/Mojolicious-Plugin-FeedReader","owner":"dotandimet","description":"Mojolicious::Plugin::FeedReader - Mojolicious plugin to find and parse RSS \u0026 Atom feeds","archived":false,"fork":false,"pushed_at":"2018-02-28T12:57:37.000Z","size":284,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-10-19T17:56:17.084Z","etag":null,"topics":["mojolicious-plugin","perl","rss","rss-feed-parser"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"artistic-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dotandimet.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-02-27T17:19:50.000Z","updated_at":"2024-02-25T21:35:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"52392504-147e-4506-8b8c-41f0b8df4ffb","html_url":"https://github.com/dotandimet/Mojolicious-Plugin-FeedReader","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/dotandimet/Mojolicious-Plugin-FeedReader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotandimet%2FMojolicious-Plugin-FeedReader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotandimet%2FMojolicious-Plugin-FeedReader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotandimet%2FMojolicious-Plugin-FeedReader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotandimet%2FMojolicious-Plugin-FeedReader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dotandimet","download_url":"https://codeload.github.com/dotandimet/Mojolicious-Plugin-FeedReader/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotandimet%2FMojolicious-Plugin-FeedReader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34900367,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mojolicious-plugin","perl","rss","rss-feed-parser"],"created_at":"2025-02-01T08:29:01.183Z","updated_at":"2026-06-28T18:31:24.479Z","avatar_url":"https://github.com/dotandimet.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nMojolicious::Plugin::FeedReader - Mojolicious plugin to find and parse RSS \u0026 Atom feeds\n\n# SYNOPSIS\n\n        # Mojolicious\n         $self-\u003eplugin('FeedReader');\n\n         # Mojolicious::Lite\n         plugin 'FeedReader';\n\n        # Blocking:\n        get '/b' =\u003e sub {\n          my $self = shift;\n          my ($feed) = $self-\u003efind_feeds(q{search.cpan.org});\n          my $out = $self-\u003eparse_feed($feed);\n          $self-\u003erender(template =\u003e 'uploads', items =\u003e $out-\u003e{items});\n        };\n\n        # Non-blocking:\n        get '/nb' =\u003e sub {\n          my $self = shift;\n          $self-\u003erender_later;\n          my $delay = Mojo::IOLoop-\u003edelay(\n            sub {\n              $self-\u003efind_feeds(\"search.cpan.org\", shift-\u003ebegin(0));\n            },\n            sub {\n              my $feed = pop;\n              $self-\u003eparse_feed($feed, shift-\u003ebegin);\n            },\n            sub {\n                my $data = pop;\n                $self-\u003erender(template =\u003e 'uploads', items =\u003e $data-\u003e{items});\n            });\n          $delay-\u003ewait unless Mojo::IOLoop-\u003eis_running;\n        };\n\n        app-\u003estart;\n\n        __DATA__\n\n        @@ uploads.html.ep\n        \u003cul\u003e\n        % for my $item (@$items) {\n          \u003cli\u003e\u003c%= link_to $item-\u003e{title} =\u003e $item-\u003e{link} %\u003e - \u003c%= $item-\u003e{description} %\u003e\u003c/li\u003e\n        % }\n        \u003c/ul\u003e\n\n# DESCRIPTION\n\n**Mojolicious::Plugin::FeedReader** implements minimalistic helpers for identifying,\nfetching and parsing RSS and Atom Feeds.  It has minimal dependencies, relying as\nmuch as possible on Mojolicious components - Mojo::UserAgent for fetching feeds and\nchecking URLs, Mojo::DOM for XML/HTML parsing.\nIt is therefore rather fragile and naive, and should be considered Experimental/Toy\ncode - **use at your own risk**.\n\n# METHODS\n\n[Mojolicious::Plugin::FeedReader](https://metacpan.org/pod/Mojolicious::Plugin::FeedReader) inherits all methods from\n[Mojolicious::Plugin](https://metacpan.org/pod/Mojolicious::Plugin) and implements the following new ones.\n\n## register\n\n    $plugin-\u003eregister(Mojolicious-\u003enew);\n\nRegister plugin in [Mojolicious](https://metacpan.org/pod/Mojolicious) application. This method will install the helpers\nlisted below in your Mojolicious application.\n\n# HELPERS\n\n**Mojolicious::Plugin::FeedReader** implements the following helpers.\n\n## find\\_feeds\n\n    # Call blocking\n    my (@feeds) = app-\u003efind_feeds('search.cpan.org');\n    # @feeds is a list of Mojo::URL objects\n\n    # Call non-blocking\n    $self-\u003efind_feeds('http://example.com', sub {\n      my (@feeds) = @_;\n      unless (@feeds) {\n        $self-\u003erender_exception(\"no feeds found, \" . $info-\u003e{error});\n      }\n      else {\n        ....\n      }\n    });\n\nA Mojolicious port of [Feed::Find](https://metacpan.org/pod/Feed::Find) by Benjamin Trott. This helper implements feed auto-discovery for finding syndication feeds, given a URI.\nIf given a callback function as an additional argument, execution will be non-blocking.\n\n## parse\\_feed\n\n    # parse an RSS/Atom feed\n    # blocking\n    my $url = Mojo::URL-\u003enew('http://rss.slashdot.org/Slashdot/slashdot');\n    my $feed = $self-\u003eparse_feed($url);\n    for my $item (@{$feed-\u003e{items}}) {\n      say $_ for ($item-\u003e{title}, $item-\u003e{description}, 'Tags: ' . join q{,}, @{$item-\u003e{tags}});\n    }\n\n    # non-blocking\n    $self-\u003eparse_feed($url, sub {\n      my ($feed) = @_;\n      $c-\u003erender(text =\u003e \"Feed tagline: \" . $feed-\u003e{tagline});\n    });\n\n    # parse a file\n    $feed2 = $self-\u003eparse_feed('/downloads/foo.rss');\n\n    # parse response\n    $self-\u003eua-\u003eget($feed_url, sub {\n      my ($ua, $tx) = @_;\n      my $feed = $self-\u003eparse_feed($tx-\u003eres);\n    });\n\nA minimalist liberal RSS/Atom parser, using Mojo::DOM queries.\n\nDates are parsed using [HTTP::Date](https://metacpan.org/pod/HTTP::Date).\n\nIf parsing fails (for example, the parser was given an HTML page), the helper will return undef.\n\nOn success, the result returned is a hashref with the following keys:\n\n- title\n- description (may be filled from subtitle or tagline if absent)\n- htmlUrl - web page URL associated with the feed\n- items - array ref of feed news items\n- subtitle (optional)\n- tagline (optional)\n- author (name of author field, or dc:creator or webMaster)\n- published - time in epoch seconds (may be filled with pubDate, dc:date, created, issued, updated or modified)\n\nEach item in the items array is a hashref with the following keys:\n\n- title\n- link\n- content (may be filled with content:encoded, xhtml:body or description fields)\n- id (will be equal to link or guid if it is undefined and either of those fields exists)\n- description (optional) - usually a shorter form of the content (may be filled with summary if description is missing)\n- guid (optional)\n- published - time in epoch seconds (may be filled with pubDate, dc:date, created, issued, updated or modified)\n- author (may be filled from author or dc:creator)\n- tags (optional) - array ref of tags, categories or dc:subjects.\n- \\_raw - XML serialized text of the item's Mojo::DOM node. Note that this can be different from the original XML text in the feed.\n\n## parse\\_opml\n\n    my @subscriptions = app-\u003eparse_opml( 'mysubs.opml' );\n    foreach my $sub (@subscriptions) {\n      say 'RSS URL is: ',     $sub-\u003e{xmlUrl};\n      say 'Website URL is: ', $sub-\u003e{htmlUrl};\n      say 'categories: ', join ',', @{$sub-\u003e{categories}};\n    }\n\nParse an OPML subscriptions file and return the list of feeds as an array of hashrefs.\n\nEach hashref will contain an array ref in the key 'categories' listing the folders (parent nodes) in the OPML tree the subscription item appears in.\n\n# STAND-ALONE USE\n\n[Mojolicious::Plugin::FeedReader](https://metacpan.org/pod/Mojolicious::Plugin::FeedReader) can also be used directly, rather than as a plugin:\n\n    use Mojolicious::Plugin::FeedReader;\n    my $fr = Mojolicious::Plugin::FeedReader-\u003enew( ua =\u003e Mojo::UserAgent-\u003enew );\n    my ($feed) = $fr-\u003efind_feeds($url);\n    ...\n\nIn the future, the feed-parsing code will probably move into its own module.\n\n# CREDITS\n\nDotan Dimet\n\nMario Domgoergen\n\nSome tests adapted from [Feed::Find](https://metacpan.org/pod/Feed::Find) and [XML:Feed](XML:Feed), Feed autodiscovery adapted from [Feed::Find](https://metacpan.org/pod/Feed::Find).\n\n# COPYRIGHT AND LICENSE\n\nCopyright (C) 2014, Dotan Dimet.\n\nThis program is free software, you can redistribute it and/or modify it\nunder the terms of the Artistic License version 2.0.\n\nTest data (web pages, feeds and excerpts) included in this package is intended for testing purposes only, and is not meant in any way\nto infringe on the rights of the respective authors.\n\n# SEE ALSO\n\n[Mojolicious](https://metacpan.org/pod/Mojolicious), [Mojolicious::Guides](https://metacpan.org/pod/Mojolicious::Guides), [http://mojolicio.us](http://mojolicio.us)\n\n[XML::Feed](https://metacpan.org/pod/XML::Feed), [Feed::Find](https://metacpan.org/pod/Feed::Find), [HTTP::Date](https://metacpan.org/pod/HTTP::Date)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotandimet%2Fmojolicious-plugin-feedreader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdotandimet%2Fmojolicious-plugin-feedreader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotandimet%2Fmojolicious-plugin-feedreader/lists"}