dev #2
89
src/boardService.js
Normal file
89
src/boardService.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
const { startAuthentication } = require('./auth');
|
||||||
|
const { fetchClosedTickets } = require('./tickets');
|
||||||
|
|
||||||
|
function createBoardService({ clientId, clientSecret, technicians, statusSet, windowMinutes, checkMinutes }) {
|
||||||
|
const state = {
|
||||||
|
auth: 'disconnected',
|
||||||
|
verificationUrl: null,
|
||||||
|
userCode: null,
|
||||||
|
lastCheck: null,
|
||||||
|
lastError: null
|
||||||
|
};
|
||||||
|
|
||||||
|
const tickets = new Map();
|
||||||
|
let accessToken = null;
|
||||||
|
let pollingTimer = null;
|
||||||
|
|
||||||
|
async function refreshTickets() {
|
||||||
|
if (!accessToken) return;
|
||||||
|
|
||||||
|
await fetchClosedTickets({
|
||||||
|
accessToken,
|
||||||
|
state,
|
||||||
|
tickets,
|
||||||
|
technicians,
|
||||||
|
statusSet,
|
||||||
|
windowMinutes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startPolling() {
|
||||||
|
if (pollingTimer) return;
|
||||||
|
|
||||||
|
pollingTimer = setInterval(() => {
|
||||||
|
refreshTickets().catch(err => {
|
||||||
|
state.lastError = err.message;
|
||||||
|
state.lastCheck = Date.now();
|
||||||
|
});
|
||||||
|
}, checkMinutes * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function connect() {
|
||||||
|
const authResult = await startAuthentication({
|
||||||
|
clientId,
|
||||||
|
clientSecret,
|
||||||
|
state
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!authResult?.accessToken) return;
|
||||||
|
|
||||||
|
accessToken = authResult.accessToken;
|
||||||
|
console.log('Authorization successful');
|
||||||
|
|
||||||
|
await refreshTickets();
|
||||||
|
startPolling();
|
||||||
|
}
|
||||||
|
|
||||||
|
function failConnection(err) {
|
||||||
|
state.auth = 'error';
|
||||||
|
state.lastError = err.message;
|
||||||
|
state.verificationUrl = null;
|
||||||
|
state.userCode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getState() {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
windowMinutes,
|
||||||
|
checkMinutes,
|
||||||
|
watching: technicians,
|
||||||
|
serverTime: Date.now(),
|
||||||
|
tickets: [...tickets.values()].sort((a, b) => b.closedAt - a.closedAt)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkNow() {
|
||||||
|
await refreshTickets();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
connect,
|
||||||
|
checkNow,
|
||||||
|
failConnection,
|
||||||
|
getState
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createBoardService
|
||||||
|
};
|
||||||
37
src/routes.js
Normal file
37
src/routes.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const express = require('express');
|
||||||
|
|
||||||
|
function createRoutes(boardService) {
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get('/state', (req, res) => {
|
||||||
|
res.json(boardService.getState());
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/connect', async (req, res) => {
|
||||||
|
const currentState = boardService.getState();
|
||||||
|
if (currentState.auth === 'pending' || currentState.auth === 'connected') {
|
||||||
|
return res.json({ ok: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
boardService.connect().catch(err => {
|
||||||
|
boardService.failConnection(err);
|
||||||
|
});
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch (err) {
|
||||||
|
boardService.failConnection(err);
|
||||||
|
res.status(500).json({ ok: false, error: err.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/check', async (req, res) => {
|
||||||
|
await boardService.checkNow();
|
||||||
|
res.json({ ok: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createRoutes
|
||||||
|
};
|
||||||
100
src/server.js
100
src/server.js
@ -3,8 +3,8 @@ require('dotenv').config({ quiet: true });
|
|||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const { startAuthentication } = require('./auth');
|
const { createBoardService } = require('./boardService');
|
||||||
const { fetchClosedTickets } = require('./tickets');
|
const { createRoutes } = require('./routes');
|
||||||
|
|
||||||
const { CLIENT_ID, CLIENT_SECRET, TECHNICIAN_NAMES, STATUS_NAMES } = process.env;
|
const { CLIENT_ID, CLIENT_SECRET, TECHNICIAN_NAMES, STATUS_NAMES } = process.env;
|
||||||
const PORT = process.env.PORT || 3000; // change to 3000 after done testing using 3001 as I have a second server running to make sure it functions correctly
|
const PORT = process.env.PORT || 3000; // change to 3000 after done testing using 3001 as I have a second server running to make sure it functions correctly
|
||||||
@ -21,95 +21,19 @@ const statusSet = new Set(statuses.map(s => s.toLowerCase()));
|
|||||||
const WINDOW_MINUTES = 10;
|
const WINDOW_MINUTES = 10;
|
||||||
const CHECK_MINUTES = 1;
|
const CHECK_MINUTES = 1;
|
||||||
|
|
||||||
let accessToken = null;
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
auth: 'disconnected',
|
|
||||||
verificationUrl: null,
|
|
||||||
userCode: null,
|
|
||||||
lastCheck: null,
|
|
||||||
lastError: null
|
|
||||||
};
|
|
||||||
|
|
||||||
const tickets = new Map();
|
|
||||||
|
|
||||||
async function connect() {
|
|
||||||
try {
|
|
||||||
const authResult = await startAuthentication({
|
|
||||||
clientId: CLIENT_ID,
|
|
||||||
clientSecret: CLIENT_SECRET,
|
|
||||||
state
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!authResult?.accessToken) return;
|
|
||||||
|
|
||||||
accessToken = authResult.accessToken;
|
|
||||||
console.log('Authorization successful');
|
|
||||||
|
|
||||||
await fetchClosedTickets({
|
|
||||||
accessToken,
|
|
||||||
state,
|
|
||||||
tickets,
|
|
||||||
technicians,
|
|
||||||
statusSet,
|
|
||||||
windowMinutes: WINDOW_MINUTES
|
|
||||||
});
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
fetchClosedTickets({
|
|
||||||
accessToken,
|
|
||||||
state,
|
|
||||||
tickets,
|
|
||||||
technicians,
|
|
||||||
statusSet,
|
|
||||||
windowMinutes: WINDOW_MINUTES
|
|
||||||
});
|
|
||||||
}, CHECK_MINUTES * 60 * 1000);
|
|
||||||
} catch (err) {
|
|
||||||
state.auth = 'error';
|
|
||||||
state.lastError = err.message;
|
|
||||||
state.verificationUrl = null;
|
|
||||||
state.userCode = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
const boardService = createBoardService({
|
||||||
|
clientId: CLIENT_ID,
|
||||||
|
clientSecret: CLIENT_SECRET,
|
||||||
|
technicians,
|
||||||
|
statusSet,
|
||||||
|
windowMinutes: WINDOW_MINUTES,
|
||||||
|
checkMinutes: CHECK_MINUTES
|
||||||
|
});
|
||||||
|
|
||||||
app.use(express.static(path.join(__dirname, 'public')));
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
|
||||||
app.get('/api/state', (req, res) => {
|
app.use('/api', createRoutes(boardService));
|
||||||
res.json({
|
|
||||||
...state,
|
|
||||||
windowMinutes: WINDOW_MINUTES,
|
|
||||||
checkMinutes: CHECK_MINUTES,
|
|
||||||
watching: technicians,
|
|
||||||
serverTime: Date.now(),
|
|
||||||
tickets: [...tickets.values()].sort((a, b) => b.closedAt - a.closedAt)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post('/api/connect', async (req, res) => {
|
|
||||||
if (state.auth === 'pending' || state.auth === 'connected') {
|
|
||||||
return res.json({ ok: true });
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
connect().catch(err => {
|
|
||||||
state.auth = 'error';
|
|
||||||
state.lastError = err.message;
|
|
||||||
state.verificationUrl = null;
|
|
||||||
state.userCode = null;
|
|
||||||
});
|
|
||||||
res.json({ ok: true });
|
|
||||||
} catch (err) {
|
|
||||||
state.auth = 'error';
|
|
||||||
state.lastError = err.message;
|
|
||||||
res.status(500).json({ ok: false, error: err.message });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post('/api/check', async (req, res) => {
|
|
||||||
await fetchClosedTickets();
|
|
||||||
res.json({ ok: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Open http://localhost:${PORT}`);
|
console.log(`Open http://localhost:${PORT}`);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user