kakaoforge 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/LICENSE +33 -0
- package/README.md +772 -0
- package/dist/auth/crypto.d.ts +4 -0
- package/dist/auth/crypto.js +69 -0
- package/dist/auth/login.d.ts +53 -0
- package/dist/auth/login.js +559 -0
- package/dist/crypto/v2sl.d.ts +14 -0
- package/dist/crypto/v2sl.js +118 -0
- package/dist/db/kakao-db.d.ts +51 -0
- package/dist/db/kakao-db.js +194 -0
- package/dist/db/kakao-schema-secondary.d.ts +2 -0
- package/dist/db/kakao-schema-secondary.js +57 -0
- package/dist/db/kakao-schema.d.ts +2 -0
- package/dist/db/kakao-schema.js +236 -0
- package/dist/db/kakao-secondary-db.d.ts +9 -0
- package/dist/db/kakao-secondary-db.js +69 -0
- package/dist/index.d.ts +634 -0
- package/dist/index.js +5181 -0
- package/dist/net/booking-client.d.ts +38 -0
- package/dist/net/booking-client.js +202 -0
- package/dist/net/brewery-client.d.ts +148 -0
- package/dist/net/brewery-client.js +419 -0
- package/dist/net/bubble-client.d.ts +45 -0
- package/dist/net/bubble-client.js +64 -0
- package/dist/net/calendar-client.d.ts +41 -0
- package/dist/net/calendar-client.js +80 -0
- package/dist/net/carriage-client.d.ts +56 -0
- package/dist/net/carriage-client.js +426 -0
- package/dist/net/loco-stream.d.ts +9 -0
- package/dist/net/loco-stream.js +39 -0
- package/dist/net/ticket-client.d.ts +11 -0
- package/dist/net/ticket-client.js +30 -0
- package/dist/net/upload-client.d.ts +18 -0
- package/dist/net/upload-client.js +209 -0
- package/dist/protocol/loco-packet.d.ts +19 -0
- package/dist/protocol/loco-packet.js +54 -0
- package/dist/types/attachments.d.ts +17 -0
- package/dist/types/attachments.js +14 -0
- package/dist/types/member-type.d.ts +8 -0
- package/dist/types/member-type.js +10 -0
- package/dist/types/message.d.ts +14 -0
- package/dist/types/message.js +16 -0
- package/dist/types/reaction.d.ts +10 -0
- package/dist/types/reaction.js +12 -0
- package/dist/util/client-msg-id.d.ts +1 -0
- package/dist/util/client-msg-id.js +48 -0
- package/dist/util/media.d.ts +6 -0
- package/dist/util/media.js +173 -0
- package/package.json +40 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.uploadMultipartFile = uploadMultipartFile;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const http = __importStar(require("http"));
|
|
40
|
+
const https = __importStar(require("https"));
|
|
41
|
+
const zlib = __importStar(require("zlib"));
|
|
42
|
+
const crypto = __importStar(require("crypto"));
|
|
43
|
+
const url_1 = require("url");
|
|
44
|
+
function isGzip(headers) {
|
|
45
|
+
const encoding = headers?.['content-encoding'] || headers?.['Content-Encoding'];
|
|
46
|
+
if (!encoding)
|
|
47
|
+
return false;
|
|
48
|
+
return String(encoding).toLowerCase().includes('gzip');
|
|
49
|
+
}
|
|
50
|
+
function toBuffer(input) {
|
|
51
|
+
return Buffer.from(input, 'utf-8');
|
|
52
|
+
}
|
|
53
|
+
function collectFieldBuffers(fields, boundary) {
|
|
54
|
+
const buffers = [];
|
|
55
|
+
if (!fields)
|
|
56
|
+
return buffers;
|
|
57
|
+
const pushField = (key, value) => {
|
|
58
|
+
const content = value === undefined || value === null ? '' : String(value);
|
|
59
|
+
const part = `--${boundary}\r\n`
|
|
60
|
+
+ `Content-Disposition: form-data; name="${key}"\r\n\r\n`
|
|
61
|
+
+ `${content}\r\n`;
|
|
62
|
+
buffers.push(toBuffer(part));
|
|
63
|
+
};
|
|
64
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
65
|
+
if (Array.isArray(value)) {
|
|
66
|
+
for (const item of value)
|
|
67
|
+
pushField(key, item);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
pushField(key, value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return buffers;
|
|
74
|
+
}
|
|
75
|
+
function uploadMultipartFile(opts) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
let settled = false;
|
|
78
|
+
const done = (err, res) => {
|
|
79
|
+
if (settled)
|
|
80
|
+
return;
|
|
81
|
+
settled = true;
|
|
82
|
+
if (err)
|
|
83
|
+
reject(err);
|
|
84
|
+
else
|
|
85
|
+
resolve(res);
|
|
86
|
+
};
|
|
87
|
+
if (!opts?.url) {
|
|
88
|
+
done(new Error('upload url is required'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (!opts?.filePath) {
|
|
92
|
+
done(new Error('filePath is required'));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (!fs.existsSync(opts.filePath)) {
|
|
96
|
+
done(new Error(`file not found: ${opts.filePath}`));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
let fileStat;
|
|
100
|
+
try {
|
|
101
|
+
fileStat = fs.statSync(opts.filePath);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
done(err);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const boundary = `----KakaoForge${crypto.randomBytes(8).toString('hex')}`;
|
|
108
|
+
const fieldName = opts.fieldName || 'file_1';
|
|
109
|
+
const filename = opts.filename || path.basename(opts.filePath);
|
|
110
|
+
const mime = opts.mime || 'application/octet-stream';
|
|
111
|
+
const fieldBuffers = collectFieldBuffers(opts.fields || {}, boundary);
|
|
112
|
+
const fileHeader = `--${boundary}\r\n`
|
|
113
|
+
+ `Content-Disposition: form-data; name="${fieldName}"; filename="${filename}"\r\n`
|
|
114
|
+
+ `Content-Type: ${mime}\r\n\r\n`;
|
|
115
|
+
const fileHeaderBuf = toBuffer(fileHeader);
|
|
116
|
+
const fileFooterBuf = toBuffer('\r\n');
|
|
117
|
+
const closingBuf = toBuffer(`--${boundary}--\r\n`);
|
|
118
|
+
const totalLength = fieldBuffers.reduce((sum, buf) => sum + buf.length, 0)
|
|
119
|
+
+ fileHeaderBuf.length
|
|
120
|
+
+ fileStat.size
|
|
121
|
+
+ fileFooterBuf.length
|
|
122
|
+
+ closingBuf.length;
|
|
123
|
+
let url;
|
|
124
|
+
try {
|
|
125
|
+
url = new url_1.URL(opts.url);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
done(new Error(`invalid upload url: ${opts.url}`));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const isHttps = url.protocol === 'https:';
|
|
132
|
+
const request = (isHttps ? https : http).request({
|
|
133
|
+
method: 'POST',
|
|
134
|
+
hostname: url.hostname,
|
|
135
|
+
port: url.port ? Number(url.port) : (isHttps ? 443 : 80),
|
|
136
|
+
path: `${url.pathname}${url.search}`,
|
|
137
|
+
headers: {
|
|
138
|
+
'Content-Type': `multipart/form-data; boundary=${boundary}`,
|
|
139
|
+
'Content-Length': totalLength,
|
|
140
|
+
'Accept': '*/*',
|
|
141
|
+
...opts.headers,
|
|
142
|
+
},
|
|
143
|
+
}, (res) => {
|
|
144
|
+
const chunks = [];
|
|
145
|
+
const stream = isGzip(res.headers) ? res.pipe(zlib.createGunzip()) : res;
|
|
146
|
+
stream.on('data', (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
147
|
+
stream.on('error', (err) => done(err));
|
|
148
|
+
stream.on('end', () => {
|
|
149
|
+
const body = Buffer.concat(chunks).toString('utf-8');
|
|
150
|
+
let json;
|
|
151
|
+
try {
|
|
152
|
+
json = JSON.parse(body);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
json = undefined;
|
|
156
|
+
}
|
|
157
|
+
const response = {
|
|
158
|
+
statusCode: res.statusCode || 0,
|
|
159
|
+
headers: res.headers,
|
|
160
|
+
body,
|
|
161
|
+
json,
|
|
162
|
+
};
|
|
163
|
+
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
164
|
+
done(new Error(`upload failed: status=${response.statusCode} body=${body}`));
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
done(undefined, response);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
request.on('error', (err) => done(err));
|
|
171
|
+
if (opts.timeoutMs && opts.timeoutMs > 0) {
|
|
172
|
+
request.setTimeout(opts.timeoutMs, () => {
|
|
173
|
+
request.destroy(new Error('upload timed out'));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
let sent = 0;
|
|
177
|
+
const reportProgress = () => {
|
|
178
|
+
if (opts.onProgress) {
|
|
179
|
+
opts.onProgress(sent, totalLength);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const writeBuffer = (buf) => {
|
|
183
|
+
if (!buf || buf.length === 0)
|
|
184
|
+
return;
|
|
185
|
+
request.write(buf);
|
|
186
|
+
sent += buf.length;
|
|
187
|
+
reportProgress();
|
|
188
|
+
};
|
|
189
|
+
for (const buf of fieldBuffers) {
|
|
190
|
+
writeBuffer(buf);
|
|
191
|
+
}
|
|
192
|
+
writeBuffer(fileHeaderBuf);
|
|
193
|
+
const stream = fs.createReadStream(opts.filePath);
|
|
194
|
+
stream.on('data', (chunk) => {
|
|
195
|
+
sent += chunk.length;
|
|
196
|
+
reportProgress();
|
|
197
|
+
});
|
|
198
|
+
stream.on('error', (err) => {
|
|
199
|
+
request.destroy();
|
|
200
|
+
done(err);
|
|
201
|
+
});
|
|
202
|
+
stream.on('end', () => {
|
|
203
|
+
writeBuffer(fileFooterBuf);
|
|
204
|
+
writeBuffer(closingBuf);
|
|
205
|
+
request.end();
|
|
206
|
+
});
|
|
207
|
+
stream.pipe(request, { end: false });
|
|
208
|
+
});
|
|
209
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BSON } from 'bson';
|
|
2
|
+
export declare const HEADER_SIZE = 22;
|
|
3
|
+
export declare class LocoPacket {
|
|
4
|
+
packetId: number;
|
|
5
|
+
status: number;
|
|
6
|
+
method: string;
|
|
7
|
+
body: any;
|
|
8
|
+
constructor(packetId: number, status: number, method: string, body?: any);
|
|
9
|
+
serialize(): Buffer<ArrayBuffer>;
|
|
10
|
+
static parseHeader(buf: Buffer): {
|
|
11
|
+
packetId: number;
|
|
12
|
+
status: number;
|
|
13
|
+
method: string;
|
|
14
|
+
bodyLength: number;
|
|
15
|
+
};
|
|
16
|
+
static parseBody(bodyBuf: Buffer): BSON.Document;
|
|
17
|
+
static fromBuffer(buf: Buffer): LocoPacket;
|
|
18
|
+
toString(): string;
|
|
19
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LocoPacket = exports.HEADER_SIZE = void 0;
|
|
4
|
+
const bson_1 = require("bson");
|
|
5
|
+
exports.HEADER_SIZE = 22;
|
|
6
|
+
const METHOD_LENGTH = 11;
|
|
7
|
+
class LocoPacket {
|
|
8
|
+
constructor(packetId, status, method, body = {}) {
|
|
9
|
+
this.packetId = packetId;
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.method = method;
|
|
12
|
+
this.body = body;
|
|
13
|
+
}
|
|
14
|
+
serialize() {
|
|
15
|
+
const bodyBytes = bson_1.BSON.serialize(this.body);
|
|
16
|
+
const header = Buffer.alloc(exports.HEADER_SIZE);
|
|
17
|
+
header.writeInt32LE(this.packetId, 0);
|
|
18
|
+
header.writeInt16LE(this.status, 4);
|
|
19
|
+
const methodBuf = Buffer.alloc(METHOD_LENGTH, 0);
|
|
20
|
+
Buffer.from(this.method, 'utf8').copy(methodBuf, 0, 0, METHOD_LENGTH);
|
|
21
|
+
methodBuf.copy(header, 6);
|
|
22
|
+
header.writeUInt8(0, 17);
|
|
23
|
+
header.writeInt32LE(bodyBytes.length, 18);
|
|
24
|
+
return Buffer.concat([header, bodyBytes]);
|
|
25
|
+
}
|
|
26
|
+
static parseHeader(buf) {
|
|
27
|
+
if (buf.length < exports.HEADER_SIZE)
|
|
28
|
+
return null;
|
|
29
|
+
const packetId = buf.readInt32LE(0);
|
|
30
|
+
const status = buf.readInt16LE(4);
|
|
31
|
+
const methodRaw = buf.subarray(6, 17);
|
|
32
|
+
const nullIdx = methodRaw.indexOf(0);
|
|
33
|
+
const method = methodRaw.subarray(0, nullIdx === -1 ? METHOD_LENGTH : nullIdx).toString('utf8').trim();
|
|
34
|
+
const bodyLength = buf.readInt32LE(18);
|
|
35
|
+
return { packetId, status, method, bodyLength };
|
|
36
|
+
}
|
|
37
|
+
static parseBody(bodyBuf) {
|
|
38
|
+
if (bodyBuf.length === 0)
|
|
39
|
+
return {};
|
|
40
|
+
return bson_1.BSON.deserialize(bodyBuf);
|
|
41
|
+
}
|
|
42
|
+
static fromBuffer(buf) {
|
|
43
|
+
const header = LocoPacket.parseHeader(buf);
|
|
44
|
+
if (!header)
|
|
45
|
+
return null;
|
|
46
|
+
const bodyBuf = buf.subarray(exports.HEADER_SIZE, exports.HEADER_SIZE + header.bodyLength);
|
|
47
|
+
const body = LocoPacket.parseBody(bodyBuf);
|
|
48
|
+
return new LocoPacket(header.packetId, header.status, header.method, body);
|
|
49
|
+
}
|
|
50
|
+
toString() {
|
|
51
|
+
return `LocoPacket(id=${this.packetId}, status=${this.status}, method=${this.method}, bodyLen=${JSON.stringify(this.body).length})`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.LocoPacket = LocoPacket;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MessageTypeValue } from './message';
|
|
2
|
+
export declare const AttachmentTypes: {
|
|
3
|
+
readonly Photo: "photo";
|
|
4
|
+
readonly Video: "video";
|
|
5
|
+
readonly Audio: "audio";
|
|
6
|
+
readonly File: "file";
|
|
7
|
+
readonly Contact: "contact";
|
|
8
|
+
readonly Location: "location";
|
|
9
|
+
readonly Schedule: "schedule";
|
|
10
|
+
readonly Link: "link";
|
|
11
|
+
readonly Unknown: "unknown";
|
|
12
|
+
};
|
|
13
|
+
export type AttachmentType = typeof AttachmentTypes[keyof typeof AttachmentTypes];
|
|
14
|
+
export type MessageAttachment = {
|
|
15
|
+
type: MessageTypeValue;
|
|
16
|
+
raw: any;
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AttachmentTypes = void 0;
|
|
4
|
+
exports.AttachmentTypes = {
|
|
5
|
+
Photo: 'photo',
|
|
6
|
+
Video: 'video',
|
|
7
|
+
Audio: 'audio',
|
|
8
|
+
File: 'file',
|
|
9
|
+
Contact: 'contact',
|
|
10
|
+
Location: 'location',
|
|
11
|
+
Schedule: 'schedule',
|
|
12
|
+
Link: 'link',
|
|
13
|
+
Unknown: 'unknown',
|
|
14
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const MessageType: {
|
|
2
|
+
readonly Text: 1;
|
|
3
|
+
readonly Photo: 2;
|
|
4
|
+
readonly Video: 3;
|
|
5
|
+
readonly Contact: 4;
|
|
6
|
+
readonly Audio: 5;
|
|
7
|
+
readonly Link: 9;
|
|
8
|
+
readonly Schedule: 13;
|
|
9
|
+
readonly Location: 16;
|
|
10
|
+
readonly Profile: 17;
|
|
11
|
+
readonly File: 18;
|
|
12
|
+
readonly Reply: 26;
|
|
13
|
+
};
|
|
14
|
+
export type MessageTypeValue = typeof MessageType[keyof typeof MessageType] | number;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessageType = void 0;
|
|
4
|
+
exports.MessageType = {
|
|
5
|
+
Text: 1,
|
|
6
|
+
Photo: 2,
|
|
7
|
+
Video: 3,
|
|
8
|
+
Contact: 4,
|
|
9
|
+
Audio: 5,
|
|
10
|
+
Link: 9,
|
|
11
|
+
Schedule: 13,
|
|
12
|
+
Location: 16,
|
|
13
|
+
Profile: 17,
|
|
14
|
+
File: 18,
|
|
15
|
+
Reply: 26,
|
|
16
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const Reactions: {
|
|
2
|
+
readonly CANCEL: 0;
|
|
3
|
+
readonly HEART: 1;
|
|
4
|
+
readonly LIKE: 2;
|
|
5
|
+
readonly CHECK: 3;
|
|
6
|
+
readonly LAUGH: 4;
|
|
7
|
+
readonly SURPRISE: 5;
|
|
8
|
+
readonly SAD: 6;
|
|
9
|
+
};
|
|
10
|
+
export type ReactionTypeValue = (typeof Reactions)[keyof typeof Reactions];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function nextClientMsgId(seed: string, timeMillis?: number): number;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nextClientMsgId = nextClientMsgId;
|
|
4
|
+
const MAX_MOD = 2147483547;
|
|
5
|
+
const STEP = 100;
|
|
6
|
+
const stateBySeed = new Map();
|
|
7
|
+
function javaStringHash(str) {
|
|
8
|
+
let hash = 0;
|
|
9
|
+
for (let i = 0; i < str.length; i += 1) {
|
|
10
|
+
hash = (hash * 31 + str.charCodeAt(i)) | 0;
|
|
11
|
+
}
|
|
12
|
+
return hash;
|
|
13
|
+
}
|
|
14
|
+
function baseId(timeMillis, deviceHash) {
|
|
15
|
+
const base = Math.floor((timeMillis % MAX_MOD) / STEP) * STEP;
|
|
16
|
+
return base + deviceHash;
|
|
17
|
+
}
|
|
18
|
+
function getState(seed) {
|
|
19
|
+
const key = seed || '';
|
|
20
|
+
let state = stateBySeed.get(key);
|
|
21
|
+
if (!state) {
|
|
22
|
+
const deviceHash = javaStringHash(key) % 100;
|
|
23
|
+
const initial = baseId(Date.now(), deviceHash);
|
|
24
|
+
state = {
|
|
25
|
+
deviceHash,
|
|
26
|
+
lastId: initial,
|
|
27
|
+
lastGenId: initial,
|
|
28
|
+
};
|
|
29
|
+
stateBySeed.set(key, state);
|
|
30
|
+
}
|
|
31
|
+
return state;
|
|
32
|
+
}
|
|
33
|
+
function nextClientMsgId(seed, timeMillis = Date.now()) {
|
|
34
|
+
const state = getState(seed);
|
|
35
|
+
const gen = baseId(timeMillis, state.deviceHash);
|
|
36
|
+
if (gen <= state.lastId && gen >= state.lastGenId) {
|
|
37
|
+
let next = state.lastId + STEP;
|
|
38
|
+
if (next > 2147483647) {
|
|
39
|
+
next = baseId(next, state.deviceHash);
|
|
40
|
+
}
|
|
41
|
+
state.lastId = next;
|
|
42
|
+
state.lastGenId = gen;
|
|
43
|
+
return state.lastId;
|
|
44
|
+
}
|
|
45
|
+
state.lastId = gen;
|
|
46
|
+
state.lastGenId = gen;
|
|
47
|
+
return state.lastId;
|
|
48
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.guessMime = guessMime;
|
|
37
|
+
exports.readImageSize = readImageSize;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const MIME_BY_EXT = {
|
|
41
|
+
'.jpg': 'image/jpeg',
|
|
42
|
+
'.jpeg': 'image/jpeg',
|
|
43
|
+
'.png': 'image/png',
|
|
44
|
+
'.gif': 'image/gif',
|
|
45
|
+
'.webp': 'image/webp',
|
|
46
|
+
'.bmp': 'image/bmp',
|
|
47
|
+
'.heic': 'image/heic',
|
|
48
|
+
'.heif': 'image/heif',
|
|
49
|
+
'.mp4': 'video/mp4',
|
|
50
|
+
'.m4v': 'video/x-m4v',
|
|
51
|
+
'.mov': 'video/quicktime',
|
|
52
|
+
'.mkv': 'video/x-matroska',
|
|
53
|
+
'.webm': 'video/webm',
|
|
54
|
+
'.mp3': 'audio/mpeg',
|
|
55
|
+
'.m4a': 'audio/mp4',
|
|
56
|
+
'.wav': 'audio/wav',
|
|
57
|
+
'.ogg': 'audio/ogg',
|
|
58
|
+
'.flac': 'audio/flac',
|
|
59
|
+
'.pdf': 'application/pdf',
|
|
60
|
+
'.txt': 'text/plain',
|
|
61
|
+
'.json': 'application/json',
|
|
62
|
+
'.zip': 'application/zip',
|
|
63
|
+
'.7z': 'application/x-7z-compressed',
|
|
64
|
+
'.rar': 'application/x-rar-compressed',
|
|
65
|
+
};
|
|
66
|
+
function guessMime(filePath, fallback = 'application/octet-stream') {
|
|
67
|
+
const ext = path.extname(filePath || '').toLowerCase();
|
|
68
|
+
if (!ext)
|
|
69
|
+
return fallback;
|
|
70
|
+
return MIME_BY_EXT[ext] || fallback;
|
|
71
|
+
}
|
|
72
|
+
function readPngSize(buffer) {
|
|
73
|
+
if (buffer.length < 24)
|
|
74
|
+
return null;
|
|
75
|
+
const signature = buffer.subarray(0, 8);
|
|
76
|
+
if (!signature.equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const width = buffer.readUInt32BE(16);
|
|
80
|
+
const height = buffer.readUInt32BE(20);
|
|
81
|
+
if (!width || !height)
|
|
82
|
+
return null;
|
|
83
|
+
return { width, height };
|
|
84
|
+
}
|
|
85
|
+
function readGifSize(buffer) {
|
|
86
|
+
if (buffer.length < 10)
|
|
87
|
+
return null;
|
|
88
|
+
const header = buffer.toString('ascii', 0, 3);
|
|
89
|
+
if (header !== 'GIF')
|
|
90
|
+
return null;
|
|
91
|
+
const width = buffer.readUInt16LE(6);
|
|
92
|
+
const height = buffer.readUInt16LE(8);
|
|
93
|
+
if (!width || !height)
|
|
94
|
+
return null;
|
|
95
|
+
return { width, height };
|
|
96
|
+
}
|
|
97
|
+
function isJpegStart(buffer) {
|
|
98
|
+
return buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xd8;
|
|
99
|
+
}
|
|
100
|
+
function isJpegSof(marker) {
|
|
101
|
+
return (marker === 0xc0 ||
|
|
102
|
+
marker === 0xc1 ||
|
|
103
|
+
marker === 0xc2 ||
|
|
104
|
+
marker === 0xc3 ||
|
|
105
|
+
marker === 0xc5 ||
|
|
106
|
+
marker === 0xc6 ||
|
|
107
|
+
marker === 0xc7 ||
|
|
108
|
+
marker === 0xc9 ||
|
|
109
|
+
marker === 0xca ||
|
|
110
|
+
marker === 0xcb ||
|
|
111
|
+
marker === 0xcd ||
|
|
112
|
+
marker === 0xce ||
|
|
113
|
+
marker === 0xcf);
|
|
114
|
+
}
|
|
115
|
+
function readJpegSize(buffer) {
|
|
116
|
+
if (!isJpegStart(buffer))
|
|
117
|
+
return null;
|
|
118
|
+
let offset = 2;
|
|
119
|
+
while (offset + 9 < buffer.length) {
|
|
120
|
+
if (buffer[offset] !== 0xff) {
|
|
121
|
+
offset += 1;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
let marker = buffer[offset + 1];
|
|
125
|
+
while (marker === 0xff && offset + 2 < buffer.length) {
|
|
126
|
+
offset += 1;
|
|
127
|
+
marker = buffer[offset + 1];
|
|
128
|
+
}
|
|
129
|
+
if (marker === 0xd9 || marker === 0xda)
|
|
130
|
+
break;
|
|
131
|
+
if (offset + 4 >= buffer.length)
|
|
132
|
+
break;
|
|
133
|
+
const segmentLength = buffer.readUInt16BE(offset + 2);
|
|
134
|
+
if (segmentLength < 2)
|
|
135
|
+
break;
|
|
136
|
+
if (isJpegSof(marker)) {
|
|
137
|
+
if (offset + 7 >= buffer.length)
|
|
138
|
+
break;
|
|
139
|
+
const height = buffer.readUInt16BE(offset + 5);
|
|
140
|
+
const width = buffer.readUInt16BE(offset + 7);
|
|
141
|
+
if (!width || !height)
|
|
142
|
+
return null;
|
|
143
|
+
return { width, height };
|
|
144
|
+
}
|
|
145
|
+
offset += 2 + segmentLength;
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
function readImageSize(filePath) {
|
|
150
|
+
if (!filePath)
|
|
151
|
+
return null;
|
|
152
|
+
let fd = null;
|
|
153
|
+
try {
|
|
154
|
+
fd = fs.openSync(filePath, 'r');
|
|
155
|
+
const stat = fs.fstatSync(fd);
|
|
156
|
+
const length = Math.min(stat.size, 256 * 1024);
|
|
157
|
+
const buffer = Buffer.alloc(length);
|
|
158
|
+
fs.readSync(fd, buffer, 0, length, 0);
|
|
159
|
+
return readPngSize(buffer) || readGifSize(buffer) || readJpegSize(buffer);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
if (fd !== null) {
|
|
166
|
+
try {
|
|
167
|
+
fs.closeSync(fd);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kakaoforge",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc -p tsconfig.json",
|
|
12
|
+
"build:watch": "tsc -p tsconfig.json --watch",
|
|
13
|
+
"deploy": "npm run build && npm version patch && npm publish --access public",
|
|
14
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/aodjo/KakaoForge.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/aodjo/KakaoForge#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/aodjo/KakaoForge/issues"
|
|
25
|
+
},
|
|
26
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
27
|
+
"type": "commonjs",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"bson": "^7.1.1",
|
|
30
|
+
"hpack.js": "^2.1.6",
|
|
31
|
+
"lossless-json": "^4.3.0",
|
|
32
|
+
"protobufjs": "^8.0.0",
|
|
33
|
+
"qrcode-terminal": "^0.12.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.13.1",
|
|
37
|
+
"ts-node": "^10.9.2",
|
|
38
|
+
"typescript": "^5.7.3"
|
|
39
|
+
}
|
|
40
|
+
}
|