From 5d3c60b30ee7dd6af96aa2d5acf3fad4cf215b51 Mon Sep 17 00:00:00 2001 From: fang Date: Thu, 16 Nov 2023 21:09:42 +0100 Subject: [PATCH] lib: support summarization of new groups backend /lib/summarize now supports building summaries off of the new /app/channels. If that agent is running, it will use the new summarization logic. If it's not, it will continue on as it has. --- desk/lib/summarize.hoon | 96 ++++++++- desk/sur/channels.hoon | 461 ++++++++++++++++++++++++++++++++++++++++ desk/sur/chat-2.hoon | 356 +++++++++++++++++++++++++++++++ desk/sur/chat.hoon | 384 +++++++++++++-------------------- 4 files changed, 1054 insertions(+), 243 deletions(-) create mode 100644 desk/sur/channels.hoon create mode 100644 desk/sur/chat-2.hoon diff --git a/desk/lib/summarize.hoon b/desk/lib/summarize.hoon index 782e7545..90773fb0 100644 --- a/desk/lib/summarize.hoon +++ b/desk/lib/summarize.hoon @@ -1,6 +1,6 @@ :: summarize: utilities for summarizing groups/chat state in various ways :: -/- chat, groups +/- c=channels, ct=chat, chat=chat-2, groups :: |_ [our=@p now=@da] :: +range: period of time to summarize over @@ -14,6 +14,48 @@ [(scot %p our) term (scot %da now) spur] :: ++ summarize-activity + ?: .^(? %gu (scry-path %channels /$)) + summarize-activity-new-groups + summarize-activity-old-groups +:: +++ summarize-activity-new-groups + ^- $: sent=@ud + received=@ud + most-sent-group=@t + == + =- :+ s r + =/ g=flag:groups + =< - + ::TODO crashes if no groups + %+ snag 0 + %+ sort ~(tap by g) + |=([[* a=@ud] [* b=@ud]] (gth a b)) + =< title.meta + .^ group:groups + %gx + (scry-path %groups /groups/(scot %p p.g)/[q.g]/group) + == + %+ roll + %~ tap by + .^ channels:c + %gx + (scry-path %channels /channels/channels) + == + |= [[n=nest:c channel:c] g=(map flag:groups @ud) s=@ud r=@ud] + ?. ?=(%chat kind.n) [g s r] + =+ .^ paged-posts:c + %gx + %+ scry-path %channels + /chat/(scot %p ship.n)/[name.n]/posts/newer/(scot %ud (sub now range))/(scot %ud limit)/outline/channel-posts + == + :- %+ ~(put by g) group.perm + (add (~(gut by g) group.perm 0) (wyt:on-posts:c posts)) + %+ roll (tap:on-posts:c posts) + |= [[id-post:c p=(unit post:c)] s=_s r=_r] + ?~ p [s r] + ?:(=(our author.u.p) [+(s) r] [s +(r)]) +:: +++ summarize-activity-old-groups ^- $: sent=@ud received=@ud most-sent-group=@t @@ -31,7 +73,7 @@ (scry-path %groups /groups/(scot %p p.g)/[q.g]/group) == %+ roll - %~ tap in + %~ tap by .^ (map flag:chat chat:chat) %gx (scry-path %chat /chats/chats) @@ -50,6 +92,54 @@ ?:(=(our author) [+(s) r] [s +(r)]) :: ++ summarize-inactivity + ?: .^(? %gu (scry-path %channels /$)) + summarize-inactivity-new-groups + summarize-inactivity-old-groups +:: +++ summarize-inactivity-new-groups + ^- $: unread-dms=@ud :: unread dm count + unread-etc=@ud :: unread chats count + top-group=@t :: most active group + top-channel=@t :: most active channel + == + =+ .^(=unreads:ct %gx (scry-path %chat /unreads/chat-unreads)) + :: accumulate unread counts + :: + =/ dum=@ud + %- ~(rep by unreads) + |= [[w=whom:ct unread:unreads:ct] n=@ud] + (add n count) + :- dum + :: gather all chat channels & their groups & unread counts + :: + =/ [duc=@ud faz=(list [g=flag:groups n=nest:c u=@ud])] + %+ roll + %~ tap by + .^(channels:c %gx (scry-path %channels /channels/channels)) + =+ .^(=unreads:c %gx (scry-path %channels /unreads/channel-unreads)) + |= [[n=nest:c channel:c] duc=@ud faz=(list [flag:groups nest:c @ud])] + ?. ?=(%chat kind.n) [duc faz] :: ignore non-chat channels for now + =/ =unread:c (~(gut by unreads) n *unread:c) + :- (add duc count.unread) + [[group.perm n count.unread] faz] + :- duc + =. faz (sort faz |=([[* * a=@ud] [* * b=@ud]] (gth a b))) + :: get display titles of most active channel and its group + :: + ::NOTE in rare cases, we might not know of the existence of the associated + :: group. simply skip past it and try the next one... + =+ .^(=groups:groups %gx (scry-path %groups /groups/groups)) + |- + ?~ faz ['???' '???'] ::TODO better copy + ~| i.faz + ?. (~(has by groups) g.i.faz) + $(faz t.faz) + =/ =group:^groups (~(got by groups) g.i.faz) + ?~ chat=(~(get by channels.group) n.i.faz) + $(faz t.faz) + [title.meta.group title.meta.u.chat] +:: +++ summarize-inactivity-old-groups ^- $: unread-dms=@ud :: unread dm count unread-etc=@ud :: unread chats count top-group=@t :: most active group @@ -71,7 +161,7 @@ :: =/ faz=(list [g=flag:chat c=flag:chat n=@ud]) %+ turn - %~ tap in + %~ tap by .^ (map flag:chat chat:chat) %gx (scry-path %chat /chats/chats) diff --git a/desk/sur/channels.hoon b/desk/sur/channels.hoon new file mode 100644 index 00000000..2db94219 --- /dev/null +++ b/desk/sur/channels.hoon @@ -0,0 +1,461 @@ +:: channels: message stream structures +:: +:: four shapes that cross client-subscriber-publisher boundaries: +:: - actions client-to-subscriber change requests (user actions) +:: - commands subscriber-to-publisher change requests +:: - updates publisher-to-subscriber change notifications +:: - responses subscriber-to-client change notifications +:: +:: --action--> --command--> +:: client subscriber publisher +:: <--response-- <--update-- +:: +:: local actions _may_ become responses, +:: remote actions become commands, +:: commands _may_ become updates, +:: updates _may_ become responses. +:: +/- g=groups, c=cite +/+ mp=mop-extensions +|% ++| %ancients +:: +++ mar + |% + ++ act `mark`%channel-action + ++ cmd `mark`%channel-command + ++ upd `mark`%channel-update + ++ log `mark`%channel-logs + ++ not `mark`%channel-posts + -- +:: ++| %primitives +:: ++$ v-channels (map nest v-channel) +++ v-channel + |^ ,[global local] + :: $global: should be identical between ships + :: + +$ global + $: posts=v-posts + order=(rev order=arranged-posts) + view=(rev =view) + sort=(rev =sort) + perm=(rev =perm) + == + :: $window: sparse set of time ranges + :: + ::TODO populate this + +$ window (list [from=time to=time]) + :: .window: time range for requested posts that we haven't received + :: .diffs: diffs for posts in the window, to apply on receipt + :: + +$ future + [=window diffs=(jug id-post u-post)] + :: $local: local-only information + :: + +$ local + $: =net + =log + =remark + =window + =future + == + -- +:: $v-post: a channel post +:: ++$ v-post [v-seal (rev essay)] ++$ id-post time ++$ v-posts ((mop id-post (unit v-post)) lte) +++ on-v-posts ((on id-post (unit v-post)) lte) +++ mo-v-posts ((mp id-post (unit v-post)) lte) +:: $v-reply: a post comment +:: ++$ v-reply [v-reply-seal memo] ++$ id-reply time ++$ v-replies ((mop id-reply (unit v-reply)) lte) +++ on-v-replies ((on id-reply (unit v-reply)) lte) +++ mo-v-replies ((mp time (unit v-reply)) lte) +:: $v-seal: host-side data for a post +:: ++$ v-seal $+ channel-seal + $: id=id-post + replies=v-replies + reacts=v-reacts + == +:: $v-reply-seal: host-side data for a reply +:: ++$ v-reply-seal + $: id=id-reply + reacts=v-reacts + == +:: $essay: top-level post, with metadata +:: ++$ essay [memo =kind-data] +:: $reply-meta: metadata for all replies ++$ reply-meta + $: reply-count=@ud + last-repliers=(set ship) + last-reply=(unit time) + == +:: $kind-data: metadata for a channel type's "post" +:: ++$ kind-data + $% [%diary title=@t image=@t] + [%heap title=(unit @t)] + [%chat kind=$@(~ [%notice ~])] + == +:: $memo: post data proper +:: +:: content: the body of the comment +:: author: the ship that wrote the comment +:: sent: the client-side time the comment was made +:: ++$ memo + $: content=story + author=ship + sent=time + == +:: $story: post body content +:: ++$ story (list verse) +:: $verse: a chunk of post content +:: +:: blocks stand on their own. inlines come in groups and get wrapped +:: into a paragraph +:: ++$ verse + $% [%block p=block] + [%inline p=(list inline)] + == +:: $listing: recursive type for infinitely nested