UNPKG

@dat-platform/advertiser

Version:

An SDK for advertisers to track user actions, such as Telegram channel or bot joins, and notify publishers upon completion.

447 lines (433 loc) 19.9 kB
/****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /** @class */ ((function (_super) { __extends(APIError, _super); function APIError(message, code, details) { var _this = _super.call(this, message) || this; _this.code = code; _this.details = details; _this.name = 'APIError'; return _this; } return APIError; })(Error)); var DEFAULT_BASE_URL = 'https://cms.datplatform.com'; var AuthManager = /** @class */ (function () { function AuthManager(config) { this.token = null; this.userId = null; this.tokenExpiration = null; this.apiKey = config.apiKey; this.baseURL = config.baseURL || DEFAULT_BASE_URL; } AuthManager.prototype.parseJwt = function (token) { try { var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); } catch (error) { console.warn('Error parsing JWT token:', error); return {}; } }; AuthManager.prototype.setAuthData = function (response) { if (!response.results || !response.results.token) { throw new Error('Invalid authentication response'); } this.token = response.results.token; this.userId = response.results.user_id; if (this.token) { var decoded = this.parseJwt(this.token); if (decoded.exp) { this.tokenExpiration = decoded.exp * 1000; } else { // Set a default expiration of 1 hour if not provided this.tokenExpiration = Date.now() + (60 * 60 * 1000); } // Debug log // console.log('Token set successfully:', { // hasToken: !!this.token, // hasUserId: !!this.userId, // expiration: new Date(this.tokenExpiration || 0).toISOString() // }); } }; AuthManager.prototype.isTokenExpired = function () { if (!this.tokenExpiration) return false; // Add 5-second buffer to prevent edge cases return Date.now() > (this.tokenExpiration - 5000); }; AuthManager.prototype.initialize = function () { var _a; return __awaiter(this, void 0, void 0, function () { var result, response, error_1; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 3, , 4]); return [4 /*yield*/, fetch("".concat(this.baseURL, "/auth/verify"), { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-API-Key': this.apiKey } })]; case 1: result = _b.sent(); if (!result.ok) { if (result.status === 401 || result.status === 403) { this.clearAuth(); throw new Error('Invalid API key'); } throw new Error("HTTP error! status: ".concat(result.status)); } return [4 /*yield*/, result.json()]; case 2: response = _b.sent(); if (response.status === 200 && ((_a = response.results) === null || _a === void 0 ? void 0 : _a.token)) { this.setAuthData(response); return [2 /*return*/, true]; } return [2 /*return*/, false]; case 3: error_1 = _b.sent(); this.clearAuth(); throw new Error("Authentication failed: ".concat(error_1 instanceof Error ? error_1.message : 'Unknown error')); case 4: return [2 /*return*/]; } }); }); }; AuthManager.prototype.refreshTokenIfNeeded = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { if (this.isTokenExpired()) { return [2 /*return*/, this.initialize()]; } return [2 /*return*/, true]; }); }); }; AuthManager.prototype.getValidToken = function () { return __awaiter(this, void 0, void 0, function () { var error_2; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 3, , 4]); if (!(!this.token || this.isTokenExpired())) return [3 /*break*/, 2]; console.log('Token needs refresh...'); return [4 /*yield*/, this.initialize()]; case 1: _a.sent(); _a.label = 2; case 2: if (!this.token) { throw new Error('Unable to obtain valid token'); } return [2 /*return*/, this.token]; case 3: error_2 = _a.sent(); console.error('Token validation error:', error_2); throw error_2; case 4: return [2 /*return*/]; } }); }); }; AuthManager.prototype.getUserId = function () { if (!this.userId) { throw new Error('User ID not available'); } return this.userId; }; AuthManager.prototype.getToken = function () { return this.token; }; AuthManager.prototype.isAuthenticated = function () { return this.token !== null && !this.isTokenExpired(); }; AuthManager.prototype.clearAuth = function () { this.token = null; this.userId = null; this.tokenExpiration = null; }; return AuthManager; }()); var AdsManager = /** @class */ (function () { function AdsManager(config) { this.apiKey = config.apiKey; this.baseURL = config.baseURL || DEFAULT_BASE_URL; } AdsManager.prototype.getAds = function () { return __awaiter(this, void 0, void 0, function () { var adv_creative; return __generator(this, function (_a) { try { adv_creative = { creative: [ { creative_id: 1, icon: "https://example.com/icons/video-icon.png", title: "Watch an ad today 📺", description: "Watch an ad and earn. It's that simple.", rewardContent: "1 coins", clickTaskTrackingUrl: "https://adnetwork.com/v?id=[taskid]", redirectlink: "https://adnetwork.com/c?id=[taskid]" } ] }; return [2 /*return*/, adv_creative]; //---remove this code after testing END } catch (error) { throw new Error("Failed to fetch ads: ".concat(error instanceof Error ? error.message : 'Unknown error')); } return [2 /*return*/]; }); }); }; AdsManager.prototype.showAd = function (adId) { return __awaiter(this, void 0, void 0, function () { var result, response, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 3, , 4]); return [4 /*yield*/, fetch("".concat(this.baseURL, "/ads/").concat(adId, "/show"), { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': this.apiKey } })]; case 1: result = _a.sent(); return [4 /*yield*/, result.json()]; case 2: response = _a.sent(); return [2 /*return*/, response.success]; case 3: error_1 = _a.sent(); throw new Error("Failed to show ad: ".concat(error_1 instanceof Error ? error_1.message : 'Unknown error')); case 4: return [2 /*return*/]; } }); }); }; return AdsManager; }()); var OfferManager = /** @class */ (function () { function OfferManager(config) { this.apiKey = config.apiKey; this.baseURL = config.baseURL || DEFAULT_BASE_URL; this.authManager = new AuthManager(config); } OfferManager.prototype.isWebAppAvailable = function () { return typeof window !== 'undefined' && window.Telegram !== undefined && window.Telegram.WebApp !== undefined; }; OfferManager.prototype.getTelegramUserId = function () { var _a, _b, _c, _d; if (!this.isWebAppAvailable()) { return null; } return ((_d = (_c = (_b = (_a = window.Telegram) === null || _a === void 0 ? void 0 : _a.WebApp) === null || _b === void 0 ? void 0 : _b.initDataUnsafe) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id) || null; }; OfferManager.prototype.markActionComplete = function (advertiserId, idToken, autoClose) { if (autoClose === void 0) { autoClose = false; } return __awaiter(this, void 0, void 0, function () { var result, responseText, response, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 4, , 5]); return [4 /*yield*/, this.authManager.getValidToken()]; case 1: _a.sent(); return [4 /*yield*/, fetch("".concat(this.baseURL, "/advertiser/completionRewardWebhook"), { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ advertiserId: advertiserId, idToken: idToken }) })]; case 2: result = _a.sent(); return [4 /*yield*/, result.text()]; case 3: responseText = _a.sent(); response = JSON.parse(responseText); // Update success check based on API response if (response.status !== 200) ; if (autoClose) { setTimeout(function () { //auto close current window tab and navigate to previous history link window.close(); // window.history.back(); }, 1000); } return [2 /*return*/, response.results]; case 4: error_1 = _a.sent(); throw new Error("Failed to send rewards: ".concat(error_1 instanceof Error ? error_1.message : 'Unknown error')); case 5: return [2 /*return*/]; } }); }); }; return OfferManager; }()); var K2SDK = /** @class */ (function () { function K2SDK(config) { this.initialized = false; if (!config.apiKey) { throw new Error('API Key is required'); } this.authManager = new AuthManager(config); this.adsManager = new AdsManager(config); this.offerManager = new OfferManager(config); } K2SDK.initialize = function (config) { return __awaiter(this, void 0, void 0, function () { var isAuthenticated, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!!K2SDK.instance) return [3 /*break*/, 4]; K2SDK.instance = new K2SDK(config); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, K2SDK.instance.authManager.initialize()]; case 2: isAuthenticated = _a.sent(); if (!isAuthenticated) { throw new Error('Authentication failed'); } K2SDK.instance.initialized = true; return [3 /*break*/, 4]; case 3: error_1 = _a.sent(); K2SDK.instance = null; throw new Error("SDK initialization failed: ".concat(error_1 instanceof Error ? error_1.message : 'Unknown error')); case 4: return [2 /*return*/, K2SDK.instance]; } }); }); }; K2SDK.getInstance = function () { if (!K2SDK.instance || !K2SDK.instance.initialized) { throw new Error('SDK not initialized. Call K2SDK.initialize(config) first'); } return K2SDK.instance; }; K2SDK.prototype.getTelegramUserId = function () { var userId = this.offerManager.getTelegramUserId(); if (!userId) { throw new Error('Telegram platform not detected. Run this on Telegram to get ID'); } return userId; }; K2SDK.prototype.isTelegramWebAppAvailable = function () { return this.offerManager.isWebAppAvailable(); }; K2SDK.prototype.isInitialized = function () { return this.initialized; }; K2SDK.reset = function () { K2SDK.instance = null; }; K2SDK.prototype.markActionComplete = function (advertiserId, idToken, autoClose) { if (autoClose === void 0) { autoClose = false; } return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.offerManager.markActionComplete(advertiserId, idToken, autoClose)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; K2SDK.instance = null; return K2SDK; }()); if (typeof module !== 'undefined' && module.exports) { module.exports = K2SDK; } export { K2SDK as default }; //# sourceMappingURL=index.esm.js.map