playttm 0.0.4 → 0.0.5

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/dist/lib.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export declare const isBrowserEnvironment: () => boolean;
1
2
  export interface TTMConfig {
2
3
  cookies?: string;
3
4
  headers?: Record<string, string>;
@@ -5,6 +6,8 @@ export interface TTMConfig {
5
6
  timeout?: number;
6
7
  endpoint?: string;
7
8
  onProgress?: (step: string, message: string, data?: any) => void;
9
+ isBrowser?: boolean;
10
+ adapter?: any;
8
11
  }
9
12
  export interface RoundInfo {
10
13
  id: string;
@@ -71,11 +74,22 @@ export interface QuickBookResult {
71
74
  }
72
75
  export declare class ThaiTicketMajor {
73
76
  private client;
74
- private jar;
77
+ private jar?;
75
78
  private endpoint;
76
79
  private defaultHeaders;
77
80
  private onProgressCallback?;
81
+ inBrowser: boolean;
82
+ private rawCookies?;
78
83
  constructor(config?: TTMConfig);
84
+ /**
85
+ * Synchronize a cookie string into Chrome Extension's cookie store (chrome.cookies API).
86
+ */
87
+ static syncCookiesToChrome(cookieString: string, domainUrl?: string): Promise<void>;
88
+ /**
89
+ * Setup declarativeNetRequest session rules in Chrome Extension to set Referer and Origin headers
90
+ */
91
+ static setupExtensionRules(): Promise<void>;
92
+ syncCookies(domainUrl?: string): Promise<void>;
79
93
  private emitProgress;
80
94
  /**
81
95
  * Step 1: ดึงรอบการแสดงทั้งหมดจากหน้าหลักคอนเสิร์ต
package/dist/lib.js CHANGED
@@ -45,30 +45,188 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
45
  return (mod && mod.__esModule) ? mod : { "default": mod };
46
46
  };
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.displayQRCode = exports.ThaiTicketMajor = void 0;
48
+ exports.displayQRCode = exports.ThaiTicketMajor = exports.isBrowserEnvironment = void 0;
49
49
  const axios_1 = __importDefault(require("axios"));
50
50
  const cheerio = __importStar(require("cheerio"));
51
51
  const axios_cookiejar_support_1 = require("axios-cookiejar-support");
52
52
  const tough_cookie_1 = require("tough-cookie");
53
+ const isBrowserEnvironment = () => {
54
+ var _a, _b;
55
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
56
+ return true;
57
+ }
58
+ if (typeof globalThis !== "undefined" && Boolean((_b = (_a = globalThis.chrome) === null || _a === void 0 ? void 0 : _a.runtime) === null || _b === void 0 ? void 0 : _b.id)) {
59
+ return true;
60
+ }
61
+ if (typeof process === "undefined" || !process.versions || !process.versions.node) {
62
+ return true;
63
+ }
64
+ return false;
65
+ };
66
+ exports.isBrowserEnvironment = isBrowserEnvironment;
53
67
  // ==========================================
54
68
  // Main Library Class
55
69
  // ==========================================
56
70
  class ThaiTicketMajor {
57
71
  constructor(config = {}) {
58
- this.jar = new tough_cookie_1.CookieJar();
72
+ this.inBrowser =
73
+ typeof config.isBrowser === "boolean"
74
+ ? config.isBrowser
75
+ : (0, exports.isBrowserEnvironment)();
76
+ this.rawCookies = config.cookies;
59
77
  this.endpoint = config.endpoint || "https://booking.thaiticketmajor.com/booking/3m";
60
78
  this.onProgressCallback = config.onProgress;
61
79
  const defaultUA = config.userAgent ||
62
80
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
63
- this.defaultHeaders = Object.assign({ accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8", "accept-language": "th,en-US;q=0.9,en;q=0.8", "user-agent": defaultUA, referer: "https://booking.thaiticketmajor.com" }, (config.headers || {}));
64
- if (config.cookies) {
65
- this.defaultHeaders["cookie"] = config.cookies;
81
+ this.defaultHeaders = Object.assign({ accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8", "accept-language": "th,en-US;q=0.9,en;q=0.8" }, (config.headers || {}));
82
+ if (!this.inBrowser) {
83
+ this.jar = new tough_cookie_1.CookieJar();
84
+ this.defaultHeaders["user-agent"] = defaultUA;
85
+ this.defaultHeaders["referer"] = "https://booking.thaiticketmajor.com";
86
+ if (config.cookies) {
87
+ this.defaultHeaders["cookie"] = config.cookies;
88
+ }
89
+ this.client = (0, axios_cookiejar_support_1.wrapper)(axios_1.default.create(Object.assign({ jar: this.jar, withCredentials: true, timeout: config.timeout || 30000 }, (config.adapter ? { adapter: config.adapter } : {}))));
90
+ }
91
+ else {
92
+ // Browser / Chrome Extension environment
93
+ this.client = axios_1.default.create(Object.assign({ withCredentials: true, timeout: config.timeout || 30000 }, (config.adapter ? { adapter: config.adapter } : {})));
94
+ // Interceptor to strip unsafe headers forbidden by browsers (Fetch / XHR specification)
95
+ const unsafeHeaders = ["user-agent", "referer", "cookie", "origin", "host", "connection"];
96
+ this.client.interceptors.request.use((reqConfig) => {
97
+ if (reqConfig.headers) {
98
+ for (const header of unsafeHeaders) {
99
+ delete reqConfig.headers[header];
100
+ delete reqConfig.headers[header.toLowerCase()];
101
+ delete reqConfig.headers[header.toUpperCase()];
102
+ const titleCase = header.charAt(0).toUpperCase() + header.slice(1);
103
+ delete reqConfig.headers[titleCase];
104
+ }
105
+ }
106
+ return reqConfig;
107
+ });
66
108
  }
67
- this.client = (0, axios_cookiejar_support_1.wrapper)(axios_1.default.create({
68
- jar: this.jar,
69
- withCredentials: true,
70
- timeout: config.timeout || 30000,
71
- }));
109
+ }
110
+ /**
111
+ * Synchronize a cookie string into Chrome Extension's cookie store (chrome.cookies API).
112
+ */
113
+ static syncCookiesToChrome(cookieString_1) {
114
+ return __awaiter(this, arguments, void 0, function* (cookieString, domainUrl = "https://booking.thaiticketmajor.com") {
115
+ var _a;
116
+ if (typeof chrome === "undefined" || !((_a = chrome === null || chrome === void 0 ? void 0 : chrome.cookies) === null || _a === void 0 ? void 0 : _a.set)) {
117
+ return;
118
+ }
119
+ const pairs = cookieString.split(";");
120
+ for (const pair of pairs) {
121
+ const trimmed = pair.trim();
122
+ if (!trimmed)
123
+ continue;
124
+ const eqIndex = trimmed.indexOf("=");
125
+ if (eqIndex === -1)
126
+ continue;
127
+ const name = trimmed.substring(0, eqIndex).trim();
128
+ const value = trimmed.substring(eqIndex + 1).trim();
129
+ if (!name)
130
+ continue;
131
+ try {
132
+ yield chrome.cookies.set({
133
+ url: domainUrl,
134
+ name,
135
+ value,
136
+ domain: ".thaiticketmajor.com",
137
+ path: "/",
138
+ });
139
+ }
140
+ catch (_b) {
141
+ try {
142
+ yield chrome.cookies.set({
143
+ url: domainUrl,
144
+ name,
145
+ value,
146
+ path: "/",
147
+ });
148
+ }
149
+ catch (_c) { }
150
+ }
151
+ }
152
+ });
153
+ }
154
+ /**
155
+ * Setup declarativeNetRequest session rules in Chrome Extension to set Referer and Origin headers
156
+ */
157
+ static setupExtensionRules() {
158
+ return __awaiter(this, void 0, void 0, function* () {
159
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
160
+ if (typeof chrome === "undefined" || !((_a = chrome === null || chrome === void 0 ? void 0 : chrome.declarativeNetRequest) === null || _a === void 0 ? void 0 : _a.updateSessionRules)) {
161
+ return;
162
+ }
163
+ try {
164
+ yield chrome.declarativeNetRequest.updateSessionRules({
165
+ removeRuleIds: [1001, 1002],
166
+ addRules: [
167
+ {
168
+ id: 1001,
169
+ priority: 1,
170
+ action: {
171
+ type: ((_b = chrome.declarativeNetRequest.RuleActionType) === null || _b === void 0 ? void 0 : _b.MODIFY_HEADERS) || "modifyHeaders",
172
+ requestHeaders: [
173
+ {
174
+ header: "Referer",
175
+ operation: ((_c = chrome.declarativeNetRequest.HeaderOperation) === null || _c === void 0 ? void 0 : _c.SET) || "set",
176
+ value: "https://booking.thaiticketmajor.com",
177
+ },
178
+ {
179
+ header: "Origin",
180
+ operation: ((_d = chrome.declarativeNetRequest.HeaderOperation) === null || _d === void 0 ? void 0 : _d.SET) || "set",
181
+ value: "https://booking.thaiticketmajor.com",
182
+ },
183
+ ],
184
+ },
185
+ condition: {
186
+ urlFilter: "thaiticketmajor.com",
187
+ resourceTypes: [
188
+ ((_e = chrome.declarativeNetRequest.ResourceType) === null || _e === void 0 ? void 0 : _e.XMLHTTPREQUEST) || "xmlhttprequest",
189
+ ((_f = chrome.declarativeNetRequest.ResourceType) === null || _f === void 0 ? void 0 : _f.SUB_FRAME) || "sub_frame",
190
+ ((_g = chrome.declarativeNetRequest.ResourceType) === null || _g === void 0 ? void 0 : _g.MAIN_FRAME) || "main_frame",
191
+ ((_h = chrome.declarativeNetRequest.ResourceType) === null || _h === void 0 ? void 0 : _h.OTHER) || "other",
192
+ ],
193
+ },
194
+ },
195
+ {
196
+ id: 1002,
197
+ priority: 1,
198
+ action: {
199
+ type: ((_j = chrome.declarativeNetRequest.RuleActionType) === null || _j === void 0 ? void 0 : _j.MODIFY_HEADERS) || "modifyHeaders",
200
+ requestHeaders: [
201
+ {
202
+ header: "Referer",
203
+ operation: ((_k = chrome.declarativeNetRequest.HeaderOperation) === null || _k === void 0 ? void 0 : _k.SET) || "set",
204
+ value: "https://kpaymentgateway.kasikornbank.com/",
205
+ },
206
+ ],
207
+ },
208
+ condition: {
209
+ urlFilter: "kasikornbank.com",
210
+ resourceTypes: [
211
+ ((_l = chrome.declarativeNetRequest.ResourceType) === null || _l === void 0 ? void 0 : _l.XMLHTTPREQUEST) || "xmlhttprequest",
212
+ ((_m = chrome.declarativeNetRequest.ResourceType) === null || _m === void 0 ? void 0 : _m.OTHER) || "other",
213
+ ],
214
+ },
215
+ },
216
+ ],
217
+ });
218
+ }
219
+ catch (err) {
220
+ console.warn("Could not set declarativeNetRequest session rules:", err);
221
+ }
222
+ });
223
+ }
224
+ syncCookies(domainUrl) {
225
+ return __awaiter(this, void 0, void 0, function* () {
226
+ if (this.rawCookies) {
227
+ yield ThaiTicketMajor.syncCookiesToChrome(this.rawCookies, domainUrl);
228
+ }
229
+ });
72
230
  }
73
231
  emitProgress(step, message, data) {
74
232
  if (this.onProgressCallback) {
@@ -646,6 +804,14 @@ class ThaiTicketMajor {
646
804
  if (options.onProgress) {
647
805
  this.onProgressCallback = options.onProgress;
648
806
  }
807
+ // In Chrome Extension environment, prepare cookies and network rules
808
+ if (this.inBrowser) {
809
+ this.emitProgress("INIT_EXTENSION", "Preparing Chrome extension cookies and network rules...");
810
+ if (this.rawCookies) {
811
+ yield this.syncCookies();
812
+ }
813
+ yield ThaiTicketMajor.setupExtensionRules();
814
+ }
649
815
  // 1. ดึงรอบการแสดง
650
816
  const rounds = yield this.getRounds(eventUrl);
651
817
  if (rounds.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playttm",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Make HTML Metadata to JSON",
5
5
  "main": "dist/lib.js",
6
6
  "types": "dist/lib.d.ts",
package/src/lib.ts CHANGED
@@ -3,6 +3,21 @@ import * as cheerio from "cheerio";
3
3
  import { wrapper } from "axios-cookiejar-support";
4
4
  import { CookieJar } from "tough-cookie";
5
5
 
6
+ declare const chrome: any;
7
+
8
+ export const isBrowserEnvironment = (): boolean => {
9
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
10
+ return true;
11
+ }
12
+ if (typeof globalThis !== "undefined" && Boolean((globalThis as any).chrome?.runtime?.id)) {
13
+ return true;
14
+ }
15
+ if (typeof process === "undefined" || !process.versions || !process.versions.node) {
16
+ return true;
17
+ }
18
+ return false;
19
+ };
20
+
6
21
  // ==========================================
7
22
  // Interfaces & Types
8
23
  // ==========================================
@@ -14,6 +29,8 @@ export interface TTMConfig {
14
29
  timeout?: number;
15
30
  endpoint?: string;
16
31
  onProgress?: (step: string, message: string, data?: any) => void;
32
+ isBrowser?: boolean;
33
+ adapter?: any;
17
34
  }
18
35
 
19
36
  export interface RoundInfo {
@@ -91,13 +108,19 @@ export interface QuickBookResult {
91
108
 
92
109
  export class ThaiTicketMajor {
93
110
  private client: AxiosInstance;
94
- private jar: CookieJar;
111
+ private jar?: CookieJar;
95
112
  private endpoint: string;
96
113
  private defaultHeaders: Record<string, string>;
97
114
  private onProgressCallback?: (step: string, message: string, data?: any) => void;
115
+ public inBrowser: boolean;
116
+ private rawCookies?: string;
98
117
 
99
118
  constructor(config: TTMConfig = {}) {
100
- this.jar = new CookieJar();
119
+ this.inBrowser =
120
+ typeof config.isBrowser === "boolean"
121
+ ? config.isBrowser
122
+ : isBrowserEnvironment();
123
+ this.rawCookies = config.cookies;
101
124
  this.endpoint = config.endpoint || "https://booking.thaiticketmajor.com/booking/3m";
102
125
  this.onProgressCallback = config.onProgress;
103
126
 
@@ -108,22 +131,162 @@ export class ThaiTicketMajor {
108
131
  this.defaultHeaders = {
109
132
  accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
110
133
  "accept-language": "th,en-US;q=0.9,en;q=0.8",
111
- "user-agent": defaultUA,
112
- referer: "https://booking.thaiticketmajor.com",
113
134
  ...(config.headers || {}),
114
135
  };
115
136
 
116
- if (config.cookies) {
117
- this.defaultHeaders["cookie"] = config.cookies;
118
- }
137
+ if (!this.inBrowser) {
138
+ this.jar = new CookieJar();
139
+ this.defaultHeaders["user-agent"] = defaultUA;
140
+ this.defaultHeaders["referer"] = "https://booking.thaiticketmajor.com";
141
+ if (config.cookies) {
142
+ this.defaultHeaders["cookie"] = config.cookies;
143
+ }
119
144
 
120
- this.client = wrapper(
121
- axios.create({
122
- jar: this.jar,
145
+ this.client = wrapper(
146
+ axios.create({
147
+ jar: this.jar,
148
+ withCredentials: true,
149
+ timeout: config.timeout || 30000,
150
+ ...(config.adapter ? { adapter: config.adapter } : {}),
151
+ } as any) as any
152
+ ) as any;
153
+ } else {
154
+ // Browser / Chrome Extension environment
155
+ this.client = axios.create({
123
156
  withCredentials: true,
124
157
  timeout: config.timeout || 30000,
125
- } as any) as any
126
- ) as any;
158
+ ...(config.adapter ? { adapter: config.adapter } : {}),
159
+ });
160
+
161
+ // Interceptor to strip unsafe headers forbidden by browsers (Fetch / XHR specification)
162
+ const unsafeHeaders = ["user-agent", "referer", "cookie", "origin", "host", "connection"];
163
+ this.client.interceptors.request.use((reqConfig) => {
164
+ if (reqConfig.headers) {
165
+ for (const header of unsafeHeaders) {
166
+ delete (reqConfig.headers as any)[header];
167
+ delete (reqConfig.headers as any)[header.toLowerCase()];
168
+ delete (reqConfig.headers as any)[header.toUpperCase()];
169
+ const titleCase = header.charAt(0).toUpperCase() + header.slice(1);
170
+ delete (reqConfig.headers as any)[titleCase];
171
+ }
172
+ }
173
+ return reqConfig;
174
+ });
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Synchronize a cookie string into Chrome Extension's cookie store (chrome.cookies API).
180
+ */
181
+ public static async syncCookiesToChrome(cookieString: string, domainUrl: string = "https://booking.thaiticketmajor.com"): Promise<void> {
182
+ if (typeof chrome === "undefined" || !chrome?.cookies?.set) {
183
+ return;
184
+ }
185
+
186
+ const pairs = cookieString.split(";");
187
+ for (const pair of pairs) {
188
+ const trimmed = pair.trim();
189
+ if (!trimmed) continue;
190
+ const eqIndex = trimmed.indexOf("=");
191
+ if (eqIndex === -1) continue;
192
+
193
+ const name = trimmed.substring(0, eqIndex).trim();
194
+ const value = trimmed.substring(eqIndex + 1).trim();
195
+ if (!name) continue;
196
+
197
+ try {
198
+ await chrome.cookies.set({
199
+ url: domainUrl,
200
+ name,
201
+ value,
202
+ domain: ".thaiticketmajor.com",
203
+ path: "/",
204
+ });
205
+ } catch {
206
+ try {
207
+ await chrome.cookies.set({
208
+ url: domainUrl,
209
+ name,
210
+ value,
211
+ path: "/",
212
+ });
213
+ } catch {}
214
+ }
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Setup declarativeNetRequest session rules in Chrome Extension to set Referer and Origin headers
220
+ */
221
+ public static async setupExtensionRules(): Promise<void> {
222
+ if (typeof chrome === "undefined" || !chrome?.declarativeNetRequest?.updateSessionRules) {
223
+ return;
224
+ }
225
+
226
+ try {
227
+ await chrome.declarativeNetRequest.updateSessionRules({
228
+ removeRuleIds: [1001, 1002],
229
+ addRules: [
230
+ {
231
+ id: 1001,
232
+ priority: 1,
233
+ action: {
234
+ type: chrome.declarativeNetRequest.RuleActionType?.MODIFY_HEADERS || "modifyHeaders",
235
+ requestHeaders: [
236
+ {
237
+ header: "Referer",
238
+ operation: chrome.declarativeNetRequest.HeaderOperation?.SET || "set",
239
+ value: "https://booking.thaiticketmajor.com",
240
+ },
241
+ {
242
+ header: "Origin",
243
+ operation: chrome.declarativeNetRequest.HeaderOperation?.SET || "set",
244
+ value: "https://booking.thaiticketmajor.com",
245
+ },
246
+ ],
247
+ },
248
+ condition: {
249
+ urlFilter: "thaiticketmajor.com",
250
+ resourceTypes: [
251
+ chrome.declarativeNetRequest.ResourceType?.XMLHTTPREQUEST || "xmlhttprequest",
252
+ chrome.declarativeNetRequest.ResourceType?.SUB_FRAME || "sub_frame",
253
+ chrome.declarativeNetRequest.ResourceType?.MAIN_FRAME || "main_frame",
254
+ chrome.declarativeNetRequest.ResourceType?.OTHER || "other",
255
+ ],
256
+ },
257
+ },
258
+ {
259
+ id: 1002,
260
+ priority: 1,
261
+ action: {
262
+ type: chrome.declarativeNetRequest.RuleActionType?.MODIFY_HEADERS || "modifyHeaders",
263
+ requestHeaders: [
264
+ {
265
+ header: "Referer",
266
+ operation: chrome.declarativeNetRequest.HeaderOperation?.SET || "set",
267
+ value: "https://kpaymentgateway.kasikornbank.com/",
268
+ },
269
+ ],
270
+ },
271
+ condition: {
272
+ urlFilter: "kasikornbank.com",
273
+ resourceTypes: [
274
+ chrome.declarativeNetRequest.ResourceType?.XMLHTTPREQUEST || "xmlhttprequest",
275
+ chrome.declarativeNetRequest.ResourceType?.OTHER || "other",
276
+ ],
277
+ },
278
+ },
279
+ ],
280
+ });
281
+ } catch (err) {
282
+ console.warn("Could not set declarativeNetRequest session rules:", err);
283
+ }
284
+ }
285
+
286
+ public async syncCookies(domainUrl?: string): Promise<void> {
287
+ if (this.rawCookies) {
288
+ await ThaiTicketMajor.syncCookiesToChrome(this.rawCookies, domainUrl);
289
+ }
127
290
  }
128
291
 
129
292
  private emitProgress(step: string, message: string, data?: any) {
@@ -928,6 +1091,15 @@ export class ThaiTicketMajor {
928
1091
  this.onProgressCallback = options.onProgress;
929
1092
  }
930
1093
 
1094
+ // In Chrome Extension environment, prepare cookies and network rules
1095
+ if (this.inBrowser) {
1096
+ this.emitProgress("INIT_EXTENSION", "Preparing Chrome extension cookies and network rules...");
1097
+ if (this.rawCookies) {
1098
+ await this.syncCookies();
1099
+ }
1100
+ await ThaiTicketMajor.setupExtensionRules();
1101
+ }
1102
+
931
1103
  // 1. ดึงรอบการแสดง
932
1104
  const rounds = await this.getRounds(eventUrl);
933
1105
  if (rounds.length === 0) {