diff --git a/schema.gql b/schema.gql index 59098b0d0..3bac9d41f 100644 --- a/schema.gql +++ b/schema.gql @@ -1016,6 +1016,7 @@ type Mutation { stopNftCreate(input: StopNftCreateArgs!): TransactionNode! transferNft(input: TransferNftArgs!): TransactionNode! transferNftCreateRole(input: TransferNftCreateRoleArgs!): TransactionNode! + trigerScamUpdate(input: ScamUpdateInput!): Boolean! updateCollectionRarities(collectionTicker: String!): Boolean! updateCollectionTraits(collectionTicker: String!): Boolean! updateMarketplace(input: UpdateMarketplaceArgs!): Boolean! @@ -1342,6 +1343,16 @@ enum ScamInfoTypeEnum { scam } +enum ScamInputEnum { + allow + deny +} + +input ScamUpdateInput { + collectionIdentifier: String! + type: ScamInputEnum! +} + input SearchFilter { searchTerm: String! } diff --git a/src/modules/admins/admin-operations.module.ts b/src/modules/admins/admin-operations.module.ts index af4919db0..f8ac966c7 100644 --- a/src/modules/admins/admin-operations.module.ts +++ b/src/modules/admins/admin-operations.module.ts @@ -13,11 +13,13 @@ import { NftTraitsModule } from '../nft-traits/nft-traits.module'; import { MarketplacesModuleGraph } from '../marketplaces/marketplaces.module'; import { AuthModule } from '../auth/auth.module'; import { ReportsModuleGraph } from '../reports/reports.module'; +import { ScamUpdatePublisherModule } from '../rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.module'; @Module({ imports: [ CommonModule, CacheEventsPublisherModule, + ScamUpdatePublisherModule, MxCommunicationModule, NftRarityModuleGraph, NftTraitsModule, @@ -36,4 +38,4 @@ import { ReportsModuleGraph } from '../reports/reports.module'; ], exports: [FlagNftService], }) -export class AdminOperationsModuleGraph {} +export class AdminOperationsModuleGraph { } diff --git a/src/modules/admins/admin-operations.resolver.ts b/src/modules/admins/admin-operations.resolver.ts index 1955fdb35..3de04445d 100644 --- a/src/modules/admins/admin-operations.resolver.ts +++ b/src/modules/admins/admin-operations.resolver.ts @@ -17,6 +17,8 @@ import { ReportsService } from '../reports/reports.service'; import { ClearReportCollectionInput, ClearReportInput } from './models/clear-report.input'; import { MarketplaceReindexDataArgs } from '../marketplaces/models/MarketplaceReindexDataArgs'; import { GraphQLError } from 'graphql'; +import { ScamUpdatePublisherService } from '../rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.service'; +import { ScamUpdateInput } from './models/scam-update.input'; @Resolver(() => Boolean) export class AdminOperationsResolver { @@ -27,9 +29,10 @@ export class AdminOperationsResolver { private readonly nftRarityService: NftRarityService, private readonly nftTraitService: NftTraitsService, private readonly cacheEventsPublisherService: CacheEventsPublisherService, + private readonly scamUpdatePublisherService: ScamUpdatePublisherService, private readonly marketplaceEventsIndexingService: MarketplaceEventsIndexingService, private readonly marketplacesReindexService: MarketplacesReindexService, - ) {} + ) { } @Mutation(() => Boolean) @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) @@ -157,4 +160,11 @@ export class AdminOperationsResolver { }); return true; } + + @Mutation(() => Boolean) + @UseGuards(JwtOrNativeAuthGuard, GqlAdminAuthGuard) + async trigerScamUpdate(@Args('input', { type: () => ScamUpdateInput }) input: ScamUpdateInput): Promise { + this.scamUpdatePublisherService.publish({ collectionIdentifier: input.collectionIdentifier, type: input.type }); + return true; + } } diff --git a/src/modules/admins/models/scam-update.input.ts b/src/modules/admins/models/scam-update.input.ts new file mode 100644 index 000000000..c43ccf131 --- /dev/null +++ b/src/modules/admins/models/scam-update.input.ts @@ -0,0 +1,24 @@ +import { InputType, Field, registerEnumType } from '@nestjs/graphql'; +import { Matches } from 'class-validator'; +import { COLLECTION_IDENTIFIER_ERROR, COLLECTION_IDENTIFIER_RGX } from 'src/utils/constants'; + +@InputType() +export class ScamUpdateInput { + @Matches(RegExp(COLLECTION_IDENTIFIER_RGX), { + message: COLLECTION_IDENTIFIER_ERROR, + }) + @Field(() => String) + collectionIdentifier: string; + + @Field(() => ScamInputEnum) + type: ScamInputEnum; +} + +export enum ScamInputEnum { + deny = 'deny', + allow = 'allow' +} + +registerEnumType(ScamInputEnum, { + name: 'ScamInputEnum', +}); diff --git a/src/modules/rabbitmq/blockchain-events/nft-events.module.ts b/src/modules/rabbitmq/blockchain-events/nft-events.module.ts index e9f4d5f50..2be513663 100644 --- a/src/modules/rabbitmq/blockchain-events/nft-events.module.ts +++ b/src/modules/rabbitmq/blockchain-events/nft-events.module.ts @@ -45,7 +45,6 @@ import { PluginModule } from 'src/plugins/plugin.module'; import { AnalyticsEventsService } from './analytics-events.service'; import { AnalyticsModule } from 'src/modules/analytics/analytics.module'; import { MintersModuleGraph } from 'src/modules/minters/minters.module'; -import { DisabledMarketplaceEventsService } from './disable-marketplace/disable-marketplace-events.service'; import { DisabledMarketplaceEventsModule } from './disable-marketplace/disable-marketplace-events.module'; @Module({ imports: [ @@ -102,4 +101,4 @@ import { DisabledMarketplaceEventsModule } from './disable-marketplace/disable-m ], exports: [NftEventsService, NftEventsConsumer], }) -export class NftEventsModule {} +export class NftEventsModule { } diff --git a/src/modules/rabbitmq/cache-invalidation/cache-events.module.ts b/src/modules/rabbitmq/cache-invalidation/cache-events.module.ts index 46db42104..008f9e93e 100644 --- a/src/modules/rabbitmq/cache-invalidation/cache-events.module.ts +++ b/src/modules/rabbitmq/cache-invalidation/cache-events.module.ts @@ -18,12 +18,14 @@ import { CampaignsCachingService } from 'src/modules/campaigns/campaigns-caching import { MarketplaceRedisHandler } from 'src/modules/marketplaces/loaders/marketplace.redis-handler'; import { AssetsSupplyRedisHandler } from 'src/modules/assets/loaders/assets-supply.redis-handler'; import { PubSubListenerModule } from 'src/pubsub/pub.sub.listener.module'; +import { ScamUpdatePublisherModule } from '../elastic-updates/scam-trigger/scam-update-publiser.module'; @Module({ imports: [ PubSubListenerModule, CommonModule, CacheInvalidationEventsModule, + ScamUpdatePublisherModule, CacheAdminEventsModule, CommonRabbitModule.register(() => { return { @@ -49,4 +51,4 @@ import { PubSubListenerModule } from 'src/pubsub/pub.sub.listener.module'; ], exports: [], }) -export class CacheEventsModule {} +export class CacheEventsModule { } diff --git a/src/modules/rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.module.ts b/src/modules/rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.module.ts index f3714f555..acbec483d 100644 --- a/src/modules/rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.module.ts +++ b/src/modules/rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.module.ts @@ -16,4 +16,4 @@ import { CacheEventsPublisherService, NftLikePublisherService } from './change-e providers: [CacheEventsPublisherService, NftLikePublisherService], exports: [CacheEventsPublisherService, NftLikePublisherService], }) -export class CacheEventsPublisherModule {} +export class CacheEventsPublisherModule { } diff --git a/src/modules/rabbitmq/elastic-updates/scam-trigger/markScamCollection.event.ts b/src/modules/rabbitmq/elastic-updates/scam-trigger/markScamCollection.event.ts new file mode 100644 index 000000000..77a802390 --- /dev/null +++ b/src/modules/rabbitmq/elastic-updates/scam-trigger/markScamCollection.event.ts @@ -0,0 +1,9 @@ +import { ScamInputEnum } from "src/modules/admins/models/scam-update.input"; + +export class MarkScamCollectionEvent { + collectionIdentifier: string; + type: ScamInputEnum + constructor(init?: Partial) { + Object.assign(this, init); + } +} diff --git a/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-consumer.module.ts b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-consumer.module.ts new file mode 100644 index 000000000..90ca4a494 --- /dev/null +++ b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-consumer.module.ts @@ -0,0 +1,21 @@ +import { forwardRef, Global, Module } from '@nestjs/common'; +import { rabbitExchanges } from '../../rabbit-config'; +import { CommonRabbitModule } from '../../cache-invalidation/common-rabbitmq.module'; +import { ScamUpdateEventsConsumer } from './scam-update-events.consumer'; +import { ScamModule } from 'src/modules/scam/scam.module'; + +@Global() +@Module({ + imports: [ + CommonRabbitModule.register(() => { + return { + exchange: rabbitExchanges.SCAM_UPDATE, + uri: process.env.COMMON_RABBITMQ_URL, + }; + }), + forwardRef(() => ScamModule) + ], + providers: [ScamUpdateEventsConsumer], + exports: [ScamUpdateEventsConsumer], +}) +export class ScamUpdateConsumerModule { } diff --git a/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-events.consumer.ts b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-events.consumer.ts new file mode 100644 index 000000000..cf4d84e9f --- /dev/null +++ b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-events.consumer.ts @@ -0,0 +1,23 @@ +import { Injectable } from '@nestjs/common'; +import { rabbitExchanges, rabbitQueues } from '../../rabbit-config'; +import { MarkScamCollectionEvent } from './markScamCollection.event'; +import { CompetingRabbitConsumer } from '../../rabbitmq.consumers'; +import { CollectionScamService } from 'src/modules/scam/collection-scam.service'; +import { ScamInputEnum } from 'src/modules/admins/models/scam-update.input'; +@Injectable() +export class ScamUpdateEventsConsumer { + constructor(private readonly collectionScamService: CollectionScamService) { } + + @CompetingRabbitConsumer({ + connection: 'common', + queueName: rabbitQueues.SCAM_UPDATE, + exchange: rabbitExchanges.SCAM_UPDATE, + }) + async consumeScamEvents(event: MarkScamCollectionEvent) { + if (event.type === ScamInputEnum.allow) { + await this.collectionScamService.manuallyClearCollectionScamInfo(event.collectionIdentifier) + } else { + await this.collectionScamService.manuallySetCollectionScamInfo(event.collectionIdentifier) + } + } +} diff --git a/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.module.ts b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.module.ts new file mode 100644 index 000000000..cad00d2ed --- /dev/null +++ b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.module.ts @@ -0,0 +1,19 @@ +import { Global, Module } from '@nestjs/common'; +import { rabbitExchanges } from '../../rabbit-config'; +import { CommonRabbitModule } from '../../cache-invalidation/common-rabbitmq.module'; +import { ScamUpdatePublisherService } from './scam-update-publiser.service'; + +@Global() +@Module({ + imports: [ + CommonRabbitModule.register(() => { + return { + exchange: rabbitExchanges.SCAM_UPDATE, + uri: process.env.COMMON_RABBITMQ_URL, + }; + }), + ], + providers: [ScamUpdatePublisherService], + exports: [ScamUpdatePublisherService], +}) +export class ScamUpdatePublisherModule { } diff --git a/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.service.ts b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.service.ts new file mode 100644 index 000000000..584e69bf4 --- /dev/null +++ b/src/modules/rabbitmq/elastic-updates/scam-trigger/scam-update-publiser.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@nestjs/common'; +import { rabbitExchanges } from '../../rabbit-config'; +import { RabbitPublisherService } from '../../rabbit.publisher'; +import { MarkScamCollectionEvent } from './markScamCollection.event'; + + +@Injectable() +export class ScamUpdatePublisherService { + constructor(private readonly rabbitPublisherService: RabbitPublisherService) { } + + async publish(payload: MarkScamCollectionEvent) { + await this.rabbitPublisherService.publish(rabbitExchanges.SCAM_UPDATE, payload); + } +} diff --git a/src/modules/rabbitmq/rabbit-config.ts b/src/modules/rabbitmq/rabbit-config.ts index c6a5f890a..243712f68 100644 --- a/src/modules/rabbitmq/rabbit-config.ts +++ b/src/modules/rabbitmq/rabbit-config.ts @@ -14,8 +14,10 @@ export interface RabbitModuleConfig { export const rabbitExchanges = { CACHE_INVALIDATION: 'nft-cache-invalidation', NFT_LIKE: 'x_portal_gamification_nft_likes_exchange', + SCAM_UPDATE: 'nft-scam-update', }; export const rabbitQueues = { CACHE_INVALIDATION: 'nft-cache-invalidation', + SCAM_UPDATE: 'nft-scam-update', }; diff --git a/src/modules/scam/nft-scam.service.ts b/src/modules/scam/nft-scam.service.ts index 76723b7c9..46c06ca67 100644 --- a/src/modules/scam/nft-scam.service.ts +++ b/src/modules/scam/nft-scam.service.ts @@ -26,7 +26,7 @@ export class NftScamService { private readonly pluginsService: PluginService, private readonly cacheEventsPublisher: CacheEventsPublisherService, private readonly logger: Logger, - ) {} + ) { } async validateNftScamInfoForIdentifier(identifier: string): Promise { const nft = await this.assetByIdentifierService.getAsset(identifier); @@ -245,13 +245,7 @@ export class NftScamService { const apiNfts = await this.mxApiService.getNftsByIdentifiers(nftsMissingFromDb?.map((x) => x.identifier)); if (!apiNfts) return; - let mappedNfts: Asset[] = []; - if (scamInfo.type === ScamInfoTypeEnum.none) { - mappedNfts = apiNfts?.map((x) => new Asset({ ...Asset.fromNft(x), scamInfo })); - } else { - mappedNfts = apiNfts?.map((x) => Asset.fromNft(x)); - await this.pluginsService.computeScamInfo(mappedNfts); - } + let mappedNfts: Asset[] = apiNfts?.map((x) => new Asset({ ...Asset.fromNft(x), scamInfo })); await this.updateBulkScamInfo(scamEngineVersion, mappedNfts); } diff --git a/src/modules/scam/scam.module.ts b/src/modules/scam/scam.module.ts index 466c49fef..7cdcd398f 100644 --- a/src/modules/scam/scam.module.ts +++ b/src/modules/scam/scam.module.ts @@ -22,6 +22,6 @@ import { NftScamService } from './nft-scam.service'; CollectionScamResolver, AssetByIdentifierService, ], - exports: [NftScamService, NftScamElasticService, AssetByIdentifierService], + exports: [NftScamService, NftScamElasticService, AssetByIdentifierService, CollectionScamService], }) -export class ScamModule {} +export class ScamModule { } diff --git a/src/private.app.module.ts b/src/private.app.module.ts index aef270009..043d10d38 100644 --- a/src/private.app.module.ts +++ b/src/private.app.module.ts @@ -12,8 +12,8 @@ import { MetricsController } from './modules/metrics/metrics.controller'; import { NftRarityModuleGraph } from './modules/nft-rarity/nft-rarity.module'; import { ScamModule } from './modules/scam/scam.module'; import { NftTraitsModule } from './modules/nft-traits/nft-traits.module'; -import { CacheEventsPublisherModule } from './modules/rabbitmq/cache-invalidation/cache-invalidation-publisher/change-events-publisher.module'; import * as ormconfig from './ormconfig'; +import { ScamUpdateConsumerModule } from './modules/rabbitmq/elastic-updates/scam-trigger/scam-update-consumer.module'; @Module({ imports: [ @@ -21,7 +21,7 @@ import * as ormconfig from './ormconfig'; CommonModule, AdminOperationsModuleGraph, NftRarityModuleGraph, - CacheEventsPublisherModule, + ScamUpdateConsumerModule, ScamModule, NftTraitsModule, MarketplacesModuleGraph, @@ -31,4 +31,4 @@ import * as ormconfig from './ormconfig'; controllers: [MetricsController, ReindexController, CachingController], exports: [NsfwUpdaterService, RarityUpdaterService], }) -export class PrivateAppModule {} +export class PrivateAppModule { }