const express = require('express') const axios = require('axios') var http = require('http'); var https = require('https'); const fs = require('fs'); const sh = require('secrethash'); var key = fs.readFileSync('./projectdivar.com/privkey.pem'); var cert = fs.readFileSync('./projectdivar.com/cert.pem'); var options = { key: key, cert: cert }; const app = express() var server = https.createServer(options, app); const port = 4505 server.listen(port, () => console.log(`Example app listening at http://localhost:${port}`)) const bodyParser = require('body-parser') const { json } = require('body-parser') const moment = require('moment'); const Pool = require('pg').Pool app.use(bodyParser.json()) app.use( bodyParser.urlencoded({ extended: true, }) ) let allowCrossDomain = function(req, res, next) { res.header('Access-Control-Allow-Origin', "*"); res.header('Access-Control-Allow-Headers', "*"); res.header('Access-Control-Allow-Methods', "*"); next(); } app.use(allowCrossDomain); var db = new Pool({ user: 'postgres', password: '', host: 'postgres', database: 'sigcrafting', port: 5432, }) app.get('/',async(req,res)=>{ res.status(200).send('BUN is love, BUN is life.') }) app.get('/getData',(req,res)=>{ db.query('select * from crafting_list order by id asc') .then((data)=>{ if (data.rows.length>0) { res.status(200).json(data.rows) } else { res.status(204).send("No data") } }) .catch((err)=>{ res.status(500).send(err.message) }) }) app.get('/getNotifications',(req,res)=>{ db.query('select * from audit_log where date>$1 order by id asc limit 10',[req.query.date]) .then((data)=>{ res.status(200).json(data.rows) }) .catch((err)=>{ console.log(err) res.status(500).send(err.message) }) }) app.get('/lastUpdate',(req,res)=>{ db.query("select * from site_data limit 1") .then((data)=>{ res.status(200).json(data.rows) }) .catch((err)=>{ res.status(500).send(err.message) }) }) app.post("/updateItem",(req,res)=>{ var itemIcon="" db.query("update crafting_list set obtained=$1 where id=$2 returning *",[req.body.obtained,req.body.id]) .then((data)=>{ itemIcon = "https://xivapi.com"+data.rows[0].icon return db.query("update site_data set last_modified=$1",[req.body.last_modified]) }) .then((data)=>{ return axios.post(process.env.DISCORD_WEBHOOK,{embeds:[{ author:{ name:req.body.item_name, icon_url:itemIcon }, color:req.body.obtained==req.body.required?32768:Number(req.body.obtained)>0?20680:2172201, description:"**"+req.body.username+"** "+(req.body.operation==="FINISH"?" has finished "+(req.body.finalcraft===true?"crafting ":"collecting ")+req.body.required+" __"+req.body.item_name+"__!": req.body.operation==="INCREASE"?" has collected "+req.body.obtained+" / "+req.body.required+" __"+req.body.item_name+"__ (+"+(req.body.obtained-req.body.previous_amt)+")" :" has set __"+req.body.item_name+"__ to "+req.body.obtained+" / "+req.body.required)+"\n\n[Sig Planner - Sig crafts all the things](http://projectdivar.com:3001)", footer:{ "text":"Progress: "+((req.body.itemCount+req.body.obtained-req.body.previous_amt)/req.body.totalItemCount*100).toFixed(2)+"% ("+(req.body.itemCount+req.body.obtained-req.body.previous_amt)+"/"+req.body.totalItemCount+")" } }] })}) .then((data)=>{ return db.query("insert into audit_log(username,obtained,required,item_name,operation,date,previous_amt) values($1,$2,$3,$4,$5,$6,$7)",[req.body.username,req.body.obtained,req.body.required,req.body.item_name,req.body.operation==="FINISH"&&req.body.finalcraft===true?"FINISH_CRAFT":req.body.operation,req.body.last_modified,req.body.previous_amt]) }) .then((data)=>{ res.status(200).send("Yay!") }) .catch((err)=>{ console.log(err.message) res.status(500).send(err.message) }) }) app.post("/updateTimer",(req,res)=>{ if (req.body.timer_start!==null&&req.body.timer_end!==null&&req.body.timer_start!==undefined&&req.body.timer_end!==undefined){ var splitter=req.body.timer_start.split(",") var splitter2=req.body.timer_end.split(",") for (t of splitter){ if (t=="")continue; if (t.split(":").length!=2||(t.split(":").length==2&&(isNaN(t.split(":")[0])||isNaN(t.split(":")[1])))){ res.status(500).send("Invalid input!") return } } for (t of splitter2){ if (t=="")continue; if (t.split(":").length!=2||(t.split(":").length==2&&(isNaN(t.split(":")[0])||isNaN(t.split(":")[1])))){ console.log(t) res.status(500).send("Invalid input!") return } } db.query("update crafting_list set timer_start=$1,timer_end=$2 where id=$3 returning *",[req.body.timer_start,req.body.timer_end,req.body.id]) .then((data)=>{ itemIcon = "https://xivapi.com"+data.rows[0].icon return db.query("update site_data set last_modified=$1",[req.body.last_modified]) }) .then((data)=>{ res.status(200).send("Yay!") }) .catch((err)=>{ console.log(err.message) res.status(500).send(err.message) }) } else { res.status(500).send("Invalid input!") } }) app.post('/setItem',async(req,res)=>{ await db.query('select * from crafting_list where itemid=$1',[req.body.itemid]) .then((data)=>{ if (data.rows.length==0){ db.query('insert into crafting_list(itemid,name,obtained,required,icon) values($1,$2,$3,$4,$5)',[req.body.itemid,req.body.name,req.body.obtained,req.body.required,req.body.icon]) .then((data)=>{ res.status(200).send("Yay!") }) .catch((err)=>{ res.status(500).send(err.message) }) } else { db.query('update crafting_list set required=$1 where itemid=$2',[Number(data.rows[0].required)+Number(req.body.required),req.body.itemid]) .then((data)=>{ res.status(200).send("Yayay!") }) .catch((err)=>{ res.status(500).send(err.message) }) } }) }) app.post('/addItem',async(req,res)=>{ await db.query('select * from crafting_list where itemid=$1',[req.body.itemid]) .then((data)=>{ if (data.rows.length>0){ db.query('update crafting_list set obtained=$1 where itemid=$2',[Math.min(data.rows[0].required,Number(data.rows[0].obtained)+Number(req.body.obtained)),req.body.itemid]) .then((data)=>{ res.status(200).send("AYAYA") }) .catch((err)=>{ res.status(500).send(err.message) }) } else { res.status(200).send("Nothing to do!") } }) }) function ConvertIssues(str,repoURL){ var split=str.split("Issue #"); for(var i=0;i").replaceAll("@sigonasr2","<@176012829076226048>") } var embedItems=[]; function ParseAttachments(str){ var stage=0; var backTickRepeatCount=0; var backTicksEnabled=false; var isImage=false; var accumulatedLink=""; for(var i=0;i0&&str[i-1]=='!'){ isImage=true; } else { isImage=false; } stage++; } }break; case 1:{ //In stage 1 we look for ]. if(str[i]==']'){ stage++; } }break; case 2:{ //In stage 2 the next character should be (. If it's not, reset. if(str[i]=='('){ stage++; } else { stage=0; } }break; case 3:{ //In stage 3, we accumulate what's inside and look for ). if(str[i]==')'){ //We're done! We have a new embed. if(accumulatedLink.startsWith("http")){ if(isImage){ embedItems=[...embedItems,{image:{url:accumulatedLink}}] } else { embedItems=[...embedItems,{url:accumulatedLink}] } }else{ if(isImage){ embedItems=[...embedItems,{image:{url:"http://sig.projectdivar.com/"+accumulatedLink}}] } else { embedItems=[...embedItems,{url:"http://sig.projectdivar.com/"+accumulatedLink}] } } accumulatedLink="" isImage=false; stage=0; break; } else { accumulatedLink+=str[i]; } }break; } } return str } app.post("/postUpdate",(req,res)=>{ res.status(200).send("Thank you!") embedItems=[] if(req.body.action){ switch(req.body.action){ case "opened":{ embedItems=[{ author:{ name:"Issue #"+req.body.number+" opened by "+req.body.issue.user.username, icon_url:req.body.issue.user.avatar_url }, color:11731199, description:"**"+req.body.issue.title+":**\n\n"+ParseAttachments(ParseMentions(req.body.issue.body))+"\n\n[Link to Issue]("+req.body.issue.html_url+")", },...embedItems]; axios.post(process.env.GITEA_WEBHOOK,{embeds:embedItems}) }break; case "reopened":{ axios.post(process.env.GITEA_WEBHOOK,{embeds:[{ author:{ name:"Issue #"+req.body.number+" re-opened by "+req.body.issue.user.username, icon_url:req.body.issue.user.avatar_url }, color:13789695, description:"**"+req.body.issue.title+":**\n\n"+req.body.issue.body+"\n\n[Link to Issue]("+req.body.issue.html_url+")", }] }) }break; case "assigned":{ var assignedList="" for(assignee of req.body.issue.assignees){ if(assignedList.length==0){ assignedList+=assignee.username }else{ assignedList+=","+assignee.username } } axios.post(process.env.GITEA_WEBHOOK,{embeds:[{ author:{ name:"Assigned users to Issue #"+req.body.number, icon_url:req.body.issue.user.avatar_url }, color:50363, description:"Assigned **"+assignedList+"** to Issue **"+req.body.issue.title+"**\n\n[Link to Issue]("+req.body.issue.html_url+")", }] }) }break; case "label_updated":{ var labelsList="" for(label of req.body.issue.labels){ if(labelsList.length==0){ labelsList+="- **"+label.name+"**" }else{ labelsList+="\n- **"+label.name+"**" } } axios.post(process.env.GITEA_WEBHOOK,{embeds:[{ author:{ name:"Assigned labels to Issue #"+req.body.number, icon_url:req.body.issue.user.avatar_url }, color:365568, description:"Labels set for Issue **"+req.body.issue.title+"**:\n"+labelsList+"\n\n[Link to Issue]("+req.body.issue.html_url+")", }] }) }break; case "created":{ axios.post(process.env.GITEA_WEBHOOK,{embeds:[{ author:{ name:"Comment posted on Issue #"+req.body.issue.number, icon_url:req.body.comment.user.avatar_url }, color:11731199, description:"__**"+req.body.issue.title+"**__\nCommented by **"+req.body.comment.user.username+":**\n"+ParseAttachments(ParseMentions(req.body.comment.body))+"\n\n[Link to Comment]("+req.body.comment.html_url+")", }] }) }break; case "edited":{ if(req.body.comment){ embedItems=[{ author:{ name:"Comment edited on Issue #"+req.body.issue.number, icon_url:req.body.comment.user.avatar_url }, color:11731199, description:"__**"+req.body.issue.title+"**__\nCommented by **"+req.body.comment.user.username+":**\n"+ParseAttachments(ParseMentions(req.body.comment.body))+"\n\n[Link to Comment]("+req.body.comment.html_url+")", },...embedItems] axios.post(process.env.GITEA_WEBHOOK,{embeds:embedItems}) } else { embedItems=[{ author:{ name:"Edit on Issue #"+req.body.issue.number, icon_url:req.body.issue.user.avatar_url }, color:11731199, description:"__**"+req.body.issue.title+"**__\nEdited by **"+req.body.issue.user.username+":**\n"+ParseAttachments(ParseMentions(req.body.issue.body))+"\n\n[Link to Issue]("+req.body.issue.html_url+")", },...embedItems] axios.post(process.env.GITEA_WEBHOOK,{embeds:embedItems}) } }break; case "deleted":{ axios.post(process.env.GITEA_WEBHOOK,{embeds:[{ author:{ name:"Comment deleted on Issue #"+req.body.issue.number, icon_url:req.body.comment.user.avatar_url }, color:11731199, description:"__**"+req.body.issue.title+"**__\nCommented by **"+req.body.comment.user.username+":**\n~~"+req.body.comment.body+"~~\n\n[Link to Comment]("+req.body.comment.html_url+")", }] }) }break; case "closed":{ axios.post(process.env.GITEA_WEBHOOK,{embeds:[{ author:{ name:"Issue #"+req.body.number+" closed by "+req.body.issue.user.username, icon_url:req.body.issue.user.avatar_url }, color:9502805, description:"**"+req.body.issue.title+":**\n\n"+req.body.issue.body+"\n\n[Link to Issue]("+req.body.issue.html_url+")", }] }) }break; default:{ console.log("Unknown action "+req.body.action+". Ignoring.") } } } else if(req.body.ref){ for(var commit of req.body.commits){ var filesAdded=commit.added.length var filesRemoved=commit.removed.length var filesModified=commit.modified.length axios.post(process.env.GITEA_WEBHOOK,{embeds:[{ author:{ name:commit.author.username+" has pushed a new commit", icon_url:"http://sig.projectdivar.com/assets/update.png" }, color:17663, description:"**Commit ID "+commit.id+"**\n\n"+ConvertIssues(commit.message,req.body.repository.html_url)+"\n"+(filesAdded>0?"\n"+filesAdded+" file"+(filesAdded==1?"":"s")+" added":"")+(filesRemoved>0?"\n"+filesRemoved+" file"+(filesRemoved==1?"":"s")+" removed":"")+(filesModified>0?"\n"+filesModified+" file"+(filesModified==1?"":"s")+" modified":"")+"\n\n[Link to Commit]("+commit.url+")", }] }) } } else { console.log("Unknown webhook incoming. Ignoring.") } /* return axios.post(process.env.DISCORD_WEBHOOK,{embeds:[{ author:{ name:req.body.item_name, icon_url:itemIcon }, color:req.body.obtained==req.body.required?32768:Number(req.body.obtained)>0?20680:2172201, description:"**"+req.body.username+"** "+(req.body.operation==="FINISH"?" has finished "+(req.body.finalcraft===true?"crafting ":"collecting ")+req.body.required+" __"+req.body.item_name+"__!": req.body.operation==="INCREASE"?" has collected "+req.body.obtained+" / "+req.body.required+" __"+req.body.item_name+"__ (+"+(req.body.obtained-req.body.previous_amt)+")" :" has set __"+req.body.item_name+"__ to "+req.body.obtained+" / "+req.body.required)+"\n\n[Sig Planner - Sig crafts all the things](http://projectdivar.com:3001)", footer:{ "text":"Progress: "+((req.body.itemCount+req.body.obtained-req.body.previous_amt)/req.body.totalItemCount*100).toFixed(2)+"% ("+(req.body.itemCount+req.body.obtained-req.body.previous_amt)+"/"+req.body.totalItemCount+")" } }] })*/ }) var runInventoryScan = async()=>{ for (var item of myInv) { const it = item await db.query('select * from crafting_list where itemid=$1',[item.itemId]) .then(async(data)=>{ for (var row of data.rows) { if (row.required-row.obtained<=it.quantity) { await db.query('update crafting_list set obtained=$1 where itemid=$2',[row.required,it.itemId]) .catch((err)=>{ console.log(err.message) }) } else { await db.query('update crafting_list set obtained=$1 where itemid=$2',[row.obtained+it.quantity,it.itemId]) .catch((err)=>{ console.log(err.message) }) break; } } }) .catch((err)=>{ console.log(err.message) }) } } //runInventoryScan() //console.log(process.env.DISCORD_WEBHOOK)