@singcl/ad-execute-manager 2.0.0-alpha.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.md +545 -113
- package/dist/ad/InterstitialAdFather.d.ts +39 -7
- package/dist/ad/InterstitialAdNovel.d.ts +4 -0
- package/dist/ad/RewardAdFather.d.ts +57 -7
- package/dist/ad/RewardAdNovel.d.ts +76 -16
- package/dist/{helper → analytics}/AdAnalyticsJS.d.ts +9 -0
- package/dist/core/AdExecuteManager.d.ts +107 -1
- package/dist/core/_util.d.ts +18 -0
- package/dist/helper/SerializableError.d.ts +5 -1
- package/dist/index.cjs +2 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -1
- package/dist/{helper → other}/RewardAdSceneTriggerManager.d.ts +6 -0
- package/dist/typings/ad.d.ts +32 -8
- package/dist/typings/create-interstitial-ad.d.ts +42 -0
- package/dist/typings/create-rewarded-video-ad.d.ts +42 -0
- package/package.json +30 -23
- package/dist/ad/index.d.ts +0 -4
- package/dist/core/index.d.ts +0 -2
- package/dist/helper/index.d.ts +0 -10
- package/dist/subpackages/ad/index.js +0 -1
- package/dist/subpackages/core/index.js +0 -1
- package/dist/subpackages/helper/index.js +0 -1
- package/dist/subpackages/utils/index.js +0 -1
- /package/dist/{helper → other}/LovelUnlockManager.d.ts +0 -0
- /package/dist/{helper → other}/RewardAdGlobalRecorder.d.ts +0 -0
package/README.md
CHANGED
|
@@ -6,18 +6,19 @@ A powerful and flexible ad execution management library for handling reward-base
|
|
|
6
6
|
|
|
7
7
|
- [Features](#features)
|
|
8
8
|
- [Installation](#installation)
|
|
9
|
-
- [
|
|
9
|
+
- [Quick Start](#quick-start)
|
|
10
|
+
- [Core Concepts](#core-concepts)
|
|
11
|
+
- [Usage Examples](#usage-examples)
|
|
10
12
|
- [API Reference](#api-reference)
|
|
11
|
-
- [
|
|
12
|
-
- [Contributing](#contributing)
|
|
13
|
+
- [Development Guide](#development-guide)
|
|
13
14
|
- [License](#license)
|
|
14
15
|
|
|
15
16
|
## Features
|
|
16
17
|
|
|
17
|
-
- **Unified Ad Execution**: Single interface for managing different types of ads
|
|
18
|
+
- **Unified Ad Execution Interface**: Single interface for managing different types of ads
|
|
18
19
|
- **Task Queue Management**: Handles multiple ad execution tasks in a queue
|
|
19
|
-
- **Flexible Control**: Manual control over ad execution flow with `next` function
|
|
20
|
-
- **Error Handling**:
|
|
20
|
+
- **Flexible Control Flow**: Manual control over ad execution flow with `next` function
|
|
21
|
+
- **Comprehensive Error Handling**: Complete error handling and logging
|
|
21
22
|
- **State Persistence**: Built-in storage for ad state management
|
|
22
23
|
- **Analytics Integration**: Built-in analytics support
|
|
23
24
|
- **Middleware Pattern**: Uses middleware pattern for ad execution flow
|
|
@@ -29,163 +30,578 @@ A powerful and flexible ad execution management library for handling reward-base
|
|
|
29
30
|
npm install @singcl/ad-execute-manager
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
##
|
|
33
|
+
## Quick Start
|
|
33
34
|
|
|
34
35
|
### Basic Usage
|
|
35
36
|
|
|
36
37
|
```javascript
|
|
37
|
-
import {
|
|
38
|
+
import { RewardAdNovel, InterstitialAdNovel } from '@singcl/ad-execute-manager';
|
|
38
39
|
|
|
39
|
-
//
|
|
40
|
-
const
|
|
40
|
+
// Create reward ad instance
|
|
41
|
+
const rewardAd = RewardAdNovel.new({
|
|
42
|
+
adConfig: { /* ad configuration */ },
|
|
43
|
+
collection: {
|
|
44
|
+
always: (args) => console.log('Ad always callback', args),
|
|
45
|
+
halfway: (args) => console.log('Ad halfway callback', args),
|
|
46
|
+
finished: (args) => console.log('Ad finished callback', args),
|
|
47
|
+
before: (args) => console.log('Ad before callback', args),
|
|
48
|
+
success: (args) => console.log('Ad success callback', args),
|
|
49
|
+
prelude: (args) => console.log('Ad prelude callback', args)
|
|
50
|
+
}
|
|
51
|
+
});
|
|
41
52
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
// Initialize ad
|
|
54
|
+
rewardAd.initialize({
|
|
55
|
+
adUnitId: 'your-reward-ad-unit-id'
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Execute ad
|
|
59
|
+
const rewardResult = await rewardAd.addExecuteManager({
|
|
60
|
+
options: {
|
|
61
|
+
scene: 'reward_ad_scene',
|
|
62
|
+
timeout: 8000 // Optional timeout
|
|
52
63
|
}
|
|
53
|
-
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Create interstitial ad instance
|
|
67
|
+
const interstitialAd = InterstitialAdNovel.new({
|
|
68
|
+
adConfig: { /* ad configuration */ },
|
|
69
|
+
collection: {
|
|
70
|
+
always: (args) => console.log('Interstitial ad always callback', args),
|
|
71
|
+
halfway: (args) => console.log('Interstitial ad halfway callback', args),
|
|
72
|
+
finished: (args) => console.log('Interstitial ad finished callback', args),
|
|
73
|
+
before: (args) => console.log('Interstitial ad before callback', args),
|
|
74
|
+
success: (args) => console.log('Interstitial ad success callback', args),
|
|
75
|
+
prelude: (args) => console.log('Interstitial ad prelude callback', args)
|
|
76
|
+
}
|
|
77
|
+
});
|
|
54
78
|
|
|
55
|
-
//
|
|
56
|
-
|
|
79
|
+
// Initialize ad
|
|
80
|
+
interstitialAd.initialize({
|
|
81
|
+
adUnitId: 'your-interstitial-ad-unit-id'
|
|
82
|
+
});
|
|
57
83
|
|
|
58
|
-
//
|
|
59
|
-
const
|
|
60
|
-
options: {
|
|
61
|
-
|
|
84
|
+
// Execute ad
|
|
85
|
+
const interstitialResult = await interstitialAd.addExecuteManager({
|
|
86
|
+
options: {
|
|
87
|
+
scene: 'interstitial_ad_scene'
|
|
88
|
+
}
|
|
62
89
|
});
|
|
63
90
|
```
|
|
64
91
|
|
|
65
92
|
### Advanced Usage
|
|
66
93
|
|
|
67
94
|
```javascript
|
|
68
|
-
import {
|
|
95
|
+
import { RewardAdNovel, InterstitialAdNovel, RewardAdSceneTriggerManager } from '@singcl/ad-execute-manager';
|
|
69
96
|
|
|
70
|
-
//
|
|
71
|
-
const
|
|
97
|
+
// Create reward ad with logging enabled
|
|
98
|
+
const rewardAd = RewardAdNovel.new({
|
|
99
|
+
log: true, // Enable logging
|
|
100
|
+
adConfig: { /* ad configuration */ },
|
|
101
|
+
collection: { /* callback collection */ }
|
|
102
|
+
});
|
|
72
103
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
104
|
+
// Initialize ad with custom configuration
|
|
105
|
+
rewardAd.initialize({
|
|
106
|
+
adUnitId: 'your-reward-ad-unit-id',
|
|
107
|
+
// Other ad configuration options
|
|
108
|
+
});
|
|
77
109
|
|
|
78
|
-
//
|
|
79
|
-
const
|
|
110
|
+
// Execute ad with custom options
|
|
111
|
+
const result = await rewardAd.addExecuteManager({
|
|
112
|
+
options: {
|
|
113
|
+
scene: 'reward_ad_scene',
|
|
114
|
+
timeout: 10000 // Custom timeout
|
|
115
|
+
},
|
|
116
|
+
collection: {
|
|
117
|
+
always: (args) => {
|
|
118
|
+
console.log('Ad execution completed', args);
|
|
119
|
+
// Handle completion
|
|
120
|
+
},
|
|
121
|
+
halfway: (args) => {
|
|
122
|
+
console.log('Ad interrupted', args);
|
|
123
|
+
// Handle interruption
|
|
124
|
+
},
|
|
125
|
+
finished: (args) => {
|
|
126
|
+
console.log('Ad finished successfully', args);
|
|
127
|
+
// Handle success
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
80
131
|
|
|
81
|
-
//
|
|
82
|
-
const
|
|
132
|
+
// Use scene trigger manager
|
|
133
|
+
const sceneManager = RewardAdSceneTriggerManager.build({ sign: 'init_sign' });
|
|
134
|
+
sceneManager.addScene('custom_ad_scene');
|
|
83
135
|
|
|
84
|
-
//
|
|
85
|
-
|
|
136
|
+
// Create interstitial ad with custom settings
|
|
137
|
+
const interstitialAd = InterstitialAdNovel.new({
|
|
138
|
+
needEndOnTimeout: true, // Enable timeout handling
|
|
139
|
+
adConfig: { /* ad configuration */ }
|
|
140
|
+
});
|
|
86
141
|
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
142
|
+
// Initialize and execute
|
|
143
|
+
interstitialAd.initialize({
|
|
144
|
+
adUnitId: 'your-interstitial-ad-unit-id'
|
|
145
|
+
});
|
|
90
146
|
|
|
91
|
-
|
|
147
|
+
const interstitialResult = await interstitialAd.addExecuteManager({
|
|
148
|
+
options: {
|
|
149
|
+
scene: 'interstitial_ad_scene'
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
```
|
|
92
153
|
|
|
93
|
-
|
|
154
|
+
## Core Concepts
|
|
94
155
|
|
|
95
|
-
|
|
156
|
+
### Ad Execution Flow
|
|
96
157
|
|
|
97
|
-
|
|
158
|
+
RewardAdNovel and InterstitialAdNovel use a middleware pattern to handle ad execution flow. Each ad task goes through the following steps:
|
|
98
159
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- `isRunning()`: Check if tasks are currently running
|
|
105
|
-
- `getCurrentTaskId()`: Get the ID of the current executing task
|
|
106
|
-
- `whenAllTasksComplete()`: Returns a Promise that resolves when all tasks are complete
|
|
160
|
+
1. **Initialization**: Create ad instance and configure parameters using `new()` or `build()`
|
|
161
|
+
2. **Configuration**: Call `initialize()` to set up ad unit ID and other configuration
|
|
162
|
+
3. **Execution**: Call `addExecuteManager()` to execute the ad with custom options
|
|
163
|
+
4. **Completion Callback**: Call callback functions after ad execution completes
|
|
164
|
+
5. **Cleanup**: Automatically clean up resources after execution
|
|
107
165
|
|
|
108
|
-
###
|
|
166
|
+
### Ad Types
|
|
109
167
|
|
|
110
|
-
|
|
168
|
+
- **Reward Ads**: Use `RewardAdNovel` for scenarios where users need to complete viewing to receive rewards
|
|
169
|
+
- **Interstitial Ads**: Use `InterstitialAdNovel` for scenarios where ads are inserted into the application flow
|
|
111
170
|
|
|
112
|
-
###
|
|
171
|
+
### Scene Management
|
|
113
172
|
|
|
114
|
-
|
|
173
|
+
Manage ad trigger scenes through `RewardAdSceneTriggerManager`, which allows executing different ad logic based on different scenes.
|
|
115
174
|
|
|
116
|
-
###
|
|
175
|
+
### Frequency Control
|
|
117
176
|
|
|
118
|
-
|
|
119
|
-
- `Logger`: Logging utility
|
|
120
|
-
- `Storage`: Storage management
|
|
121
|
-
- `CountRecorder`: Ad execution counter
|
|
122
|
-
- `RewardAdGlobalRecorder`: Global ad recorder
|
|
123
|
-
- `RewardAdSceneTriggerManager`: Scene-based ad trigger manager
|
|
124
|
-
- `AdAnalyticsJS`: Analytics integration
|
|
125
|
-
- `RewardAdNovel`: Novel-specific reward ad implementation
|
|
126
|
-
- `InterstitialAdNovel`: Novel-specific interstitial ad implementation
|
|
127
|
-
- `PubSub`: Publish-subscribe pattern implementation
|
|
177
|
+
Use `CountRecorder` to implement ad display frequency control, which can set daily display limits.
|
|
128
178
|
|
|
129
|
-
## Examples
|
|
179
|
+
## Usage Examples
|
|
130
180
|
|
|
131
|
-
### Reward Ad
|
|
181
|
+
### 1. Launch Reward Ad
|
|
132
182
|
|
|
133
183
|
```javascript
|
|
134
|
-
|
|
184
|
+
// 启动激励视频
|
|
185
|
+
import { CountRecorder, PubSub } from '@singcl/ad-execute-manager';
|
|
186
|
+
import CommonSettings from './CommonSettings';
|
|
187
|
+
import { SCENT_TEXT_OBJ } from './const';
|
|
188
|
+
import RewardAdNovelExb from './RewardAdNovelExb';
|
|
189
|
+
|
|
190
|
+
class RewardAdLaunch extends RewardAdNovelExb {
|
|
191
|
+
_scene = SCENT_TEXT_OBJ.launch_ad; // 广告执行场景
|
|
192
|
+
|
|
193
|
+
constructor(args) {
|
|
194
|
+
super(args);
|
|
195
|
+
this.launchSettings = RewardAdLaunchSettings.new();
|
|
196
|
+
}
|
|
135
197
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
198
|
+
adCloseLister(args) {
|
|
199
|
+
this._clearAdTimeout();
|
|
200
|
+
this._adCloseGlobalRecorder(args);
|
|
201
|
+
this._adCloseSuccessAnalytics({ scene: this._scene, ad_is_completed: args.isEnded ? 1 : 0, ad_count: args.count });
|
|
202
|
+
|
|
203
|
+
this.launchSettings.updateToday(); // 更新今天
|
|
204
|
+
this.launchSettings.updateFrequency();
|
|
205
|
+
const baseArgs = { ...args, scene: this._scene };
|
|
206
|
+
const _end = (ctx) => {
|
|
207
|
+
this.adDestroy();
|
|
208
|
+
this._resolve?.(Object.assign({}, args, { scene: this._scene }, ctx));
|
|
209
|
+
this._resolve = null;
|
|
210
|
+
this._next?.(); // 执行下一个任务的回调函数,以继续执行流程
|
|
211
|
+
this._next = null;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const _circle = () => {
|
|
215
|
+
if (this.launchSettings.remainFrequency() > 0) {
|
|
216
|
+
this._adInner({ options: { scene: this._scene }, collection: { resolve: this._resolve } }, this._next);
|
|
152
217
|
} else {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
218
|
+
_end({ frequency: this.launchSettings.getFrequency() });
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
if (args.isEnded) {
|
|
222
|
+
this.launchSettings.updateFinished();
|
|
223
|
+
if (this.launchSettings.remainFrequency() == 0) {
|
|
224
|
+
this.launchSettings.updateLastFinished(true);
|
|
156
225
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
226
|
+
this._outerFinishedCallback(baseArgs);
|
|
227
|
+
this._onFinish?.(baseArgs);
|
|
228
|
+
} else {
|
|
229
|
+
this._outerHalfwayCallback(baseArgs);
|
|
230
|
+
this._onHalfway?.(baseArgs);
|
|
231
|
+
}
|
|
232
|
+
this._outerCloseCallback();
|
|
233
|
+
_circle();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static build(args) {
|
|
237
|
+
if (!RewardAdLaunch.instance) {
|
|
238
|
+
RewardAdLaunch.instance = new RewardAdLaunch(args);
|
|
239
|
+
}
|
|
240
|
+
return RewardAdLaunch.instance;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
static getInstance() {
|
|
244
|
+
if (!RewardAdLaunch.instance) {
|
|
245
|
+
throw new Error('RewardAdLaunch instance is not init');
|
|
246
|
+
}
|
|
247
|
+
return RewardAdLaunch.instance;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
static new(args) {
|
|
251
|
+
return new RewardAdLaunch(args);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
static ad = new Promise((resolve) => {
|
|
255
|
+
RewardAdLaunch.adResolve = resolve;
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
static satisfy(options, callback) {
|
|
259
|
+
const con = RewardAdLaunchSettings.new().condition();
|
|
260
|
+
if (typeof callback !== 'function') {
|
|
261
|
+
return Promise.resolve();
|
|
160
262
|
}
|
|
263
|
+
return callback(con ? { options } : null);
|
|
161
264
|
}
|
|
265
|
+
|
|
266
|
+
static eventEmitter = new PubSub();
|
|
162
267
|
}
|
|
163
268
|
|
|
164
|
-
|
|
165
|
-
|
|
269
|
+
export default RewardAdLaunch;
|
|
270
|
+
|
|
271
|
+
class RewardAdLaunchSettings {
|
|
272
|
+
_fixedFrequency = null; // 固定展示次数,如果为null, 表示使用配置
|
|
273
|
+
frequency = {
|
|
274
|
+
total: 0,
|
|
275
|
+
current: 0,
|
|
276
|
+
finished: 0,
|
|
277
|
+
lastFinished: false, // 最后一个是否完成
|
|
278
|
+
};
|
|
279
|
+
constructor() {
|
|
280
|
+
this.commonSettings = CommonSettings.new();
|
|
281
|
+
this.countRecorder = CountRecorder.new({
|
|
282
|
+
local_sign: 'launch_count',
|
|
283
|
+
total: this._adTimes(),
|
|
284
|
+
userId: this.commonSettings.getUserId(),
|
|
285
|
+
});
|
|
286
|
+
this.frequency.total = this.timesPerFrequency();
|
|
287
|
+
}
|
|
166
288
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
onError: (error) => console.error('Ad error:', error)
|
|
289
|
+
_adTimes() {
|
|
290
|
+
// 从系统配置中获取启动广告的配置项
|
|
291
|
+
const { inter_site_pop_ups, inter_site_pop_ups_num } = this.commonSettings.getSysConfig();
|
|
292
|
+
// 如果配置存在则返回配置值,否则返回0
|
|
293
|
+
return Number(inter_site_pop_ups) > 0 && inter_site_pop_ups_num >= 1 ? Number(inter_site_pop_ups_num) : 0;
|
|
173
294
|
}
|
|
174
|
-
|
|
295
|
+
|
|
296
|
+
updateToday() {
|
|
297
|
+
this.countRecorder.updateToday();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
updateFrequency() {
|
|
301
|
+
this.frequency.current += 1;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
updateFinished() {
|
|
305
|
+
this.frequency.finished += 1;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
updateLastFinished(v = true) {
|
|
309
|
+
this.frequency.lastFinished = v;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
remainFrequency() {
|
|
313
|
+
return this.frequency.total - this.frequency.current;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
getFrequency() {
|
|
317
|
+
return Object.assign({}, this.frequency);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
timesPerFrequency() {
|
|
321
|
+
const { inter_site_pop_ups } = this.commonSettings.getSysConfig();
|
|
322
|
+
const ups = this._fixedFrequency ?? Number(inter_site_pop_ups);
|
|
323
|
+
const count = Math.min(Math.max(0, Number(ups)), this._remain());
|
|
324
|
+
return Math.max(0, count);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
_remain() {
|
|
328
|
+
return this.countRecorder.remain();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
condition() {
|
|
332
|
+
const remain = this._remain();
|
|
333
|
+
return Number(remain) > 0 && this.timesPerFrequency() > 0;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
static new(args) {
|
|
337
|
+
return new RewardAdLaunchSettings(args);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
175
340
|
```
|
|
176
341
|
|
|
177
|
-
|
|
342
|
+
### 2. Interstitial Ad
|
|
343
|
+
|
|
344
|
+
```javascript
|
|
345
|
+
// 启动插屏广告
|
|
346
|
+
import AdExecuteManager, { CountRecorder, Logger } from '@singcl/ad-execute-manager';
|
|
347
|
+
import { matchErrorWithKeywords, getCurrentPageInterScene } from './_utils';
|
|
348
|
+
import { SCENT_TEXT_OBJ } from './const';
|
|
349
|
+
import InterstitialAdNovelExb from './InterstitialAdNovelExb';
|
|
350
|
+
import RewardAdGlobalRecorder from './RewardAdGlobalRecorder';
|
|
351
|
+
import CommonSettings from './CommonSettings';
|
|
352
|
+
|
|
353
|
+
class InterstitialAdNormal extends InterstitialAdNovelExb {
|
|
354
|
+
_scene = SCENT_TEXT_OBJ.other;
|
|
355
|
+
_launchGap = 30 * 1000;
|
|
356
|
+
_adBetweenGap = 60 * 1000;
|
|
357
|
+
_timer = null;
|
|
358
|
+
_adClose = 20000;
|
|
359
|
+
_backgroundRetryTime = 3000; // app在后台时,重试间隔时间
|
|
360
|
+
_foregroundRetryTime = 5000; // app在前台时,重试间隔时间
|
|
361
|
+
|
|
362
|
+
constructor(args) {
|
|
363
|
+
super(args);
|
|
364
|
+
this.logger = new Logger({ prefix: InterstitialAdNormal.name });
|
|
365
|
+
this.commonSettings = CommonSettings.new();
|
|
366
|
+
this.countRecorder = CountRecorder.new({
|
|
367
|
+
local_sign: 'interstitial_show_count',
|
|
368
|
+
total: this.commonSettings.getCpAdDetails().dayAd,
|
|
369
|
+
userId: this.commonSettings.getUserId(),
|
|
370
|
+
});
|
|
371
|
+
this._launchGap = this.commonSettings.getCpAdDetails().firstAdGap * 1000;
|
|
372
|
+
this._adBetweenGap = this.commonSettings.getCpAdDetails().secondAdGap * 1000;
|
|
373
|
+
this._adClose = this.commonSettings.getCpAdDetails().adClose ?? 20000;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
_adCloseSuccessAnalytics(_args) {
|
|
377
|
+
// ExbAnalyticsJS.getInstance().track('incentive_ad_close', {
|
|
378
|
+
// scene: _args.scene,
|
|
379
|
+
// ad_is_completed: _args.ad_is_completed,
|
|
380
|
+
// });
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
_onInnerAdShowSuccess() {
|
|
384
|
+
this.countRecorder.updateToday(); // 更新今日展示次数
|
|
385
|
+
if (this._adClose) {
|
|
386
|
+
setTimeout(() => {
|
|
387
|
+
this.adCloseLister();
|
|
388
|
+
}, this._adClose);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
async launch() {
|
|
393
|
+
const recordIns = RewardAdGlobalRecorder.getInstance();
|
|
394
|
+
const launchAdLastShowTime = recordIns.launchAdLastShowTime;
|
|
395
|
+
const startLaunchTime = Math.max(this._launchGap - (new Date().getTime() - launchAdLastShowTime), 0);
|
|
396
|
+
|
|
397
|
+
const circle = () => {
|
|
398
|
+
return new Promise((resolve) => {
|
|
399
|
+
const _fn = async () => {
|
|
400
|
+
await AdExecuteManager.getInstance().whenAllTasksComplete();
|
|
401
|
+
const nowTime = new Date().getTime();
|
|
402
|
+
const rewardAdLastShowTime = recordIns.rewardAdLastShowTime;
|
|
403
|
+
const interstitialAdLastShowTime = recordIns.interstitialAdLastShowTime;
|
|
404
|
+
|
|
405
|
+
const remain = Math.max(
|
|
406
|
+
this._adBetweenGap - (nowTime - Math.max(rewardAdLastShowTime, interstitialAdLastShowTime)),
|
|
407
|
+
0
|
|
408
|
+
);
|
|
409
|
+
if (remain > 0) {
|
|
410
|
+
setTimeout(_fn, remain);
|
|
411
|
+
} else {
|
|
412
|
+
resolve();
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
_fn();
|
|
416
|
+
});
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
const fn2 = async (t) => {
|
|
420
|
+
this._timer = setTimeout(async () => {
|
|
421
|
+
if (this.countRecorder.remain() <= 0) {
|
|
422
|
+
clearTimeout(this._timer);
|
|
423
|
+
this._timer = null;
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
await circle();
|
|
427
|
+
let res = null;
|
|
428
|
+
if (this.getAppDisplayStatus() === 'hide') {
|
|
429
|
+
const msg = `app in background: pause ad show, interstitial ad, time retry: ${this._backgroundRetryTime}ms`;
|
|
430
|
+
this.logger.log(msg);
|
|
431
|
+
res = {
|
|
432
|
+
apiError: {
|
|
433
|
+
errMsg: msg,
|
|
434
|
+
errorCode: 110000,
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
this.record(res);
|
|
438
|
+
} else {
|
|
439
|
+
this.logger.log(`Ad 进入队列,即将播放,GAP: ${this._adBetweenGap}ms`);
|
|
440
|
+
res = await this.addExecuteManager({
|
|
441
|
+
options: { retry: 0, scene: getCurrentPageInterScene() || this._scene },
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
if (res && !res.apiError) {
|
|
445
|
+
clearTimeout(this._timer);
|
|
446
|
+
this._timer = null;
|
|
447
|
+
fn2(this._adBetweenGap);
|
|
448
|
+
} else {
|
|
449
|
+
const e = res?.apiError;
|
|
450
|
+
if (matchErrorWithKeywords(this._ttErrorMsgs, e?.errMsg) || this._ttErrorCodes.includes(e?.errorCode)) {
|
|
451
|
+
clearTimeout(this._timer);
|
|
452
|
+
this._timer = null;
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
setTimeout(
|
|
456
|
+
() => {
|
|
457
|
+
clearTimeout(this._timer);
|
|
458
|
+
this._timer = null;
|
|
459
|
+
fn2(0);
|
|
460
|
+
},
|
|
461
|
+
this.getAppDisplayStatus() === 'hide' ? this._backgroundRetryTime : this._foregroundRetryTime
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
}, t);
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
fn2(startLaunchTime);
|
|
468
|
+
}
|
|
178
469
|
|
|
179
|
-
|
|
470
|
+
getAppDisplayStatus() {
|
|
471
|
+
return RewardAdGlobalRecorder.getInstance().appDisplayStatus;
|
|
472
|
+
}
|
|
180
473
|
|
|
181
|
-
|
|
474
|
+
static build(args) {
|
|
475
|
+
if (!InterstitialAdNormal.instance) {
|
|
476
|
+
InterstitialAdNormal.instance = new InterstitialAdNormal(args);
|
|
477
|
+
}
|
|
478
|
+
return InterstitialAdNormal.instance;
|
|
479
|
+
}
|
|
182
480
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
481
|
+
static getInstance() {
|
|
482
|
+
if (!InterstitialAdNormal.instance) {
|
|
483
|
+
throw new Error('InterstitialAdNormal instance is not init');
|
|
484
|
+
}
|
|
485
|
+
return InterstitialAdNormal.instance;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
static new(args) {
|
|
489
|
+
return new InterstitialAdNormal(args);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export default InterstitialAdNormal;
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### 3. Ad Scene Trigger Manager
|
|
497
|
+
|
|
498
|
+
```javascript
|
|
499
|
+
import { Logger } from '@singcl/ad-execute-manager';
|
|
500
|
+
import { SCENT_TYPE_OBJ } from './const';
|
|
501
|
+
|
|
502
|
+
class RewardAdSceneTriggerManager {
|
|
503
|
+
static instance = null;
|
|
504
|
+
_initSign = ''; // 初始化标识
|
|
505
|
+
_currScene = null; // 当前场景
|
|
506
|
+
|
|
507
|
+
constructor(args) {
|
|
508
|
+
if (RewardAdSceneTriggerManager.instance) {
|
|
509
|
+
return RewardAdSceneTriggerManager.instance;
|
|
510
|
+
}
|
|
511
|
+
this._initSign = args?.sign ?? ''; // 初始化标识
|
|
512
|
+
this.logger = new Logger({ prefix: '' });
|
|
513
|
+
RewardAdSceneTriggerManager.instance = this;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
initialize(args) {
|
|
517
|
+
// 初始化逻辑
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
addScene(value) {
|
|
521
|
+
this.logger.log('-------------AD trigger scene:--------------', value);
|
|
522
|
+
this._currScene = value;
|
|
523
|
+
return this;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
addSceneType(args) {
|
|
527
|
+
this.addScene(SCENT_TYPE_OBJ[args.scene]);
|
|
528
|
+
return this;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
getCurrentScene() {
|
|
532
|
+
return this._currScene;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
placeholder() {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
static build(args) {
|
|
540
|
+
if (!RewardAdSceneTriggerManager.instance) {
|
|
541
|
+
RewardAdSceneTriggerManager.instance = new RewardAdSceneTriggerManager(args);
|
|
542
|
+
}
|
|
543
|
+
return RewardAdSceneTriggerManager.instance;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
static getInstance() {
|
|
547
|
+
if (!RewardAdSceneTriggerManager.instance) {
|
|
548
|
+
throw new Error('RewardAdSceneTriggerManager instance is not init');
|
|
549
|
+
}
|
|
550
|
+
return RewardAdSceneTriggerManager.instance;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
export default RewardAdSceneTriggerManager;
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## API Reference
|
|
558
|
+
|
|
559
|
+
### RewardAdNovel
|
|
560
|
+
|
|
561
|
+
Main class for reward ad implementations, providing a complete solution for reward-based ads.
|
|
562
|
+
|
|
563
|
+
#### Methods
|
|
564
|
+
|
|
565
|
+
- `new(args)`: Create a new instance of RewardAdNovel
|
|
566
|
+
- `build(args)`: Get or create the singleton instance of RewardAdNovel
|
|
567
|
+
- `getInstance()`: Get the singleton instance of RewardAdNovel
|
|
568
|
+
- `initialize(args, callback)`: Initialize the ad with configuration
|
|
569
|
+
- `addExecuteManager(ctx)`: Execute the ad with custom options and callbacks
|
|
570
|
+
- `ad(ctx, next)`: Core ad execution method
|
|
571
|
+
- `adLoad()`: Load the ad
|
|
572
|
+
- `adShow()`: Show the ad
|
|
573
|
+
- `adDestroy()`: Destroy the ad instance
|
|
574
|
+
- `clear()`: Clear all resources
|
|
575
|
+
|
|
576
|
+
### InterstitialAdNovel
|
|
577
|
+
|
|
578
|
+
Main class for interstitial ad implementations, providing a complete solution for interstitial ads.
|
|
579
|
+
|
|
580
|
+
#### Methods
|
|
581
|
+
|
|
582
|
+
- `new(args)`: Create a new instance of InterstitialAdNovel
|
|
583
|
+
- `build(args)`: Get or create the singleton instance of InterstitialAdNovel
|
|
584
|
+
- `getInstance()`: Get the singleton instance of InterstitialAdNovel
|
|
585
|
+
- `initialize(args, callback)`: Initialize the ad with configuration
|
|
586
|
+
- `addExecuteManager(ctx)`: Execute the ad with custom options and callbacks
|
|
587
|
+
- `ad(ctx, next)`: Core ad execution method
|
|
588
|
+
- `adLoad()`: Load the ad
|
|
589
|
+
- `adShow()`: Show the ad
|
|
590
|
+
- `adDestroy()`: Destroy the ad instance
|
|
591
|
+
- `clear()`: Clear all resources
|
|
592
|
+
|
|
593
|
+
### Other Exports
|
|
594
|
+
|
|
595
|
+
- `SerializableError`: Error class that can be serialized
|
|
596
|
+
- `Logger`: Logging utility
|
|
597
|
+
- `Storage`: Storage management
|
|
598
|
+
- `CountRecorder`: Ad execution counter
|
|
599
|
+
- `RewardAdGlobalRecorder`: Global ad recorder
|
|
600
|
+
- `RewardAdSceneTriggerManager`: Scene-based ad trigger manager
|
|
601
|
+
- `AdAnalyticsJS`: Analytics integration
|
|
602
|
+
- `PubSub`: Publish-subscribe pattern implementation
|
|
603
|
+
|
|
604
|
+
## Development Guide
|
|
189
605
|
|
|
190
606
|
### Development Scripts
|
|
191
607
|
|
|
@@ -195,6 +611,22 @@ We welcome contributions to this project! Please follow these steps:
|
|
|
195
611
|
- `npm run format`: Format your code
|
|
196
612
|
- `npm run test`: Run tests
|
|
197
613
|
|
|
614
|
+
### Project Structure
|
|
615
|
+
|
|
616
|
+
```
|
|
617
|
+
src/
|
|
618
|
+
ad/ # Core ad-related code
|
|
619
|
+
helper/ # Helper utilities
|
|
620
|
+
typings/ # Type definitions
|
|
621
|
+
utils/ # Common utilities
|
|
622
|
+
index.js # Entry file
|
|
623
|
+
example/ # Example code
|
|
624
|
+
AdUnlock/ # Ad unlock related examples
|
|
625
|
+
mini_program/ # Mini program examples
|
|
626
|
+
typings/ # Example type definitions
|
|
627
|
+
*.js # Various ad implementation examples
|
|
628
|
+
```
|
|
629
|
+
|
|
198
630
|
## License
|
|
199
631
|
|
|
200
632
|
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
|