const axios = require('axios');
const crypto = require('crypto');
const { fileTypeFromBuffer } = require('file-type');
class AIKeyboard {
constructor() {
this.kid = '36ccfe00-78fc-4cab-9c5b-5460b0c78513';
this.apkSignature = 'dzeX7A8YrfJyVf01dNUo1V43mIfNpyzX/Plo9Vqqcqo=';
this.packageId = 'starnest.aitype.aikeyboard.chatbot.chatgpt';
}
sign = function () {
const timestamp = Math.floor(Date.now() / 1000);
const deviceId = crypto.randomUUID().replace(/-/g, '').substring(0, 16);
const signatureValue = crypto.createHash('sha256').update(this.kid + timestamp + '90', 'utf8').digest('hex');
const signature = 'Signature ' + [
'kid=' + this.kid,
'algorithm=sha256',
'timestamp=' + timestamp,
'validity=90',
'userId=',
'value=' + signatureValue
].join('&');
const base64UrlEncode = (str) => {
return Buffer.from(str)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
};
const header = base64UrlEncode(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));
const payload = base64UrlEncode(JSON.stringify({
token: this.apkSignature,
iat: timestamp,
exp: timestamp + 90
}));
const data = header + '.' + payload;
const jwtSignature = crypto
.createHmac('sha256', this.kid)
.update(data)
.digest('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
return {
'app-token': 'Bearer ' + data + '.' + jwtSignature,
'authorization': signature,
'device-id': deviceId
};
};
chat = async function (prompt, { attachments = [], systemPrompt = '' } = {}) {
try {
if (!prompt) throw new Error('Prompt is required.');
const messages = [];
if (systemPrompt) {
messages.push({ role: 'system', content: systemPrompt });
}
const content = [];
if (attachments.length > 0) {
for (const buffer of attachments) {
const type = await fileTypeFromBuffer(buffer);
const mime = type ? type.mime : 'application/octet-stream';
const base64 = buffer.toString('base64');
content.push({
type: 'image_url',
image_url: { url: 'data:' + mime + ';base64,' + base64 }
});
}
}
content.push({ type: 'text', text: prompt });
messages.push({ role: 'user', content: content });
const { data } = await axios.post('https://api-akeyboard.starnestsolution.com/api/v2/completions/v1', {
isVip: false,
messages: messages,
stream: false
}, {
headers: {
'accept-encoding': 'gzip',
...this.sign(),
'connection': 'Keep-Alive',
'content-type': 'application/json; charset=UTF-8',
'package-id': this.packageId,
'user-agent': 'okhttp/4.9.0'
}
});
const result = data?.data?.choices?.[0]?.message?.content;
if (!result) throw new Error('No result found.');
return result;
} catch (error) {
throw new Error(error.message);
}
};
}
const ai = new AIKeyboard();
ai.chat('hai! apa kabar?').then(console.log);