prototurk-sdk 0.0.1
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 +189 -0
- package/dist/client/Client.d.ts +61 -0
- package/dist/client/Client.d.ts.map +1 -0
- package/dist/client/Client.js +95 -0
- package/dist/client/Client.js.map +1 -0
- package/dist/client/ClientUser.d.ts +22 -0
- package/dist/client/ClientUser.d.ts.map +1 -0
- package/dist/client/ClientUser.js +19 -0
- package/dist/client/ClientUser.js.map +1 -0
- package/dist/gateway/EventPoller.d.ts +23 -0
- package/dist/gateway/EventPoller.d.ts.map +1 -0
- package/dist/gateway/EventPoller.js +99 -0
- package/dist/gateway/EventPoller.js.map +1 -0
- package/dist/gateway/GatewayEvents.d.ts +28 -0
- package/dist/gateway/GatewayEvents.d.ts.map +1 -0
- package/dist/gateway/GatewayEvents.js +2 -0
- package/dist/gateway/GatewayEvents.js.map +1 -0
- package/dist/gateway/WebhookHandler.d.ts +13 -0
- package/dist/gateway/WebhookHandler.d.ts.map +1 -0
- package/dist/gateway/WebhookHandler.js +51 -0
- package/dist/gateway/WebhookHandler.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/managers/DMManager.d.ts +37 -0
- package/dist/managers/DMManager.d.ts.map +1 -0
- package/dist/managers/DMManager.js +50 -0
- package/dist/managers/DMManager.js.map +1 -0
- package/dist/managers/PostManager.d.ts +45 -0
- package/dist/managers/PostManager.d.ts.map +1 -0
- package/dist/managers/PostManager.js +60 -0
- package/dist/managers/PostManager.js.map +1 -0
- package/dist/managers/UploadManager.d.ts +30 -0
- package/dist/managers/UploadManager.d.ts.map +1 -0
- package/dist/managers/UploadManager.js +57 -0
- package/dist/managers/UploadManager.js.map +1 -0
- package/dist/managers/UserManager.d.ts +13 -0
- package/dist/managers/UserManager.d.ts.map +1 -0
- package/dist/managers/UserManager.js +21 -0
- package/dist/managers/UserManager.js.map +1 -0
- package/dist/rest/APIError.d.ts +6 -0
- package/dist/rest/APIError.d.ts.map +1 -0
- package/dist/rest/APIError.js +11 -0
- package/dist/rest/APIError.js.map +1 -0
- package/dist/rest/RESTManager.d.ts +15 -0
- package/dist/rest/RESTManager.d.ts.map +1 -0
- package/dist/rest/RESTManager.js +62 -0
- package/dist/rest/RESTManager.js.map +1 -0
- package/dist/structures/Base.d.ts +6 -0
- package/dist/structures/Base.d.ts.map +1 -0
- package/dist/structures/Base.js +7 -0
- package/dist/structures/Base.js.map +1 -0
- package/dist/structures/DMConversation.d.ts +33 -0
- package/dist/structures/DMConversation.d.ts.map +1 -0
- package/dist/structures/DMConversation.js +28 -0
- package/dist/structures/DMConversation.js.map +1 -0
- package/dist/structures/DMMessage.d.ts +31 -0
- package/dist/structures/DMMessage.d.ts.map +1 -0
- package/dist/structures/DMMessage.js +31 -0
- package/dist/structures/DMMessage.js.map +1 -0
- package/dist/structures/Post.d.ts +63 -0
- package/dist/structures/Post.d.ts.map +1 -0
- package/dist/structures/Post.js +42 -0
- package/dist/structures/Post.js.map +1 -0
- package/dist/structures/User.d.ts +33 -0
- package/dist/structures/User.d.ts.map +1 -0
- package/dist/structures/User.js +29 -0
- package/dist/structures/User.js.map +1 -0
- package/dist/util/Collection.d.ts +14 -0
- package/dist/util/Collection.d.ts.map +1 -0
- package/dist/util/Collection.js +50 -0
- package/dist/util/Collection.js.map +1 -0
- package/dist/util/Constants.d.ts +44 -0
- package/dist/util/Constants.d.ts.map +1 -0
- package/dist/util/Constants.js +47 -0
- package/dist/util/Constants.js.map +1 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Prototurk SDK
|
|
2
|
+
|
|
3
|
+
Prototurk Developer API'si için hazırlanmış; tamamen nesne yönelimli, olay güdümlü (event-driven) ve **%100 TypeScript / Type-Safe** destekli resmi olmayan SDK.
|
|
4
|
+
|
|
5
|
+
Bu SDK, Prototurk API'sinin tüm uç noktalarına (DM'ler, Gönderiler, Kullanıcılar, Yüklemeler vb.) kolayca erişmenizi ve botlarınızı hızlıca geliştirmenizi sağlar.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🚀 Özellikler
|
|
10
|
+
|
|
11
|
+
- **Tip Güvenliği (Type-Safe):** Tüm event payload'ları, dönecek değerler ve fonksiyon parametreleri katı TypeScript tipleriyle tanımlanmıştır. Editörünüz (IntelliSense) size yol gösterir.
|
|
12
|
+
- **Olay Güdümlü (Event-Driven):** `dmMessageCreate`, `mention`, `reply` gibi olayları `EventEmitter` üzerinden kolaylıkla dinleyin.
|
|
13
|
+
- **Çoklu Event Dinleme:** `client.on(["mention", "reply"], ...)` gibi yapılarla olayları kolayca gruplayın.
|
|
14
|
+
- **Gelişmiş Manager Yapısı:** `client.posts`, `client.dms`, `client.users`, `client.uploads` ile metotlar birbirine karışmaz.
|
|
15
|
+
- **Polling ve Webhook Desteği:** İster Polling ile periyodik kontrol, isterseniz `WebhookHandler` ile HTTP tabanlı gerçek zamanlı webhook dinleme yapın.
|
|
16
|
+
- **Kolay Medya Yükleme:** Görselleri kolayca yükleyin, DM veya Gönderilere key atayarak ilişkilendirin.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 📦 Kurulum
|
|
21
|
+
|
|
22
|
+
Proje **Bun** tabanlıdır veya standart Node.js / npm projelerinde kullanılabilir.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Bun ile kurulum
|
|
26
|
+
bun install
|
|
27
|
+
|
|
28
|
+
# NPM ile kurulum
|
|
29
|
+
npm install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🛠 Hızlı Başlangıç
|
|
35
|
+
|
|
36
|
+
Aşağıdaki örnekte botunuzun API'ye nasıl bağlanıp DM ve Etkileşimleri dinleyebileceği gösterilmektedir.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Client } from "prototurk-sdk";
|
|
40
|
+
import * as fs from "fs";
|
|
41
|
+
|
|
42
|
+
const client = new Client({
|
|
43
|
+
token: "ptk_live_BURAYA_TOKEN_GELECEK",
|
|
44
|
+
autoPoll: true, // Otomatik event polling açar
|
|
45
|
+
|
|
46
|
+
// Polling cursor (kaldığı yer) kaydetme mekanizmaları (opsiyonel ama önerilir)
|
|
47
|
+
getEventSince: async () => {
|
|
48
|
+
try {
|
|
49
|
+
return await fs.promises.readFile("cursor.txt", "utf-8");
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
saveEventSince: async (cursor) => {
|
|
55
|
+
await fs.promises.writeFile("cursor.txt", cursor);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
client.on("ready", () => {
|
|
60
|
+
console.log(`🚀 ${client.user?.username} olarak giriş yapıldı!`);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// DM Mesajlarını Dinleme
|
|
64
|
+
client.on("dmMessageCreate", async (message) => {
|
|
65
|
+
// Kendi kendine veya diğer botlara cevap vermeyi engelle
|
|
66
|
+
if (message.fromBot || message.authorUsername === client.user?.username)
|
|
67
|
+
return;
|
|
68
|
+
|
|
69
|
+
console.log(`[DM] ${message.authorUsername}: ${message.text}`);
|
|
70
|
+
|
|
71
|
+
if (message.text.toLowerCase() === "ping") {
|
|
72
|
+
await message.reply("pong!");
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Çoklu Olay (Mention ve Reply) Dinleme
|
|
77
|
+
client.on(["mention", "reply"], async (payload) => {
|
|
78
|
+
if (payload.actor.username === client.user?.username) return;
|
|
79
|
+
|
|
80
|
+
const targetId =
|
|
81
|
+
payload.commentId ||
|
|
82
|
+
payload.postId ||
|
|
83
|
+
(payload.entityType === "post" ? payload.entityId : null);
|
|
84
|
+
if (!targetId) return;
|
|
85
|
+
|
|
86
|
+
console.log(
|
|
87
|
+
`[Etkileşim] ${payload.actor.username} size yanıt verdi/bahsetti.`,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Yanıt Atma
|
|
91
|
+
await client.posts.createComment(
|
|
92
|
+
targetId,
|
|
93
|
+
`Merhaba @${payload.actor.username}!`,
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Başlat
|
|
98
|
+
client.login().catch(console.error);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 📚 Modüller ve Managerlar
|
|
104
|
+
|
|
105
|
+
Client yapılandırıldıktan sonra `client` objesi üzerinden birçok farklı yöneticilere (manager) ulaşabilirsiniz:
|
|
106
|
+
|
|
107
|
+
### ✉️ DM Manager (`client.dms`)
|
|
108
|
+
|
|
109
|
+
DM API'si uç noktaları. Yalnızca birebir (1:1) konuşmaları destekler.
|
|
110
|
+
|
|
111
|
+
- `client.dms.fetchConversations({ limit, cursor })`: Gelen kutusundaki sohbetleri getirir.
|
|
112
|
+
- `client.dms.fetchMessages(conversationId, { limit, cursor })`: Bir sohbetin mesajlarını sondan başa getirir.
|
|
113
|
+
- `client.dms.createMessage(conversationId, content)`: İlgili sohbete bot adına yanıt/mesaj gönderir.
|
|
114
|
+
|
|
115
|
+
### 📝 Post Manager (`client.posts`)
|
|
116
|
+
|
|
117
|
+
Gönderiler ve yorumlarla ilgili işlemler.
|
|
118
|
+
|
|
119
|
+
- `client.posts.create(content)`: Yeni bir gönderi (post) oluşturur.
|
|
120
|
+
- `client.posts.createComment(postId, content)`: İlgili gönderiye veya yoruma yanıt atar.
|
|
121
|
+
- `client.posts.fetch(postId)`: Gönderi detaylarını ve görselleri çeker.
|
|
122
|
+
- `client.posts.fetchFeed()`: Herkese açık akışı getirir.
|
|
123
|
+
- `client.posts.search(query)`: Gönderiler arasında arama yapar.
|
|
124
|
+
|
|
125
|
+
> **İpucu:** Kısa yollar mevcuttur: `client.fetchPost(id)` => `client.posts.fetch(id)`
|
|
126
|
+
|
|
127
|
+
### 👤 User Manager (`client.users`)
|
|
128
|
+
|
|
129
|
+
Kullanıcı profilleri için kullanılır.
|
|
130
|
+
|
|
131
|
+
- `client.users.fetch("username")`: Belirtilen kullanıcının detaylarını (isBot, avatarUrl vs.) getirir.
|
|
132
|
+
|
|
133
|
+
### 🖼️ Upload Manager (`client.uploads`)
|
|
134
|
+
|
|
135
|
+
Medya (resim) yüklemelerini yönetir. Bir resim yüklendiğinde size tek kullanımlık bir `key` verilir. Bu key'i daha sonra gönderi veya mesaja ekleyebilirsiniz.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
const upload = await client.uploads.uploadFromFile("./ornek-resim.jpg");
|
|
139
|
+
|
|
140
|
+
// Post'a resimli yanıt atmak
|
|
141
|
+
await client.posts.createComment(targetId, {
|
|
142
|
+
text: "İşte istediğin resim!",
|
|
143
|
+
imageKeys: [upload.key],
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 📡 Olaylar (Events)
|
|
150
|
+
|
|
151
|
+
Olay güdümlü mimari sayesinde API'den gelen aksiyonları anında dinleyebilirsiniz.
|
|
152
|
+
|
|
153
|
+
Mevcut Event'ler (`ClientEvents`):
|
|
154
|
+
|
|
155
|
+
- `ready`: Bot başarılı bir şekilde bağlandığında tetiklenir.
|
|
156
|
+
- `error`: SDK içinde (örneğin polling anında) bir API hatası meydana geldiğinde fırlatılır.
|
|
157
|
+
- `dmMessageCreate`: Biri bota DM yazdığında tetiklenir. Payload: `DMMessage` objesidir. İçinden direkt `.reply()` kullanılabilir.
|
|
158
|
+
- `mention`: Bir post veya yorumda bottan bahsedildiğinde tetiklenir.
|
|
159
|
+
- `reply`: Botun bir postuna/yorumuna yanıt geldiğinde tetiklenir.
|
|
160
|
+
- `comment`: Yeni bir yorum atıldığında.
|
|
161
|
+
- `follow`: Biri botu takip ettiğinde.
|
|
162
|
+
- `like`: Botun içeriği beğenildiğinde.
|
|
163
|
+
- `repost`: Botun içeriği paylaşıldığında.
|
|
164
|
+
- `quote`: Botun içeriği alıntılandığında.
|
|
165
|
+
|
|
166
|
+
> `mention`, `reply` ve diğer etkileşim eventleri ortak bir `GenericEventPayload` döndürür. Bu obje içerisindeki `actor`, `entityId`, `postId`, `commentId` gibi özellikleri kullanarak tepki verebilirsiniz.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 🏗️ Gelişmiş Özellikler
|
|
171
|
+
|
|
172
|
+
### Webhook Kullanımı
|
|
173
|
+
|
|
174
|
+
Eğer Polling yerine Webhook kullanmak isterseniz, `ClientOptions` içinde `autoPoll: false` yapıp gelen istekleri doğrudan içeri aktarabilirsiniz.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { WebhookHandler } from "prototurk-sdk";
|
|
178
|
+
|
|
179
|
+
const handler = new WebhookHandler(client, "webhook_secret_key");
|
|
180
|
+
|
|
181
|
+
// Örnek bir Express.js Controller'ı
|
|
182
|
+
app.post("/webhook", (req, res) => {
|
|
183
|
+
const signature = req.headers["x-prototurk-signature"];
|
|
184
|
+
const isVerified = handler.handleRequest(req.body, signature);
|
|
185
|
+
|
|
186
|
+
if (!isVerified) return res.status(401).send("Invalid Signature");
|
|
187
|
+
res.status(200).send("OK");
|
|
188
|
+
});
|
|
189
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { RESTManager } from "../rest/RESTManager";
|
|
3
|
+
import { ClientUser } from "./ClientUser";
|
|
4
|
+
import { PostManager } from "../managers/PostManager";
|
|
5
|
+
import { UserManager } from "../managers/UserManager";
|
|
6
|
+
import { DMManager } from "../managers/DMManager";
|
|
7
|
+
import { UploadManager } from "../managers/UploadManager";
|
|
8
|
+
import { EventPoller } from "../gateway/EventPoller";
|
|
9
|
+
import { type ClientEvents } from "../gateway/GatewayEvents";
|
|
10
|
+
export interface ClientOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The token to use for authenticating requests.
|
|
13
|
+
*/
|
|
14
|
+
token?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Automatically start polling for events upon login. Default: true.
|
|
17
|
+
*/
|
|
18
|
+
autoPoll?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Function to save the last processed event cursor.
|
|
21
|
+
*/
|
|
22
|
+
saveEventSince?: (cursor: string) => Promise<void> | void;
|
|
23
|
+
/**
|
|
24
|
+
* Function to retrieve the last processed event cursor on startup.
|
|
25
|
+
*/
|
|
26
|
+
getEventSince?: () => Promise<string | null> | string | null;
|
|
27
|
+
}
|
|
28
|
+
export declare interface Client {
|
|
29
|
+
on<K extends keyof ClientEvents>(event: K | K[], listener: (...args: ClientEvents[K]) => void): this;
|
|
30
|
+
on(event: string | symbol | (string | symbol)[], listener: (...args: any[]) => void): this;
|
|
31
|
+
once<K extends keyof ClientEvents>(event: K | K[], listener: (...args: ClientEvents[K]) => void): this;
|
|
32
|
+
once(event: string | symbol | (string | symbol)[], listener: (...args: any[]) => void): this;
|
|
33
|
+
emit<K extends keyof ClientEvents>(event: K, ...args: ClientEvents[K]): boolean;
|
|
34
|
+
emit(event: string | symbol, ...args: any[]): boolean;
|
|
35
|
+
}
|
|
36
|
+
export declare class Client extends EventEmitter {
|
|
37
|
+
options: ClientOptions;
|
|
38
|
+
rest: RESTManager;
|
|
39
|
+
user: ClientUser | null;
|
|
40
|
+
posts: PostManager;
|
|
41
|
+
users: UserManager;
|
|
42
|
+
dms: DMManager;
|
|
43
|
+
uploads: UploadManager;
|
|
44
|
+
poller: EventPoller;
|
|
45
|
+
constructor(options?: ClientOptions);
|
|
46
|
+
/**
|
|
47
|
+
* Fetch a post by ID
|
|
48
|
+
*/
|
|
49
|
+
fetchPost(id: string): Promise<import("..").Post>;
|
|
50
|
+
/**
|
|
51
|
+
* Logs in to the Prototurk API, fetching the bot user profile.
|
|
52
|
+
* If `autoPoll` is true, it starts listening to events.
|
|
53
|
+
* @param token The token to use.
|
|
54
|
+
*/
|
|
55
|
+
login(token?: string): Promise<string>;
|
|
56
|
+
/**
|
|
57
|
+
* Disconnects the client, stopping any active polling.
|
|
58
|
+
*/
|
|
59
|
+
destroy(): void;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=Client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../../src/client/Client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAuB,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;CAChE;AAED,MAAM,CAAC,OAAO,WAAW,MAAM;IAC3B,EAAE,CAAC,CAAC,SAAS,MAAM,YAAY,EAC3B,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,EACd,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,GAC7C,IAAI,CAAC;IACR,EAAE,CACE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAC5C,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GACnC,IAAI,CAAC;IACR,IAAI,CAAC,CAAC,SAAS,MAAM,YAAY,EAC7B,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,EACd,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,GAC7C,IAAI,CAAC;IACR,IAAI,CACA,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAC5C,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GACnC,IAAI,CAAC;IACR,IAAI,CAAC,CAAC,SAAS,MAAM,YAAY,EAC7B,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC;IACX,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;CACzD;AAED,qBAAa,MAAO,SAAQ,YAAY;IAC7B,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,SAAS,CAAC;IACf,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,WAAW,CAAC;gBAEf,OAAO,GAAE,aAAkB;IAiDvC;;OAEG;IACU,SAAS,CAAC,EAAE,EAAE,MAAM;IAIjC;;;;OAIG;IACU,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBnD;;OAEG;IACI,OAAO;CAGjB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { RESTManager } from "../rest/RESTManager";
|
|
3
|
+
import { Endpoints, Events } from "../util/Constants";
|
|
4
|
+
import { ClientUser } from "./ClientUser";
|
|
5
|
+
import { PostManager } from "../managers/PostManager";
|
|
6
|
+
import { UserManager } from "../managers/UserManager";
|
|
7
|
+
import { DMManager } from "../managers/DMManager";
|
|
8
|
+
import { UploadManager } from "../managers/UploadManager";
|
|
9
|
+
import { EventPoller } from "../gateway/EventPoller";
|
|
10
|
+
export class Client extends EventEmitter {
|
|
11
|
+
options;
|
|
12
|
+
rest;
|
|
13
|
+
user;
|
|
14
|
+
posts;
|
|
15
|
+
users;
|
|
16
|
+
dms;
|
|
17
|
+
uploads;
|
|
18
|
+
poller;
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
super();
|
|
21
|
+
this.options = { autoPoll: true, ...options };
|
|
22
|
+
this.rest = new RESTManager();
|
|
23
|
+
this.user = null;
|
|
24
|
+
this.posts = new PostManager(this);
|
|
25
|
+
this.users = new UserManager(this);
|
|
26
|
+
this.dms = new DMManager(this);
|
|
27
|
+
this.uploads = new UploadManager(this);
|
|
28
|
+
this.poller = new EventPoller(this);
|
|
29
|
+
if (this.options.token) {
|
|
30
|
+
this.rest.setToken(this.options.token);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Override on to support array of events
|
|
35
|
+
*/
|
|
36
|
+
on(event, listener) {
|
|
37
|
+
if (Array.isArray(event)) {
|
|
38
|
+
for (const e of event) {
|
|
39
|
+
super.on(e, listener);
|
|
40
|
+
}
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
return super.on(event, listener);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Override once to support array of events
|
|
47
|
+
*/
|
|
48
|
+
once(event, listener) {
|
|
49
|
+
if (Array.isArray(event)) {
|
|
50
|
+
for (const e of event) {
|
|
51
|
+
super.once(e, listener);
|
|
52
|
+
}
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
return super.once(event, listener);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Fetch a post by ID
|
|
59
|
+
*/
|
|
60
|
+
async fetchPost(id) {
|
|
61
|
+
return this.posts.fetch(id);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Logs in to the Prototurk API, fetching the bot user profile.
|
|
65
|
+
* If `autoPoll` is true, it starts listening to events.
|
|
66
|
+
* @param token The token to use.
|
|
67
|
+
*/
|
|
68
|
+
async login(token) {
|
|
69
|
+
const loginToken = token || this.options.token;
|
|
70
|
+
if (!loginToken) {
|
|
71
|
+
throw new Error("TOKEN_MISSING: A token is required to login.");
|
|
72
|
+
}
|
|
73
|
+
this.options.token = loginToken;
|
|
74
|
+
this.rest.setToken(loginToken);
|
|
75
|
+
try {
|
|
76
|
+
const userData = await this.rest.get(Endpoints.ME);
|
|
77
|
+
this.user = new ClientUser(this, userData);
|
|
78
|
+
this.emit(Events.READY);
|
|
79
|
+
if (this.options.autoPoll) {
|
|
80
|
+
this.poller.start();
|
|
81
|
+
}
|
|
82
|
+
return loginToken;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Disconnects the client, stopping any active polling.
|
|
90
|
+
*/
|
|
91
|
+
destroy() {
|
|
92
|
+
this.poller.stop();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=Client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Client.js","sourceRoot":"","sources":["../../src/client/Client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Base } from '../structures/Base';
|
|
2
|
+
import { Client } from './Client';
|
|
3
|
+
export interface ClientUserData {
|
|
4
|
+
id: string;
|
|
5
|
+
username: string;
|
|
6
|
+
name: string;
|
|
7
|
+
avatarUrl: string | null;
|
|
8
|
+
isBot: boolean;
|
|
9
|
+
app: {
|
|
10
|
+
id: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare class ClientUser extends Base {
|
|
14
|
+
id: string;
|
|
15
|
+
username: string;
|
|
16
|
+
name: string;
|
|
17
|
+
avatarUrl: string | null;
|
|
18
|
+
isBot: boolean;
|
|
19
|
+
appId: string;
|
|
20
|
+
constructor(client: Client, data: ClientUserData);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=ClientUser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientUser.d.ts","sourceRoot":"","sources":["../../src/client/ClientUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE;QACH,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;CACH;AAED,qBAAa,UAAW,SAAQ,IAAI;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;gBAET,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc;CASjD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Base } from '../structures/Base';
|
|
2
|
+
export class ClientUser extends Base {
|
|
3
|
+
id;
|
|
4
|
+
username;
|
|
5
|
+
name;
|
|
6
|
+
avatarUrl;
|
|
7
|
+
isBot;
|
|
8
|
+
appId;
|
|
9
|
+
constructor(client, data) {
|
|
10
|
+
super(client);
|
|
11
|
+
this.id = data.id;
|
|
12
|
+
this.username = data.username;
|
|
13
|
+
this.name = data.name;
|
|
14
|
+
this.avatarUrl = data.avatarUrl;
|
|
15
|
+
this.isBot = data.isBot;
|
|
16
|
+
this.appId = data.app.id;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ClientUser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClientUser.js","sourceRoot":"","sources":["../../src/client/ClientUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAc1C,MAAM,OAAO,UAAW,SAAQ,IAAI;IAC3B,EAAE,CAAS;IACX,QAAQ,CAAS;IACjB,IAAI,CAAS;IACb,SAAS,CAAgB;IACzB,KAAK,CAAU;IACf,KAAK,CAAS;IAErB,YAAY,MAAc,EAAE,IAAoB;QAC9C,KAAK,CAAC,MAAM,CAAC,CAAC;QACd,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Client } from "../client/Client";
|
|
2
|
+
export interface EventData {
|
|
3
|
+
id: string;
|
|
4
|
+
type: string;
|
|
5
|
+
payload: any;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
}
|
|
8
|
+
export interface EventsResponse {
|
|
9
|
+
events: EventData[];
|
|
10
|
+
cursor: string | null;
|
|
11
|
+
}
|
|
12
|
+
export declare class EventPoller {
|
|
13
|
+
client: Client;
|
|
14
|
+
private intervalId;
|
|
15
|
+
private since;
|
|
16
|
+
private pollIntervalMs;
|
|
17
|
+
constructor(client: Client);
|
|
18
|
+
start(): Promise<void>;
|
|
19
|
+
stop(): void;
|
|
20
|
+
private poll;
|
|
21
|
+
handleEvent(event: EventData): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=EventPoller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventPoller.d.ts","sourceRoot":"","sources":["../../src/gateway/EventPoller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1C,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,qBAAa,WAAW;IACb,MAAM,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,cAAc,CAAgB;gBAE1B,MAAM,EAAE,MAAM;IAIb,KAAK;IAqBX,IAAI;YAOG,IAAI;IA2CX,WAAW,CAAC,KAAK,EAAE,SAAS;CAqCtC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Endpoints, Events as ClientEvents } from "../util/Constants";
|
|
2
|
+
import { DMMessage } from "../structures/DMMessage";
|
|
3
|
+
export class EventPoller {
|
|
4
|
+
client;
|
|
5
|
+
intervalId = null;
|
|
6
|
+
since = null;
|
|
7
|
+
pollIntervalMs = 3000; // default to 3s
|
|
8
|
+
constructor(client) {
|
|
9
|
+
this.client = client;
|
|
10
|
+
}
|
|
11
|
+
async start() {
|
|
12
|
+
if (this.intervalId)
|
|
13
|
+
return;
|
|
14
|
+
if (this.client.options.getEventSince) {
|
|
15
|
+
try {
|
|
16
|
+
const savedSince = await this.client.options.getEventSince();
|
|
17
|
+
if (savedSince) {
|
|
18
|
+
this.since = savedSince;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
this.client.emit(ClientEvents.ERROR, err instanceof Error ? err : new Error(err?.toString()));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
this.intervalId = setInterval(() => this.poll(), this.pollIntervalMs);
|
|
26
|
+
this.poll(); // Trigger an immediate poll upon start
|
|
27
|
+
}
|
|
28
|
+
stop() {
|
|
29
|
+
if (this.intervalId) {
|
|
30
|
+
clearInterval(this.intervalId);
|
|
31
|
+
this.intervalId = null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async poll() {
|
|
35
|
+
try {
|
|
36
|
+
const query = {};
|
|
37
|
+
if (this.since) {
|
|
38
|
+
query.since = this.since;
|
|
39
|
+
}
|
|
40
|
+
const response = await this.client.rest.get(Endpoints.EVENTS, query);
|
|
41
|
+
let cursorUpdated = false;
|
|
42
|
+
if (response.cursor && response.cursor !== this.since) {
|
|
43
|
+
this.since = response.cursor;
|
|
44
|
+
cursorUpdated = true;
|
|
45
|
+
}
|
|
46
|
+
for (const evt of response.events) {
|
|
47
|
+
this.handleEvent(evt);
|
|
48
|
+
// keep track of max cursor just in case response.cursor is missing but events exist
|
|
49
|
+
if (this.since !== evt.id) {
|
|
50
|
+
this.since = evt.id;
|
|
51
|
+
cursorUpdated = true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (cursorUpdated &&
|
|
55
|
+
this.client.options.saveEventSince &&
|
|
56
|
+
this.since) {
|
|
57
|
+
await this.client.options.saveEventSince(this.since);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
this.client.emit(ClientEvents.ERROR, err instanceof Error ? err : new Error(err?.toString()));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
handleEvent(event) {
|
|
65
|
+
switch (event.type) {
|
|
66
|
+
case "dm.message": {
|
|
67
|
+
const payload = event.payload;
|
|
68
|
+
// payload: { conversationId, from: { userId, username, name }, excerpt }
|
|
69
|
+
// Attempt to create a mock DMMessage to emit, or fetch full DM if needed.
|
|
70
|
+
// For standard event emission, we can emit raw data or a partial DMMessage.
|
|
71
|
+
const msg = new DMMessage(this.client, {
|
|
72
|
+
id: event.id, // we don't have the message ID in the payload unfortunately, using event ID as fallback
|
|
73
|
+
conversationId: payload.conversationId,
|
|
74
|
+
fromBot: payload.from.userId === this.client.user?.id,
|
|
75
|
+
authorUsername: payload.from.username,
|
|
76
|
+
text: payload.excerpt,
|
|
77
|
+
createdAt: event.createdAt,
|
|
78
|
+
replyToId: null,
|
|
79
|
+
});
|
|
80
|
+
this.client.emit(ClientEvents.DM_MESSAGE_CREATE, msg);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
case "mention":
|
|
84
|
+
case "comment":
|
|
85
|
+
case "reply":
|
|
86
|
+
case "follow":
|
|
87
|
+
case "like":
|
|
88
|
+
case "repost":
|
|
89
|
+
case "quote":
|
|
90
|
+
// Emit other events generically for now
|
|
91
|
+
this.client.emit(event.type, event.payload);
|
|
92
|
+
break;
|
|
93
|
+
default:
|
|
94
|
+
// Unknown event
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=EventPoller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventPoller.js","sourceRoot":"","sources":["../../src/gateway/EventPoller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DMMessage } from '../structures/DMMessage';
|
|
2
|
+
export interface EventActor {
|
|
3
|
+
username: string;
|
|
4
|
+
name: string;
|
|
5
|
+
avatarUrl?: string | null;
|
|
6
|
+
isBot?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface GenericEventPayload {
|
|
9
|
+
actor: EventActor;
|
|
10
|
+
entityType: string;
|
|
11
|
+
entityId: string;
|
|
12
|
+
excerpt: string | null;
|
|
13
|
+
postId: string | null;
|
|
14
|
+
commentId: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface ClientEvents {
|
|
17
|
+
ready: [];
|
|
18
|
+
error: [error: Error];
|
|
19
|
+
dmMessageCreate: [message: DMMessage];
|
|
20
|
+
mention: [payload: GenericEventPayload];
|
|
21
|
+
reply: [payload: GenericEventPayload];
|
|
22
|
+
comment: [payload: GenericEventPayload];
|
|
23
|
+
follow: [payload: GenericEventPayload];
|
|
24
|
+
like: [payload: GenericEventPayload];
|
|
25
|
+
repost: [payload: GenericEventPayload];
|
|
26
|
+
quote: [payload: GenericEventPayload];
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=GatewayEvents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GatewayEvents.d.ts","sourceRoot":"","sources":["../../src/gateway/GatewayEvents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,EAAE,CAAC;IACV,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtB,eAAe,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACxC,KAAK,EAAE,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACvC,IAAI,EAAE,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACrC,MAAM,EAAE,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACvC,KAAK,EAAE,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;CACvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GatewayEvents.js","sourceRoot":"","sources":["../../src/gateway/GatewayEvents.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Client } from "../client/Client";
|
|
2
|
+
export declare class WebhookHandler {
|
|
3
|
+
client: Client;
|
|
4
|
+
private secret;
|
|
5
|
+
constructor(client: Client, secret: string);
|
|
6
|
+
/**
|
|
7
|
+
* Verifies the webhook signature and processes the payload.
|
|
8
|
+
* @param rawBody The raw text body of the webhook request.
|
|
9
|
+
* @param signatureHeader The `X-Prototurk-Signature` header value (`t=<unix>,v1=<hex>`).
|
|
10
|
+
*/
|
|
11
|
+
handleRequest(rawBody: string, signatureHeader: string): boolean;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=WebhookHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebhookHandler.d.ts","sourceRoot":"","sources":["../../src/gateway/WebhookHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,qBAAa,cAAc;IAChB,MAAM,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAK1C;;;;OAIG;IACI,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO;CA2C1E"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
export class WebhookHandler {
|
|
3
|
+
client;
|
|
4
|
+
secret;
|
|
5
|
+
constructor(client, secret) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
this.secret = secret;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Verifies the webhook signature and processes the payload.
|
|
11
|
+
* @param rawBody The raw text body of the webhook request.
|
|
12
|
+
* @param signatureHeader The `X-Prototurk-Signature` header value (`t=<unix>,v1=<hex>`).
|
|
13
|
+
*/
|
|
14
|
+
handleRequest(rawBody, signatureHeader) {
|
|
15
|
+
const parts = signatureHeader.split(",");
|
|
16
|
+
let timestamp = "";
|
|
17
|
+
let signature = "";
|
|
18
|
+
for (const part of parts) {
|
|
19
|
+
if (part.startsWith("t="))
|
|
20
|
+
timestamp = part.slice(2);
|
|
21
|
+
if (part.startsWith("v1="))
|
|
22
|
+
signature = part.slice(3);
|
|
23
|
+
}
|
|
24
|
+
if (!timestamp || !signature)
|
|
25
|
+
return false;
|
|
26
|
+
// Optional: check if timestamp is not too old to prevent replay attacks (e.g. 5 minutes)
|
|
27
|
+
// const now = Math.floor(Date.now() / 1000);
|
|
28
|
+
// if (now - parseInt(timestamp, 10) > 300) return false;
|
|
29
|
+
const payloadToSign = `${timestamp}.${rawBody}`;
|
|
30
|
+
const expectedSignature = crypto
|
|
31
|
+
.createHmac("sha256", this.secret)
|
|
32
|
+
.update(payloadToSign)
|
|
33
|
+
.digest("hex");
|
|
34
|
+
if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {
|
|
35
|
+
try {
|
|
36
|
+
const body = JSON.parse(rawBody);
|
|
37
|
+
if (body.events && Array.isArray(body.events)) {
|
|
38
|
+
for (const evt of body.events) {
|
|
39
|
+
this.client.poller.handleEvent(evt);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=WebhookHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebhookHandler.js","sourceRoot":"","sources":["../../src/gateway/WebhookHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAIjC,MAAM,OAAO,cAAc;IAChB,MAAM,CAAS;IACd,MAAM,CAAS;IAEvB,YAAY,MAAc,EAAE,MAAc;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACI,aAAa,CAAC,OAAe,EAAE,eAAuB;QACzD,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,IAAI,SAAS,GAAG,EAAE,CAAC;QAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrD,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAE3C,yFAAyF;QACzF,6CAA6C;QAC7C,yDAAyD;QAEzD,MAAM,aAAa,GAAG,GAAG,SAAS,IAAI,OAAO,EAAE,CAAC;QAChD,MAAM,iBAAiB,GAAG,MAAM;aAC3B,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC;aACjC,MAAM,CAAC,aAAa,CAAC;aACrB,MAAM,CAAC,KAAK,CAAC,CAAC;QAEnB,IACI,MAAM,CAAC,eAAe,CAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CACjC,EACH,CAAC;YACC,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACjC,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,GAAgB,CAAC,CAAC;oBACrD,CAAC;gBACL,CAAC;gBACD,OAAO,IAAI,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACL,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;CACJ"}
|