diff --git a/src/hooks/useIsMessageBlocked.ts b/src/hooks/useIsMessageBlocked.ts index bf7c19f44..4f6081b7a 100644 --- a/src/hooks/useIsMessageBlocked.ts +++ b/src/hooks/useIsMessageBlocked.ts @@ -1,6 +1,7 @@ import { getPostQuery } from '@/services/api/query' import { getBlockedResourcesQuery } from '@/services/datahub/moderation/query' import { isMessageBlocked } from '@/utils/chat' +import { getAppId } from '@/utils/env/client' import { PostData } from '@subsocial/api/types' import { useMemo } from 'react' @@ -27,6 +28,9 @@ export default function useIsMessageBlocked( message: PostData | null | undefined, chatId: string ) { + const { data: appModerationData } = getBlockedResourcesQuery.useQuery({ + appId: getAppId(), + }) const { data: hubModerationData } = getBlockedResourcesQuery.useQuery( { spaceId: hubId }, { @@ -39,6 +43,8 @@ export default function useIsMessageBlocked( { postEntityId: entityId }, { enabled: !!entityId } ) + // TODO: use blocked in app + const blockedInApp = appModerationData?.blockedResources const blockedInHub = hubModerationData?.blockedResources const blockedInChat = chatModerationData?.blockedResources diff --git a/src/pages/[hubId]/[slug]/index.tsx b/src/pages/[hubId]/[slug]/index.tsx index 0475efda4..a50a6dfa5 100644 --- a/src/pages/[hubId]/[slug]/index.tsx +++ b/src/pages/[hubId]/[slug]/index.tsx @@ -165,7 +165,10 @@ export const getStaticProps = getCommonStaticProps< if (blockedData) { let isChatModerated = false - blockedData.blockedInSpaceIds.forEach(({ blockedResources }) => { + ;[ + ...blockedData.blockedInSpaceIds, + ...blockedData.blockedInAppIds, + ].forEach(({ blockedResources }) => { if (blockedResources.postId.includes(chatId)) { isChatModerated = true } diff --git a/src/server/moderation/prefetch.ts b/src/server/moderation/prefetch.ts index 4e1879d6f..e4b3ec837 100644 --- a/src/server/moderation/prefetch.ts +++ b/src/server/moderation/prefetch.ts @@ -2,6 +2,7 @@ import { getBlockedResources, getBlockedResourcesQuery, } from '@/services/datahub/moderation/query' +import { getAppId } from '@/utils/env/client' import { QueryClient } from '@tanstack/react-query' export async function prefetchBlockedEntities( @@ -10,10 +11,12 @@ export async function prefetchBlockedEntities( postIds: string[] ) { try { - const { blockedInPostIds, blockedInSpaceIds } = await getBlockedResources({ - spaceIds, - postEntityIds: postIds, - }) + const { blockedInPostIds, blockedInSpaceIds, blockedInAppIds } = + await getBlockedResources({ + spaceIds, + postEntityIds: postIds, + appIds: [getAppId()], + }) blockedInSpaceIds.forEach((data) => { getBlockedResourcesQuery.setQueryData( queryClient, @@ -28,8 +31,15 @@ export async function prefetchBlockedEntities( { ...data, type: 'postEntityId' } ) }) + blockedInAppIds.forEach((data) => { + getBlockedResourcesQuery.setQueryData( + queryClient, + { appId: data.id }, + { ...data, type: 'appId' } + ) + }) - return { blockedInSpaceIds, blockedInPostIds } + return { blockedInSpaceIds, blockedInPostIds, blockedInAppIds } } catch (err) { console.log('Error prefetching blocked entities', err) } diff --git a/src/services/datahub/generated-query.ts b/src/services/datahub/generated-query.ts index 28a048f39..7b675d79c 100644 --- a/src/services/datahub/generated-query.ts +++ b/src/services/datahub/generated-query.ts @@ -127,6 +127,15 @@ export enum ContentExtensionSchemaId { SubsocialSecretBox = 'subsocial_secret_box', } +export type CreateOrganizationInput = { + ctxAppIds?: InputMaybe> + ctxPostIds?: InputMaybe> + ctxSpaceIds?: InputMaybe> + description?: InputMaybe + name?: InputMaybe + ownedByAccountAddress: Scalars['String']['input'] +} + export enum DataHubSubscriptionEventEnum { EvmAddressLinkedToAccount = 'EVM_ADDRESS_LINKED_TO_ACCOUNT', EvmAddressLinkToAccountStateUpdated = 'EVM_ADDRESS_LINK_TO_ACCOUNT_STATE_UPDATED', @@ -200,6 +209,14 @@ export type FindPostsResponseDto = { total?: Maybe } +export type GetModeratorByInput = { + substrateAccountAddress: Scalars['String']['input'] +} + +export type GetOrganizationWhere = { + id: Scalars['String']['input'] +} + export type IdTimestampPair = { id: Scalars['String']['input'] timestamp_gt: Scalars['String']['input'] @@ -214,6 +231,14 @@ export enum InReplyToKind { Post = 'Post', } +export type InitModeratorInputDto = { + ctxAppIds?: InputMaybe> + ctxPostIds?: InputMaybe> + ctxSpaceIds?: InputMaybe> + substrateAddress: Scalars['String']['input'] + withOrganization?: InputMaybe +} + export type LinkedIdentitiesArgs = { externalId?: InputMaybe id?: InputMaybe @@ -271,6 +296,15 @@ export type ModerationBlockedResourceSubscriptionPayload = { event: DataHubSubscriptionEventEnum } +export type ModerationCreateOrganizationModeratorInput = { + defaultCtxAppIds?: InputMaybe> + defaultCtxPostIds?: InputMaybe> + defaultCtxSpaceIds?: InputMaybe> + moderatorId: Scalars['String']['input'] + organizationId: Scalars['String']['input'] + role: ModeratorRole +} + export type ModerationOrganization = { __typename?: 'ModerationOrganization' ctxAppIds?: Maybe> @@ -314,6 +348,15 @@ export enum ModerationResourceType { Post = 'POST', } +export type ModerationUpdateOrganizationModeratorInput = { + defaultCtxAppIds?: InputMaybe> + defaultCtxPostIds?: InputMaybe> + defaultCtxSpaceIds?: InputMaybe> + moderatorId: Scalars['String']['input'] + organizationId: Scalars['String']['input'] + role?: InputMaybe +} + export type Moderator = { __typename?: 'Moderator' id: Scalars['String']['output'] @@ -324,9 +367,9 @@ export type Moderator = { export enum ModeratorRole { Admin = 'admin', - Editor = 'editor', + Moderator = 'moderator', Owner = 'owner', - Reader = 'reader', + Spectator = 'spectator', } export type ModeratorSubscriptionPayload = { @@ -354,6 +397,35 @@ export type ModeratorsWhereArgs = { substrateAddress?: InputMaybe } +export type Mutation = { + __typename?: 'Mutation' + moderationCreateOrganization: ModerationOrganization + moderationCreateOrganizationModerator?: Maybe + moderationInitModerator?: Maybe + moderationUpdateOrganization: ModerationOrganization + moderationUpdateOrganizationModerator?: Maybe +} + +export type MutationModerationCreateOrganizationArgs = { + args: CreateOrganizationInput +} + +export type MutationModerationCreateOrganizationModeratorArgs = { + args: ModerationCreateOrganizationModeratorInput +} + +export type MutationModerationInitModeratorArgs = { + args: InitModeratorInputDto +} + +export type MutationModerationUpdateOrganizationArgs = { + args: UpdateOrganizationInput +} + +export type MutationModerationUpdateOrganizationModeratorArgs = { + args: ModerationUpdateOrganizationModeratorInput +} + export enum PinnedResourceType { Post = 'Post', Space = 'Space', @@ -461,6 +533,9 @@ export type Query = { moderationBlockedResourceIds: Array moderationBlockedResourceIdsBatch: BlockedResourceIdsBatchResponse moderationBlockedResourcesDetailed: Array + moderationModerator?: Maybe + moderationOrganization?: Maybe + moderationOrganizations?: Maybe> moderationReason: ModerationBlockReason moderationReasonsAll: Array moderators?: Maybe @@ -511,6 +586,14 @@ export type QueryModerationBlockedResourcesDetailedArgs = { spaceId?: InputMaybe } +export type QueryModerationModeratorArgs = { + where: GetModeratorByInput +} + +export type QueryModerationOrganizationArgs = { + where: GetOrganizationWhere +} + export type QueryModerationReasonArgs = { id: Scalars['String']['input'] } @@ -615,9 +698,19 @@ export type UnreadPostsCountResponse = { unreadCount: Scalars['Int']['output'] } +export type UpdateOrganizationInput = { + ctxAppIds?: InputMaybe> + ctxPostIds?: InputMaybe> + ctxSpaceIds?: InputMaybe> + description?: InputMaybe + id: Scalars['String']['input'] + name?: InputMaybe +} + export type GetBlockedResourcesQueryVariables = Exact<{ spaceIds: Array | Scalars['String']['input'] postIds: Array | Scalars['String']['input'] + appIds: Array | Scalars['String']['input'] }> export type GetBlockedResourcesQuery = { @@ -634,6 +727,11 @@ export type GetBlockedResourcesQuery = { id: string blockedResourceIds: Array }> + byCtxAppIds: Array<{ + __typename?: 'BlockedResourceIdsBatchItem' + id: string + blockedResourceIds: Array + }> } } @@ -1098,10 +1196,15 @@ export const DatahubPostFragment = gql` } ` export const GetBlockedResources = gql` - query GetBlockedResources($spaceIds: [String!]!, $postIds: [String!]!) { + query GetBlockedResources( + $spaceIds: [String!]! + $postIds: [String!]! + $appIds: [String!]! + ) { moderationBlockedResourceIdsBatch( ctxSpaceIds: $spaceIds ctxPostIds: $postIds + ctxAppIds: $appIds ) { byCtxSpaceIds { id @@ -1111,6 +1214,10 @@ export const GetBlockedResources = gql` id blockedResourceIds } + byCtxAppIds { + id + blockedResourceIds + } } } ` diff --git a/src/services/datahub/moderation/query.ts b/src/services/datahub/moderation/query.ts index 33f9968e3..1fe971dd8 100644 --- a/src/services/datahub/moderation/query.ts +++ b/src/services/datahub/moderation/query.ts @@ -14,10 +14,15 @@ import { datahubQueryRequest } from '../utils' import { mapBlockedResources, ResourceTypes } from './utils' const GET_BLOCKED_RESOURCES = gql` - query GetBlockedResources($spaceIds: [String!]!, $postIds: [String!]!) { + query GetBlockedResources( + $spaceIds: [String!]! + $postIds: [String!]! + $appIds: [String!]! + ) { moderationBlockedResourceIdsBatch( ctxSpaceIds: $spaceIds ctxPostIds: $postIds + ctxAppIds: $appIds ) { byCtxSpaceIds { id @@ -27,12 +32,17 @@ const GET_BLOCKED_RESOURCES = gql` id blockedResourceIds } + byCtxAppIds { + id + blockedResourceIds + } } } ` export async function getBlockedResources(variables: { postEntityIds: string[] spaceIds: string[] + appIds: string[] }) { variables.postEntityIds = variables.postEntityIds.filter((id) => !!id) variables.spaceIds = variables.spaceIds.filter((id) => !!id) @@ -44,6 +54,7 @@ export async function getBlockedResources(variables: { variables: { postIds: variables.postEntityIds, spaceIds: variables.spaceIds, + appIds: variables.appIds, }, }) @@ -61,32 +72,42 @@ export async function getBlockedResources(variables: { blockedResources: mapBlockedResources(blockedResourceIds, (id) => id), }) ) + const blockedInAppIds = + data.moderationBlockedResourceIdsBatch.byCtxAppIds.map( + ({ blockedResourceIds, id }) => ({ + id, + blockedResources: mapBlockedResources(blockedResourceIds, (id) => id), + }) + ) - return { blockedInSpaceIds, blockedInPostIds } + return { blockedInSpaceIds, blockedInPostIds, blockedInAppIds } } const pooledGetBlockedResource = poolQuery< - { postEntityId: string } | { spaceId: string }, + { postEntityId: string } | { spaceId: string } | { appId: string }, { id: string blockedResources: Record - type: 'spaceId' | 'postEntityId' + type: 'spaceId' | 'postEntityId' | 'appId' } >({ multiCall: async (params) => { if (!params.length) return [] const spaceIds: string[] = [] const postEntityIds: string[] = [] + const appIds: string[] = [] params.forEach((param) => { if ('postEntityId' in param && param.postEntityId) postEntityIds.push(param.postEntityId) else if ('spaceId' in param && param.spaceId) spaceIds.push(param.spaceId) + else if ('appId' in param && param.appId) appIds.push(param.appId) }) - if (!postEntityIds.length && !spaceIds.length) return [] + if (!postEntityIds.length && !spaceIds.length && !appIds.length) return [] const response = await getBlockedResources({ postEntityIds, spaceIds, + appIds, }) return [ ...response.blockedInPostIds.map((data) => ({ @@ -97,16 +118,22 @@ const pooledGetBlockedResource = poolQuery< ...data, type: 'spaceId' as const, })), + ...response.blockedInAppIds.map((data) => ({ + ...data, + type: 'appId' as const, + })), ] }, resultMapper: { paramToKey: (param) => { if ('postEntityId' in param) return `postEntityId:${param.postEntityId}` - else return `spaceId:${param.spaceId}` + else if ('spaceId' in param) return `spaceId:${param.spaceId}` + else return `appId:${param.appId}` }, resultToKey: ({ type, id }) => { if (type === 'postEntityId') return `postEntityId:${id}` - else return `spaceId:${id}` + else if (type === 'spaceId') return `spaceId:${id}` + else return `appId:${id}` }, }, })