Files
T
2024-09-09 15:12:35 +05:30

8 lines
12 KiB
JavaScript

let path=require("path"),express=require("express"),args=process.argv.slice(2),fs=require("fs"),fsp=require("fs/promises"),qrcode=require("qrcode"),{Client,LocalAuth,MessageMedia}=require("whatsapp-web.js"),CONFIG={PORT:4e3,BROWSER_DIRECTORY:path.join(__dirname,"user"),MODELS_DIRECTORY:path.join(__dirname,"models"),TEMP_DIRECTORY:path.join(__dirname,"temp"),OUTPUT_DIRECTORY:path.join(__dirname,"output"),WEB_DIRECTORY:path.join(__dirname,"website"),API_URL:"http://127.0.0.1:8188",CHROME:"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",MODE:null,ADMIN:null,EXPRESS:express(),WA:null,QRCODE:null,READY:!1,KSAMPLER_SEED_CHANGE:1,MODELS:{},PROMPT:{MODEL:{},NODES:{}},WATCHER:{}},deleteContentsInsideDirectory=async t=>{try{var e=await fsp.readdir(t);await Promise.all(e.map(async e=>{e=path.join(t,e);(await fsp.stat(e)).isDirectory()?(await deleteContentsInsideDirectory(e),await fsp.rmdir(e)):await fsp.unlink(e)})),console.log("Successfully deleted contents inside "+t)}catch(e){throw console.error(`Error deleting contents inside ${t}:`,e),e}};function readJsonFile(e){try{var t=fs.readFileSync(e,"utf8");return JSON.parse(t)}catch(e){return console.error("Error reading or parsing file: "+e),null}}function addDirectories(){CONFIG.BROWSER_DIRECTORY=path.join(CONFIG.MAIN_DIRECTORY,"user"),CONFIG.MODELS_DIRECTORY=path.join(CONFIG.MAIN_DIRECTORY,"workflows"),CONFIG.TEMP_DIRECTORY=path.join(CONFIG.MAIN_DIRECTORY,"temp"),CONFIG.OUTPUT_DIRECTORY=path.join(CONFIG.MAIN_DIRECTORY,"output"),WA_CONFIG=readJsonFile(path.join(CONFIG.MAIN_DIRECTORY,"whatsapp.json")),CONFIG.MODE=parseInt(WA_CONFIG.mode),CONFIG.ADMIN=""+WA_CONFIG.phone_code+WA_CONFIG.phone+"@c.us",CONFIG.CHROME=WA_CONFIG.chrome}function createDirectories(e){for(var t in e)t.endsWith("_DIRECTORY")&&(t=e[t],fs.existsSync(t)?console.log("Directory already exists: "+t):(fs.mkdirSync(t,{recursive:!0}),console.log("Directory created: "+t)))}function botMediaMessage(e,t,r){CONFIG.WA.sendMessage(e,"🤖\n\n"+t,{media:r})}function botTextMessage(e,t){CONFIG.WA.sendMessage(e,"🤖\n\n"+t)}function botTextMessagReply(e,t){e.reply("🤖\n\n"+t)}function isAdmin(e){return CONFIG.ADMIN==e}function allCommands(){var e="";e+="Write */wfs* to get a numbered list of uploaded workflows.\n\n";return"Write */wfs* to get a numbered list of uploaded workflows.\n\nWrite */wf id* to select the workflow.\n\nWrite */wns* to get numbered list of selected workflow nodes.\n\nWrite */wn id* to get numbered list of inputs available.\n\nWrite */s node_id input_id value* to set value for input selected.\n\nWrite */sce* enable auto ksampler seed change.\n\nWrite */scd* disable auto ksampler seed change.\n\nWrite */r* to reset all to default settings.\n\nWrite */q* to queue.\n\nWrite */i* to interrupt queue.\n\nWrite */m number* to set bot usage mode. *1*: Single User, *2*: Multi User.\n\n"}function readModels(e){return fs.readdirSync(e)}function formatModelObject(e){return Object.entries(e).map(([e,t])=>`*${e}* | `+t).join("\n")}function containsIndex(e,t){return 0<=t&&t<e.length&&void 0!==e[t]}function containsValue(e,t){return e.includes(t)}function containsValueAtIndex(e,t,r){return 0<=t&&t<e.length&&e[t]===r}function readJSONFile(e){try{var t=path.join(CONFIG.MODELS_DIRECTORY,e),r=fs.readFileSync(t,"utf8");return JSON.parse(r)}catch(e){return console.error("Error reading file:",e),null}}function extractTitleFromModel(e){var t={};if(e)for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]._meta.title);return t}function formatOutput(e){let t="*ID* | Node Name\n";for(var r in e)e.hasOwnProperty(r)&&(t+=`*${r}* | ${e[r]}
`);return t}function formatInputsIgnoreArray(e,t){var r,s=t[e].inputs;let o=`ID | Input Name | Input Value
`,n=0;for(r in s)s.hasOwnProperty(r)&&!Array.isArray(s[r])&&(o+=`*${n++}* | *${r}* | *${s[r]}*
`);return o.trim()}function containsSettings(t,r,s){if(s[t]&&s[t].inputs){var o,n=s[t].inputs;let e=0;for(o in n)if(n.hasOwnProperty(o)&&!Array.isArray(n[o])){if(e==r)break;e++}return e==r}}function getSettingName(r,s,o){if(o[r]&&o[r].inputs){var n,a=o[r].inputs;let e=0,t="";for(n in a)if(a.hasOwnProperty(n)&&!Array.isArray(a[n])){if(e==s){t=n;break}e++}return t}}function editInputs(e,t,r,s){for(var o in e)if(e[o]._meta&&e[o]._meta.title===t)return void(e[o].inputs?e[o].inputs[r]=s:e[o].inputs={[r]:s})}function getNodeID(e,t){let r=-1;for(var s in e)if(e[s]._meta&&e[s]._meta.title===t){r=s;break}return r}function editJSON(t,r,s,o){if(o[t]&&o[t].inputs){var n=o[t].inputs[r];if(void 0===n)return console.log("Invalid input name."),null;{var a=typeof n;let e;return e="number"==a&&Number.isInteger(n)?parseInt(s):"number"!=a||Number.isInteger(n)?"boolean"==a?"true"===s.toLowerCase():s:parseFloat(s),o[t].inputs[r]=e,o}}return console.log("Invalid number."),null}function extractPhoneNumber(e){return e.split("@")[0].slice(-10)}async function sendResultToUser(t,e){0<e.length&&e.forEach(async e=>{e=path.join(e.subfolder,e.filename),e=await MessageMedia.fromFilePath(e);botMediaMessage(t,"Here is your image",e)})}async function watch(t,e){try{CONFIG.WATCHER[t]||(CONFIG.WATCHER[t]={count:0});var r,s,o=e.prompt_id,n=await fetch(CONFIG.API_URL+"/history/"+o).then(e=>e.json());n&&n[o]?(r=n[o].status).completed&&"success"===r.status_str?-1!=(s=getNodeID(CONFIG.PROMPT.NODES[t],"WA_ImageSaver"))&&sendResultToUser(t,n[o].outputs[s].images||[]):botTextMessage(t,"Workflow failed/interrupted to generate result. Please try again!"):setTimeout(watch,1e3,t,e)}catch(e){console.log(e),botTextMessage(t,"Workflow failed/interrupted to generate result. Please try again!")}}function setCommand(r){var s=r.body.split(" ");switch(s[0]){case"/c":botTextMessagReply(r,allCommands());break;case"/wfs":CONFIG.MODELS[r.from]=readModels(CONFIG.MODELS_DIRECTORY);var e=formatModelObject(CONFIG.MODELS[r.from]);botTextMessagReply(r,"Here are your workflows:\n\n*ID* | Model Name\n\n"+e+"\n\nTo select workfloe write /wf id");break;case"/wf":CONFIG.MODELS[r.from]||(CONFIG.MODELS[r.from]=readModels(CONFIG.MODELS_DIRECTORY));var e=parseInt(s[1]);containsIndex(CONFIG.MODELS[r.from],e)?(CONFIG.PROMPT.MODEL[r.from]=CONFIG.MODELS[r.from][e],CONFIG.PROMPT.NODES[r.from]||(CONFIG.PROMPT.NODES[r.from]=readJSONFile(CONFIG.PROMPT.MODEL[r.from])),botTextMessagReply(r,`Workflow *${CONFIG.PROMPT.MODEL[r.from]}* selected!`)):botTextMessagReply(r,"Workflows does not exists!");break;case"/wns":CONFIG.MODELS[r.from]?(CONFIG.PROMPT.NODES[r.from]=readJSONFile(CONFIG.PROMPT.MODEL[r.from]),e=formatOutput(extractTitleFromModel(CONFIG.PROMPT.NODES[r.from])),botTextMessagReply(r,"Here are your workflow nodes:\n\n"+e+"\n\nTo get the datail of a particular node write /wn id")):botTextMessagReply(r,"Workflow not selected!");break;case"/wn":CONFIG.MODELS[r.from]?(CONFIG.PROMPT.NODES[r.from]||(CONFIG.PROMPT.NODES[r.from]=readJSONFile(CONFIG.PROMPT.MODEL[r.from])),e=s[1],containsValue(Object.keys(CONFIG.PROMPT.NODES[r.from]),e)?(e=formatInputsIgnoreArray(e,CONFIG.PROMPT.NODES[r.from]),botTextMessagReply(r,"Here are your node inputs:\n\n"+e+"\n\nTo edit a particular input write /s wns_id wn_id value")):botTextMessagReply(r,"Node does not exists!")):botTextMessagReply(r,"Workflow not selected!");break;case"/sce":CONFIG.KSAMPLER_SEED_CHANGE=1,botTextMessagReply(r,"KSampler Seed Change: *Enabled*");break;case"/scd":CONFIG.KSAMPLER_SEED_CHANGE=0,botTextMessagReply(r,"KSampler Seed Change: *Disabled*");break;case"/s":if(CONFIG.MODELS[r.from]){CONFIG.PROMPT.NODES[r.from]||(CONFIG.PROMPT.NODES[r.from]=readJSONFile(CONFIG.PROMPT.MODEL[r.from]));var e=s[1],o=s[2];let t=s[3];if(4<s.length)for(let e=4;e<s.length;e++){var n=s[e];t+=" "+n}containsValue(Object.keys(CONFIG.PROMPT.NODES[r.from]),e)?containsSettings(e,o,CONFIG.PROMPT.NODES[r.from])?(editJSON(e,getSettingName(e,o,CONFIG.PROMPT.NODES[r.from]),t,CONFIG.PROMPT.NODES[r.from]),o=formatInputsIgnoreArray(e,CONFIG.PROMPT.NODES[r.from]),botTextMessagReply(r,"Node setting changed.\n\n"+o)):botTextMessagReply(r,"Node setting does not exists."):botTextMessagReply(r,"Node does not exists.")}else botTextMessagReply(r,"Workflow not selected!");break;case"/r":CONFIG.MODELS[r.from]=null,CONFIG.PROMPT.MODEL[r.from]=null,CONFIG.PROMPT.NODES[r.from]=null,botTextMessagReply(r,"Reset Done.\n");break;case"/q":CONFIG.KSAMPLER_SEED_CHANGE&&editInputs(CONFIG.PROMPT.NODES[r.from],"KSampler","seed",Date.now()),editInputs(CONFIG.PROMPT.NODES[r.from],"WA_ImageSaver","Path",path.join(CONFIG.OUTPUT_DIRECTORY,extractPhoneNumber(r.from)));e={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({prompt:CONFIG.PROMPT.NODES[r.from]})};fetch(CONFIG.API_URL+"/prompt",e).then(e=>e.json()).then(e=>{botTextMessagReply(r,"Promt Submitted.\n"),watch(r.from,e)}).catch(e=>console.error("Error:",e));break;case"/m":if(isAdmin(r.from)){let e=parseInt(s[1]);1==e?(CONFIG.MODE=1,botTextMessagReply(r,`Usage Mode changed to: *${1==CONFIG.MODE?"Single User":"Multi User"}*`)):2==e?(CONFIG.MODE=2,botTextMessagReply(r,`Usage Mode changed to: *${1==CONFIG.MODE?"Single User":"Multi User"}*`)):botTextMessagReply(r,"Invalid Mode.")}else botTextMessagReply(r,"You are not Admin.");break;case"/i":fetch(CONFIG.API_URL+"/interrupt",{method:"POST"}).then(e=>{botTextMessagReply(r,"Promt Interrupted.\n\n")}).catch(e=>console.error("Error:",e));break;default:2==$a&&botTextMessagReply(r,"Invalid command. Message */c*")}}args.forEach(e=>{var[e,t]=e.split("=");"--mode"===e?CONFIG.MODE=parseInt(t):"--admin"===e?CONFIG.ADMIN=t+"@c.us":"--api"===e?CONFIG.API_URL=t:"--pd"===e&&(CONFIG.MAIN_DIRECTORY=t,addDirectories())});let options={executablePath:CONFIG.CHROME,headless:!0},ON=(CONFIG.CHROME||0!=CONFIG.CHROME.length||delete options.executablePath,CONFIG.WA=new Client({authStrategy:new LocalAuth({dataPath:CONFIG.BROWSER_DIRECTORY}),puppeteer:options}),CONFIG.WA.on("qr",e=>{CONFIG.QRCODE=e,qrcode.toFile(path.join(CONFIG.TEMP_DIRECTORY,"qr.png"),e,{color:{dark:"#000",light:"#fff"}},e=>{if(e)throw e;console.log("QR code generated successfully!")})}),CONFIG.WA.on("ready",()=>{CONFIG.READY=!0,CONFIG.ADMIN&&botTextMessage(CONFIG.ADMIN,`ComfyUI Bot is *Online*.
Message */c* to start.
Usage Mode: *${1==CONFIG.MODE?"Single User":"Multi User"}*`)}),CONFIG.WA.on("message_create",e=>{e.body.includes("🤖")||(1==CONFIG.MODE&&1==e.id.fromMe?setCommand(e):1==CONFIG.MODE&&0==e.id.fromMe?botTextMessagReply("I can't fulfill your request sorry 😅."):2==CONFIG.MODE&&setCommand(e))}),CONFIG.EXPRESS.use(express.static(CONFIG.WEB_DIRECTORY)),CONFIG.EXPRESS.use(express.json()),CONFIG.EXPRESS.get("/ping",(e,t)=>t.json({TIME:+new Date})),CONFIG.EXPRESS.get("/qr",(e,t)=>{var r=path.join(CONFIG.TEMP_DIRECTORY,"qr.png");return fs.existsSync(r)?t.sendFile(path.resolve(r)):t.status(404).send("QR code image not found")}),CONFIG.EXPRESS.get("/ready",(e,t)=>t.json({ready:CONFIG.READY})),CONFIG.EXPRESS.post("/model",async(e,t)=>{try{var r=e.body,s=r.name,o=path.join(CONFIG.MODELS_DIRECTORY,s);await fsp.mkdir(CONFIG.MODELS_DIRECTORY,{recursive:!0}),await fsp.writeFile(o,JSON.stringify(r.data,null,2),"utf8"),t.status(200).json({success:!0,message:"Model data saved successfully"})}catch(e){console.error("Error saving model data:",e),t.status(500).json({success:!1,message:"Failed to save model data"})}}),CONFIG.EXPRESS.get("/models",async(e,t)=>{try{var r=await fsp.readdir(CONFIG.MODELS_DIRECTORY),s=await Promise.all(r.map(async e=>{var t=path.join(CONFIG.MODELS_DIRECTORY,e),t=await fsp.stat(t);return{name:e.split(".")[0],dateCreated:t.mtime.toISOString()}}));t.status(200).json(s)}catch(e){console.error("Error retrieving models:",e),t.status(500).json({success:!1,message:"Failed to retrieve models"})}}),CONFIG.EXPRESS.delete("/model/:name",async(e,t)=>{try{var r=e.params.name,s=path.join(CONFIG.MODELS_DIRECTORY,r+".json");await fsp.unlink(s),t.status(200).json({success:!0,message:"Model deleted successfully"})}catch(e){console.error("Error deleting model:",e),t.status(500).json({success:!1,message:"Failed to delete model"})}}),CONFIG.EXPRESS.get("/",(e,t)=>t.sendFile(path.join(__dirname,"website","index.html"))),!0);ON&&(createDirectories(CONFIG),CONFIG.WA.initialize(),CONFIG.EXPRESS.listen(CONFIG.PORT,()=>{console.log("Server running at http://localhost:"+CONFIG.PORT)}));