Last user activity now marked on humie-friendly page-loads and last-socket disconnects, ensuring accurate 'online' status when disconnected from a channel.
This commit is contained in:
parent
6222535c47
commit
6445950f90
|
|
@ -24,6 +24,7 @@ const {userModel} = require('../../schemas/user/userSchema');
|
||||||
const userBanModel = require('../../schemas/user/userBanSchema');
|
const userBanModel = require('../../schemas/user/userBanSchema');
|
||||||
const loggerUtils = require('../../utils/loggerUtils');
|
const loggerUtils = require('../../utils/loggerUtils');
|
||||||
const csrfUtils = require('../../utils/csrfUtils');
|
const csrfUtils = require('../../utils/csrfUtils');
|
||||||
|
const presenceUtils = require('../../utils/presenceUtils');
|
||||||
const activeChannel = require('./activeChannel');
|
const activeChannel = require('./activeChannel');
|
||||||
const chatHandler = require('./chatHandler');
|
const chatHandler = require('./chatHandler');
|
||||||
|
|
||||||
|
|
@ -259,7 +260,7 @@ class channelManager{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a disconnection event for a single active user within a given channel (when all sockets disconnect)
|
* Handles a disconnection event for a single active user within a given channel (when all sockets disconnect)
|
||||||
* @param {*} userObj
|
* @param {connectedUser} userObj - Connected user object to handle disconnection of
|
||||||
*/
|
*/
|
||||||
handleUserDisconnect(userObj){
|
handleUserDisconnect(userObj){
|
||||||
//Create array to hold
|
//Create array to hold
|
||||||
|
|
@ -282,6 +283,9 @@ class channelManager{
|
||||||
}else{
|
}else{
|
||||||
//Delete the user from the status map
|
//Delete the user from the status map
|
||||||
this.activeUsers.delete(userObj.user);
|
this.activeUsers.delete(userObj.user);
|
||||||
|
|
||||||
|
//Mark last disconnection as user activity, as they'll no longer be marked as streaming.
|
||||||
|
presenceUtils.handlePresence(userObj.user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
//npm imports
|
//npm imports
|
||||||
const { Router } = require('express');
|
const { Router } = require('express');
|
||||||
|
|
||||||
|
|
||||||
//local imports
|
//local imports
|
||||||
const permissionSchema = require("../schemas/permissionSchema");
|
const permissionSchema = require("../schemas/permissionSchema");
|
||||||
const adminPanelController = require("../controllers/adminPanelController");
|
const adminPanelController = require("../controllers/adminPanelController");
|
||||||
|
const presenceUtils = require("../utils/presenceUtils");
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
//Use authentication middleware
|
//Use authentication middleware
|
||||||
router.use(permissionSchema.reqPermCheck("adminPanel"))
|
router.use(permissionSchema.reqPermCheck("adminPanel"))
|
||||||
|
router.use(presenceUtils.presenceMiddleware);
|
||||||
|
|
||||||
//routing functions
|
//routing functions
|
||||||
router.get('/', adminPanelController.get);
|
router.get('/', adminPanelController.get);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ const { Router } = require('express');
|
||||||
const channelModel = require("../schemas/channel/channelSchema");
|
const channelModel = require("../schemas/channel/channelSchema");
|
||||||
const channelController = require("../controllers/channelController");
|
const channelController = require("../controllers/channelController");
|
||||||
const channelSettingsController = require("../controllers/channelSettingsController");
|
const channelSettingsController = require("../controllers/channelSettingsController");
|
||||||
|
const presenceUtils = require("../utils/presenceUtils");
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
@ -29,6 +30,9 @@ const router = Router();
|
||||||
//User authentication middleware
|
//User authentication middleware
|
||||||
router.use("/*/settings",channelModel.reqPermCheck("manageChannel","/c/"));
|
router.use("/*/settings",channelModel.reqPermCheck("manageChannel","/c/"));
|
||||||
|
|
||||||
|
//Use presence middleware
|
||||||
|
router.use(presenceUtils.presenceMiddleware);
|
||||||
|
|
||||||
//routing functions
|
//routing functions
|
||||||
router.get('/*/settings', channelSettingsController.get);
|
router.get('/*/settings', channelSettingsController.get);
|
||||||
router.get('/*/', channelController.get);
|
router.get('/*/', channelController.get);
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,14 @@ const { Router } = require('express');
|
||||||
|
|
||||||
//local imports
|
//local imports
|
||||||
const indexController = require("../controllers/indexController");
|
const indexController = require("../controllers/indexController");
|
||||||
|
const presenceUtils = require("../utils/presenceUtils");
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
|
//Use presence middleware
|
||||||
|
router.use(presenceUtils.presenceMiddleware);
|
||||||
|
|
||||||
//routing functions
|
//routing functions
|
||||||
router.get('/', indexController.get);
|
router.get('/', indexController.get);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ const { Router } = require('express');
|
||||||
//local imports
|
//local imports
|
||||||
const permissionSchema = require("../schemas/permissionSchema");
|
const permissionSchema = require("../schemas/permissionSchema");
|
||||||
const newChannelController = require("../controllers/newChannelController");
|
const newChannelController = require("../controllers/newChannelController");
|
||||||
|
const presenceUtils = require("../utils/presenceUtils");
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
@ -28,6 +29,9 @@ const router = Router();
|
||||||
//user authentication middleware
|
//user authentication middleware
|
||||||
router.use("/",permissionSchema.reqPermCheck("registerChannel"));
|
router.use("/",permissionSchema.reqPermCheck("registerChannel"));
|
||||||
|
|
||||||
|
//Use presence middleware
|
||||||
|
router.use(presenceUtils.presenceMiddleware);
|
||||||
|
|
||||||
//routing functions
|
//routing functions
|
||||||
router.get('/', newChannelController.get);
|
router.get('/', newChannelController.get);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,11 @@ const userSchema = new mongoose.Schema({
|
||||||
required: true,
|
required: true,
|
||||||
default: new Date()
|
default: new Date()
|
||||||
},
|
},
|
||||||
|
lastActive: {
|
||||||
|
type: mongoose.SchemaTypes.Date,
|
||||||
|
required: true,
|
||||||
|
default: new Date()
|
||||||
|
},
|
||||||
rank: {
|
rank: {
|
||||||
type: mongoose.SchemaTypes.String,
|
type: mongoose.SchemaTypes.String,
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
||||||
75
src/utils/presenceUtils.js
Normal file
75
src/utils/presenceUtils.js
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 Rainbownapkin and the TTN Community
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
|
||||||
|
//local includes
|
||||||
|
const userSchema = require('../schemas/user/userSchema');
|
||||||
|
|
||||||
|
//User activity map to keep us from constantly reading off of the DB
|
||||||
|
let activityMap = new Map();
|
||||||
|
|
||||||
|
//How much difference between last write and now until we hit the DB again (in millis)
|
||||||
|
//Defaults to two minutes
|
||||||
|
const tolerance = 2 * (60 * 1000);
|
||||||
|
|
||||||
|
module.exports.presenceMiddleware = function(req, res, next){
|
||||||
|
//Pull user from session
|
||||||
|
const user = req.session.user;
|
||||||
|
|
||||||
|
//if we have a user object
|
||||||
|
if(user != null){
|
||||||
|
//Handle Presence
|
||||||
|
module.exports.handlePresence(user.user);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Go on to next part of the middleware chain
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.handlePresence = async function(user, userDB, noSave = false){
|
||||||
|
//If we don't have a user
|
||||||
|
if(user == null || user == ''){
|
||||||
|
//Drop that shit
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get current date as epoch (millis)
|
||||||
|
const now = new Date();
|
||||||
|
const millis = now.getTime();
|
||||||
|
|
||||||
|
//Check last user activity
|
||||||
|
const activity = activityMap.get(user);
|
||||||
|
|
||||||
|
//If we have no recorded activity, or if the the time between now and the last activity is greater than two minutes
|
||||||
|
if(activity == null || millis - activity > tolerance){
|
||||||
|
//Set last user activity
|
||||||
|
activityMap.set(user, millis);
|
||||||
|
|
||||||
|
//If we wheren't handed a free user doc
|
||||||
|
if(userDB == null){
|
||||||
|
//Pull one from the username
|
||||||
|
userDB = await userSchema.userModel.findOne({user: user});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set last active in user's DB document
|
||||||
|
userDB.lastActive = now;
|
||||||
|
|
||||||
|
//If saving is enabled
|
||||||
|
if(!noSave){
|
||||||
|
//Save document to
|
||||||
|
await userDB.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue