writely.jsJul 10, 20263.3 KB
raw
const axios = require('axios');
const https = require('https');
const crypto = require('crypto');
const { fileTypeFromBuffer } = require('file-type');

class Writely {
    constructor() {
        this.keyId = Buffer.from([169, 104, 30, 162, 2, 40, 63, 114, 75, 236, 194, 200, 194, 226, 56, 146]);
        this.secretKey = Buffer.from([171, 7, 153, 58, 27, 53, 26, 43, 184, 175, 80, 19, 242, 44, 202, 66, 130, 117, 152, 2, 229, 228, 233, 44, 86, 100, 49, 43, 151, 216, 78, 89]);
        this.baseUrl = 'https://test-project.aiby.mobi';
        this.version = '1.8.0';
    }
    
    sign = function (method, path, date, body) {
        const message = method + ':' + path + ':' + date + '\n' + body;
        const messageBytes = Buffer.from(message, 'utf8');
        
        const hmac = crypto.createHmac('sha256', this.secretKey);
        hmac.update(messageBytes);
        
        return 'Bearer ' + this.keyId.toString('base64') + '.' + hmac.digest('base64');
    };
    
    chat = async function (prompt, { model = 'gpt-4o-mini', attachments = [], systemPrompt = '', ...options } = {}) {
        try {
            if (!prompt) throw new Error('Prompt is required.');
            
            const path = '/chats/text';
            const date = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
            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 body = {
                model: model,
                messages: messages,
                ...options
            };
            
            const bodyStr = JSON.stringify(body);
            const authorization = this.sign('POST', path, date, bodyStr);
            
            const { data } = await axios.post(this.baseUrl + path, body, {
                headers: {
                    'authorization': authorization,
                    'connect_timeout': '20',
                    'content-type': 'application/json; charset=UTF-8',
                    'date': date,
                    'read_timeout': '20',
                    'user-agent': 'KeyboardAi_Android/' + this.version,
                    'write_timeout': '20'
                }
            });
            
            const result = 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 Writely();
ai.chat('hai! apa kabar?').then(console.log);