/** * What the whole site did, told two ways. Over a period, one of the digests' * cadences: its most upvoted dumps, who joined, the new public playlists and * the totals, which the `/community` page shows as they were at the server's * last refresh and the digests gather for each reader's own period. And as it * happens: the community feed, the latest things its members did in public, * which the GeoCities style's marquee scrolls. * * @module */ import type { Dump } from "./dump.ts"; import type { OwnedItem } from "./paths.ts"; import type { Playlist } from "./playlist.ts"; import type { PublicUser } from "./user.ts"; /** * Returned by `GET /api/community?period=` to the `Community` page, and * gathered by `community-service.ts`, which the digests read too. */ export interface CommunityStats { /** The period covered, from `from` to `to`. */ from: Date; to: Date; /** The most upvoted public dumps posted in it, 10 at most. */ top: Dump[]; /** In sign-up order, each with `invitedByUsername` when someone invited them. */ members: PublicUser[]; /** The public playlists created in it, the fullest first, with `dumpCount`. */ playlists: Playlist[]; chatMessages: number; /** Public dumps posted, upvotes cast and comments written in it. */ totals: { dumps: number; upvotes: number; comments: number }; } /** * Names a dump or a playlist in a {@link CommunityEvent}: its title, and what * `dumpPath` or `playlistPath` builds its page's path from. */ export interface CommunityItem extends OwnedItem { title: string; } /** What every {@link CommunityEvent} carries. */ interface CommunityEventBase { /** * The event's kind and what it is about, `dump_upvoted:`: unique in * a feed, where a dump has one event of each kind at most. */ id: string; at: Date; /** Who did it, by their current name. */ username: string; } /** A public dump was posted. A dump made public later keeps its date. */ export interface DumpPostedEvent extends CommunityEventBase { type: "dump_posted"; dump: CommunityItem; } /** A public playlist was created. */ export interface PlaylistCreatedEvent extends CommunityEventBase { type: "playlist_created"; playlist: CommunityItem; } /** * A public dump got a comment. However many it got, the feed tells of its * latest alone. */ export interface DumpCommentedEvent extends CommunityEventBase { type: "dump_commented"; dump: CommunityItem; /** For the `#comment-` anchor on the dump's page. */ commentId: string; } /** A public dump got an upvote, told as {@link DumpCommentedEvent} is. */ export interface DumpUpvotedEvent extends CommunityEventBase { type: "dump_upvoted"; dump: CommunityItem; } /** Someone joined the site: `username` is theirs. */ export interface UserJoinedEvent extends CommunityEventBase { type: "user_joined"; invitedByUsername?: string; } /** One line of the community feed, told apart by `type`. */ export type CommunityEvent = | DumpPostedEvent | PlaylistCreatedEvent | DumpCommentedEvent | DumpUpvotedEvent | UserJoinedEvent; /** * Returned by `GET /api/community/feed` to `CommunityFeedProvider`, which * asks again as the socket tells of changes, and rendered by the * `CommunityFeed` component with who is online, which the client knows from * its socket. `community-service.ts` gathers it. Everything in it is public: * every reader gets the same feed. */ export interface CommunityFeed { /** The latest events, newest first, 12 at most. */ events: CommunityEvent[]; /** * The last week's figures, as `/community` shows them: as of the server's * last refresh. */ week: Pick & { /** The week's most upvoted dump, when one was upvoted. */ top?: CommunityItem; }; }