My agentic slop goes here. Not intended for anyone else!
at main 6.6 kB view raw
1(* 2 * Copyright (c) 2014, OCaml.org project 3 * Copyright (c) 2015 KC Sivaramakrishnan <sk826@cl.cam.ac.uk> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 *) 17 18(** State management for sync state and feeds. 19 20 User contact data is read from Sortal on-demand. River only persists 21 sync timestamps and feed data. *) 22 23type t 24(** State handle for managing sync state and feeds on disk. *) 25 26val create : 27 < fs : Eio.Fs.dir_ty Eio.Path.t; .. > -> 28 app_name:string -> 29 t 30(** [create env ~app_name] creates a state handle using XDG directories. 31 32 Data is stored in: 33 - Sync state: $XDG_STATE_HOME/[app_name]/sync_state.json 34 - Feeds: $XDG_STATE_HOME/[app_name]/feeds/[username]/ 35 36 User contact data is read from Sortal's XDG location. 37 38 @param env The Eio environment with filesystem access 39 @param app_name Application name for XDG paths *) 40 41(** {2 User Operations} *) 42 43val get_user : t -> username:string -> User.t option 44(** [get_user state ~username] retrieves a user by username. 45 46 This reads contact data from Sortal and combines it with River's sync state. 47 Returns [None] if the username doesn't exist in Sortal or has no feeds. *) 48 49val list_users : t -> string list 50(** [list_users state] returns all usernames with feeds from Sortal. *) 51 52val get_all_users : t -> User.t list 53(** [get_all_users state] returns all users from Sortal with their sync state. *) 54 55val update_sync_state : t -> username:string -> timestamp:string -> (unit, string) result 56(** [update_sync_state state ~username ~timestamp] updates the last sync timestamp. 57 58 @param username The user to update 59 @param timestamp ISO 8601 timestamp of the sync *) 60 61(** {2 Feed Operations} *) 62 63val sync_user : 64 < clock : float Eio.Time.clock_ty Eio.Resource.t; 65 fs : Eio.Fs.dir_ty Eio.Path.t; 66 net : [ `Generic | `Unix ] Eio.Net.ty Eio.Resource.t; .. > -> 67 t -> 68 username:string -> 69 (unit, string) result 70(** [sync_user env state ~username] fetches all feeds for the user and stores merged result. 71 72 Posts are fetched concurrently and merged with existing posts. 73 The result is stored as an Atom feed. *) 74 75val sync_all : 76 < clock : float Eio.Time.clock_ty Eio.Resource.t; 77 fs : Eio.Fs.dir_ty Eio.Path.t; 78 net : [ `Generic | `Unix ] Eio.Net.ty Eio.Resource.t; .. > -> 79 t -> 80 (int * int, string) result 81(** [sync_all env state] syncs all users concurrently. 82 83 Returns [Ok (success_count, fail_count)]. *) 84 85val get_user_posts : 86 t -> 87 username:string -> 88 ?limit:int -> 89 unit -> 90 Syndic.Atom.entry list 91(** [get_user_posts state ~username ()] retrieves stored posts for a user. 92 93 @param limit Optional maximum number of posts to return *) 94 95val get_all_posts : 96 t -> 97 ?limit:int -> 98 unit -> 99 (string * Syndic.Atom.entry) list 100(** [get_all_posts state ()] retrieves posts from all users, sorted by date. 101 102 Returns list of (username, entry) tuples. 103 @param limit Optional maximum number of posts to return *) 104 105(** {2 Export} *) 106 107val export_merged_feed : 108 t -> 109 title:string -> 110 format:[ `Atom | `Jsonfeed ] -> 111 ?limit:int -> 112 unit -> 113 (string, string) result 114(** [export_merged_feed state ~title ~format ()] exports a merged feed of all users. 115 116 @param title Feed title 117 @param format Output format 118 @param limit Optional maximum number of entries *) 119 120val export_html_site : 121 t -> 122 output_dir:Eio.Fs.dir_ty Eio.Path.t -> 123 title:string -> 124 ?posts_per_page:int -> 125 unit -> 126 (unit, string) result 127(** [export_html_site state ~output_dir ~title ()] exports a static HTML site. 128 129 Generates a complete static site with: 130 - Paginated post listings 131 - Author index and individual author pages 132 - Category index and individual category pages 133 - Links page showing all outgoing links from posts 134 135 @param output_dir Directory to write HTML files to 136 @param title Site title 137 @param posts_per_page Number of posts per page (default: 25) *) 138 139(** {2 Category Management} *) 140 141val list_categories : t -> Category.t list 142(** [list_categories state] returns all custom categories. *) 143 144val get_category : t -> id:string -> Category.t option 145(** [get_category state ~id] retrieves a category by ID. *) 146 147val add_category : t -> Category.t -> (unit, string) result 148(** [add_category state category] adds or updates a category. 149 150 @param category The category to add/update *) 151 152val remove_category : t -> id:string -> (unit, string) result 153(** [remove_category state ~id] removes a category. 154 155 This also removes the category from any posts that were tagged with it. 156 @param id The category ID to remove *) 157 158val get_post_categories : t -> post_id:string -> string list 159(** [get_post_categories state ~post_id] returns the list of category IDs 160 assigned to a post. *) 161 162val set_post_categories : t -> post_id:string -> category_ids:string list -> (unit, string) result 163(** [set_post_categories state ~post_id ~category_ids] sets the categories for a post. 164 165 Replaces any existing category assignments for this post. 166 @param post_id The post ID to categorize 167 @param category_ids List of category IDs to assign *) 168 169val add_post_category : t -> post_id:string -> category_id:string -> (unit, string) result 170(** [add_post_category state ~post_id ~category_id] adds a category to a post. 171 172 @param post_id The post ID 173 @param category_id The category ID to add *) 174 175val remove_post_category : t -> post_id:string -> category_id:string -> (unit, string) result 176(** [remove_post_category state ~post_id ~category_id] removes a category from a post. 177 178 @param post_id The post ID 179 @param category_id The category ID to remove *) 180 181val get_posts_by_category : t -> category_id:string -> string list 182(** [get_posts_by_category state ~category_id] returns all post IDs with this category. *) 183 184(** {2 Analysis} *) 185 186val analyze_user_quality : 187 t -> 188 username:string -> 189 (Quality.t, string) result 190(** [analyze_user_quality state ~username] analyzes quality metrics for a user's feed. *)