(* * Copyright (c) 2014, OCaml.org project * Copyright (c) 2015 KC Sivaramakrishnan * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *) (** River RSS/Atom feed aggregator *) (** {1 Session Management} *) type session (** An abstract River session for fetching feeds. The session manages HTTP connections and is tied to an Eio switch for proper resource cleanup. *) val init : sw:Eio.Switch.t -> < clock : float Eio.Time.clock_ty Eio.Resource.t; fs : Eio.Fs.dir_ty Eio.Path.t; net : [ `Generic | `Unix ] Eio.Net.ty Eio.Resource.t; .. > -> session (** [init ~sw env] creates a new River session. The session is configured with appropriate defaults for fetching feeds: - User-Agent: "OCaml-River/1.0" - Automatic redirect following (max 5 redirects) - TLS verification enabled @param sw The switch for resource management @param env The Eio environment *) val with_session : < clock : float Eio.Time.clock_ty Eio.Resource.t; fs : Eio.Fs.dir_ty Eio.Path.t; net : [ `Generic | `Unix ] Eio.Net.ty Eio.Resource.t; .. > -> (session -> 'a) -> 'a (** [with_session env f] creates a session and automatically manages its lifecycle. This is the recommended way to use River as it ensures proper cleanup. @param env The Eio environment @param f The function to run with the session *) (** {1 Feed Sources and Fetching} *) type source = { name : string; url : string } (** The source of a feed. *) type feed (** An Atom, RSS2, or JSON Feed. *) type post (** A post from a feed. *) val fetch : session -> source -> feed (** [fetch session source] returns an Atom or RSS feed from a source. @param session The River session @param source The feed source to fetch *) val name : feed -> string (** [name feed] is the name of the feed source passed to [fetch]. *) val url : feed -> string (** [url feed] is the url of the feed source passed to [fetch]. *) val posts : feed list -> post list (** [posts feeds] is the list of deduplicated posts of the given feeds. *) val feed : post -> feed (** [feed post] is the feed the post originates from. *) val title : post -> string (** [title post] is the title of the post. *) val link : post -> Uri.t option (** [link post] is the link of the post. *) val date : post -> Syndic.Date.t option (** [date post] is the date of the post. *) val author : post -> string (** [author post] is the author of the post. *) val email : post -> string (** [email post] is the email of the post. *) val content : post -> string (** [content post] is the content of the post. *) val id : post -> string (** [id post] is the unique identifier of the post. *) val tags : post -> string list (** [tags post] is the list of tags associated with the post. *) val summary : post -> string option (** [summary post] is the summary/excerpt of the post, if available. *) val meta_description : post -> string option (** [meta_description post] is the meta description of the post on the origin site. To get the meta description, we make get the content of [link post] and look for an HTML meta tag with the name "description" or "og:description".*) val seo_image : post -> string option (** [seo_image post] is the image to be used by social networks and links to the post. To get the seo image, we make get the content of [link post] and look for an HTML meta tag with the name "og:image" or "twitter:image". *) val create_atom_entries : post list -> Syndic.Atom.entry list (** [create_atom_feed posts] creates a list of atom entries, which can then be used to create an atom feed that is an aggregate of the posts. *) (** {1 JSON Feed Support} *) val create_jsonfeed_items : post list -> Jsonfeed.Item.t list (** [create_jsonfeed_items posts] creates a list of JSONFeed items from posts. *) val create_jsonfeed : title:string -> ?home_page_url:string -> ?feed_url:string -> ?description:string -> ?icon:string -> ?favicon:string -> post list -> Jsonfeed.t (** [create_jsonfeed ~title ?home_page_url ?feed_url ?description posts] creates a complete JSONFeed from the given posts. @param title The feed title (required) @param home_page_url The URL of the website the feed represents @param feed_url The URL of the feed itself @param description A description of the feed @param icon URL of an icon for the feed (512x512 recommended) @param favicon URL of a favicon for the feed (64x64 recommended) @param posts The posts to include in the feed *) val jsonfeed_to_string : ?minify:bool -> Jsonfeed.t -> (string, string) result (** [jsonfeed_to_string ?minify jsonfeed] serializes a JSONFeed to a string. @param minify If true, output compact JSON; if false, pretty-print (default: false) *) type feed_content = Atom of Syndic.Atom.feed | Rss2 of Syndic.Rss2.channel | JSONFeed of Jsonfeed.t (** The native format of a feed. *) val feed_content : feed -> feed_content (** [feed_content feed] returns the feed in its native format (Atom, RSS2, or JSONFeed). This allows access to format-specific features like JSONFeed attachments. *)