From bd1e1665a0a708ba954e0459060b8b14507bc824 Mon Sep 17 00:00:00 2001 From: Inokentii Mazhara Date: Thu, 25 Jul 2024 09:10:45 +0300 Subject: [PATCH] TW-1492 Add an entrypoint for elements to hide or remove --- src/advertising/external-ads.ts | 19 ++ .../elements-to-hide-or-remove.ts | 210 ++++++++++++++++++ src/routers/slise-ad-rules/index.ts | 2 + src/utils/schemas.ts | 17 +- 4 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 src/routers/slise-ad-rules/elements-to-hide-or-remove.ts diff --git a/src/advertising/external-ads.ts b/src/advertising/external-ads.ts index 1384c4f..597ec44 100644 --- a/src/advertising/external-ads.ts +++ b/src/advertising/external-ads.ts @@ -11,6 +11,11 @@ export const stylePropsNames = [ 'aspect-ratio', 'background', 'border', + 'border-top', + 'border-bottom', + 'border-left', + 'border-right', + 'border-color', 'border-radius', 'bottom', 'box-shadow', @@ -154,6 +159,14 @@ export interface ReplaceAdsUrlsBlacklistEntry extends ExtVersionConstraints { regexes: string[]; } +export interface ElementsToHideOrRemoveEntry extends ExtVersionConstraints { + cssString: string; + parentDepth: number; + isMultiple: boolean; + urlRegexes: string[]; + shouldHide: boolean; +} + const AD_PLACES_RULES_KEY = 'ad_places_rules'; const AD_PROVIDERS_BY_SITES_KEY = 'ad_providers_by_sites'; const AD_PROVIDERS_ALL_SITES_KEY = 'ad_providers_all_sites'; @@ -161,6 +174,7 @@ const AD_PROVIDERS_LIST_KEY = 'ad_providers_list'; const PERMANENT_AD_PLACES_RULES_KEY = 'permanent_ad_places_rules'; 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'; export const adPlacesRulesMethods = objectStorageMethodsFactory(AD_PLACES_RULES_KEY, []); @@ -186,6 +200,11 @@ export const replaceAdsUrlsBlacklistMethods = objectStorageMethodsFactory( + ELEMENTS_TO_HIDE_OR_REMOVE_KEY, + [] +); + export const getAdProvidersForAllSites = async () => redisClient.smembers(AD_PROVIDERS_ALL_SITES_KEY); export const addAdProvidersForAllSites = async (providers: string[]) => diff --git a/src/routers/slise-ad-rules/elements-to-hide-or-remove.ts b/src/routers/slise-ad-rules/elements-to-hide-or-remove.ts new file mode 100644 index 0000000..1e479e0 --- /dev/null +++ b/src/routers/slise-ad-rules/elements-to-hide-or-remove.ts @@ -0,0 +1,210 @@ +import { Router, Request } from 'express'; + +import { + ElementsToHideOrRemoveEntry, + elementsToHideOrRemoveMethods, + filterRules +} from '../../advertising/external-ads'; +import { addObjectStorageMethodsToRouter } from '../../utils/express-helpers'; +import { transformValues } from '../../utils/helpers'; +import { elementsToHideOrRemoveDictionarySchema, hostnamesListSchema } from '../../utils/schemas'; + +export const elementsToHideOrRemoveRouter = Router(); + +const transformElementsToHideOrRemoveRules = (value: ElementsToHideOrRemoveEntry[], req: Request) => + filterRules(value, req.query.extVersion as string | undefined); +const transformRulesDictionary = (value: Record, req: Request) => + transformValues(value, rules => filterRules(rules, req.query.extVersion as string | undefined)); + +/** + * @swagger + * tags: + * name: Elements to hide or remove + * components: + * schemas: + * ElementsToHideOrRemoveEntry: + * allOf: + * - $ref: '#/components/schemas/ExtVersionConstraints' + * - type: object + * required: + * - cssString + * - parentDepth + * - isMultiple + * - urlRegexes + * - shouldHide + * properties: + * cssString: + * type: string + * parentDepth: + * type: number + * min: 0 + * integer: true + * description: > + * Indicates the depth of the parent element of the selected element + * isMultiple: + * type: boolean + * description: Whether the selector should select multiple elements + * urlRegexes: + * type: array + * items: + * type: string + * format: regex + * shouldHide: + * type: boolean + * ElementsToHideOrRemoveDictionary: + * type: object + * additionalProperties: + * type: array + * items: + * $ref: '#/components/schemas/ElementsToHideOrRemoveEntry' + * example: + * 'm.economictimes.com': + * - extVersion: '>=1.21.1' + * cssString: '#iframeDisplay, #closeDisplay' + * parentDepth: 0 + * isMultiple: true + * urlRegexes: + * - "^https://m\\.economictimes\\.com" + * shouldHide: true + * /api/slise-ad-rules/elements-to-hide-or-remove/raw/all: + * get: + * summary: Get all rules for hiding or removing elements + * tags: + * - Elements to hide or remove + * responses: + * '200': + * description: A dictionary of all rules + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ElementsToHideOrRemoveDictionary' + * '500': + * $ref: '#/components/responses/ErrorResponse' + * /api/slise-ad-rules/elements-to-hide-or-remove/{domain}/raw: + * get: + * summary: Get rules for hiding or removing elements by domain + * tags: + * - Elements to hide or remove + * parameters: + * - name: domain + * in: path + * required: true + * schema: + * type: string + * description: Domain name + * responses: + * '200': + * description: An array of rules + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/ElementsToHideOrRemoveEntry' + * '500': + * $ref: '#/components/responses/ErrorResponse' + * /api/slise-ad-rules/elements-to-hide-or-remove/{domain}: + * get: + * summary: Get rules for hiding or removing elements by domain and extension version + * tags: + * - Elements to hide or remove + * parameters: + * - name: domain + * in: path + * required: true + * schema: + * type: string + * description: Domain name + * - name: extVersion + * in: query + * schema: + * type: string + * default: '0.0.0' + * description: Extension version + * responses: + * '200': + * description: An array of rules + * content: + * application/json: + * schema: + * type: array + * items: + * $ref: '#/components/schemas/ElementsToHideOrRemoveEntry' + * '500': + * $ref: '#/components/responses/ErrorResponse' + * /api/slise-ad-rules/elements-to-hide-or-remove: + * get: + * summary: Get all rules for hiding or removing elements filtered by extension version + * tags: + * - Elements to hide or remove + * parameters: + * - name: extVersion + * in: query + * schema: + * type: string + * default: '0.0.0' + * description: Extension version + * responses: + * '200': + * description: A dictionary of rules + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ElementsToHideOrRemoveDictionary' + * '500': + * $ref: '#/components/responses/ErrorResponse' + * post: + * summary: Add rules for hiding or removing elements. If a rule already exists, it will be updated + * tags: + * - Elements to hide or remove + * security: + * - basicAuth: [] + * requestBody: + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ElementsToHideOrRemoveDictionary' + * responses: + * '200': + * $ref: '#/components/responses/SuccessResponse' + * '400': + * $ref: '#/components/responses/ErrorResponse' + * '401': + * $ref: '#/components/responses/UnauthorizedError' + * '500': + * $ref: '#/components/responses/ErrorResponse' + * delete: + * summary: Delete rules for hiding or removing elements + * tags: + * - Elements to hide or remove + * security: + * - basicAuth: [] + * requestBody: + * content: + * application/json: + * schema: + * type: array + * items: + * type: string + * example: + * - 'm.economictimes.com' + * responses: + * '200': + * $ref: '#/components/responses/SuccessResponse' + * '400': + * $ref: '#/components/responses/ErrorResponse' + * '401': + * $ref: '#/components/responses/UnauthorizedError' + * '500': + * $ref: '#/components/responses/ErrorResponse' + */ +addObjectStorageMethodsToRouter(elementsToHideOrRemoveRouter, { + path: '/', + methods: elementsToHideOrRemoveMethods, + keyName: 'domain', + objectValidationSchema: elementsToHideOrRemoveDictionarySchema, + keysArrayValidationSchema: hostnamesListSchema, + successfulRemovalMessage: entriesCount => `${entriesCount} entries have been removed`, + objectTransformFn: transformRulesDictionary, + valueTransformFn: transformElementsToHideOrRemoveRules +}); diff --git a/src/routers/slise-ad-rules/index.ts b/src/routers/slise-ad-rules/index.ts index ea84c98..a136617 100644 --- a/src/routers/slise-ad-rules/index.ts +++ b/src/routers/slise-ad-rules/index.ts @@ -1,6 +1,7 @@ import { Router } from 'express'; import { adPlacesRulesRouter } from './ad-places'; +import { elementsToHideOrRemoveRouter } from './elements-to-hide-or-remove'; import { adProvidersRouter } from './providers'; import { replaceUrlsBlacklistRouter } from './replace-urls-blacklist'; @@ -43,3 +44,4 @@ export const adRulesRouter = Router(); adRulesRouter.use('/ad-places', adPlacesRulesRouter); adRulesRouter.use('/providers', adProvidersRouter); adRulesRouter.use('/replace-urls-blacklist', replaceUrlsBlacklistRouter); +adRulesRouter.use('/elements-to-hide-or-remove', elementsToHideOrRemoveRouter); diff --git a/src/utils/schemas.ts b/src/utils/schemas.ts index 5fb11e3..be62bcc 100644 --- a/src/utils/schemas.ts +++ b/src/utils/schemas.ts @@ -18,7 +18,8 @@ import { StylePropName, stylePropsNames, AdProviderSelectorsRule, - ReplaceAdsUrlsBlacklistEntry + ReplaceAdsUrlsBlacklistEntry, + ElementsToHideOrRemoveEntry } from '../advertising/external-ads'; import { isValidSelectorsGroup } from '../utils/selectors.min.js'; import { isDefined } from './helpers'; @@ -263,3 +264,17 @@ export const replaceUrlsBlacklistDictionarySchema = makeDictionarySchema( + hostnameSchema.clone().required(), + arraySchema().of(elementsToHideOrRemoveEntrySchema.clone().required()).required() +).required();