Initial Emmelia merge
This commit is contained in:
85
Server/controllers/accountController.js
Normal file
85
Server/controllers/accountController.js
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||
const log = new DebugBuilder("server", "accountController");
|
||||
|
||||
const { UserStorage } = require("../libStorage");
|
||||
const userStorage = new UserStorage();
|
||||
|
||||
/**
|
||||
* Check to see if the discord ID has an account associated with it
|
||||
* @param {*} _discordAccountId The discord account to look for
|
||||
* @param {*} callback The callback function to be called
|
||||
* @callback false|*
|
||||
*/
|
||||
exports.checkForAccount = (_discordAccountId, callback) => {
|
||||
userStorage.getRecordBy("discord_account_id", _discordAccountId, (err, results) => {
|
||||
if (err) return callback(err, undefined);
|
||||
|
||||
if (!results) return callback(undefined, false);
|
||||
return callback(undefined, results);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an account from a discord ID
|
||||
* @param {*} _discordAccountId
|
||||
* @param {*} callback
|
||||
*/
|
||||
exports.createAccount = (_discordAccountId, callback) => {
|
||||
if (!_discordAccountId) return callback(new Error("No discord account specified before creation"));
|
||||
userStorage.saveAccount(_discordAccountId, (err, results) => {
|
||||
if (err) return callback(err, undefined);
|
||||
|
||||
if (!results) return callback(new Error("No results from creating account"), undefined);
|
||||
|
||||
return callback(undefined, results);
|
||||
})
|
||||
}
|
||||
|
||||
exports.withdrawBalance = async (_withdrawAmount, _discordAccountId, callback) => {
|
||||
userStorage.updateBalance('withdraw', _withdrawAmount, _discordAccountId, async (err, result) => {
|
||||
if (err) return callback(err, undefined);
|
||||
|
||||
if(result) return callback(undefined, result);
|
||||
|
||||
return callback(undefined, undefined);
|
||||
})
|
||||
}
|
||||
|
||||
exports.verifyBalance = (_tokensToBeUsed, _accountId, callback) => {
|
||||
userStorage.checkBalance(_tokensToBeUsed, _accountId, (err, results) => {
|
||||
if (err) return callback(err, undefined);
|
||||
|
||||
if(!results) return callback(undefined, false);
|
||||
|
||||
return callback(undefined, true);
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Check the given account for the token balance
|
||||
*
|
||||
* @param {*} _discordAccountId
|
||||
* @param {*} callback
|
||||
*/
|
||||
exports.checkBalance = (_discordAccountId, callback) => {
|
||||
if (!_discordAccountId) return callback(new Error("No discord account given to check balance of"), undefined);
|
||||
userStorage.getRecordBy("discord_account_id", _discordAccountId, (err, accountRecord) => {
|
||||
if (err) return callback(err, undefined);
|
||||
|
||||
if (!accountRecord) return callback(new Error("No account record given"), undefined);
|
||||
|
||||
return callback(undefined, accountRecord.balance);
|
||||
})
|
||||
}
|
||||
|
||||
exports.insufficientTokensResponse = (interaction) => {
|
||||
log.DEBUG("INSUFFICIENT TOKENS RESPONSE")
|
||||
|
||||
return interaction.reply({ content: `Sorry ${interaction.member.user}, you don't have enough tokens for this purchase. Please contact your bot rep to increase your balance to have more fun playing around!`, ephemeral: true });
|
||||
}
|
||||
|
||||
exports.welcomeResponse = (interaction) => {
|
||||
log.DEBUG("WELCOME RESPONSE")
|
||||
|
||||
return interaction.reply({ content: `Hey there ${interaction.member.user}! You haven't ran any commands that require tokens before. I've gone ahead and created an account for you. When you get a chance reach out to your nearest bot rep to fill your balance to start playing around! In the meantime however, you can run \`/pricing\` to view the current pricing.`, ephemeral: true });
|
||||
}
|
||||
@@ -20,7 +20,7 @@ async function getPresetsOfOnlineNodes(callback) {
|
||||
systems[onlineNode.id] = utils.BufferToJson(onlineNode.nearbySystems);
|
||||
});
|
||||
|
||||
callback(systems);
|
||||
return callback(systems);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ async function requestNodeListenToPreset(preset, nodeId, callback) {
|
||||
"channelID": discordConfig.channelID,
|
||||
"presetName": preset
|
||||
}), (responseObject) => {
|
||||
callback(responseObject)
|
||||
return callback(responseObject)
|
||||
});
|
||||
})
|
||||
}
|
||||
@@ -46,7 +46,7 @@ async function getNodeBotStatus(nodeId, callback) {
|
||||
else {
|
||||
// Bot is free
|
||||
}
|
||||
callback(responseObject);
|
||||
return callback(responseObject);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -58,13 +58,13 @@ async function requestNodeLeaveServer(nodeId, callback) {
|
||||
mysqlHandler.getNodeInfoFromId(nodeId, (nodeObject) =>{
|
||||
reqOptions = new requests.requestOptions("/bot/leave", "POST", nodeObject.ip, nodeObject.port);
|
||||
requests.sendHttpRequest(reqOptions, JSON.stringify({}), (responseObject) => {
|
||||
callback(responseObject);
|
||||
return callback(responseObject);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Bot is free
|
||||
callback(false);
|
||||
return callback(false);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
179
Server/controllers/openAiController.js
Normal file
179
Server/controllers/openAiController.js
Normal file
@@ -0,0 +1,179 @@
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||
const log = new DebugBuilder("server", "openAiController");
|
||||
const crypto = require('crypto')
|
||||
|
||||
const { createTransaction } = require("./transactionController");
|
||||
const { authorizeTokenUsage } = require("../middleware/balanceAuthorization");
|
||||
|
||||
const { encode } = require("gpt-3-encoder")
|
||||
const { Configuration, OpenAIApi } = require('openai');
|
||||
const configuration = new Configuration({
|
||||
organization: process.env.OPENAI_ORG,
|
||||
apiKey: process.env.OPENAI_KEY
|
||||
});
|
||||
|
||||
const openai = new OpenAIApi(configuration);
|
||||
|
||||
// Global Vars for Other functions
|
||||
exports.DALLE_COLOR = 0x34c6eb;
|
||||
exports.CHATGPT_COLOR = 0x34eb9b;
|
||||
|
||||
async function getImageGeneration(_prompt, { _images_to_generate = 1, _image_size = "256x256" }, callback){
|
||||
const validImageSizes = ["256x256", "512x512", "1024x1024"];
|
||||
|
||||
if (!_prompt) callback(new Error("No prompt given before generating image"), undefined);
|
||||
if (!validImageSizes.includes(_image_size)) callback(new Error("Image size given is not valid, valid size: ", validImageSizes));
|
||||
if (!_images_to_generate || _images_to_generate === 0 || _images_to_generate > 10) callback(new Error("Invalid image count given"));
|
||||
|
||||
// Calculate token usage?
|
||||
|
||||
log.DEBUG("Getting image generation with these properties: ", _prompt, _images_to_generate, _image_size)
|
||||
try{
|
||||
const response = await openai.createImage({
|
||||
prompt: _prompt,
|
||||
n: _images_to_generate,
|
||||
size: _image_size
|
||||
})
|
||||
|
||||
|
||||
if(!response?.data) return callback(new Error("Error in response data: ", response));
|
||||
return callback(undefined, response.data);
|
||||
} catch (err){
|
||||
log.ERROR(err);
|
||||
log.ERROR("Error when handing image model request");
|
||||
return callback(err, undefined);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response from GPT with the specified parameters
|
||||
*
|
||||
* @param {*} _prompt The text prompt to send to the model
|
||||
* @param {*} callback The callback to call with errors or results
|
||||
* @param {*} param2 Any parameters the user has changed for this request
|
||||
* @returns
|
||||
*/
|
||||
async function getTextGeneration(_prompt, callback, { _model = "text-davinci-003", _temperature = 0, _max_tokens = 100}) {
|
||||
// If the temperature is set to null
|
||||
_temperature = _temperature ?? 0;
|
||||
// If the tokens are set to null
|
||||
_max_tokens = _max_tokens ?? 100;
|
||||
|
||||
const encodedPrompt = encode(_prompt);
|
||||
const promptTokens = encodedPrompt.length;
|
||||
log.DEBUG("Tokens in prompt: ", promptTokens);
|
||||
if (promptTokens >= _max_tokens) return callback(new Error("Tokens of request are greater than the set max tokens", promptTokens, _max_tokens));
|
||||
|
||||
_max_tokens = _max_tokens - promptTokens;
|
||||
log.DEBUG("Updated max tokens: ", _max_tokens);
|
||||
|
||||
log.DEBUG("Getting chat with these properties: ", _prompt, _model, _temperature, _max_tokens)
|
||||
try{
|
||||
const response = await openai.createCompletion({
|
||||
model: _model,
|
||||
prompt: _prompt,
|
||||
temperature: _temperature,
|
||||
max_tokens: _max_tokens
|
||||
});
|
||||
if(!response?.data) return callback(new Error("Error in response data: ", response));
|
||||
return callback(undefined, response.data);
|
||||
} catch (err){
|
||||
log.ERROR("Error when handing text model request: ", err);
|
||||
return callback(err, undefined);
|
||||
}
|
||||
//var responseData = response.data.choices[0].text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use ChatGPT to generate a response
|
||||
*
|
||||
* @param {*} _prompt The use submitted text prompt
|
||||
* @param {*} param1 Default parameters can be modified
|
||||
* @returns
|
||||
*/
|
||||
exports.submitTextPromptTransaction = async (prompt, temperature, max_tokens, discord_account_id, interaction, command, callback) => {
|
||||
|
||||
getTextGeneration(prompt, (err, gptResult) => {
|
||||
if (err) callback(err, undefined);
|
||||
|
||||
// TODO - Use the pricing table to calculate discord tokens
|
||||
log.DEBUG("GPT Response", gptResult);
|
||||
const discordTokensUsed = gptResult.usage.total_tokens;
|
||||
|
||||
if (gptResult){
|
||||
createTransaction(gptResult.id, discord_account_id, discordTokensUsed, gptResult.usage.total_tokens, 1, async (err, transactionResult) => {
|
||||
if (err) callback(err, undefined);
|
||||
|
||||
if (transactionResult){
|
||||
log.DEBUG("Transaction Created: ", transactionResult);
|
||||
callback(undefined, ({ promptResult: gptResult.choices[0].text, totalTokens: discordTokensUsed}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}, { _temperature: temperature, _max_tokens: max_tokens });
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to generate an image from a prompt and params and store this information in a transaction
|
||||
*
|
||||
* @param {*} prompt The prompt of the image
|
||||
* @param {*} images_to_generate The number of images to generate
|
||||
* @param {*} image_size The size of the image ["256x256" | "512x512" | "1024x1024"]
|
||||
* @param {*} callback
|
||||
*/
|
||||
exports.submitImagePromptTransaction = async (prompt, discord_account_id, images_to_generate, image_size, interaction, command, callback) => {
|
||||
let pricePerImage = 800;
|
||||
log.DEBUG(image_size)
|
||||
switch(image_size){
|
||||
case "1024x1024":
|
||||
log.DEBUG("1024 selected");
|
||||
pricePerImage = 1000;
|
||||
break;
|
||||
case "512x512":
|
||||
pricePerImage = 900;
|
||||
log.DEBUG("512 selected");
|
||||
break;
|
||||
case "256x256":
|
||||
log.DEBUG("256 selected");
|
||||
pricePerImage = 800;
|
||||
break;
|
||||
default:
|
||||
log.DEBUG("256px defaulted");
|
||||
pricePerImage = 800;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!images_to_generate) images_to_generate = 1;
|
||||
if (!image_size) image_size = "256x256";
|
||||
|
||||
totalTokensToBeUsed = pricePerImage * images_to_generate;
|
||||
|
||||
log.DEBUG("Total tokens to be used", totalTokensToBeUsed, pricePerImage, images_to_generate);
|
||||
|
||||
authorizeTokenUsage(interaction, command, totalTokensToBeUsed, (isAuthorized) => {
|
||||
if (isAuthorized) {
|
||||
getImageGeneration(prompt, {
|
||||
_image_size: image_size,
|
||||
_images_to_generate: images_to_generate
|
||||
}, (err, dalleResult) => {
|
||||
if (err) callback(err, undefined);
|
||||
|
||||
// TODO - Use the pricing table to calculate discord tokens
|
||||
log.DEBUG("DALL-E Result", dalleResult);
|
||||
|
||||
const dalleResultHash = crypto.createHash('sha1').update(JSON.stringify({ discord_account_id : prompt, images_to_generate: image_size })).digest('hex')
|
||||
|
||||
if (dalleResult){
|
||||
createTransaction(dalleResultHash, discord_account_id, totalTokensToBeUsed, totalTokensToBeUsed, 2, async (err, transactionResult) => {
|
||||
if (err) callback(err, undefined);
|
||||
|
||||
if (transactionResult){
|
||||
log.DEBUG("Transaction Created: ", transactionResult);
|
||||
callback(undefined, ({ results: dalleResult, totalTokens: totalTokensToBeUsed}));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
38
Server/controllers/rssController.js
Normal file
38
Server/controllers/rssController.js
Normal file
@@ -0,0 +1,38 @@
|
||||
//Will handle updating feeds in all channels
|
||||
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||
const log = new DebugBuilder("server", "rssController");
|
||||
|
||||
const libCore = require("../libCore");
|
||||
const libUtils = require("../libUtils");
|
||||
|
||||
const refreshInterval = process.env.RSS_REFRESH_INTERVAL ?? 300000;
|
||||
|
||||
exports.RSSController = class RSSController {
|
||||
constructor(_client) {
|
||||
this.client = _client;
|
||||
}
|
||||
|
||||
async start(){
|
||||
// Wait for the refresh period before starting rss feeds, so the rest of the bot can start
|
||||
await new Promise(resolve => setTimeout(resolve, refreshInterval));
|
||||
|
||||
log.INFO("Starting RSS Controller");
|
||||
// Get initial feeds before the starting the infinite loop
|
||||
await libCore.updateFeeds(this.client);
|
||||
|
||||
while(true){
|
||||
// Wait for the refresh interval, then wait for the posts to return, then wait a quarter of the refresh interval to make sure everything is cleared up
|
||||
await new Promise(resolve => setTimeout(resolve, refreshInterval));
|
||||
await this.collectLatestPosts();
|
||||
await new Promise(resolve => setTimeout(resolve, refreshInterval / 4));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
async collectLatestPosts(){
|
||||
log.INFO("Updating sources");
|
||||
await libCore.updateFeeds(this.client)
|
||||
return;
|
||||
}
|
||||
}
|
||||
35
Server/controllers/transactionController.js
Normal file
35
Server/controllers/transactionController.js
Normal file
@@ -0,0 +1,35 @@
|
||||
// Controller for managing transactions
|
||||
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||
const log = new DebugBuilder("server", "transactionController");
|
||||
|
||||
const { TransactionStorage } = require("../libStorage");
|
||||
const transactionStorage = new TransactionStorage();
|
||||
|
||||
const { BaseTransaction } = require("../utilities/recordHelper");
|
||||
const { withdrawBalance } = require("./accountController");
|
||||
|
||||
exports.createTransaction = async (_provider_transaction_id, _account_id, _discord_tokens_used, _provider_tokens_used, _provider_id, callback) => {
|
||||
if (!_provider_transaction_id && !_account_id && !_discord_tokens_used && !_provider_id) return callback(new Error("Invalid vars when creating transaction", {vars: [_provider_transaction_id, _account_id, _discord_tokens_used, _provider_id, callback]}))
|
||||
|
||||
const newTransaction = new BaseTransaction(_provider_transaction_id, _account_id, _discord_tokens_used, _provider_tokens_used, _provider_id, callback);
|
||||
log.DEBUG("New Transaction Object: ", newTransaction);
|
||||
withdrawBalance(newTransaction.discord_tokens_used, newTransaction.account_id, (err, withdrawResult) => {
|
||||
if (err) return callback(err, undefined);
|
||||
|
||||
if (withdrawResult){
|
||||
log.DEBUG("New withdraw result: ", withdrawResult);
|
||||
transactionStorage.createTransaction(newTransaction, async (err, transactionResult) =>{
|
||||
if (err) return callback(err, undefined);
|
||||
|
||||
if(transactionResult){
|
||||
log.DEBUG("New transaction result: ", transactionResult);
|
||||
return callback(undefined, transactionResult);
|
||||
}
|
||||
})
|
||||
}
|
||||
else {
|
||||
return callback(undefined, undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user