ai-keyboard.jsJul 10, 20263.8 KB
raw
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);
        }
    };
}

// caraa pemakaiannyaa:
const ai = new AIKeyboard();
ai.chat('hai! apa kabar?').then(console.log);