diff --git a/lib/hooks/thread-hooks.js b/lib/hooks/thread-hooks.js --- a/lib/hooks/thread-hooks.js +++ b/lib/hooks/thread-hooks.js @@ -19,6 +19,7 @@ import { useUpdateFarcasterGroupNameAndDescription, useModifyFarcasterMembershipInput, + useAcceptInvite, } from '../shared/farcaster/farcaster-api.js'; import { useFetchConversation, @@ -505,6 +506,9 @@ state => state.currentUserInfo && state.currentUserInfo.id, ); const keyserverCall = useJoinKeyserverThread(); + const farcasterAcceptInvite = useAcceptInvite(); + const refreshFarcasterConversation = useRefreshFarcasterConversation(); + return React.useCallback( async (input: UseJoinThreadInput) => threadSpecs[input.rawThreadInfo.type].protocol().joinThread( @@ -516,9 +520,17 @@ processAndSendDMOperation, keyserverJoinThread: keyserverCall, calendarQuery: input.calendarQuery, + farcasterAcceptInvite, + refreshFarcasterConversation, }, ), - [keyserverCall, processAndSendDMOperation, viewerID], + [ + farcasterAcceptInvite, + keyserverCall, + processAndSendDMOperation, + refreshFarcasterConversation, + viewerID, + ], ); } diff --git a/lib/shared/farcaster/farcaster-api.js b/lib/shared/farcaster/farcaster-api.js --- a/lib/shared/farcaster/farcaster-api.js +++ b/lib/shared/farcaster/farcaster-api.js @@ -568,6 +568,25 @@ ); } +export type AcceptInviteInput = { + +conversationId: string, +}; + +function useAcceptInvite(): (input: AcceptInviteInput) => Promise { + const { sendFarcasterRequest } = useTunnelbroker(); + return React.useCallback( + async (input: AcceptInviteInput) => { + await sendFarcasterRequest({ + apiVersion: 'v2', + endpoint: 'direct-cast-accept-group-invite', + method: { type: 'POST' }, + payload: JSON.stringify(input), + }); + }, + [sendFarcasterRequest], + ); +} + export { useSendFarcasterTextMessage, useFetchFarcasterMessages, @@ -581,4 +600,5 @@ useGetFarcasterDirectCastUsers, useModifyFarcasterMembershipInput, useSendFarcasterReaction, + useAcceptInvite, }; diff --git a/lib/shared/threads/protocols/farcaster-thread-protocol.js b/lib/shared/threads/protocols/farcaster-thread-protocol.js --- a/lib/shared/threads/protocols/farcaster-thread-protocol.js +++ b/lib/shared/threads/protocols/farcaster-thread-protocol.js @@ -106,6 +106,8 @@ SendMultimediaMessageUtils, ProtocolSendReactionInput, SendReactionUtils, + JoinThreadUtils, + ProtocolJoinThreadInput, } from '../thread-spec.js'; import { threadTypeIsPersonal } from '../thread-specs.js'; @@ -905,8 +907,24 @@ throw new Error('deleteMessage method is not yet implemented'); }, - joinThread: async (): Promise => { - throw new Error('joinThread method is not yet implemented'); + joinThread: async ( + input: ProtocolJoinThreadInput, + utils: JoinThreadUtils, + ): Promise => { + const threadID = input.rawThreadInfo.id; + const conversationID = conversationIDFromFarcasterThreadID(threadID); + await utils.farcasterAcceptInvite({ + conversationId: conversationID, + }); + + await utils.refreshFarcasterConversation(conversationID); + + return ({ + updatesResult: { newUpdates: [] }, + rawMessageInfos: [], + truncationStatuses: {}, + userInfos: [], + }: ThreadJoinPayload); }, onOpenThread: ( diff --git a/lib/shared/threads/thread-spec.js b/lib/shared/threads/thread-spec.js --- a/lib/shared/threads/thread-spec.js +++ b/lib/shared/threads/thread-spec.js @@ -100,6 +100,7 @@ CreateFarcasterGroupInput, ModifyFarcasterMembershipInput, SendReactionInput, + AcceptInviteInput, } from '../farcaster/farcaster-api.js'; import type { FarcasterConversation } from '../farcaster/farcaster-conversation-types.js'; import type { FarcasterMessageFetchingContextType } from '../farcaster/farcaster-message-fetching-context.js'; @@ -374,6 +375,8 @@ +processAndSendDMOperation: OutboundDMOperationSpecification => Promise, +keyserverJoinThread: ClientThreadJoinRequest => Promise, +calendarQuery: () => CalendarQuery, + +farcasterAcceptInvite: (input: AcceptInviteInput) => Promise, + +refreshFarcasterConversation: (conversationId: string) => Promise, }; export type ProtocolOnOpenThreadInput = {