Open
Description
Thanks for the work EveripediaNetwork! For anyone who needs this really well working script but as nodejs. Maybe you can open a repo for nodejs as well EveripediaNetwork?
//grokit.js
const { EventEmitter } = require('events');
const GrokModels = Object.freeze({
GROK_2: 'grok-2',
GROK_2_MINI: 'grok-2-mini',
});
class Grokit {
static BEARER_TOKEN = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
/**
* Initializes the Grokit instance.
* @param {Object} options
* @param {string} options.auth_token - Authentication token.
* @param {string} options.csrf_token - CSRF token.
*/
constructor({ auth_token = process.env.X_AUTH_TOKEN, csrf_token = process.env.X_CSRF_TOKEN } = {}) {
this.auth_token = auth_token;
this.csrf_token = csrf_token;
this._validateTokens();
this.cookie = this._createCookie();
this.headers = this._createHeaders();
}
_validateTokens() {
if (!this.auth_token || !this.csrf_token) {
throw new Error('X_AUTH_TOKEN and X_CSRF_TOKEN must be provided');
}
}
_createCookie() {
return `auth_token=${this.auth_token}; ct0=${this.csrf_token};`;
}
_createHeaders() {
return {
'X-Csrf-Token': this.csrf_token,
'Authorization': `Bearer ${Grokit.BEARER_TOKEN}`,
'Content-Type': 'application/json',
'Cookie': this.cookie,
};
}
async createConversation() {
const url = 'https://x.com/i/api/graphql/UBIjqHqsA5aixuibXTBheQ/CreateGrokConversation';
const payload = {
variables: {},
queryId: 'UBIjqHqsA5aixuibXTBheQ',
};
const response = await this._makeRequest(url, payload);
if (response && response.data && response.data.create_grok_conversation) {
return response.data.create_grok_conversation.conversation_id;
}
return null;
}
/**
* Generates a response based on the input message.
* @param {string} message - The input message.
* @param {Object} options
* @param {string} [options.conversation_id] - Existing conversation ID.
* @param {string} [options.system_prompt_name] - System prompt name.
* @param {string} [options.model_id] - Model ID.
* @returns {Promise<string>} - The generated response.
*/
async generate(message, { conversation_id = null, system_prompt_name = '', model_id = GrokModels.GROK_2_MINI } = {}) {
const convoId = await this._ensureConversationId(conversation_id);
const response = await this._streamResponse(convoId, message, system_prompt_name, model_id);
return response.join('');
}
/**
* Streams the response based on the input message.
* @param {string} message - The input message.
* @param {Object} options
* @param {string} [options.conversation_id] - Existing conversation ID.
* @param {string} [options.system_prompt_name] - System prompt name.
* @param {string} [options.model_id] - Model ID.
* @returns {EventEmitter} - An event emitter that emits 'data' and 'error' events.
*/
async stream(message, { conversation_id = null, system_prompt_name = '', model_id = GrokModels.GROK_2_MINI } = {}) {
const emitter = new EventEmitter();
try {
const convoId = await this._ensureConversationId(conversation_id);
this._streamResponse(convoId, message, system_prompt_name, model_id, emitter);
} catch (error) {
emitter.emit('error', error);
}
return emitter;
}
/**
* Generates an image based on the prompt.
* @param {string} prompt - The image prompt.
* @returns {Promise<Buffer>} - The image data.
*/
async image(prompt) {
const imageUrl = await this.image_url(prompt);
const imageResponse = await fetch(imageUrl);
if (imageResponse.ok) {
return await imageResponse.arrayBuffer().then(buffer => Buffer.from(buffer));
}
throw new Error('Failed to download the image');
}
/**
* Retrieves the image URL based on the prompt.
* @param {string} prompt - The image prompt.
* @returns {Promise<string>} - The image URL.
*/
async image_url(prompt) {
const conversation_id = await this.createConversation();
if (!conversation_id) {
throw new Error('Failed to create conversation');
}
const imagePrompt = `Generate an image of "${prompt}"`;
const response = await this._streamResponse(conversation_id, imagePrompt, '', GrokModels.GROK_2_MINI);
for (const chunk of response) {
try {
const data = JSON.parse(chunk);
if (data.result && data.result.imageAttachment && data.result.imageAttachment.imageUrl) {
return data.result.imageAttachment.imageUrl;
}
} catch (e) {
continue;
}
}
throw new Error('Failed to generate the image');
}
async _ensureConversationId(conversation_id) {
if (!conversation_id) {
conversation_id = await this.createConversation();
if (!conversation_id) {
throw new Error('Failed to create conversation');
}
}
return conversation_id;
}
async _streamResponse(conversation_id, message, system_prompt_name, model_id, emitter = null) {
const url = 'https://api.x.com/2/grok/add_response.json';
const payload = this._createAddResponsePayload(conversation_id, message, system_prompt_name, model_id);
try {
const response = await fetch(url, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(payload),
});
if (!response.ok) {
const errorText = await response.text();
if (emitter) {
emitter.emit('error', new Error(`Error adding response: ${errorText}`));
} else {
console.error(`Error adding response: ${errorText}`);
}
return [];
}
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
let doneReading = false;
const result = [];
while (!doneReading) {
const { value, done } = await reader.read();
if (done) {
doneReading = true;
break;
}
const chunk = decoder.decode(value, { stream: true });
const lines = chunk.split('\n').filter(line => line.trim() !== '');
for (const line of lines) {
try {
const parsed = JSON.parse(line);
if (parsed.result) {
if (parsed.result.message) {
result.push(parsed.result.message);
if (emitter) emitter.emit('data', parsed.result.message);
} else if (parsed.result.imageAttachment) {
const jsonString = JSON.stringify(parsed);
result.push(jsonString);
if (emitter) emitter.emit('data', jsonString);
}
}
} catch (e) {
continue;
}
}
}
return result;
} catch (error) {
if (emitter) {
emitter.emit('error', error);
} else {
console.error(`Error adding response: ${error.message}`);
}
return [];
}
}
async _makeRequest(url, payload) {
try {
const response = await fetch(url, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(payload),
});
if (response.ok) {
return await response.json();
} else {
const errorText = await response.text();
console.error(`Error making request: ${errorText}`);
return null;
}
} catch (error) {
console.error(`Request failed: ${error.message}`);
return null;
}
}
_createAddResponsePayload(conversation_id, message, system_prompt_name, model_id) {
return {
responses: [
{
message: message,
sender: 1,
},
],
systemPromptName: system_prompt_name,
grokModelOptionId: typeof model_id === 'object' ? model_id.value : model_id,
conversationId: conversation_id,
};
}
}
module.exports = { Grokit, GrokModels };
// app.js
const { Grokit, GrokModels } = require('./grokit');
// Extract tokens from cookies
const auth_token = "***";
const csrf_token = "***";
(async () => {
try {
// Initialize Grokit instance
const grok = new Grokit({
auth_token: auth_token,
csrf_token: csrf_token,
});
// Test with a sample question
const response = await grok.generate('Who are you?, { model_id: GrokModels.GROK_2_MINI });
console.log('Generated Response:', response);
} catch (error) {
console.error('Error:', error);
}
})();
Metadata
Metadata
Assignees
Labels
No labels