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 < split . length - 1 ; i ++ ) {
split [ i ] += "[Issue #"
split [ i + 1 ] = split [ i + 1 ] . at ( 0 ) + "](" + repoURL + "/issues/" + split [ i + 1 ] . at ( 0 ) + ")" + split [ i + 1 ] . slice ( - 1 )
}
var split2 = split . join ( "" ) . split ( "Issue#" )
for ( var i = 0 ; i < split2 . length - 1 ; i ++ ) {
split2 [ i ] += "[Issue #"
split2 [ i + 1 ] = split2 [ i + 1 ] . at ( 0 ) + "](" + repoURL + "/issues/" + split2 [ i + 1 ] . at ( 0 ) + ")" + split2 [ i + 1 ] . slice ( - 1 )
}
return split2 . join ( "" ) ;
}
function ParseMentions ( str ) {
//@quapsel: 155789951571591168
//@sigonasr2: 176012829076226048
return str . replaceAll ( "@Quapsel" , "<@155789951571591168>" ) . 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 ; i < str . length ; i ++ ) {
//If at any time we find ```, we continue until they close.
if ( str [ i ] == '`' ) {
backTickRepeatCount ++ ;
if ( backTickRepeatCount == 3 ) {
backTickRepeatCount = 0 ;
backTicksEnabled = ! backTicksEnabled ;
}
continue ;
} else {
backTickRepeatCount = 0 ;
}
if ( backTicksEnabled ) {
continue ; //As long as we are in back tick mode, we don't care what is posted.
}
switch ( stage ) {
case 0 : {
//In stage 0 we look for [.
if ( str [ i ] == '[' ) {
if ( i > 0 && 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)