@singcl/ad-execute-manager 1.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/README.md ADDED
@@ -0,0 +1,268 @@
1
+ # ad-execute-manager
2
+
3
+ 广告执行管理器是一个用于管理和执行广告任务的JavaScript库,特别适用于激励视频广告的场景化管理和执行。
4
+
5
+ ## 功能特性
6
+
7
+ - **任务管理**:支持广告任务的添加、执行和取消
8
+ - **场景化**:支持不同场景下的广告展示和统计
9
+ - **激励视频**:专注于激励视频广告的管理和执行
10
+ - **回调机制**:提供丰富的回调函数来处理广告的各种状态
11
+ - **统计分析**:集成广告展示和点击的统计分析功能
12
+ - **单例模式**:使用单例模式管理广告实例,确保资源的有效利用
13
+
14
+ ## 目录结构
15
+
16
+ ```
17
+ src/
18
+ ├── ad/ # 广告相关核心代码
19
+ │ ├── AdExecuteManager.js # 广告执行管理器
20
+ │ ├── RewardAdFather.js # 激励视频广告基类
21
+ │ ├── RewardAdNovel.js # 小说场景激励视频广告
22
+ │ ├── RewardAdLaunch.js # 启动场景激励视频广告
23
+ │ ├── RewardAdLaunchAlone.js # 单独启动场景激励视频广告
24
+ │ ├── RewardAdReadingLoad.js # 阅读加载场景激励视频广告
25
+ │ ├── RewardAdReadingUnload.js # 阅读卸载场景激励视频广告
26
+ │ ├── RewardAdSceneTriggerManager.js # 广告场景触发管理器
27
+ │ ├── RewardAdGlobalRecorder.js # 广告全局记录器
28
+ │ ├── LovelUnlockManager.js # 解锁管理器
29
+ │ ├── AdUnlock/ # 广告解锁相关代码
30
+ │ ├── ExbAnalyticsJS.js # 统计分析工具
31
+ │ ├── Storage.js # 存储工具
32
+ │ ├── CountRecorder.js # 计数记录器
33
+ │ ├── Logger.js # 日志工具
34
+ │ ├── SerializableError.js # 可序列化错误
35
+ │ ├── compose.js # 函数组合工具
36
+ │ └── const.js # 常量定义
37
+ ├── typings/ # 类型定义
38
+ │ ├── ad.js # 广告相关类型定义
39
+ │ └── tracker.js # 统计跟踪相关类型定义
40
+ ├── utils/ # 工具函数
41
+ │ └── functional.js # 函数式工具函数
42
+ └── index.js # 入口文件
43
+ ```
44
+
45
+ ## 安装
46
+
47
+ ```bash
48
+ npm install @singcl/ad-execute-manager
49
+ ```
50
+
51
+ ## 快速开始
52
+
53
+ ### 导入
54
+
55
+ ```javascript
56
+ import AdExecuteManager from '@singcl/ad-execute-manager';
57
+ import RewardAdNovel from '@singcl/ad-execute-manager/lib/ad/RewardAdNovel';
58
+ ```
59
+
60
+ ### 创建广告实例
61
+
62
+ ```javascript
63
+ // 创建激励视频广告实例
64
+ const rewardAdNovel = new RewardAdNovel({
65
+ sign: 'novel_ad',
66
+ adConfig: {
67
+ adUnitId: 'your_ad_unit_id',
68
+ multiton: true,
69
+ multitonRewardTimes: 4,
70
+ multitonRewardMsg: ['全部小说免费看'],
71
+ progressTip: true
72
+ },
73
+ collection: {
74
+ onShow: (args) => {
75
+ console.log('广告展示', args);
76
+ },
77
+ onFinish: (args) => {
78
+ console.log('广告看完', args);
79
+ },
80
+ onHalfway: (args) => {
81
+ console.log('广告中途退出', args);
82
+ },
83
+ onError: (error) => {
84
+ console.error('广告错误', error);
85
+ }
86
+ }
87
+ });
88
+ ```
89
+
90
+ ### 执行广告任务
91
+
92
+ ```javascript
93
+ // 获取广告执行管理器实例
94
+ const adManager = AdExecuteManager.getInstance({ log: true });
95
+
96
+ // 添加广告任务
97
+ adManager.addTask(rewardAdNovel, {
98
+ options: {
99
+ scene: 1, // 小说插件强制广告场景
100
+ log: true
101
+ },
102
+ collection: {
103
+ always: (args) => {
104
+ console.log('广告总是回调', args);
105
+ },
106
+ finished: (args) => {
107
+ console.log('广告完成回调', args);
108
+ },
109
+ halfway: (args) => {
110
+ console.log('广告中途回调', args);
111
+ }
112
+ }
113
+ }).then((result) => {
114
+ console.log('广告任务完成', result);
115
+ }).catch((error) => {
116
+ console.error('广告任务失败', error);
117
+ });
118
+ ```
119
+
120
+ ## API 文档
121
+
122
+ ### AdExecuteManager
123
+
124
+ 广告执行管理器,用于管理广告任务的执行流程。
125
+
126
+ #### 静态方法
127
+
128
+ - `getInstance(args)`: 获取单例实例
129
+ - `args`: 配置参数
130
+ - `log`: 是否打印日志
131
+
132
+ #### 实例方法
133
+
134
+ - `addTask(adInstance, ctx)`: 添加广告任务
135
+ - `adInstance`: 广告实例(必须是RewardAdFather的子类)
136
+ - `ctx`: 广告执行上下文
137
+ - `options`: 广告执行选项
138
+ - `collection`: 回调集合
139
+ - 返回: Promise对象
140
+
141
+ - `clearTasks()`: 清空所有任务(包括正在执行的任务)
142
+
143
+ - `getTaskCount()`: 获取当前未完成的任务总数
144
+
145
+ - `isRunning()`: 检查是否有任务正在运行
146
+
147
+ - `getCurrentTaskId()`: 获取当前执行的任务ID
148
+
149
+ ### RewardAdFather
150
+
151
+ 激励视频广告基类,所有具体的激励视频广告类都继承自此类。
152
+
153
+ #### 构造方法
154
+
155
+ - `constructor(args)`: 创建广告实例
156
+ - `args`: 配置参数
157
+ - `sign`: 初始化标识
158
+ - `adConfig`: 广告配置
159
+ - `preserveOnEnd`: 是否保留广告实例
160
+
161
+ #### 实例方法
162
+
163
+ - `initialize(params, callback)`: 初始化广告
164
+ - `params`: 初始化参数
165
+ - `callback`: 初始化成功回调
166
+
167
+ - `ad(ctx, next)`: 执行广告展示(抽象方法,子类必须实现)
168
+ - `ctx`: 广告执行上下文
169
+ - `next`: 执行下一个任务的回调函数
170
+
171
+ - `addExecuteManager(ctx)`: 确保广告按顺序执行
172
+
173
+ - `destroy()`: 销毁广告实例
174
+
175
+ - `show()`: 显示广告
176
+
177
+ - `load()`: 加载广告
178
+
179
+ - `onClose(callback)`: 监听广告关闭事件
180
+
181
+ - `onError(callback)`: 监听广告错误事件
182
+
183
+ - `onLoad(callback)`: 监听广告加载事件
184
+
185
+ ### RewardAdNovel
186
+
187
+ 小说场景激励视频广告实现类。
188
+
189
+ #### 静态方法
190
+
191
+ - `build(args)`: 创建并获取单例实例
192
+
193
+ - `getInstance()`: 获取单例实例
194
+
195
+ - `new(args)`: 创建新实例
196
+
197
+ ## 广告场景类型
198
+
199
+ | 场景值 | 场景名称 | 说明 |
200
+ | --- | --- | --- |
201
+ | 0 | launch_ad | 启动广告 |
202
+ | 1 | novel_plugin_strong_ad | 小说插件强制广告 |
203
+ | 2 | novel_plugin_unlock_btn | 小说插件解锁按钮 |
204
+ | 3 | novel_plugin_free_benefit_btn | 小说插件免费福利按钮 |
205
+ | 4 | home_free_welfare_btn | 首页免费福利按钮 |
206
+ | 5 | home_free_popup | 首页免费弹窗 |
207
+ | 6 | other | 其他场景 |
208
+ | 7 | home_back_show | 首页返回展示 |
209
+ | 8 | novel_plugin_free_time_btn | 小说插件免费时间按钮 |
210
+ | 9 | launch_ad_alone | 单独启动广告 |
211
+
212
+ ## 回调集合
213
+
214
+ ### CallbackCollection
215
+
216
+ | 回调函数 | 说明 |
217
+ | --- | --- |
218
+ | always | 每次广告结束时都会调用 |
219
+ | finished | 完整看完广告时调用 |
220
+ | halfway | 半途退出广告时调用 |
221
+ | complete | 完成广告时调用(不管是否看完) |
222
+ | onCancel | 取消广告时调用 |
223
+ | before | 展示广告前调用 |
224
+ | success | 展示广告成功时调用 |
225
+ | prelude | 计时回调 |
226
+
227
+ ## 开发
228
+
229
+ ### 构建
230
+
231
+ ```bash
232
+ npm run build
233
+ ```
234
+
235
+ ### 开发模式
236
+
237
+ ```bash
238
+ npm run dev
239
+ ```
240
+
241
+ ### 代码格式化
242
+
243
+ ```bash
244
+ npm run format
245
+ ```
246
+
247
+ ### 代码检查
248
+
249
+ ```bash
250
+ npm run lint
251
+ ```
252
+
253
+ ### 测试
254
+
255
+ ```bash
256
+ npm run test
257
+ ```
258
+
259
+ ## 依赖
260
+
261
+ - @rslib/core: 用于项目构建
262
+ - @rstest/core: 用于测试
263
+ - eslint: 用于代码检查
264
+ - prettier: 用于代码格式化
265
+
266
+ ## 许可证
267
+
268
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";const __rslib_import_meta_url__="u"<typeof document?new(require("url".replace("",""))).URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href;var __webpack_require__={};__webpack_require__.d=(e,t)=>{for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{RewardAdNovel:()=>ad_RewardAdNovel,RewardAdFather:()=>ad_RewardAdFather,default:()=>src,AdExecuteManager:()=>ad_AdExecuteManager,Storage:()=>ad_Storage,ExbAnalyticsJS:()=>ad_ExbAnalyticsJS});const compose=e=>e.map(e=>(t,r)=>async s=>await e(Object.assign({},t,s),r)).reduce((e,t)=>(r,s)=>e(r,t(r,s))),ad_compose=compose;class Logger{constructor(e={}){const{prefix:t="Logger",level:r="info",enabled:s=!0}=e;this.prefix=t,this.enabled=s,this.levels={error:0,warn:1,info:2,debug:3},this.currentLevel=this.levels[r]||this.levels.info}enable(){this.enabled=!0}disable(){this.enabled=!1}isEnabled(){return this.enabled}setLevel(e){Object.prototype.hasOwnProperty.call(this.levels,e)&&(this.currentLevel=this.levels[e])}formatMessage(e,t){let r=new Date().toLocaleString();return`[${r}] [${e.toUpperCase()}] [${this.prefix}] ${t}`}_log(e,t,...r){if(!this.enabled)return;let s=this.levels[e];if(void 0!==s&&this.currentLevel>=s){let s=this.formatMessage(e,t);switch(e){case"error":console.error(s,...r);break;case"warn":console.warn(s,...r);break;case"info":console.info(s,...r);break;case"debug":console.debug(s,...r);break;default:console.log(s,...r)}}}error(e,...t){this._log("error",e,...t)}warn(e,...t){this._log("warn",e,...t)}info(e,...t){this._log("info",e,...t)}debug(e,...t){this._log("debug",e,...t)}log(e,t,...r){this._log(e,t,...r)}}class AdExecuteManager{static _instance=null;_taskStack=[];_currentBatchTasks=[];_isRunning=!1;_currentTask=null;constructor(e){if(this.logger=new Logger({prefix:"AdExecuteManager",enabled:!!e?.log}),AdExecuteManager._instance)return AdExecuteManager._instance;AdExecuteManager._instance=this}static getInstance(e){return AdExecuteManager._instance||(AdExecuteManager._instance=new AdExecuteManager(e)),AdExecuteManager._instance}addTask(e,t){return e&&"function"==typeof e.ad?new Promise((r,s)=>{let i={adInstance:e,options:t.options??{},callbackCollection:t.collection??{},resolve:r,reject:s,id:`ad_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,_isResolved:!1,_isRejected:!1};this._taskStack.push(i),this._isRunning||this._compose()}):(this.logger.error("无效的广告实例 请正确实现.ad方法"),Promise.reject(Error("无效的广告实例")))}_compose(){if(0===this._taskStack.length){this._isRunning=!1,this._currentTask=null;return}this._isRunning=!0;let e=[...this._taskStack];this._taskStack=[],this._currentBatchTasks=e;let t=e.map(e=>async(t,r)=>{let{adInstance:s,options:i,callbackCollection:n,resolve:a,id:o}=e;if(e._isResolved||e._isRejected)return void await r(t);this._currentTask=e;try{let l=async e=>{await r(Object.assign({},t,e))},c=await s.initialize(i).ad({options:i,collection:n},l),d=Object.assign({id:o},c);this.logger.info(`任务执行成功,成功信息:${JSON.stringify(d)}`),e._isResolved=!0,a(d)}catch(n){let i=Object.assign({id:o,apiError:n});this.logger.error(`任务执行失败, 继续下一个任务,错误信息:${JSON.stringify(i)}`),e._isRejected=!0;try{s?.clear()}catch(e){this.logger.error("clear error: ",JSON.stringify(Object.assign({id:o,apiError:e})))}a(i),await r(t)}}),r={roundTasks:t.length};compose(t)(r,async e=>{this.logger.info("本轮活动队列已经清空",e),this._taskStack.length>0?Promise.resolve().then(()=>{this._compose()}):(this._isRunning=!1,this._currentTask=null,this._currentBatchTasks=[])})()}clearTasks(){if(this._currentTask){if(this._currentTask._isResolved||this._currentTask._isRejected){this._currentTask=null;return}try{this._currentTask.callbackCollection&&this._currentTask.callbackCollection.onCancel&&this._currentTask.callbackCollection.onCancel(),this._currentTask._isResolved=!0,this._currentTask.resolve()}catch(e){this.logger.error("clear current task error: ",e)}this._currentTask=null}this._currentBatchTasks.length>0&&(this._currentBatchTasks.forEach(e=>{if(e!==this._currentTask&&!e._isResolved&&!e._isRejected)try{e.callbackCollection&&e.callbackCollection.onCancel&&e.callbackCollection.onCancel(),e._isResolved=!0,e.resolve()}catch(e){this.logger.error("clear current batch task error: ",e)}}),this._currentBatchTasks=[]),this._taskStack.forEach(e=>{if(!e._isResolved&&!e._isRejected&&(e._isResolved=!0,e.resolve(),e.callbackCollection&&e.callbackCollection.onCancel))try{e.callbackCollection.onCancel()}catch(e){this.logger.error("clear task error: ",e)}}),this._taskStack=[],this._isRunning=!1}getTaskCount(){return this._taskStack.filter(e=>!e._isResolved&&!e._isRejected).length+this._currentBatchTasks.filter(e=>e!==this._currentTask&&!e._isResolved&&!e._isRejected).length+(!this._currentTask||this._currentTask._isResolved||this._currentTask._isRejected?0:1)}isRunning(){return this._isRunning}getCurrentTaskId(){return this._currentTask?.id||null}}const ad_AdExecuteManager=AdExecuteManager;class SerializableError extends Error{constructor(e){super(e),this.name=this.constructor.name,this.stack=Error(e).stack,Object.defineProperty(this,"message",{enumerable:!0}),Object.defineProperty(this,"name",{enumerable:!0}),Object.defineProperty(this,"stack",{enumerable:!0})}toJSON(){return{name:this.name,message:this.message,stack:this.stack}}}class RewardAdFather{static args=null;_initSign="";_preserveOnEnd=!1;_rewardAd=null;_ttErrorMsgs=["The adUnitId is closed","The adUnitId is prohibit","The adUnitId is invalid","The adUnitId is empty","feature is not supported in app"];_ttErrorCodes=[139902,123302];constructor(e){this._initSign=e?.sign??"",this._adConfig=e?.adConfig??{},this._preserveOnEnd=e?.preserveOnEnd??!1}initialize(e,t){if(this._rewardAd)return console.warn("RewardAdFather: rewardAd has been initialized"),t?.(this._rewardAd),this;let r=Object.assign({},RewardAdFather.args,this._adConfig,e);if(!r.adUnitId)throw console.error("[RewardAdFather] reward args adUnitId is required",r),new SerializableError("[RewardAdFather] reward args adUnitId is required");return this._rewardAd=tt.createRewardedVideoAd(r),t?.(this._rewardAd),this}initialized(){return!!this._rewardAd}async ad(e,t=null){throw Error("子类必须实现ad方法")}async addExecuteManager(e){let t=Object.assign({},this._adConfig,e?.options??{});return RewardAdFather.executeWithManager(this,Object.assign({},e,{options:t}))}destroy(){this._rewardAd&&!this._preserveOnEnd&&(this._rewardAd.destroy(),this._rewardAd=null)}clear(){throw Error("子类必须实现clear方法")}onClose(e){this._rewardAd&&this._rewardAd.onClose(e)}offClose(e){this._rewardAd&&this._rewardAd.offClose(e)}show(){return this._rewardAd?this._rewardAd.show():Promise.reject({errMsg:"rewardAd is null"})}load(){if(this._rewardAd)return this._rewardAd.load()}onError(e){this._rewardAd&&this._rewardAd.onError(e)}offError(e){this._rewardAd&&this._rewardAd.offError(e)}onLoad(e){this._rewardAd&&this._rewardAd.onLoad(e)}offLoad(e){this._rewardAd&&this._rewardAd.offLoad(e)}placeholder(){return null}static buildArgs(e){e?.adUnitId||console.error("[RewardAdFather] RewardParams.adUnitId is required"),RewardAdFather.args=e}static async executeWithManager(e,t){return e&&e instanceof RewardAdFather?ad_AdExecuteManager.getInstance({log:t?.options?.log??!0}).addTask(e,t):(console.error("RewardAdFather: executeWithManager - 无效的广告实例"),Promise.reject(Error("无效的广告实例")))}}const ad_RewardAdFather=RewardAdFather;function matchErrorWithKeywords(e,t){return!!t&&e.some(e=>RegExp(e,"i").test(t))}function findAdTypeBySceneFlag(e,t,r="showTimes"){if(!Array.isArray(e))return console.error("第一个参数必须是数组"),null;let s=e.find(e=>e&&e.adSceneFlag===t);return s?s[r]:null}class CommonSettings{static instance=null;_initSign="";constructor(e){this._initSign=e?.sign??"",this._loginInfo=e?.loginInfo??{}}getUserConfig(){let e=this._loginInfo.getAppUnlockConfig()??[];return{is_unlock_all:0,max_tan_ad_num:e.replayTimes??0,look_jlsp_num:e.requiredVideos??1,ad_unlock_chapter_num:e.unlockAble??2,jlsp_is_look_complete:e.requireFullWatch??1}}getUserInfo(){let e=this._loginInfo.getUserInfo();return Object.assign({},e,{id:e?.appUserId??-1,user_type:e?.versionType??0,user_ab:e?.userAb??0})}getSysConfig(){let e=this._loginInfo.getUserAdConfig().appAdStrategyList||[],t=findAdTypeBySceneFlag(e,"read_other","showTimes"),r=findAdTypeBySceneFlag(e,"inter_site_pop_ups_num","showTimes")||0,s=findAdTypeBySceneFlag(e,"inter_site_pop_ups","showTimes")||0,i=findAdTypeBySceneFlag(e,"read_page_back_ad","showTimes"),n=findAdTypeBySceneFlag(e,"first_user_day","showTimes");return{free_incentive_frequency:t?Math.max(Number(t),0):0,inter_site_pop_ups:s,inter_site_pop_ups_num:r,read_page_back_ad:i?Math.max(Number(i),0):0,first_user_day:n?Math.max(Number(n),0):0}}getUserId(){let e=this.getUserInfo();return e?.id??null}getUserAB(){return Number(this.getUserInfo()?.user_ab??0)}placeholder(){return null}static build(e){return CommonSettings.instance||(CommonSettings.instance=new CommonSettings(e)),CommonSettings.instance}static getInstance(){if(!CommonSettings.instance)throw Error("CommonSettings instance is not init");return CommonSettings.instance}static new(e){return CommonSettings.build(e)}}const ad_CommonSettings=CommonSettings;class ExbAnalyticsJS{static instance=null;_initSign="";_needReport=!1;commonSettings=null;constructor(e){if(ExbAnalyticsJS.instance)return ExbAnalyticsJS.instance;this._initSign=e?.sign??"",this._needReport=e?.needReport??!1,this.commonSettings=CommonSettings.new(e),ExbAnalyticsJS.instance=this}initialize(e){return this._needReport?e:void console.warn("ExbAnalyticsJS needReport is false, do not report")}track(e,t,r){if(!this._needReport)return;if(!e)throw Error("eventName is required");let s=Object.assign({},this._getCommonUserInfo(),t),i=r?.sign??"track";console.log(`-------------${i}-----------------------:`,e,s),tt.reportAnalytics(e,s)}_getCommonUserInfo(){let{id:e,user_type:t,user_ab:r}=this.commonSettings?.getUserInfo()??{};return{user_id:e,user_type:t,user_group:r}}identify(){return null}alias(){return null}pages(){return null}page(e,t){this.track(e,t,{sign:"page"})}cpage(e){return this.page("cpage",e)}placeholder(){return null}static build(e){return ExbAnalyticsJS.instance||(ExbAnalyticsJS.instance=new ExbAnalyticsJS(e)),ExbAnalyticsJS.instance}static getInstance(){if(!ExbAnalyticsJS.instance)throw Error("ExbAnalyticsJS instance is not init");return ExbAnalyticsJS.instance}static new(e){return new ExbAnalyticsJS(e)}}const ad_ExbAnalyticsJS=ExbAnalyticsJS,SCENT_TYPE_OBJ={0:"launch_ad",1:"novel_plugin_strong_ad",2:"novel_plugin_unlock_btn",3:"novel_plugin_free_benefit_btn",4:"home_free_welfare_btn",5:"home_free_popup",6:"other",7:"home_back_show",8:"novel_plugin_free_time_btn",9:"launch_ad_alone"},SCENT_TEXT_OBJ=Object.entries(SCENT_TYPE_OBJ).reduce((e,[t,r])=>(e[r]=Number(t),e),{});class RewardAdSceneTriggerManager{static instance=null;_initSign="";_currScene=null;constructor(e){if(RewardAdSceneTriggerManager.instance)return RewardAdSceneTriggerManager.instance;this._initSign=e?.sign??"",RewardAdSceneTriggerManager.instance=this}initialize(e){}addScene(e){return console.log("----------------------AD触发场景:--------------------",e),this._currScene=e,this}addSceneType(e=1){return this.addScene(SCENT_TYPE_OBJ[e]),this}getCurrentScene(){return this._currScene}placeholder(){return null}static build(e){return RewardAdSceneTriggerManager.instance||(RewardAdSceneTriggerManager.instance=new RewardAdSceneTriggerManager(e)),RewardAdSceneTriggerManager.instance}static getInstance(){if(!RewardAdSceneTriggerManager.instance)throw Error("RewardAdSceneTriggerManager instance is not init");return RewardAdSceneTriggerManager.instance}}const ad_RewardAdSceneTriggerManager=RewardAdSceneTriggerManager;class RewardAdGlobalRecorder{static instance=null;_initSign="";_halfway=[{scene:SCENT_TEXT_OBJ.other,count:0}];_finished=[{scene:SCENT_TEXT_OBJ.other,count:0}];constructor(e){if(RewardAdGlobalRecorder.instance)return RewardAdGlobalRecorder.instance;this._initSign=e?.sign??"",RewardAdGlobalRecorder.instance=this}initialize(e){}_halfwayUpdate(e){let t=this._halfway.find(t=>t.scene===e.scene);t?t.count+=1:this._halfway.push({scene:e.scene,count:1})}_halfwayGet(e){let t=e?.scenes??[];return(t.length>0?this._halfway.filter(e=>t.includes(e.scene)):this._halfway).reduce((e,t)=>e+t.count,0)}_halfwayReset(){this._halfway=[{scene:SCENT_TEXT_OBJ.other,count:0}]}_finishedUpdate(e){let t=this._finished.find(t=>t.scene===e.scene);t?t.count+=1:this._finished.push({scene:e.scene,count:1})}_finishedGet(e){let t=e?.scenes??[];return(t.length>0?this._finished.filter(e=>t.includes(e.scene)):this._finished).reduce((e,t)=>e+t.count,0)}_finishedReset(){this._finished=[{scene:SCENT_TEXT_OBJ.other,count:0}]}record(e){switch(e.type){case"halfway":this._halfwayUpdate(e);break;case"finished":this._finishedUpdate(e)}}rest(e){switch(e){case"halfway":this._halfwayReset();break;case"finished":this._finishedReset()}}get(e){switch(e.type){case"halfway":return this._halfwayGet(e);case"finished":return this._finishedGet(e);default:return null}}placeholder(){return null}static build(e){return RewardAdGlobalRecorder.instance||(RewardAdGlobalRecorder.instance=new RewardAdGlobalRecorder(e)),RewardAdGlobalRecorder.instance}static getInstance(){if(!RewardAdGlobalRecorder.instance)throw Error("RewardAdGlobalRecorder instance is not init");return RewardAdGlobalRecorder.instance}}const ad_RewardAdGlobalRecorder=RewardAdGlobalRecorder;class RewardAdNovel extends ad_RewardAdFather{_onHalfway=null;_onShow=null;_onFinish=null;_onAlways=null;_onError=null;_initSign="";_alwaysCallback=null;_halfwayCallback=null;_finishedCallback=null;_resolve=null;_next=null;_scene=SCENT_TEXT_OBJ.other;_adTimeout=null;_adTimeoutTime=8e3;_adBeforeShowTimer=null;_adBeforeShowTime=300;bindAdCloseLister=this.adCloseLister.bind(this);bindAdErrorLister=this.adErrorLister.bind(this);bindAdLoadLister=this.adLoadLister.bind(this);bindApiAdErrorLister=this.apiAdErrorLister.bind(this);_bindShiftCloseLister=this._shiftCloseLister.bind(this);_bindShiftErrorLister=this._shiftErrorLister.bind(this);constructor(e){const t=Object.assign({},RewardAdNovelConfig.new().options(),e?.adConfig),r=Object.assign({},e,{adConfig:t});super(r),this._initSign=r?.sign??"",this._adConfig=r?.adConfig??{},this._onHalfway=r?.collection?.onHalfway??null,this._onShow=r?.collection?.onShow??null,this._onFinish=r?.collection?.onFinish??null,this._onAlways=r?.collection?.onAlways??null,this._onError=r?.collection?.onError??null}initialize(e,t){return super.initialize(e,t),this._initAdLister(),this._initNovelConfig(e),this}_initAdLister(){this.onClose(this.bindAdCloseLister),this.onError(this.bindAdErrorLister),this.onLoad(this.bindAdLoadLister),tt.onError(this.bindApiAdErrorLister)}_initNovelConfig(e){this.novelConfig=RewardAdNovelConfig.new({retry:e?.retry})}_onInnerExecuteBefore(){return null}_onInnerAdShowSuccess(){return null}_clearAdTimeout(){this._adTimeout&&(clearTimeout(this._adTimeout),this._adTimeout=null),this._adBeforeShowTimer&&(clearTimeout(this._adBeforeShowTimer),this._adBeforeShowTimer=null)}get rewardAd(){return this._rewardAd}addExecuteManager(e){return super.addExecuteManager(e)}ad(e,t=null){return this._alwaysCallback=e?.collection?.always,this._halfwayCallback=e?.collection?.halfway,this._finishedCallback=e?.collection?.finished,this._onInnerExecuteBefore(),new Promise(r=>{this._adInner({options:{scene:e?.options?.scene},collection:{resolve:r,before:e.collection?.before,success:e.collection?.success,prelude:e.collection?.prelude}},t)})}_adInner(e,t=null){let r=e?.collection?.resolve,s=e?.options?.scene??this._scene??SCENT_TEXT_OBJ.other,i=e?.collection?.before,n=e?.collection?.success,a=e?.collection?.prelude,o=e=>{this._clearAdTimeout(),this.adDestroy(),r?.(Object.assign({scene:s},e?.resolvedValue)),t?.(Object.assign({scene:s},e?.nextValue))},l=()=>{this._scene=s,i?.({scene:s}),this._before=i,this._onShow?.({scene:s}),RewardAdSceneTriggerManager.getInstance().addSceneType(s),this._resolve=r,this._next=t,this._adTimeout=setTimeout(()=>{console.warn("[RewardAdNovel] Ad show timeout, handling fallback ad case"),ad_ExbAnalyticsJS.getInstance().track("incentive_ad_show",{scene:s,result:0,msg:"ad_show_timeout"}),o({resolvedValue:{apiError:{errMsg:"ad_show_timeout"}},nextValue:null})},this._adTimeoutTime),a?.({scene:s,frequency:this._adBeforeShowTime,time:new Date().getTime()}),this._adBeforeShowTimer=setInterval(()=>{a?.({scene:s,frequency:this._adBeforeShowTime,time:new Date().getTime()})},this._adBeforeShowTime),this.adShow().then(()=>{this._clearAdTimeout(),n?.({scene:s}),this._success=n,ad_ExbAnalyticsJS.getInstance().track("incentive_ad_show",{scene:s,result:1}),this._onInnerAdShowSuccess()}).catch(e=>{(this._clearAdTimeout(),ad_ExbAnalyticsJS.getInstance().track("incentive_ad_show",{scene:s,result:0,msg:e?.errMsg}),matchErrorWithKeywords(this._ttErrorMsgs,e?.errMsg)||this._ttErrorCodes.includes(e?.errorCode))?o({scene:s,resolvedValue:{apiError:e},nextValue:null}):0>=this.novelConfig.remain()?o({scene:s,resolvedValue:null,nextValue:null}):(this.novelConfig.updateRetry(),this.adLoad().then(()=>{ad_ExbAnalyticsJS.getInstance().track("incentive_ad_load",{scene:s,result:1}),l()}).catch(e=>{ad_ExbAnalyticsJS.getInstance().track("incentive_ad_load",{scene:s,result:0}),o({scene:s,resolvedValue:{apiError:e},nextValue:null})}))})};l()}adLoad(){return this.load()}adShow(){return this.show()}_outerCloseCallback(e){this._alwaysCallback?.(e)}_outerHalfwayCallback(e){this._halfwayCallback?.(e)}_outerFinishedCallback(e){this._finishedCallback?.(e)}adCloseLister(e){this._clearAdTimeout(),RewardAdGlobalRecorder.getInstance().record({type:e.isEnded?"finished":"halfway",scene:this._scene}),ad_ExbAnalyticsJS.getInstance().track("incentive_ad_close",{scene:this._scene,ad_is_completed:+!!e.isEnded,ad_count:e.count});let t={...e,scene:this._scene},r=t=>{this.adDestroy(),this._resolve?.(Object.assign({},e,{scene:this._scene},t)),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null};e?.isEnded?(this._outerFinishedCallback(t),this._onFinish?.(t)):(this._outerHalfwayCallback(t),this._onHalfway?.(t)),this._outerCloseCallback(t),this._onAlways?.(t),r({end_type:e.isEnded?"finished":"halfway"})}adErrorLister(e){this._clearAdTimeout(),console.error("[RewardAdNovel] adErrorLister",JSON.stringify(e)),this.adDestroy(),this._onError?.(e),this._resolve?.({apiError:e}),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}apiAdErrorLister(e){this._clearAdTimeout(),console.error("[API RewardAdNovel] apiAdErrorLister:",JSON.stringify(e)),this.adDestroy(),this._onError?.(e),this._resolve?.({apiError:e}),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}adLoadLister(){}adDestroy(){this.offClose(this.bindAdCloseLister),this.offError(this.bindAdErrorLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.destroy()}clear(){this._clearAdTimeout(),this.offClose(this.bindAdCloseLister),this.offClose(this._bindShiftCloseLister),this.offError(this.bindAdErrorLister),this.offError(this._bindShiftErrorLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.destroy(),this._resolve=null,this._next=null,this._success=null,this._before=null}_shiftCloseLister(e){this._clearAdTimeout(),this.offError(this._bindShiftErrorLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.offClose(this._bindShiftCloseLister),this.destroy(),this._resolve?.(Object.assign({},e,{scene:this._scene})),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}_shiftErrorLister(e){this._clearAdTimeout(),this.offClose(this._bindShiftCloseLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.offError(this._bindShiftErrorLister),this.destroy(),this._resolve?.(Object.assign({},e,{scene:this._scene})),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}shift(){this.offClose(this.bindAdCloseLister),this.onClose(this._bindShiftCloseLister),this.offError(this.bindAdErrorLister),this.onError(this._bindShiftErrorLister)}static build(e){return RewardAdNovel.instance||(RewardAdNovel.instance=new RewardAdNovel(e)),RewardAdNovel.instance}static getInstance(){if(!RewardAdNovel.instance)throw Error("RewardAdNovel instance is not init");return RewardAdNovel.instance}static new(e){return new RewardAdNovel(e)}}class RewardAdNovelConfig{free_incentive_frequency=0;frequency={total:0,current:0};constructor(e){this.commonSettings=CommonSettings.new(),this._init(e)}_init(e){this._adTimes(e)}_adTimes(e){this.frequency.total=e?.retry??4;let{free_incentive_frequency:t=0}=this.commonSettings.getSysConfig();this.free_incentive_frequency=Math.min(4,Math.max(0,Number(t)))}reset(){this.frequency.current=0}updateRetry(){this.frequency.current=this.frequency.current+1}remain(){return this.frequency.total-this.frequency.current}options(){return this.free_incentive_frequency>0?{multiton:!0,multitonRewardTimes:this.free_incentive_frequency,multitonRewardMsg:["全部小说免费看"],progressTip:!0}:{}}static new(e){return new RewardAdNovelConfig(e)}}const ad_RewardAdNovel=RewardAdNovel;class Storage{_commonSettings=null;constructor(e={}){this.config={prefix:"storage_",expire:null,...e},this._commonSettings=CommonSettings.new()}getTodayEndTimestamp(){let e=new Date;return new Date(e.getFullYear(),e.getMonth(),e.getDate(),23,59,59,999).getTime()}_setItem(e,t,r){let s=void 0!==r?r:this.config.expire;"today"===s&&(s=this.getTodayEndTimestamp()-Date.now());let i={value:t,expire:s,timestamp:Date.now()};try{tt.setStorageSync(e,JSON.stringify(i))}catch(e){console.error("Storage setItem error:",e)}}_getItem(e){try{let t=tt.getStorageSync(e);if(!t)return null;let r=JSON.parse(t);if(r.expire&&Date.now()-r.timestamp>r.expire)return this.removeItem(e),null;return r.value}catch(e){return console.error("Storage getItem error:",e),null}}setItem(e,t,r){let s=this.config.prefix+e;return this._setItem(s,t,r)}getItem(e){let t=this.config.prefix+e;return this._getItem(t)}getUserItem(e){let t=this._commonSettings.getUserId()??"null",r=`${this.config.prefix}_${t}_${e}`;return this._getItem(r)}setUserItem(e,t,r){let s=this._commonSettings.getUserId()??"null",i=`${this.config.prefix}_${s}_${e}`;return this._setItem(i,t,r)}removeItem(e){try{tt.removeStorageSync(e)}catch(e){console.error("Storage removeItem error:",e)}}clear(){try{tt.clearStorageSync()}catch(e){console.error("Storage clear error:",e)}}keys(){try{let e=[];return(tt.getStorageInfoSync().keys??[]).forEach(t=>{if(t.startsWith(this.config.prefix)){let r=JSON.parse(tt.getStorageSync(t));(!r.expire||Date.now()-r.timestamp<=r.expire)&&e.push(t.replace(this.config.prefix,""))}}),e}catch(e){return console.error("Storage keys error:",e),[]}}static new(e){return new Storage(e)}}const ad_Storage=Storage,src=ad_AdExecuteManager;for(var __rspack_i in exports.AdExecuteManager=__webpack_exports__.AdExecuteManager,exports.ExbAnalyticsJS=__webpack_exports__.ExbAnalyticsJS,exports.RewardAdFather=__webpack_exports__.RewardAdFather,exports.RewardAdNovel=__webpack_exports__.RewardAdNovel,exports.Storage=__webpack_exports__.Storage,exports.default=__webpack_exports__.default,__webpack_exports__)-1===["AdExecuteManager","ExbAnalyticsJS","RewardAdFather","RewardAdNovel","Storage","default"].indexOf(__rspack_i)&&(exports[__rspack_i]=__webpack_exports__[__rspack_i]);Object.defineProperty(exports,"__esModule",{value:!0});
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ class e{constructor(e={}){let{prefix:t="Logger",level:s="info",enabled:i=!0}=e;this.prefix=t,this.enabled=i,this.levels={error:0,warn:1,info:2,debug:3},this.currentLevel=this.levels[s]||this.levels.info}enable(){this.enabled=!0}disable(){this.enabled=!1}isEnabled(){return this.enabled}setLevel(e){Object.prototype.hasOwnProperty.call(this.levels,e)&&(this.currentLevel=this.levels[e])}formatMessage(e,t){let s=new Date().toLocaleString();return`[${s}] [${e.toUpperCase()}] [${this.prefix}] ${t}`}_log(e,t,...s){if(!this.enabled)return;let i=this.levels[e];if(void 0!==i&&this.currentLevel>=i){let i=this.formatMessage(e,t);switch(e){case"error":console.error(i,...s);break;case"warn":console.warn(i,...s);break;case"info":console.info(i,...s);break;case"debug":console.debug(i,...s);break;default:console.log(i,...s)}}}error(e,...t){this._log("error",e,...t)}warn(e,...t){this._log("warn",e,...t)}info(e,...t){this._log("info",e,...t)}debug(e,...t){this._log("debug",e,...t)}log(e,t,...s){this._log(e,t,...s)}}class t{static _instance=null;_taskStack=[];_currentBatchTasks=[];_isRunning=!1;_currentTask=null;constructor(s){if(this.logger=new e({prefix:"AdExecuteManager",enabled:!!s?.log}),t._instance)return t._instance;t._instance=this}static getInstance(e){return t._instance||(t._instance=new t(e)),t._instance}addTask(e,t){return e&&"function"==typeof e.ad?new Promise((s,i)=>{let r={adInstance:e,options:t.options??{},callbackCollection:t.collection??{},resolve:s,reject:i,id:`ad_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,_isResolved:!1,_isRejected:!1};this._taskStack.push(r),this._isRunning||this._compose()}):(this.logger.error("无效的广告实例 请正确实现.ad方法"),Promise.reject(Error("无效的广告实例")))}_compose(){if(0===this._taskStack.length){this._isRunning=!1,this._currentTask=null;return}this._isRunning=!0;let e=[...this._taskStack];this._taskStack=[],this._currentBatchTasks=e;let t=e.map(e=>async(t,s)=>{let{adInstance:i,options:r,callbackCollection:n,resolve:a,id:o}=e;if(e._isResolved||e._isRejected)return void await s(t);this._currentTask=e;try{let l=async e=>{await s(Object.assign({},t,e))},c=await i.initialize(r).ad({options:r,collection:n},l),h=Object.assign({id:o},c);this.logger.info(`任务执行成功,成功信息:${JSON.stringify(h)}`),e._isResolved=!0,a(h)}catch(n){let r=Object.assign({id:o,apiError:n});this.logger.error(`任务执行失败, 继续下一个任务,错误信息:${JSON.stringify(r)}`),e._isRejected=!0;try{i?.clear()}catch(e){this.logger.error("clear error: ",JSON.stringify(Object.assign({id:o,apiError:e})))}a(r),await s(t)}}),s={roundTasks:t.length};t.map(e=>(t,s)=>async i=>await e(Object.assign({},t,i),s)).reduce((e,t)=>(s,i)=>e(s,t(s,i)))(s,async e=>{this.logger.info("本轮活动队列已经清空",e),this._taskStack.length>0?Promise.resolve().then(()=>{this._compose()}):(this._isRunning=!1,this._currentTask=null,this._currentBatchTasks=[])})()}clearTasks(){if(this._currentTask){if(this._currentTask._isResolved||this._currentTask._isRejected){this._currentTask=null;return}try{this._currentTask.callbackCollection&&this._currentTask.callbackCollection.onCancel&&this._currentTask.callbackCollection.onCancel(),this._currentTask._isResolved=!0,this._currentTask.resolve()}catch(e){this.logger.error("clear current task error: ",e)}this._currentTask=null}this._currentBatchTasks.length>0&&(this._currentBatchTasks.forEach(e=>{if(e!==this._currentTask&&!e._isResolved&&!e._isRejected)try{e.callbackCollection&&e.callbackCollection.onCancel&&e.callbackCollection.onCancel(),e._isResolved=!0,e.resolve()}catch(e){this.logger.error("clear current batch task error: ",e)}}),this._currentBatchTasks=[]),this._taskStack.forEach(e=>{if(!e._isResolved&&!e._isRejected&&(e._isResolved=!0,e.resolve(),e.callbackCollection&&e.callbackCollection.onCancel))try{e.callbackCollection.onCancel()}catch(e){this.logger.error("clear task error: ",e)}}),this._taskStack=[],this._isRunning=!1}getTaskCount(){return this._taskStack.filter(e=>!e._isResolved&&!e._isRejected).length+this._currentBatchTasks.filter(e=>e!==this._currentTask&&!e._isResolved&&!e._isRejected).length+(!this._currentTask||this._currentTask._isResolved||this._currentTask._isRejected?0:1)}isRunning(){return this._isRunning}getCurrentTaskId(){return this._currentTask?.id||null}}let s=t;class i extends Error{constructor(e){super(e),this.name=this.constructor.name,this.stack=Error(e).stack,Object.defineProperty(this,"message",{enumerable:!0}),Object.defineProperty(this,"name",{enumerable:!0}),Object.defineProperty(this,"stack",{enumerable:!0})}toJSON(){return{name:this.name,message:this.message,stack:this.stack}}}class r{static args=null;_initSign="";_preserveOnEnd=!1;_rewardAd=null;_ttErrorMsgs=["The adUnitId is closed","The adUnitId is prohibit","The adUnitId is invalid","The adUnitId is empty","feature is not supported in app"];_ttErrorCodes=[139902,123302];constructor(e){this._initSign=e?.sign??"",this._adConfig=e?.adConfig??{},this._preserveOnEnd=e?.preserveOnEnd??!1}initialize(e,t){if(this._rewardAd)return console.warn("RewardAdFather: rewardAd has been initialized"),t?.(this._rewardAd),this;let s=Object.assign({},r.args,this._adConfig,e);if(!s.adUnitId)throw console.error("[RewardAdFather] reward args adUnitId is required",s),new i("[RewardAdFather] reward args adUnitId is required");return this._rewardAd=tt.createRewardedVideoAd(s),t?.(this._rewardAd),this}initialized(){return!!this._rewardAd}async ad(e,t=null){throw Error("子类必须实现ad方法")}async addExecuteManager(e){let t=Object.assign({},this._adConfig,e?.options??{});return r.executeWithManager(this,Object.assign({},e,{options:t}))}destroy(){this._rewardAd&&!this._preserveOnEnd&&(this._rewardAd.destroy(),this._rewardAd=null)}clear(){throw Error("子类必须实现clear方法")}onClose(e){this._rewardAd&&this._rewardAd.onClose(e)}offClose(e){this._rewardAd&&this._rewardAd.offClose(e)}show(){return this._rewardAd?this._rewardAd.show():Promise.reject({errMsg:"rewardAd is null"})}load(){if(this._rewardAd)return this._rewardAd.load()}onError(e){this._rewardAd&&this._rewardAd.onError(e)}offError(e){this._rewardAd&&this._rewardAd.offError(e)}onLoad(e){this._rewardAd&&this._rewardAd.onLoad(e)}offLoad(e){this._rewardAd&&this._rewardAd.offLoad(e)}placeholder(){return null}static buildArgs(e){e?.adUnitId||console.error("[RewardAdFather] RewardParams.adUnitId is required"),r.args=e}static async executeWithManager(e,t){return e&&e instanceof r?s.getInstance({log:t?.options?.log??!0}).addTask(e,t):(console.error("RewardAdFather: executeWithManager - 无效的广告实例"),Promise.reject(Error("无效的广告实例")))}}let n=r;function a(e,t,s="showTimes"){if(!Array.isArray(e))return console.error("第一个参数必须是数组"),null;let i=e.find(e=>e&&e.adSceneFlag===t);return i?i[s]:null}class o{static instance=null;_initSign="";constructor(e){this._initSign=e?.sign??"",this._loginInfo=e?.loginInfo??{}}getUserConfig(){let e=this._loginInfo.getAppUnlockConfig()??[];return{is_unlock_all:0,max_tan_ad_num:e.replayTimes??0,look_jlsp_num:e.requiredVideos??1,ad_unlock_chapter_num:e.unlockAble??2,jlsp_is_look_complete:e.requireFullWatch??1}}getUserInfo(){let e=this._loginInfo.getUserInfo();return Object.assign({},e,{id:e?.appUserId??-1,user_type:e?.versionType??0,user_ab:e?.userAb??0})}getSysConfig(){let e=this._loginInfo.getUserAdConfig().appAdStrategyList||[],t=a(e,"read_other","showTimes"),s=a(e,"inter_site_pop_ups_num","showTimes")||0,i=a(e,"inter_site_pop_ups","showTimes")||0,r=a(e,"read_page_back_ad","showTimes"),n=a(e,"first_user_day","showTimes");return{free_incentive_frequency:t?Math.max(Number(t),0):0,inter_site_pop_ups:i,inter_site_pop_ups_num:s,read_page_back_ad:r?Math.max(Number(r),0):0,first_user_day:n?Math.max(Number(n),0):0}}getUserId(){let e=this.getUserInfo();return e?.id??null}getUserAB(){return Number(this.getUserInfo()?.user_ab??0)}placeholder(){return null}static build(e){return o.instance||(o.instance=new o(e)),o.instance}static getInstance(){if(!o.instance)throw Error("CommonSettings instance is not init");return o.instance}static new(e){return o.build(e)}}class l{static instance=null;_initSign="";_needReport=!1;commonSettings=null;constructor(e){if(l.instance)return l.instance;this._initSign=e?.sign??"",this._needReport=e?.needReport??!1,this.commonSettings=o.new(e),l.instance=this}initialize(e){return this._needReport?e:void console.warn("ExbAnalyticsJS needReport is false, do not report")}track(e,t,s){if(!this._needReport)return;if(!e)throw Error("eventName is required");let i=Object.assign({},this._getCommonUserInfo(),t),r=s?.sign??"track";console.log(`-------------${r}-----------------------:`,e,i),tt.reportAnalytics(e,i)}_getCommonUserInfo(){let{id:e,user_type:t,user_ab:s}=this.commonSettings?.getUserInfo()??{};return{user_id:e,user_type:t,user_group:s}}identify(){return null}alias(){return null}pages(){return null}page(e,t){this.track(e,t,{sign:"page"})}cpage(e){return this.page("cpage",e)}placeholder(){return null}static build(e){return l.instance||(l.instance=new l(e)),l.instance}static getInstance(){if(!l.instance)throw Error("ExbAnalyticsJS instance is not init");return l.instance}static new(e){return new l(e)}}let c=l,h={0:"launch_ad",1:"novel_plugin_strong_ad",2:"novel_plugin_unlock_btn",3:"novel_plugin_free_benefit_btn",4:"home_free_welfare_btn",5:"home_free_popup",6:"other",7:"home_back_show",8:"novel_plugin_free_time_btn",9:"launch_ad_alone"},d=Object.entries(h).reduce((e,[t,s])=>(e[s]=Number(t),e),{});class u{static instance=null;_initSign="";_currScene=null;constructor(e){if(u.instance)return u.instance;this._initSign=e?.sign??"",u.instance=this}initialize(e){}addScene(e){return console.log("----------------------AD触发场景:--------------------",e),this._currScene=e,this}addSceneType(e=1){return this.addScene(h[e]),this}getCurrentScene(){return this._currScene}placeholder(){return null}static build(e){return u.instance||(u.instance=new u(e)),u.instance}static getInstance(){if(!u.instance)throw Error("RewardAdSceneTriggerManager instance is not init");return u.instance}}class _{static instance=null;_initSign="";_halfway=[{scene:d.other,count:0}];_finished=[{scene:d.other,count:0}];constructor(e){if(_.instance)return _.instance;this._initSign=e?.sign??"",_.instance=this}initialize(e){}_halfwayUpdate(e){let t=this._halfway.find(t=>t.scene===e.scene);t?t.count+=1:this._halfway.push({scene:e.scene,count:1})}_halfwayGet(e){let t=e?.scenes??[];return(t.length>0?this._halfway.filter(e=>t.includes(e.scene)):this._halfway).reduce((e,t)=>e+t.count,0)}_halfwayReset(){this._halfway=[{scene:d.other,count:0}]}_finishedUpdate(e){let t=this._finished.find(t=>t.scene===e.scene);t?t.count+=1:this._finished.push({scene:e.scene,count:1})}_finishedGet(e){let t=e?.scenes??[];return(t.length>0?this._finished.filter(e=>t.includes(e.scene)):this._finished).reduce((e,t)=>e+t.count,0)}_finishedReset(){this._finished=[{scene:d.other,count:0}]}record(e){switch(e.type){case"halfway":this._halfwayUpdate(e);break;case"finished":this._finishedUpdate(e)}}rest(e){switch(e){case"halfway":this._halfwayReset();break;case"finished":this._finishedReset()}}get(e){switch(e.type){case"halfway":return this._halfwayGet(e);case"finished":return this._finishedGet(e);default:return null}}placeholder(){return null}static build(e){return _.instance||(_.instance=new _(e)),_.instance}static getInstance(){if(!_.instance)throw Error("RewardAdGlobalRecorder instance is not init");return _.instance}}class f extends n{_onHalfway=null;_onShow=null;_onFinish=null;_onAlways=null;_onError=null;_initSign="";_alwaysCallback=null;_halfwayCallback=null;_finishedCallback=null;_resolve=null;_next=null;_scene=d.other;_adTimeout=null;_adTimeoutTime=8e3;_adBeforeShowTimer=null;_adBeforeShowTime=300;bindAdCloseLister=this.adCloseLister.bind(this);bindAdErrorLister=this.adErrorLister.bind(this);bindAdLoadLister=this.adLoadLister.bind(this);bindApiAdErrorLister=this.apiAdErrorLister.bind(this);_bindShiftCloseLister=this._shiftCloseLister.bind(this);_bindShiftErrorLister=this._shiftErrorLister.bind(this);constructor(e){let t=Object.assign({},g.new().options(),e?.adConfig),s=Object.assign({},e,{adConfig:t});super(s),this._initSign=s?.sign??"",this._adConfig=s?.adConfig??{},this._onHalfway=s?.collection?.onHalfway??null,this._onShow=s?.collection?.onShow??null,this._onFinish=s?.collection?.onFinish??null,this._onAlways=s?.collection?.onAlways??null,this._onError=s?.collection?.onError??null}initialize(e,t){return super.initialize(e,t),this._initAdLister(),this._initNovelConfig(e),this}_initAdLister(){this.onClose(this.bindAdCloseLister),this.onError(this.bindAdErrorLister),this.onLoad(this.bindAdLoadLister),tt.onError(this.bindApiAdErrorLister)}_initNovelConfig(e){this.novelConfig=g.new({retry:e?.retry})}_onInnerExecuteBefore(){return null}_onInnerAdShowSuccess(){return null}_clearAdTimeout(){this._adTimeout&&(clearTimeout(this._adTimeout),this._adTimeout=null),this._adBeforeShowTimer&&(clearTimeout(this._adBeforeShowTimer),this._adBeforeShowTimer=null)}get rewardAd(){return this._rewardAd}addExecuteManager(e){return super.addExecuteManager(e)}ad(e,t=null){return this._alwaysCallback=e?.collection?.always,this._halfwayCallback=e?.collection?.halfway,this._finishedCallback=e?.collection?.finished,this._onInnerExecuteBefore(),new Promise(s=>{this._adInner({options:{scene:e?.options?.scene},collection:{resolve:s,before:e.collection?.before,success:e.collection?.success,prelude:e.collection?.prelude}},t)})}_adInner(e,t=null){let s=e?.collection?.resolve,i=e?.options?.scene??this._scene??d.other,r=e?.collection?.before,n=e?.collection?.success,a=e?.collection?.prelude,o=e=>{this._clearAdTimeout(),this.adDestroy(),s?.(Object.assign({scene:i},e?.resolvedValue)),t?.(Object.assign({scene:i},e?.nextValue))},l=()=>{this._scene=i,r?.({scene:i}),this._before=r,this._onShow?.({scene:i}),u.getInstance().addSceneType(i),this._resolve=s,this._next=t,this._adTimeout=setTimeout(()=>{console.warn("[RewardAdNovel] Ad show timeout, handling fallback ad case"),c.getInstance().track("incentive_ad_show",{scene:i,result:0,msg:"ad_show_timeout"}),o({resolvedValue:{apiError:{errMsg:"ad_show_timeout"}},nextValue:null})},this._adTimeoutTime),a?.({scene:i,frequency:this._adBeforeShowTime,time:new Date().getTime()}),this._adBeforeShowTimer=setInterval(()=>{a?.({scene:i,frequency:this._adBeforeShowTime,time:new Date().getTime()})},this._adBeforeShowTime),this.adShow().then(()=>{this._clearAdTimeout(),n?.({scene:i}),this._success=n,c.getInstance().track("incentive_ad_show",{scene:i,result:1}),this._onInnerAdShowSuccess()}).catch(e=>{var t,s;(this._clearAdTimeout(),c.getInstance().track("incentive_ad_show",{scene:i,result:0,msg:e?.errMsg}),t=this._ttErrorMsgs,(s=e?.errMsg)&&t.some(e=>RegExp(e,"i").test(s))||this._ttErrorCodes.includes(e?.errorCode))?o({scene:i,resolvedValue:{apiError:e},nextValue:null}):0>=this.novelConfig.remain()?o({scene:i,resolvedValue:null,nextValue:null}):(this.novelConfig.updateRetry(),this.adLoad().then(()=>{c.getInstance().track("incentive_ad_load",{scene:i,result:1}),l()}).catch(e=>{c.getInstance().track("incentive_ad_load",{scene:i,result:0}),o({scene:i,resolvedValue:{apiError:e},nextValue:null})}))})};l()}adLoad(){return this.load()}adShow(){return this.show()}_outerCloseCallback(e){this._alwaysCallback?.(e)}_outerHalfwayCallback(e){this._halfwayCallback?.(e)}_outerFinishedCallback(e){this._finishedCallback?.(e)}adCloseLister(e){this._clearAdTimeout(),_.getInstance().record({type:e.isEnded?"finished":"halfway",scene:this._scene}),c.getInstance().track("incentive_ad_close",{scene:this._scene,ad_is_completed:+!!e.isEnded,ad_count:e.count});let t={...e,scene:this._scene},s=t=>{this.adDestroy(),this._resolve?.(Object.assign({},e,{scene:this._scene},t)),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null};e?.isEnded?(this._outerFinishedCallback(t),this._onFinish?.(t)):(this._outerHalfwayCallback(t),this._onHalfway?.(t)),this._outerCloseCallback(t),this._onAlways?.(t),s({end_type:e.isEnded?"finished":"halfway"})}adErrorLister(e){this._clearAdTimeout(),console.error("[RewardAdNovel] adErrorLister",JSON.stringify(e)),this.adDestroy(),this._onError?.(e),this._resolve?.({apiError:e}),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}apiAdErrorLister(e){this._clearAdTimeout(),console.error("[API RewardAdNovel] apiAdErrorLister:",JSON.stringify(e)),this.adDestroy(),this._onError?.(e),this._resolve?.({apiError:e}),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}adLoadLister(){}adDestroy(){this.offClose(this.bindAdCloseLister),this.offError(this.bindAdErrorLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.destroy()}clear(){this._clearAdTimeout(),this.offClose(this.bindAdCloseLister),this.offClose(this._bindShiftCloseLister),this.offError(this.bindAdErrorLister),this.offError(this._bindShiftErrorLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.destroy(),this._resolve=null,this._next=null,this._success=null,this._before=null}_shiftCloseLister(e){this._clearAdTimeout(),this.offError(this._bindShiftErrorLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.offClose(this._bindShiftCloseLister),this.destroy(),this._resolve?.(Object.assign({},e,{scene:this._scene})),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}_shiftErrorLister(e){this._clearAdTimeout(),this.offClose(this._bindShiftCloseLister),this.offLoad(this.bindAdLoadLister),tt.offError(this.bindApiAdErrorLister),this._onHalfway=null,this._onFinish=null,this._onAlways=null,this._onShow=null,this._onError=null,this._alwaysCallback=null,this._halfwayCallback=null,this._finishedCallback=null,this.offError(this._bindShiftErrorLister),this.destroy(),this._resolve?.(Object.assign({},e,{scene:this._scene})),this._resolve=null,this._next?.(),this._next=null,this._success=null,this._before=null}shift(){this.offClose(this.bindAdCloseLister),this.onClose(this._bindShiftCloseLister),this.offError(this.bindAdErrorLister),this.onError(this._bindShiftErrorLister)}static build(e){return f.instance||(f.instance=new f(e)),f.instance}static getInstance(){if(!f.instance)throw Error("RewardAdNovel instance is not init");return f.instance}static new(e){return new f(e)}}class g{free_incentive_frequency=0;frequency={total:0,current:0};constructor(e){this.commonSettings=o.new(),this._init(e)}_init(e){this._adTimes(e)}_adTimes(e){this.frequency.total=e?.retry??4;let{free_incentive_frequency:t=0}=this.commonSettings.getSysConfig();this.free_incentive_frequency=Math.min(4,Math.max(0,Number(t)))}reset(){this.frequency.current=0}updateRetry(){this.frequency.current=this.frequency.current+1}remain(){return this.frequency.total-this.frequency.current}options(){return this.free_incentive_frequency>0?{multiton:!0,multitonRewardTimes:this.free_incentive_frequency,multitonRewardMsg:["全部小说免费看"],progressTip:!0}:{}}static new(e){return new g(e)}}let w=f;class b{_commonSettings=null;constructor(e={}){this.config={prefix:"storage_",expire:null,...e},this._commonSettings=o.new()}getTodayEndTimestamp(){let e=new Date;return new Date(e.getFullYear(),e.getMonth(),e.getDate(),23,59,59,999).getTime()}_setItem(e,t,s){let i=void 0!==s?s:this.config.expire;"today"===i&&(i=this.getTodayEndTimestamp()-Date.now());let r={value:t,expire:i,timestamp:Date.now()};try{tt.setStorageSync(e,JSON.stringify(r))}catch(e){console.error("Storage setItem error:",e)}}_getItem(e){try{let t=tt.getStorageSync(e);if(!t)return null;let s=JSON.parse(t);if(s.expire&&Date.now()-s.timestamp>s.expire)return this.removeItem(e),null;return s.value}catch(e){return console.error("Storage getItem error:",e),null}}setItem(e,t,s){let i=this.config.prefix+e;return this._setItem(i,t,s)}getItem(e){let t=this.config.prefix+e;return this._getItem(t)}getUserItem(e){let t=this._commonSettings.getUserId()??"null",s=`${this.config.prefix}_${t}_${e}`;return this._getItem(s)}setUserItem(e,t,s){let i=this._commonSettings.getUserId()??"null",r=`${this.config.prefix}_${i}_${e}`;return this._setItem(r,t,s)}removeItem(e){try{tt.removeStorageSync(e)}catch(e){console.error("Storage removeItem error:",e)}}clear(){try{tt.clearStorageSync()}catch(e){console.error("Storage clear error:",e)}}keys(){try{let e=[];return(tt.getStorageInfoSync().keys??[]).forEach(t=>{if(t.startsWith(this.config.prefix)){let s=JSON.parse(tt.getStorageSync(t));(!s.expire||Date.now()-s.timestamp<=s.expire)&&e.push(t.replace(this.config.prefix,""))}}),e}catch(e){return console.error("Storage keys error:",e),[]}}static new(e){return new b(e)}}let m=b,p=s;export{s as AdExecuteManager,c as ExbAnalyticsJS,n as RewardAdFather,w as RewardAdNovel,m as Storage,p as default};
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@singcl/ad-execute-manager",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "import": "./dist/index.js",
8
+ "require": "./dist/index.cjs"
9
+ }
10
+ },
11
+ "main": "./dist/index.cjs",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "scripts": {
16
+ "build": "rslib build",
17
+ "dev": "rslib build --watch",
18
+ "format": "prettier --write .",
19
+ "lint": "eslint .",
20
+ "test": "rstest"
21
+ },
22
+ "devDependencies": {
23
+ "@babel/eslint-parser": "^7.28.5",
24
+ "@babel/preset-env": "^7.28.5",
25
+ "@eslint/js": "^9.39.1",
26
+ "@rslib/core": "^0.18.5",
27
+ "@rstest/core": "^0.7.2",
28
+ "eslint": "^9.39.2",
29
+ "eslint-plugin-import": "^2.32.0",
30
+ "globals": "^16.5.0",
31
+ "prettier": "^3.7.3"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ }
36
+ }