Skip to content

Commit

Permalink
TW-1518: Add an entrypoint for blacklisted Hypelab campaigns (#174)
Browse files Browse the repository at this point in the history
  • Loading branch information
keshan3262 authored Sep 25, 2024
1 parent 463fd63 commit fc0d150
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 42 deletions.
12 changes: 4 additions & 8 deletions src/advertising/external-ads.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { satisfies as versionSatisfiesRange } from 'semver';

import { objectStorageMethodsFactory, redisClient } from '../redis';
import { objectStorageMethodsFactory, setStorageMethodsFactory } from '../redis';

/** Style properties names that are likely to be unnecessary for banners are skipped */
export const stylePropsNames = [
Expand Down Expand Up @@ -176,6 +176,7 @@ const PERMANENT_NATIVE_AD_PLACES_RULES_KEY = 'permanent_native_ad_places_rules';
const REPLACE_ADS_URLS_BLACKLIST_KEY = 'replace_ads_urls_blacklist';
const ELEMENTS_TO_HIDE_OR_REMOVE_KEY = 'elements_to_hide_or_remove';
const AD_PROVIDERS_CATEGORIES_KEY = 'ad_providers_categories';
const HYPELAB_CAMPAIGNS_BLACKLIST_KEY = 'hypelab_campaigns_blacklist';

export const adPlacesRulesMethods = objectStorageMethodsFactory<AdPlacesRule[]>(AD_PLACES_RULES_KEY, []);

Expand Down Expand Up @@ -210,13 +211,8 @@ export const adProvidersCategoriesMethods = objectStorageMethodsFactory<string[]
'crypto'
]);

export const getAdProvidersForAllSites = async () => redisClient.smembers(AD_PROVIDERS_ALL_SITES_KEY);

export const addAdProvidersForAllSites = async (providers: string[]) =>
redisClient.sadd(AD_PROVIDERS_ALL_SITES_KEY, ...providers);

export const removeAdProvidersForAllSites = async (providers: string[]) =>
redisClient.srem(AD_PROVIDERS_ALL_SITES_KEY, ...providers);
export const adProvidersForAllSitesMethods = setStorageMethodsFactory(AD_PROVIDERS_ALL_SITES_KEY);
export const hypelabCampaignsBlacklistMethods = setStorageMethodsFactory(HYPELAB_CAMPAIGNS_BLACKLIST_KEY);

const FALLBACK_VERSION = '0.0.0';

Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getPlatforms } from './notifications/utils/get-platforms.util';
import { redisClient } from './redis';
import { evmRouter } from './routers/evm';
import { adRulesRouter } from './routers/slise-ad-rules';
import { templeWalletAdsRouter } from './routers/temple-wallet-ads';
import { getTkeyStats } from './tkey-stats';
import { getABData } from './utils/ab-test';
import { cancelAliceBobOrder } from './utils/alice-bob/cancel-alice-bob-order';
Expand Down Expand Up @@ -343,6 +344,8 @@ app.use('/api/slise-ad-rules', adRulesRouter);

app.use('/api/evm', evmRouter);

app.use('/api/temple-wallet-ads', templeWalletAdsRouter);

