Skip to content

Commit 3a36381

Browse files
authored
TW-1492: Ads replacement rework for mobile browsing (#167)
* TW-1464 Prepare backend for new native ads * TW-1464 Update API documentation * TW-1464 Enable adding native ads in replace-only mode * TW-1492 Add some properties for ads definitions * TW-1492 Prepare the backend to additional fixtures for Mises * TW-1492 Add an entrypoint for elements to hide or remove
1 parent 9afaa86 commit 3a36381

File tree

7 files changed

+391
-24
lines changed

7 files changed

+391
-24
lines changed

src/advertising/external-ads.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ export const stylePropsNames = [
1111
'aspect-ratio',
1212
'background',
1313
'border',
14+
'border-top',
15+
'border-bottom',
16+
'border-left',
17+
'border-right',
18+
'border-color',
1419
'border-radius',
1520
'bottom',
1621
'box-shadow',
@@ -49,6 +54,7 @@ export const stylePropsNames = [
4954
'min-inline-size',
5055
'min-width',
5156
'opacity',
57+
'order',
5258
'overflow',
5359
'overflow-anchor',
5460
'overflow-wrap',
@@ -127,8 +133,10 @@ export interface PermanentAdPlacesRule extends ExtVersionConstraints {
127133
divWrapperStyle?: Record<StylePropName, string>;
128134
wrapperStyle?: Record<StylePropName, string>;
129135
elementToMeasureSelector?: string;
136+
elementsToMeasureSelectors?: Record<'width' | 'height', string>;
130137
stylesOverrides?: AdStylesOverrides[];
131138
shouldHideOriginal?: boolean;
139+
displayWidth?: string;
132140
}
133141

134142
export interface AdProvidersByDomainRule extends ExtVersionConstraints {
@@ -138,7 +146,9 @@ export interface AdProvidersByDomainRule extends ExtVersionConstraints {
138146

139147
export interface AdProviderSelectorsRule extends ExtVersionConstraints {
140148
selectors: string[];
149+
negativeSelectors?: string[];
141150
parentDepth?: number;
151+
enableForMises?: boolean;
142152
}
143153

144154
export interface AdProviderForAllSitesRule extends ExtVersionConstraints {
@@ -149,13 +159,22 @@ export interface ReplaceAdsUrlsBlacklistEntry extends ExtVersionConstraints {
149159
regexes: string[];
150160
}
151161

162+
export interface ElementsToHideOrRemoveEntry extends ExtVersionConstraints {
163+
cssString: string;
164+
parentDepth: number;
165+
isMultiple: boolean;
166+
urlRegexes: string[];
167+
shouldHide: boolean;
168+
}
169+
152170
const AD_PLACES_RULES_KEY = 'ad_places_rules';
153171
const AD_PROVIDERS_BY_SITES_KEY = 'ad_providers_by_sites';
154172
const AD_PROVIDERS_ALL_SITES_KEY = 'ad_providers_all_sites';
155173
const AD_PROVIDERS_LIST_KEY = 'ad_providers_list';
156174
const PERMANENT_AD_PLACES_RULES_KEY = 'permanent_ad_places_rules';
157175
const PERMANENT_NATIVE_AD_PLACES_RULES_KEY = 'permanent_native_ad_places_rules';
158176
const REPLACE_ADS_URLS_BLACKLIST_KEY = 'replace_ads_urls_blacklist';
177+
const ELEMENTS_TO_HIDE_OR_REMOVE_KEY = 'elements_to_hide_or_remove';
159178

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

@@ -181,6 +200,11 @@ export const replaceAdsUrlsBlacklistMethods = objectStorageMethodsFactory<Replac
181200
[]
182201
);
183202

203+
export const elementsToHideOrRemoveMethods = objectStorageMethodsFactory<ElementsToHideOrRemoveEntry[]>(
204+
ELEMENTS_TO_HIDE_OR_REMOVE_KEY,
205+
[]
206+
);
207+
184208
export const getAdProvidersForAllSites = async () => redisClient.smembers(AD_PROVIDERS_ALL_SITES_KEY);
185209

186210
export const addAdProvidersForAllSites = async (providers: string[]) =>
@@ -191,5 +215,19 @@ export const removeAdProvidersForAllSites = async (providers: string[]) =>
191215

192216
const FALLBACK_VERSION = '0.0.0';
193217

194-
export const filterByVersion = <T extends ExtVersionConstraints>(rules: T[], version?: string) =>
195-
rules.filter(({ extVersion }) => versionSatisfiesRange(version ?? FALLBACK_VERSION, extVersion));
218+
export function filterRules<T extends ExtVersionConstraints>(rules: T[], version: string | undefined): T[];
219+
export function filterRules<T extends ExtVersionConstraints & { enableForMises?: boolean }>(
220+
rules: T[],
221+
version: string | undefined,
222+
isMisesBrowser: boolean
223+
): T[];
224+
export function filterRules<T extends ExtVersionConstraints & { enableForMises?: boolean }>(
225+
rules: T[],
226+
version: string | undefined,
227+
isMisesBrowser = false
228+
) {
229+
return rules.filter(
230+
({ extVersion, enableForMises = true }) =>
231+
versionSatisfiesRange(version ?? FALLBACK_VERSION, extVersion) && (!isMisesBrowser || enableForMises)
232+
);
233+
}

src/routers/slise-ad-rules/ad-places.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Request, Router } from 'express';
22

33
import {
4-
filterByVersion,
4+
filterRules,
55
permanentNativeAdPlacesMethods,
66
permanentAdPlacesMethods,
77
adPlacesRulesMethods,
@@ -18,7 +18,7 @@ import {
1818
} from '../../utils/schemas';
1919

2020
const transformAdPlaces = <T extends ExtVersionConstraints>(value: T[], req: Request) =>
21-
filterByVersion(value, req.query.extVersion as string | undefined);
21+
filterRules(value, req.query.extVersion as string | undefined);
2222
const transformAdPlacesDictionary = <T extends ExtVersionConstraints>(rules: Record<string, T[]>, req: Request) =>
2323
transformValues(rules, value => transformAdPlaces(value, req));
2424

@@ -280,6 +280,18 @@ const transformAdPlacesDictionary = <T extends ExtVersionConstraints>(rules: Rec
280280
* elementToMeasureSelector:
281281
* type: string
282282
* description: A selector of the element which should be measured to define banner size
283+
* elementsToMeasureSelectors:
284+
* type: object
285+
* required:
286+
* - width
287+
* - height
288+
* properties:
289+
* width:
290+
* type: string
291+
* description: A selector of the element which should be measured to define banner width
292+
* height:
293+
* type: string
294+
* description: A selector of the element which should be measured to define banner height
283295
* stylesOverrides:
284296
* type: array
285297
* items:
@@ -288,6 +300,12 @@ const transformAdPlacesDictionary = <T extends ExtVersionConstraints>(rules: Rec
288300
* type: boolean
289301
* description: Whether original ads banners should be hidden but not removed
290302
* default: false
303+
* displayWidth:
304+
* type: string
305+
* description: >
306+
* A range of display widths in a semver-like format where the rule is applicable. Numbers can be only
307+
* integers. If not specified, the rule is applicable for all display widths.
308+
* example: '>=1024 <1280'
291309
* example:
292310
* urlRegexes:
293311
* - '^https://etherscan\.io/tx/'
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
import { Router, Request } from 'express';
2+
3+
import {
4+
ElementsToHideOrRemoveEntry,
5+
elementsToHideOrRemoveMethods,
6+
filterRules
7+
} from '../../advertising/external-ads';
8+
import { addObjectStorageMethodsToRouter } from '../../utils/express-helpers';
9+
import { transformValues } from '../../utils/helpers';
10+
import { elementsToHideOrRemoveDictionarySchema, hostnamesListSchema } from '../../utils/schemas';
11+
12+
export const elementsToHideOrRemoveRouter = Router();
13+
14+
const transformElementsToHideOrRemoveRules = (value: ElementsToHideOrRemoveEntry[], req: Request) =>
15+
filterRules(value, req.query.extVersion as string | undefined);
16+
const transformRulesDictionary = (value: Record<string, ElementsToHideOrRemoveEntry[]>, req: Request) =>
17+
transformValues(value, rules => filterRules(rules, req.query.extVersion as string | undefined));
18+
19+
/**
20+
* @swagger
21+
* tags:
22+
* name: Elements to hide or remove
23+
* components:
24+
* schemas:
25+
* ElementsToHideOrRemoveEntry:
26+
* allOf:
27+
* - $ref: '#/components/schemas/ExtVersionConstraints'
28+
* - type: object
29+
* required:
30+
* - cssString
31+
* - parentDepth
32+
* - isMultiple
33+
* - urlRegexes
34+
* - shouldHide
35+
* properties:
36+
* cssString:
37+
* type: string
38+
* parentDepth:
39+
* type: number
40+
* min: 0
41+
* integer: true
42+
* description: >
43+
* Indicates the depth of the parent element of the selected element
44+
* isMultiple:
45+
* type: boolean
46+
* description: Whether the selector should select multiple elements
47+
* urlRegexes:
48+
* type: array
49+
* items:
50+
* type: string
51+
* format: regex
52+
* shouldHide:
53+
* type: boolean
54+
* ElementsToHideOrRemoveDictionary:
55+
* type: object
56+
* additionalProperties:
57+
* type: array
58+
* items:
59+
* $ref: '#/components/schemas/ElementsToHideOrRemoveEntry'
60+
* example:
61+
* 'm.economictimes.com':
62+
* - extVersion: '>=1.21.1'
63+
* cssString: '#iframeDisplay, #closeDisplay'
64+
* parentDepth: 0
65+
* isMultiple: true
66+
* urlRegexes:
67+
* - "^https://m\\.economictimes\\.com"
68+
* shouldHide: true
69+
* /api/slise-ad-rules/elements-to-hide-or-remove/raw/all:
70+
* get:
71+
* summary: Get all rules for hiding or removing elements
72+
* tags:
73+
* - Elements to hide or remove
74+
* responses:
75+
* '200':
76+
* description: A dictionary of all rules
77+
* content:
78+
* application/json:
79+
* schema:
80+
* $ref: '#/components/schemas/ElementsToHideOrRemoveDictionary'
81+
* '500':
82+
* $ref: '#/components/responses/ErrorResponse'
83+
* /api/slise-ad-rules/elements-to-hide-or-remove/{domain}/raw:
84+
* get:
85+
* summary: Get rules for hiding or removing elements by domain
86+
* tags:
87+
* - Elements to hide or remove
88+
* parameters:
89+
* - name: domain
90+
* in: path
91+
* required: true
92+
* schema:
93+
* type: string
94+
* description: Domain name
95+
* responses:
96+
* '200':
97+
* description: An array of rules
98+
* content:
99+
* application/json:
100+
* schema:
101+
* type: array
102+
* items:
103+
* $ref: '#/components/schemas/ElementsToHideOrRemoveEntry'
104+
* '500':
105+
* $ref: '#/components/responses/ErrorResponse'
106+
* /api/slise-ad-rules/elements-to-hide-or-remove/{domain}:
107+
* get:
108+
* summary: Get rules for hiding or removing elements by domain and extension version
109+
* tags:
110+
* - Elements to hide or remove
111+
* parameters:
112+
* - name: domain
113+
* in: path
114+
* required: true
115+
* schema:
116+
* type: string
117+
* description: Domain name
118+
* - name: extVersion
119+
* in: query
120+
* schema:
121+
* type: string
122+
* default: '0.0.0'
123+
* description: Extension version
124+
* responses:
125+
* '200':
126+
* description: An array of rules
127+
* content:
128+
* application/json:
129+
* schema:
130+
* type: array
131+
* items:
132+
* $ref: '#/components/schemas/ElementsToHideOrRemoveEntry'
133+
* '500':
134+
* $ref: '#/components/responses/ErrorResponse'
135+
* /api/slise-ad-rules/elements-to-hide-or-remove:
136+
* get:
137+
* summary: Get all rules for hiding or removing elements filtered by extension version
138+
* tags:
139+
* - Elements to hide or remove
140+
* parameters:
141+
* - name: extVersion
142+
* in: query
143+
* schema:
144+
* type: string
145+
* default: '0.0.0'
146+
* description: Extension version
147+
* responses:
148+
* '200':
149+
* description: A dictionary of rules
150+
* content:
151+
* application/json:
152+
* schema:
153+
* $ref: '#/components/schemas/ElementsToHideOrRemoveDictionary'
154+
* '500':
155+
* $ref: '#/components/responses/ErrorResponse'
156+
* post:
157+
* summary: Add rules for hiding or removing elements. If a rule already exists, it will be updated
158+
* tags:
159+
* - Elements to hide or remove
160+
* security:
161+
* - basicAuth: []
162+
* requestBody:
163+
* content:
164+
* application/json:
165+
* schema:
166+
* $ref: '#/components/schemas/ElementsToHideOrRemoveDictionary'
167+
* responses:
168+
* '200':
169+
* $ref: '#/components/responses/SuccessResponse'
170+
* '400':
171+
* $ref: '#/components/responses/ErrorResponse'
172+
* '401':
173+
* $ref: '#/components/responses/UnauthorizedError'
174+
* '500':
175+
* $ref: '#/components/responses/ErrorResponse'
176+
* delete:
177+
* summary: Delete rules for hiding or removing elements
178+
* tags:
179+
* - Elements to hide or remove
180+
* security:
181+
* - basicAuth: []
182+
* requestBody:
183+
* content:
184+
* application/json:
185+
* schema:
186+
* type: array
187+
* items:
188+
* type: string
189+
* example:
190+
* - 'm.economictimes.com'
191+
* responses:
192+
* '200':
193+
* $ref: '#/components/responses/SuccessResponse'
194+
* '400':
195+
* $ref: '#/components/responses/ErrorResponse'
196+
* '401':
197+
* $ref: '#/components/responses/UnauthorizedError'
198+
* '500':
199+
* $ref: '#/components/responses/ErrorResponse'
200+
*/
201+
addObjectStorageMethodsToRouter(elementsToHideOrRemoveRouter, {
202+
path: '/',
203+
methods: elementsToHideOrRemoveMethods,
204+
keyName: 'domain',
205+
objectValidationSchema: elementsToHideOrRemoveDictionarySchema,
206+
keysArrayValidationSchema: hostnamesListSchema,
207+
successfulRemovalMessage: entriesCount => `${entriesCount} entries have been removed`,
208+
objectTransformFn: transformRulesDictionary,
209+
valueTransformFn: transformElementsToHideOrRemoveRules
210+
});

src/routers/slise-ad-rules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Router } from 'express';
22

33
import { adPlacesRulesRouter } from './ad-places';
4+
import { elementsToHideOrRemoveRouter } from './elements-to-hide-or-remove';
45
import { adProvidersRouter } from './providers';
56
import { replaceUrlsBlacklistRouter } from './replace-urls-blacklist';
67

@@ -43,3 +44,4 @@ export const adRulesRouter = Router();
4344
adRulesRouter.use('/ad-places', adPlacesRulesRouter);
4445
adRulesRouter.use('/providers', adProvidersRouter);
4546
adRulesRouter.use('/replace-urls-blacklist', replaceUrlsBlacklistRouter);
47+
adRulesRouter.use('/elements-to-hide-or-remove', elementsToHideOrRemoveRouter);

0 commit comments

Comments
 (0)