diff --git a/lib/shared/farcaster/farcaster-conversation-types.js b/lib/shared/farcaster/farcaster-conversation-types.js --- a/lib/shared/farcaster/farcaster-conversation-types.js +++ b/lib/shared/farcaster/farcaster-conversation-types.js @@ -15,21 +15,52 @@ } from './farcaster-user-types.js'; import { tShapeInexact } from '../../utils/validation-utils.js'; +type FarcasterUnreadReactionMessage = { + +fid: number, + +displayName: string, + +username: string, + +reaction: string, + +timestamp: number, + +reactedMessageFid: number, + +reactedMessage: string, + ... +}; +const farcasterUnreadReactionMessageValidator: TInterface = + tShapeInexact({ + fid: t.Number, + displayName: t.String, + username: t.String, + reaction: t.String, + timestamp: t.Number, + reactedMessageFid: t.Number, + reactedMessage: t.String, + }); + type FarcasterInboxViewerContext = { +category: 'default' | 'archived' | 'request', + +lastReadAt: number, +muted: boolean, +manuallyMarkedUnread: boolean, + +pinned: boolean, +unreadCount: number, + +unreadMentionsCount: number, + +unreadReactionMessage?: FarcasterUnreadReactionMessage, +counterParty?: FarcasterDCUser, + +tag?: 'automated' | 'new-user', ... }; const farcasterInboxViewerContextValidator: TInterface = tShapeInexact({ category: t.enums.of(['default', 'archived', 'request']), + lastReadAt: t.Number, muted: t.Boolean, manuallyMarkedUnread: t.Boolean, + pinned: t.Boolean, unreadCount: t.Number, + unreadMentionsCount: t.Number, + unreadReactionMessage: t.maybe(farcasterUnreadReactionMessageValidator), counterParty: t.maybe(farcasterDCUserValidator), + tag: t.maybe(t.enums.of(['automated', 'new-user'])), }); export type FarcasterInboxConversation = { @@ -38,6 +69,8 @@ +description?: string, +photoUrl?: string, +adminFids: $ReadOnlyArray, + +lastReadTime: number, + +lastMessage?: FarcasterMessage, +isGroup: boolean, +createdAt: number, +viewerContext: FarcasterInboxViewerContext, @@ -50,6 +83,8 @@ description: t.maybe(t.String), photoUrl: t.maybe(t.String), adminFids: t.list(t.Number), + lastReadTime: t.Number, + lastMessage: t.maybe(farcasterMessageValidator), isGroup: t.Boolean, createdAt: t.Number, viewerContext: farcasterInboxViewerContextValidator, @@ -58,20 +93,34 @@ type FarcasterConversationViewerContext = { +access: 'read' | 'read-write' | 'admin', +category: 'default' | 'archived' | 'request', + +archived: boolean, + +lastReadAt: number, +muted: boolean, +manuallyMarkedUnread: boolean, + +pinned: boolean, +unreadCount: number, + +unreadMentionsCount: number, + +unreadReactionMessage?: FarcasterUnreadReactionMessage, +counterParty?: FarcasterDCUser, + +tag?: 'automated' | 'new-user', + +inviter?: FarcasterDCUserBase, ... }; const farcasterConversationViewerContextValidator: TInterface = tShapeInexact({ access: t.enums.of(['read', 'read-write', 'admin']), category: t.enums.of(['default', 'archived', 'request']), + archived: t.Boolean, + lastReadAt: t.Number, muted: t.Boolean, manuallyMarkedUnread: t.Boolean, + pinned: t.Boolean, unreadCount: t.Number, + unreadMentionsCount: t.Number, + unreadReactionMessage: t.maybe(farcasterUnreadReactionMessageValidator), counterParty: t.maybe(farcasterDCUserValidator), + tag: t.maybe(t.enums.of(['automated', 'new-user'])), + inviter: t.maybe(FarcasterDCUserBaseValidator), }); type FarcasterConversationGroupPreferences = { @@ -95,11 +144,18 @@ +adminFids: $ReadOnlyArray, +removedFids: $ReadOnlyArray, +participants: $ReadOnlyArray, + +lastReadTime: number, + +selfLastReadTime: number, + +lastMessage?: FarcasterMessage, +pinnedMessages: $ReadOnlyArray, + +hasPinnedMessages: boolean, +isGroup: boolean, +groupPreferences?: FarcasterConversationGroupPreferences, + +activeParticipantsCount: number, +createdAt: number, +unreadCount: number, + +muted: boolean, + +hasMention: boolean, +viewerContext: FarcasterConversationViewerContext, ... }; @@ -112,11 +168,18 @@ adminFids: t.list(t.Number), removedFids: t.list(t.Number), participants: t.list(farcasterDCUserValidator), + lastReadTime: t.Number, + selfLastReadTime: t.Number, + lastMessage: t.maybe(farcasterMessageValidator), pinnedMessages: t.list(farcasterMessageValidator), + hasPinnedMessages: t.Boolean, isGroup: t.Boolean, groupPreferences: t.maybe(farcasterConversationGroupPreferencesValidator), + activeParticipantsCount: t.Number, createdAt: t.Number, unreadCount: t.Number, + muted: t.Boolean, + hasMention: t.Boolean, viewerContext: farcasterConversationViewerContextValidator, }); diff --git a/lib/shared/farcaster/farcaster-messages-types.js b/lib/shared/farcaster/farcaster-messages-types.js --- a/lib/shared/farcaster/farcaster-messages-types.js +++ b/lib/shared/farcaster/farcaster-messages-types.js @@ -3,8 +3,14 @@ import type { TInterface } from 'tcomb'; import t from 'tcomb'; -import type { FarcasterMessageUserContext } from './farcaster-user-types.js'; -import { farcasterMessageUserContextValidator } from './farcaster-user-types.js'; +import type { + FarcasterDCUserBase, + FarcasterMessageUserContext, +} from './farcaster-user-types.js'; +import { + FarcasterDCUserBaseValidator, + farcasterMessageUserContextValidator, +} from './farcaster-user-types.js'; import { tShapeInexact, tFarcasterID } from '../../utils/validation-utils.js'; export const farcasterMessageTypes = Object.freeze({ @@ -31,12 +37,18 @@ ); type FarcasterMessageViewerContext = { + +isLastReadMessage: boolean, + +focused: boolean, +reactions: $ReadOnlyArray, + +isOptimistic?: boolean, ... }; const farcasterMessageViewerContextValidator: TInterface = tShapeInexact({ + isLastReadMessage: t.Boolean, + focused: t.Boolean, reactions: t.list(t.String), + isOptimistic: t.maybe(t.Boolean), }); type FarcasterMessageMedia = { @@ -88,6 +100,19 @@ videos: t.maybe(t.list(farcasterMessageVideoValidator)), }); +type FarcasterMentionMetadata = { + +user: FarcasterDCUserBase, + +textIndex: number, + +length: number, + ... +}; +const farcasterMentionMetadataValidator: TInterface = + tShapeInexact({ + user: FarcasterDCUserBaseValidator, + textIndex: t.Number, + length: t.Number, + }); + export type FarcasterMessage = { +conversationId: string, +senderFid: number, @@ -95,12 +120,16 @@ +serverTimestamp: number, +type: FarcasterMessageType, +message: string, + +hasMention: boolean, +reactions: $ReadOnlyArray, +metadata?: FarcasterMessageMetadata, +viewerContext?: FarcasterMessageViewerContext, +isPinned: boolean, +isDeleted: boolean, + +senderContext: FarcasterMessageUserContext, +actionTargetUserContext?: FarcasterMessageUserContext, + +isProgrammatic?: boolean, + +mentions?: $ReadOnlyArray, +inReplyTo?: FarcasterMessage, ... }; @@ -119,12 +148,16 @@ 'rich_announcement', ]), message: t.String, + hasMention: t.Boolean, reactions: t.list(farcasterReactionValidator), metadata: t.maybe(farcasterMessageMetadataValidator), viewerContext: t.maybe(farcasterMessageViewerContextValidator), isPinned: t.Boolean, isDeleted: t.Boolean, + senderContext: farcasterMessageUserContextValidator, actionTargetUserContext: t.maybe(farcasterMessageUserContextValidator), + isProgrammatic: t.maybe(t.Boolean), + mentions: t.maybe(t.list(farcasterMentionMetadataValidator)), }); export { farcasterMessageValidator };