diff --git a/divabotguardian/DivaBotGuardian b/divabotguardian/DivaBotGuardian index e9b45b3..729b36e 160000 --- a/divabotguardian/DivaBotGuardian +++ b/divabotguardian/DivaBotGuardian @@ -1 +1 @@ -Subproject commit e9b45b34b72f559faf87ea51d9746da802fd0aff +Subproject commit 729b36e47deaaa403ae45d8f94ce0ac67d31ed2b diff --git a/divabotguardian/cropped.png b/divabotguardian/cropped.png index da3799c..50fd93b 100644 Binary files a/divabotguardian/cropped.png and b/divabotguardian/cropped.png differ diff --git a/divabotguardian/processes/3.divabotguardian b/divabotguardian/processes/3.divabotguardian index 1b28c18..ebef980 100644 --- a/divabotguardian/processes/3.divabotguardian +++ b/divabotguardian/processes/3.divabotguardian @@ -1 +1 @@ -31083 +28613 diff --git a/divabotguardian/processes/3.ffmpeg b/divabotguardian/processes/3.ffmpeg index 84fdc56..a08c2f1 100644 --- a/divabotguardian/processes/3.ffmpeg +++ b/divabotguardian/processes/3.ffmpeg @@ -1 +1 @@ -31081 +28611 diff --git a/divabotguardian/streams/tempoutput0_3.png b/divabotguardian/streams/tempoutput0_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput0_3.png and b/divabotguardian/streams/tempoutput0_3.png differ diff --git a/divabotguardian/streams/tempoutput1_3.png b/divabotguardian/streams/tempoutput1_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput1_3.png and b/divabotguardian/streams/tempoutput1_3.png differ diff --git a/divabotguardian/streams/tempoutput2_3.png b/divabotguardian/streams/tempoutput2_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput2_3.png and b/divabotguardian/streams/tempoutput2_3.png differ diff --git a/divabotguardian/streams/tempoutput3_3.png b/divabotguardian/streams/tempoutput3_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput3_3.png and b/divabotguardian/streams/tempoutput3_3.png differ diff --git a/divabotguardian/streams/tempoutput4_3.png b/divabotguardian/streams/tempoutput4_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput4_3.png and b/divabotguardian/streams/tempoutput4_3.png differ diff --git a/divabotguardian/streams/tempoutput5_3.png b/divabotguardian/streams/tempoutput5_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput5_3.png and b/divabotguardian/streams/tempoutput5_3.png differ diff --git a/divabotguardian/streams/tempoutput6_3.png b/divabotguardian/streams/tempoutput6_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput6_3.png and b/divabotguardian/streams/tempoutput6_3.png differ diff --git a/divabotguardian/streams/tempoutput7_3.png b/divabotguardian/streams/tempoutput7_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput7_3.png and b/divabotguardian/streams/tempoutput7_3.png differ diff --git a/divabotguardian/streams/tempoutput8_3.png b/divabotguardian/streams/tempoutput8_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput8_3.png and b/divabotguardian/streams/tempoutput8_3.png differ diff --git a/divabotguardian/streams/tempoutput9_3.png b/divabotguardian/streams/tempoutput9_3.png index ae959eb..de0d73e 100644 Binary files a/divabotguardian/streams/tempoutput9_3.png and b/divabotguardian/streams/tempoutput9_3.png differ diff --git a/frontend/package-lock.json b/frontend/package-lock.json index dc6cd5b..022c054 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8483,6 +8483,11 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", + "integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index f8d5b59..068fd99 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,6 +9,7 @@ "@testing-library/user-event": "^7.2.1", "axios": "^0.19.2", "http-proxy-middleware": "^1.0.5", + "moment": "^2.29.0", "react": "^16.13.1", "react-bootstrap": "^1.3.0", "react-dom": "^16.13.1", diff --git a/frontend/src/App.js b/frontend/src/App.js index e663a77..bb7c5b3 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -21,6 +21,7 @@ import { const REMOTE_ADDR = "http://45.33.13.215:4502"; const axios = require('axios'); +const moment = require('moment'); var IMAGE_CAMERA=(p)=>{ return( @@ -688,6 +689,8 @@ function LoadMore(p) { var [visible,setVisible] = useState(false) var [update,setUpdate] = useState(false) + const firstUpdate = useRef(true); + useEffect(()=>{ axios.get(p.url+constructParams(params)) .then((data)=>{ @@ -695,7 +698,17 @@ function LoadMore(p) { setVisible(true) } }) - },[update]) + },[update,p.profileUpdate]) + + useEffect(()=>{ + if (firstUpdate.current) { + firstUpdate.current = false; + return; + } + var obj = params + obj.offset=p.params.offset + setParams(obj) + },[p.profileUpdate,p.username]) function constructParams(params) { var st = Object.keys(params).reduce((str,key)=>{ @@ -791,14 +804,14 @@ function BestPlaysPanel(p) { useEffect(()=>{ axios.get("http://www.projectdivar.com/bestplays/"+p.username+"?fails=false&limit=5&offset=0") .then((data)=>{setBestPlays(data.data);}) - },[update,p.username]) + },[p.profileUpdate,update,p.username]) var content=
@@ -887,7 +900,7 @@ function PlayData(p) { useEffect(()=>{ axios.get("http://projectdivar.com/plays/"+p.username+"/"+p.song.id) .then((data)=>{setData(data.data);}) - },[update]) + },[p.profileUpdate,update]) return ( <> @@ -895,7 +908,7 @@ function PlayData(p) {
Individual Plays for {p.song.name} from {p.username}
{data.map((play,i)=>)} - +
@@ -931,14 +944,16 @@ function HoverSongName(p) { if ((p.song.report.ecount+p.song.report.ncount+p.song.report.hcount+p.song.report.excount+p.song.report.exexcount>0)) { if (toggle) { setExpand( - + ) - window.scroll(0,cumulativeOffset(document.getElementById("songRow_"+p.song.name)).top-document.getElementById("songRow_"+p.song.name).getBoundingClientRect().height); + if (match!==null) { + window.scroll(0,cumulativeOffset(document.getElementById("songRow_"+p.song.name)).top-document.getElementById("songRow_"+p.song.name).getBoundingClientRect().height); + } } else { setExpand(<>) } } - },[toggle]) + },[p.profileUpdate,toggle]) return ( <> @@ -981,6 +996,15 @@ function CompletionPanel(p) { .then((data)=>{setReport(data.data)}) .catch((err)=>{console.log(err.message)}) },[update,p.username]) + useEffect(()=>{ + if (firstUpdate.current) { + firstUpdate.current = false; + return; + } + setUpdate(!update) + },[p.profileUpdate]) + + const firstUpdate = useRef(true); return ( <> @@ -1009,7 +1033,7 @@ function CompletionPanel(p) { - {report.filter((report)=>Object.keys(filter).length==0||report.id in filter).map((song,i)=>{return (HasSong(song,p.user))?:<> + {report.filter((report)=>Object.keys(filter).length==0||report.id in filter).map((song,i)=>{return (HasSong(song,p.user))?:<> })} @@ -1112,6 +1136,10 @@ function Profile(p){ var [modalsrc,setModalSrc] = useState({}) var [modalVisible,setModalVisible] = useState(false); var [mouseOver,setMouseOver] = useState(false); + var [loadedTime,setLoadedTime] = useState(new Date()); + + const firstUpdate = useRef(true); + let history = useHistory(); function CalculateClear(easy,normal,hard,ex,exex,fcdata,pfcdata) { return <> @@ -1123,12 +1151,39 @@ function Profile(p){ } + useEffect(()=>{ + if (firstUpdate.current) { + firstUpdate.current = false; + return; + } + setUpdate(!update) + },[loadedTime]) + useEffect(()=>{ axios.get("http://projectdivar.com:4501/userdata/"+username) .then((data)=>{setUserData(data.data);setPlayCount(data.data.playcount);setFCCount(data.data.fccount);setRating(data.data.rating);setLastPlayed(data.data.last_played);setAccuracy(CalculateAccuracy(data.data.cool,data.data.fine,data.data.safe,data.data.sad,data.data.worst))}); axios.get("http://projectdivar.com:4501/songdiffs") .then((data)=>{setDiffs(data.data)}) setModalVisible(false); + const interval = setInterval(()=>{ + axios.get("http://projectdivar.com/userdata/"+username) + .then((data)=>{ + return axios.get("http://projectdivar.com/updates/"+data.data.id) + }) + .then((data)=>{ + //Positive number means new update is available for this profile. + //console.log(moment(data.data.date).diff(loadedTime)) + if (moment(data.data.date).diff(loadedTime)>0) { + setLoadedTime(new Date()) + history.push("/user/"+username) + } + }) + .catch((err)=>{ + //console.log(err.message) + }) + },10000) + + return ()=>clearInterval(interval) },[update,username]) useEffect(()=>{ @@ -1155,8 +1210,8 @@ function Profile(p){ } - - + + :<> @@ -1508,6 +1563,7 @@ function LoginInfo(p) { Welcome, {username}!
My Profile
Edit Profile Settings
+ My Stream Panel
App Auth Code
:<> @@ -1849,6 +1905,17 @@ function DivaBot() { ) } +function StreamPanel(p) { + + const [update,setUpdate] = useState(false); + + return ( + <> + + + ) +} + function StreamData() { const [imageSet,setImageSet] = useState(0); const [rando1,setRando1] = useState(Date.now()); @@ -1938,6 +2005,10 @@ function Website() {

Register New Account

+ +

Stream Panel

+ +

Stream

diff --git a/frontend/src/setupProxy.js b/frontend/src/setupProxy.js index e4c8d4c..37a72f5 100644 --- a/frontend/src/setupProxy.js +++ b/frontend/src/setupProxy.js @@ -1,6 +1,13 @@ const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { + app.use( + "/updates/:userid", + createProxyMiddleware({ + target: 'http://server:4501', + changeOrigin: true, + }) + ); app.use( "/passImageData", createProxyMiddleware({ diff --git a/imgparser/projectDivaImgParser b/imgparser/projectDivaImgParser index 457bbb6..bcf0448 160000 --- a/imgparser/projectDivaImgParser +++ b/imgparser/projectDivaImgParser @@ -1 +1 @@ -Subproject commit 457bbb6fa840d8a36b2f6b935bb2fc4066891a5f +Subproject commit bcf04481d4cb70d35b8c5a9d8602eb2fde115cc3 diff --git a/server/app.js b/server/app.js index 8c58607..0e0285c 100644 --- a/server/app.js +++ b/server/app.js @@ -117,7 +117,9 @@ app.delete('/remove',(req,res)=>{ .then((data)=>{if(data && data.rows.length>0){songObj=data.rows[0];return CalculateRating(req.body.username)}else{throw new Error("Could not find play!")}}) .then((data)=>{rating=data;return db.query("select * from plays where songid=$1 and userid=$2 and difficulty=$3 and score>0 limit 1",[songObj.songid,userObj.id,songObj.difficulty])}) .then((data)=>{if(data && data.rows.length===0){isFirstClear=true;}/*console.log([data,userObj.playcount-1,(songObj.safe==0&&songObj.sad==0&&songObj.worst==0)?userObj.fccount-1:userObj.fccount,userObj.cool-songObj.cool,userObj.fine-songObj.fine,userObj.safe-songObj.safe,userObj.sad-songObj.sad,userObj.worst-songObj.worst,(songObj.difficulty=="E")?userObj.ecount-1:userObj.ecount,(songObj.difficulty=="N")?userObj.ncount-1:userObj.ncount,(songObj.difficulty=="H")?userObj.hcount-1:userObj.hcount,(songObj.difficulty=="EX")?userObj.excount-1:userObj.excount,(songObj.difficulty=="EXEX")?userObj.exexcount-1:userObj.exexcount]);*/return db.query("update users set rating=$1,playcount=$2,fccount=$3,cool=$4,fine=$5,safe=$6,sad=$7,worst=$8,eclear=$9,nclear=$10,hclear=$11,exclear=$12,exexclear=$13 where id=$14 returning rating,playcount,fccount,cool,fine,safe,sad,worst,eclear,nclear,hclear,exclear,exexclear",[rating,userObj.playcount-1,(songObj.safe==0&&songObj.sad==0&&songObj.worst==0)?userObj.fccount-1:userObj.fccount,userObj.cool-songObj.cool,userObj.fine-songObj.fine,userObj.safe-songObj.safe,userObj.sad-songObj.sad,userObj.worst-songObj.worst,(songObj.difficulty=="E" && isFirstClear)?userObj.eclear-1:userObj.eclear,(songObj.difficulty=="N" && isFirstClear)?userObj.nclear-1:userObj.nclear,(songObj.difficulty=="H" && isFirstClear)?userObj.hclear-1:userObj.hclear,(songObj.difficulty=="EX" && isFirstClear)?userObj.exclear-1:userObj.exclear,(songObj.difficulty=="EXEX" && isFirstClear)?userObj.exexclear-1:userObj.exexclear,userObj.id])}) - .then((data)=>{if(data && data.rows.length>0){res.status(200).json({user:data.rows[0],song:songObj})}else{throw new Error("Could not update user information, but song is deleted!")}}) + .then((data)=>{if(data && data.rows.length>0){res.status(200).json({user:data.rows[0],song:songObj}) + axios.post("http://projectdivar.com/updates/"+userObj.id,{password:process.env.GMAIL,type:"delete"}) + }else{throw new Error("Could not update user information, but song is deleted!")}}) .catch((err)=>{res.status(500).json(err.message)}) } else { res.status(400).send("Missing required parameters!"); @@ -296,10 +298,14 @@ app.post('/submit', (req, res) => { .then((data)=>{return db.query("update users set rating=$1,last_played=$3,playcount=$4,fccount=$5,cool=$6,fine=$7,safe=$8,sad=$9,worst=$10,eclear=$11,nclear=$12,hclear=$13,exclear=$14,exexclear=$15,megamix=$16,futuretone=$17 where username=$2",[data,req.body.username,new Date(),++playcount,fccount+((isFC)?1:0),cool+Number(req.body.cool),fine+Number(req.body.fine),safe+Number(req.body.safe),sad+Number(req.body.sad),worst+Number(req.body.worst),eclear,nclear,hclear,exclear,exexclear,(songdata.mega39s||userObj.megamix),(songdata.futuretone&&!songdata.mega39s)||userObj.futuretone])}) .then((data)=>{return songsubmitdata;}) .then((data)=>{ + //userId + //password, type + axios.post("http://projectdivar.com/updates/"+userId,{password:process.env.GMAIL,type:"submit"}) if (req.body.src) { db.query("delete from uploadedplays where filename=$1",[req.body.src]) } - res.status(200).json(data);}) + res.status(200).json(data); + }) .catch((err)=>{ //console.log(req.body); console.log(err); @@ -384,6 +390,42 @@ app.get('/accuracy/:username',(req,res)=>{ .catch((err)=>{res.status(500).send(err.message)}) }) +app.get('/updates/:userid',(req,res)=>{ + db.query('select * from userupdate where userid=$1',[req.params.userid]) + .then((data)=>{ + if (data.rows.length>0) { + res.status(200).json(data.rows[0]) + } else { + res.status(400).send("No user update found!") + } + }) + .catch((err)=>{ + res.status(500).send(err.message) + }) +}) + +app.post('/updates/:userid',(req,res)=>{ + if (req.body&&req.body.password&&req.body.type) { + if (req.body.password===process.env.GMAIL) { + db.query("insert into userupdate(userid,update_type,date) values($1,$2,$3) on conflict(userid) do update set update_type=$2,date=$3 where userupdate.userid=$1 returning *",[req.params.userid,req.body.type,moment()]) + .then((data)=>{ + if (data.rows.length>=0) { + res.status(200).send(data.rows[0]) + } else { + throw new Error("Could not update user.") + } + }) + .catch((err)=>{ + res.status(500).send(err.message) + }) + } else { + res.status(403).send("Could not authenticate") + } + } else { + res.status(400).send("Invalid credentials!") + } +}) + app.get('/recalculatescore/:playid',(req,res)=>{ var userId=-1; var username=null; @@ -400,6 +442,9 @@ app.get('/recalculatescore/:playid',(req,res)=>{ return db.query('select username from users where id=$1',[userId]).then((data)=>{username=data.rows[0].username; return CalculateRating(username)}).then((data)=>{db.query("update users set rating=$1 where username=$2",[data,username])}) .then(()=>{return scoreData;}) }else{throw new Error("Failed to update score!")}}) + .then((data)=>{ + axios.post("http://projectdivar.com/updates/"+userId,{password:process.env.GMAIL,type:"recalculate"}) + }) .then((data)=>res.status(200).json(data)).catch((err)=>{console.log(err);res.status(500).send(err.message);}) }); @@ -492,7 +537,7 @@ app.get('/bestplay/:username/:songname/:difficulty',(req,res)=>{ app.get('/userdata/:username',(req,res)=>{ var songId=-1,userId=-1,finalData={}; - db.query('select megamix,futuretone,playstyle,playcount,fccount,rating,last_played,cool,fine,safe,sad,worst,eclear,nclear,hclear,exclear,exexclear from users where username=$1 limit 1',[req.params.username]) + db.query('select id,megamix,futuretone,playstyle,playcount,fccount,rating,last_played,cool,fine,safe,sad,worst,eclear,nclear,hclear,exclear,exexclear from users where username=$1 limit 1',[req.params.username]) .then((data)=>{if(data && data.rows.length>0){finalData=data.rows[0];return db.query("select t.difficulty,COUNT(t.difficulty) from (select distinct on(songid) songid,*,users.id from plays join users on userid=users.id where users.username=$1 and plays.safe=0 and plays.worst=0 and plays.sad=0)t group by t.difficulty",[req.params.username])}else{throw new Error("Could not retrieve user data!")}}) .then((data)=>{ if (data) { @@ -799,7 +844,7 @@ function GetUserInfo(username) { return db.query("select id,username,email,code_time from users where username=$1 limit 1",[username]) } function GetUserLoginAllowed(username,authCode) { - return db.query("select id,username,email,code_time,playstyle,twitter_name from users where username=$1 and code=$2 limit 1",[username,authCode]) + return db.query("select id,username,email,code_time,playstyle,twitter_name,twitch_name from users where username=$1 and code=$2 limit 1",[username,authCode]) } app.post('/authenticate/authToken',(req,res)=>{ if (req.body&&req.body.username&&req.body.authCode) { diff --git a/server/invalidSongs b/server/invalidSongs index bfd8779..c65d194 100644 --- a/server/invalidSongs +++ b/server/invalidSongs @@ -81,3 +81,6 @@ {"song":"深海シティアンダーグラウンド","username":"sigonasr2","authentication_token":"sig","difficulty":"","cool":"-1","fine":"-1","safe":"-1","sad":"-1","worst":"-1","percent":"-1.0","fail":"false","combo":"-1","mod":"","gameScore":"-1","src":"http://pbs.twimg.com/media/EiK0POLVkAIFpho.jpg"} {"song":"深海シティアンダーグラウンド","username":"sigonasr2","authentication_token":"sig","difficulty":"","cool":"-1","fine":"-1","safe":"-1","sad":"-1","worst":"-1","percent":"-1.0","fail":"false","combo":"-1","mod":"","gameScore":"-1","src":"http://pbs.twimg.com/media/EiK0POLVkAIFpho.jpg"} {"song":"スノーマン","username":"sigonasr2","authentication_token":"sig","difficulty":"","cool":"-1","fine":"-1","safe":"-1","sad":"-1","worst":"-1","percent":"-1.0","fail":"false","combo":"-1","mod":"","gameScore":"-1","src":"http://projectdivar.com/files/plays/3/690"} +{"song":"恋は戦争","username":"sigonasr2","authentication_token":"sig","difficulty":"","cool":"-1","fine":"-1","safe":"-1","sad":"-1","worst":"-1","percent":"-1.0","fail":"false","combo":"-1","mod":"","gameScore":"-1","src":"http://projectdivar.com/files/plays/3/692"} +{"song":"スノーマン","username":"sigonasr2","authentication_token":"sig","difficulty":"","cool":"-1","fine":"-1","safe":"-1","sad":"-1","worst":"-1","percent":"-1.0","fail":"false","combo":"-1","mod":"","gameScore":"-1","src":"http://projectdivar.com/files/plays/3/695"} +{"song":"スノーマン","username":"testStreamer","authentication_token":"test","difficulty":"","cool":"-1","fine":"-1","safe":"-1","sad":"-1","worst":"-1","percent":"-1.0","fail":"false","combo":"-1","mod":"","gameScore":"-1","src":"http://projectdivar.com/files/plays/64/7"}