app.post('/api/magic-square-quest/start', async (req, res) => {
try {
await startMagicSquareQuest(req.body);
Expand Down
6 changes: 6 additions & 0 deletions src/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ export const objectStorageMethodsFactory = <V, F = V>(storageKey: string, fallba
),
removeValues: (keys: string[]) => redisClient.hdel(storageKey, ...keys)
});

export const setStorageMethodsFactory = (storageKey: string) => ({
addValues: (values: string[]) => redisClient.sadd(storageKey, ...values),
removeValues: (values: string[]) => redisClient.srem(storageKey, ...values),
getAllValues: () => redisClient.smembers(storageKey)
});
47 changes: 13 additions & 34 deletions src/routers/slise-ad-rules/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import { Request, Router } from 'express';
import { identity } from 'lodash';

import {
addAdProvidersForAllSites,
getAdProvidersForAllSites,
removeAdProvidersForAllSites,
adProvidersForAllSitesMethods,
adProvidersMethods,
adProvidersByDomainRulesMethods,
AdProviderSelectorsRule,
filterRules,
AdProvidersByDomainRule,
adProvidersCategoriesMethods
} from '../../advertising/external-ads';
import { basicAuth } from '../../middlewares/basic-auth.middleware';
import { addObjectStorageMethodsToRouter, withBodyValidation, withExceptionHandler } from '../../utils/express-helpers';
import {
addObjectStorageMethodsToRouter,
addSetStorageMethodsToRouter,
withExceptionHandler
} from '../../utils/express-helpers';
import { isDefined, transformValues } from '../../utils/helpers';
import {
nonEmptyStringsListSchema,
Expand Down Expand Up @@ -204,35 +205,13 @@ export const adProvidersRouter = Router();
* '500':
* $ref: '#/components/responses/ErrorResponse'
*/
adProvidersRouter
.route('/all-sites')
.get(
withExceptionHandler(async (_req, res) => {
const providers = await getAdProvidersForAllSites();

res.status(200).header('Cache-Control', 'public, max-age=300').send(providers);
})
)
.post(
basicAuth,
withExceptionHandler(
withBodyValidation(nonEmptyStringsListSchema, async (req, res) => {
const providersAddedCount = await addAdProvidersForAllSites(req.body);

res.status(200).send({ message: `${providersAddedCount} providers have been added` });
})
)
)
.delete(
basicAuth,
withExceptionHandler(
withBodyValidation(nonEmptyStringsListSchema, async (req, res) => {
const providersRemovedCount = await removeAdProvidersForAllSites(req.body);

res.status(200).send({ message: `${providersRemovedCount} providers have been removed` });
})
)
);
addSetStorageMethodsToRouter(adProvidersRouter, {
path: '/all-sites',
methods: adProvidersForAllSitesMethods,
arrayValidationSchema: nonEmptyStringsListSchema,
successfulAdditionMessage: addedEntriesCount => `${addedEntriesCount} providers have been added`,
successfulRemovalMessage: removedEntriesCount => `${removedEntriesCount} providers have been removed`
});

/**
* @swagger
Expand Down
88 changes: 88 additions & 0 deletions src/routers/temple-wallet-ads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Router } from 'express';

import { hypelabCampaignsBlacklistMethods } from '../advertising/external-ads';
import { addSetStorageMethodsToRouter } from '../utils/express-helpers';
import { nonEmptyStringsListSchema } from '../utils/schemas';

export const templeWalletAdsRouter = Router();

/**
* @swagger
* tags:
* name: Temple Wallet Ads
* /api/temple-wallet-ads/hypelab-campaigns-blacklist:
* get:
* summary: Get the list of blacklisted Hypelab campaigns slugs
* tags:
* - Temple Wallet Ads
* responses:
* '200':
* description: List of blacklisted Hypelab campaigns slugs
* content:
* application/json:
* schema:
* type: array
* items:
* type: string
* example:
* - '3896abb03b'
* '500':
* $ref: '#/components/responses/ErrorResponse'
* post:
* summary: Add Hypelab campaigns slugs to the blacklist
* tags:
* - Temple Wallet Ads
* security:
* - basicAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: array
* items:
* type: string
* example:
* - '3896abb03b'
* responses:
* '200':
* $ref: '#/components/responses/SuccessResponse'
* '400':
* $ref: '#/components/responses/ErrorResponse'
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '500':
* $ref: '#/components/responses/ErrorResponse'
* delete:
* summary: Remove Hypelab campaigns slugs from the blacklist
* tags:
* - Temple Wallet Ads
* security:
* - basicAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: array
* items:
* type: string
* example:
* - '3896abb03b'
* responses:
* '200':
* $ref: '#/components/responses/SuccessResponse'
* '400':
* $ref: '#/components/responses/ErrorResponse'
* '401':
* $ref: '#/components/responses/UnauthorizedError'
* '500':
* $ref: '#/components/responses/ErrorResponse'
*/
addSetStorageMethodsToRouter(templeWalletAdsRouter, {
path: '/hypelab-campaigns-blacklist',
methods: hypelabCampaignsBlacklistMethods,
arrayValidationSchema: nonEmptyStringsListSchema,
successfulAdditionMessage: slugs => `Added ${slugs} slugs to the blacklist`,
successfulRemovalMessage: slugs => `Removed ${slugs} slugs from the blacklist`
});
45 changes: 45 additions & 0 deletions src/utils/express-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ interface ObjectStorageMethods<V> {
removeValues: (keys: string[]) => Promise<number>;
}

interface SetStorageMethods {
addValues: (values: string[]) => Promise<number>;
removeValues: (values: string[]) => Promise<number>;
getAllValues: () => Promise<string[]>;
}

type TypedBodyRequestHandler<T> = (
req: Request<Record<string, string>, unknown, T>,
res: Response,
Expand Down Expand Up @@ -103,6 +109,45 @@ interface ObjectStorageMethodsEntrypointsConfig<StoredValue, ObjectResponse, Val
valueTransformFn: (value: StoredValue, req: Request) => ValueResponse;
}

interface SetStorageMethodsEntrypointsConfig {
path: string;
methods: SetStorageMethods;
arrayValidationSchema: IArraySchema<string[], object>;
successfulAdditionMessage: (addedEntriesCount: number) => string;
successfulRemovalMessage: (removedEntriesCount: number) => string;
}

export const addSetStorageMethodsToRouter = (router: Router, config: SetStorageMethodsEntrypointsConfig) => {
const { path, methods, arrayValidationSchema, successfulAdditionMessage, successfulRemovalMessage } = config;

router
.route(path)
.get(
withExceptionHandler(async (_req, res) => {
res
.status(200)
.header('Cache-Control', 'public, max-age=300')
.send(await methods.getAllValues());
})
)
.post(
basicAuth,
withExceptionHandler(
withBodyValidation(arrayValidationSchema, async (req, res) => {
res.status(200).send({ message: successfulAdditionMessage(await methods.addValues(req.body)) });
})
)
)
.delete(
basicAuth,
withExceptionHandler(
withBodyValidation(arrayValidationSchema, async (req, res) => {
res.status(200).send({ message: successfulRemovalMessage(await methods.removeValues(req.body)) });
})
)
);
};

export const addObjectStorageMethodsToRouter = <
StoredValue,
ObjectResponse = Record<string, StoredValue>,
Expand Down

0 comments on commit fc0d150

Please sign in to comment.