|
@@ -3,6 +3,7 @@ import awaitFs from 'await-fs'
|
|
|
import express from 'express'
|
|
|
import bhttp from 'bhttp'
|
|
|
import Excel from '../excel'
|
|
|
+import Config from '../models/config'
|
|
|
import Player from '../models/player'
|
|
|
import Match from '../models/match'
|
|
|
import PlayerList from '../models/playerList'
|
|
@@ -15,8 +16,20 @@ const swisstennis = express.Router()
|
|
|
// Use this variable for the session
|
|
|
const session = bhttp.session()
|
|
|
|
|
|
+// Try to fetch config data for swisstennis login
|
|
|
+const config = {}
|
|
|
+Config.find({ key: { $in: ['tournament', 'tournamentId', 'tournamentPW'] } }).exec((error, results) => {
|
|
|
+ if (error) {
|
|
|
+ console.log(error.toString())
|
|
|
+ } else {
|
|
|
+ results.forEach(result => {
|
|
|
+ config[result.key] = result.value
|
|
|
+ })
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
function fileDate (date) {
|
|
|
- return `${date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate()}${date.getHours() * 10000 + date.getMinutes() * 100 + date.getSeconds()}`
|
|
|
+ return `${(date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate()) * 1000000 + date.getHours() * 10000 + date.getMinutes() * 100 + date.getSeconds()}`
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -25,27 +38,27 @@ function fileDate (date) {
|
|
|
|
|
|
// Login
|
|
|
swisstennis.post('/login', async (req, res) => {
|
|
|
- const { username, password } = req.body
|
|
|
-
|
|
|
- // return, if username or password are missing
|
|
|
- if (!username || !password) {
|
|
|
- return res.status(400).json({ msg: 'Parameters username and password are required' })
|
|
|
- }
|
|
|
-
|
|
|
- // assemble the login data
|
|
|
- const loginData = {
|
|
|
- Lang: 'D',
|
|
|
- id: username,
|
|
|
- pwd: password,
|
|
|
- Tournament: ''
|
|
|
- }
|
|
|
-
|
|
|
try {
|
|
|
+ const username = req.body.username || config.tournament
|
|
|
+ const password = req.body.pasword || config.tournamentPW
|
|
|
+
|
|
|
+ // return, if username or password are missing
|
|
|
+ if (!username || !password) {
|
|
|
+ throw Error('Parameters username and password are required')
|
|
|
+ }
|
|
|
+
|
|
|
+ // assemble the login data
|
|
|
+ const loginData = {
|
|
|
+ Lang: 'D',
|
|
|
+ id: username,
|
|
|
+ pwd: password,
|
|
|
+ Tournament: ''
|
|
|
+ }
|
|
|
const myTournamentsPage = await session.get('https://comp.swisstennis.ch/advantage/servlet/MyTournamentList?Lang=D')
|
|
|
const loginPage = await session.post('https://comp.swisstennis.ch/advantage/servlet/Login', loginData)
|
|
|
const strLoginPage = loginPage.body.toString()
|
|
|
if (strLoginPage.includes('Zugriff verweigert')) {
|
|
|
- return res.status(400).json({ msg: 'Access denied!' })
|
|
|
+ throw Error('Access denied!')
|
|
|
}
|
|
|
} catch (error) {
|
|
|
return res.status(400).json({ msg: error })
|
|
@@ -55,13 +68,13 @@ swisstennis.post('/login', async (req, res) => {
|
|
|
|
|
|
// Overview of tournaments
|
|
|
swisstennis.get('/tournaments', async (req, res) => {
|
|
|
- const tournaments = {}
|
|
|
try {
|
|
|
+ const tournaments = {}
|
|
|
let match
|
|
|
const myTournamentsPage = await session.get('https://comp.swisstennis.ch/advantage/servlet/MyTournamentList?Lang=D')
|
|
|
const strMyTournamentsPage = myTournamentsPage.body.toString()
|
|
|
if (strMyTournamentsPage.includes('Login-Zone')) {
|
|
|
- return res.status(400).json({ message: 'Not logged in.' })
|
|
|
+ throw Error('Not logged in.')
|
|
|
}
|
|
|
const tournamentRegexp = /<a href=".*ProtectedDisplayTournament.*tournament=Id(\d+)">([^<]+)<\/a>/gm
|
|
|
|
|
@@ -71,26 +84,26 @@ swisstennis.get('/tournaments', async (req, res) => {
|
|
|
tournaments[match[1]] = match[2]
|
|
|
}
|
|
|
} while (match)
|
|
|
+ res.json({ tournaments })
|
|
|
} catch (error) {
|
|
|
return res.status(400).json({ msg: error.toString() })
|
|
|
}
|
|
|
- res.json({ tournaments })
|
|
|
})
|
|
|
|
|
|
// Draws of a tournament
|
|
|
-swisstennis.get('/draws/:tournament', async (req, res) => {
|
|
|
- const { tournament } = req.params
|
|
|
-
|
|
|
- if (!tournament) {
|
|
|
- return res.json({ msg: 'No tournament given.' })
|
|
|
- }
|
|
|
+swisstennis.get('/draws', async (req, res) => {
|
|
|
try {
|
|
|
+ const tournament = req.query.tournament || config.tournamentId
|
|
|
+
|
|
|
+ if (!tournament) {
|
|
|
+ throw Error('No tournament given.')
|
|
|
+ }
|
|
|
let match
|
|
|
const draws = {}
|
|
|
const tournamentPage = await session.get(`https://comp.swisstennis.ch/advantage/servlet/ProtectedDisplayTournament?Lang=D&tournament=Id${tournament}`)
|
|
|
const strTournamentPage = tournamentPage.body.toString()
|
|
|
if (strTournamentPage.includes('Login-Zone')) {
|
|
|
- return res.status(400).json({ message: 'Not logged in.' })
|
|
|
+ throw Error('Not logged in.')
|
|
|
}
|
|
|
const drawRegexp = /<a (?:class="text" )?href=".*DisplayEvent.*eventId=(\d+).*">([^<]+)<\/a>/gm
|
|
|
|
|
@@ -107,14 +120,14 @@ swisstennis.get('/draws/:tournament', async (req, res) => {
|
|
|
})
|
|
|
|
|
|
// Download a playerlist
|
|
|
-swisstennis.get('/playerlist/download/:tournament', async (req, res) => {
|
|
|
- const { tournament } = req.params
|
|
|
-
|
|
|
- if (!tournament) {
|
|
|
- return res.json({ msg: 'No tournament given.' })
|
|
|
- }
|
|
|
+swisstennis.get('/playerlist/download', async (req, res) => {
|
|
|
try {
|
|
|
- const playerListFile = fs.createWriteStream(`swisstennis_files/PlayerList-${fileDate(new Date())}.xls`)
|
|
|
+ const tournament = req.query.tournament || config.tournamentId
|
|
|
+
|
|
|
+ if (!tournament) {
|
|
|
+ throw Error('No tournament given.')
|
|
|
+ }
|
|
|
+ const playerListFile = fs.createWriteStream(`swisstennis_files/PlayerList-${tournament}-${fileDate(new Date())}.xls`)
|
|
|
const playerList = await session.get(`https://comp.swisstennis.ch/advantage/servlet/PlayerList.xls?tournament=Id${tournament}&lang=D`, {stream: true})
|
|
|
playerList.pipe(playerListFile)
|
|
|
return res.json({ msg: 'Download successful.' })
|
|
@@ -128,10 +141,16 @@ swisstennis.get('/playerlist/parse/:filename', async (req, res) => {
|
|
|
console.log('Parsing file', req.params.filename)
|
|
|
|
|
|
const filePath = `swisstennis_files/${req.params.filename}`
|
|
|
- const dateElems = req.params.filename.match(/\w+\-(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.xls/).slice(1,7)
|
|
|
+ const dateElems = req.params.filename.match(/\w+\-\d+\-(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.xls/).slice(1,7)
|
|
|
const fileDate = new Date(`${dateElems[0]}-${dateElems[1]}-${dateElems[2]} ${dateElems[3]}:${dateElems[4]}:${dateElems[5]}`)
|
|
|
const stat = fs.statSync(filePath)
|
|
|
|
|
|
+ const fileNewer = await PlayerList.find({ imported: { $gte: fileDate } })
|
|
|
+ console.log(fileNewer, fileNewer.length)
|
|
|
+ if (fileNewer.length) {
|
|
|
+ throw Error('File has to be newer.')
|
|
|
+ }
|
|
|
+
|
|
|
console.log('About to read the player list.')
|
|
|
const worksheets = await Excel.readWorkbook(filePath)
|
|
|
const worksheet = worksheets.Players
|
|
@@ -141,29 +160,28 @@ swisstennis.get('/playerlist/parse/:filename', async (req, res) => {
|
|
|
|
|
|
const headers = worksheet.slice(3, 4)
|
|
|
|
|
|
- const dbPlayers = await Player.find().lean()
|
|
|
- console.log(dbPlayers.slice(0,3))
|
|
|
+ const dbPlayers = await Player.find()
|
|
|
|
|
|
const allPlayers = worksheet.slice(4, worksheet.length).map(data => {
|
|
|
const filePlayer = {
|
|
|
- created: new Date(),
|
|
|
+ created: fileDate,
|
|
|
category: normalize(data[0]),
|
|
|
licenseNr: normalize(data[2]),
|
|
|
name: normalize(data[5]),
|
|
|
firstName: normalize(data[6]),
|
|
|
nameDP: normalize(data[24]),
|
|
|
firstNameDP: normalize(data[25]),
|
|
|
- birthDate: data[7],
|
|
|
+ birthDate: data[7] || null,
|
|
|
email: normalize(data[16]),
|
|
|
ranking: normalize(data[17]),
|
|
|
licenseNrDP: normalize(data[23]),
|
|
|
phonePrivate: normalizePhone(data[13]),
|
|
|
phoneWork: normalizePhone(data[14]),
|
|
|
phoneMobile: normalizePhone(data[15]),
|
|
|
- birthDateDP: data[26],
|
|
|
+ birthDateDP: data[26] || null,
|
|
|
rankingDP: normalize(data[27]),
|
|
|
- confirmed: data[29],
|
|
|
- paid: data[31],
|
|
|
+ confirmed: !!data[29],
|
|
|
+ paid: !!data[31],
|
|
|
}
|
|
|
filePlayer.gender = filePlayer.category ?
|
|
|
filePlayer.category[0] === 'M' ? 'm' :
|
|
@@ -192,19 +210,19 @@ swisstennis.get('/playerlist/parse/:filename', async (req, res) => {
|
|
|
const dbPlayer = dbPlayers.filter(player => player.idString == filePlayer.idString).sort((a, b) =>
|
|
|
a.created > b.created ? 1 : a.created == b.created ? 0 : -1
|
|
|
)[0]
|
|
|
- console.log('sorted:', dbPlayer)
|
|
|
+ //console.log('sorted:', dbPlayer)
|
|
|
|
|
|
- if (filePlayer != dbPlayer) {
|
|
|
+ if (dbPlayer && dbPlayer.equal(filePlayer)) {
|
|
|
+ return dbPlayer._id
|
|
|
+ } else {
|
|
|
const player = new Player(filePlayer)
|
|
|
player.save()
|
|
|
return player._id
|
|
|
- } else {
|
|
|
- return dbPlayer._id
|
|
|
}
|
|
|
})
|
|
|
|
|
|
const playerList = new PlayerList({
|
|
|
- imported: new Date(),
|
|
|
+ imported: fileDate,
|
|
|
file: req.params.filename,
|
|
|
fileSize: stat.size,
|
|
|
players: allPlayers
|
|
@@ -218,36 +236,39 @@ swisstennis.get('/playerlist/parse/:filename', async (req, res) => {
|
|
|
})
|
|
|
|
|
|
// List downloaded files
|
|
|
-swisstennis.get('/files/list/:tournament', async (req, res) => {
|
|
|
- const { tournament } = req.params
|
|
|
-
|
|
|
- if (!tournament) {
|
|
|
- return res.json({ msg: 'No tournament given.' })
|
|
|
- }
|
|
|
+swisstennis.get('/files', async (req, res) => {
|
|
|
+ throw Error('Diini mueter!')
|
|
|
+ const tournament = req.query.tournament
|
|
|
+ const dirContent = await awaitFs.readdir('swisstennis_files')
|
|
|
+ const fileList = dirContent.filter(filename => {
|
|
|
+ return tournament ? filename.includes(tournament) : true
|
|
|
+ }).map(filename => {
|
|
|
+ const stats = fs.statSync(`swisstennis_files/${filename}`)
|
|
|
+ return { filename, size: stats.size, ctime: stats.ctime }
|
|
|
+ })
|
|
|
+ return res.json({ fileList })
|
|
|
+})
|
|
|
+
|
|
|
+swisstennis.delete('/files', async (req, res) => {
|
|
|
try {
|
|
|
- const dirContent = await awaitFs.readdir('swisstennis_files')
|
|
|
- const fileList = dirContent.filter(filename => {
|
|
|
- console.log(filename)
|
|
|
- return filename.includes(tournament) || true
|
|
|
- }).map(filename => {
|
|
|
- console.log(filename)
|
|
|
- const stats = fs.statSync(`swisstennis_files/${filename}`)
|
|
|
- return { [filename]: stats.size }
|
|
|
+ const { filename } = req.body
|
|
|
+ fs.unlink(`swisstennis_files/${filename}`, (error) => {
|
|
|
+ if (error) throw error
|
|
|
+ res.json({ msg: `successfully deleted swisstennis_files/${filename}.` })
|
|
|
})
|
|
|
- return res.json({ fileList })
|
|
|
} catch (error) {
|
|
|
return res.status(400).json({ msg: error.toString() })
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-swisstennis.get('/calendar/download/:tournament', async (req, res) => {
|
|
|
- const { tournament } = req.params
|
|
|
+swisstennis.get('/calendar/download', async (req, res) => {
|
|
|
+ const tournament = req.query.tournament || config.tournamentId
|
|
|
|
|
|
if (!tournament) {
|
|
|
return res.json({ msg: 'No tournament given.' })
|
|
|
}
|
|
|
try {
|
|
|
- const calendarFile = fs.createWriteStream(`swisstennis_files/Calendar-${fileDate(new Date())}.xls`)
|
|
|
+ const calendarFile = fs.createWriteStream(`swisstennis_files/Calendar-${tournament}-${fileDate(new Date())}.xls`)
|
|
|
const calendar = await session.get(`https://comp.swisstennis.ch/advantage/servlet/Calendar.xls?Lang=D&tournament=Id${tournament}&Type=Match&Inp_DateRangeFilter.fromDate=04.06.2018&Inp_DateRangeFilter.toDate=16.09.2018`, {stream: true})
|
|
|
calendar.pipe(calendarFile)
|
|
|
return res.json({ msg: 'Download successful.' })
|
|
@@ -259,45 +280,75 @@ swisstennis.get('/calendar/download/:tournament', async (req, res) => {
|
|
|
swisstennis.get('/calendar/parse/:filename', async (req,res) => {
|
|
|
try {
|
|
|
console.log('Parsing file', req.params.filename)
|
|
|
- console.log('About to read the calendar list.')
|
|
|
|
|
|
+ const filePath = `swisstennis_files/${req.params.filename}`
|
|
|
+ const dateElems = req.params.filename.match(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/).slice(1,7)
|
|
|
+ const fileDate = new Date(`${dateElems[0]}-${dateElems[1]}-${dateElems[2]} ${dateElems[3]}:${dateElems[4]}:${dateElems[5]}`)
|
|
|
+ const stat = fs.statSync(filePath)
|
|
|
+
|
|
|
+ const fileNewer = await MatchList.find({ imported: { $gte: fileDate } })
|
|
|
+ if (fileNewer.length) {
|
|
|
+ throw Error('File has to be newer.')
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('About to read the calendar list.')
|
|
|
const worksheets = await Excel.readWorkbook(`swisstennis_files/${req.params.filename}`)
|
|
|
const worksheet = worksheets.Sheet1
|
|
|
if (worksheet[2].length < 8 | worksheet[2].length > 9) {
|
|
|
throw Error(`Wrong file structure.`)
|
|
|
}
|
|
|
- const calendar = await Promise.all(worksheet.slice(2, worksheet.length).map(async data => {
|
|
|
- const category = normalize(data[3])
|
|
|
- const player1 = await Player.findOne({idString: `${category} % ${normalize(data[4])}`})
|
|
|
- const player2 = await Player.findOne({idString: `${category} % ${normalize(data[6])}`})
|
|
|
- const match = new Match({
|
|
|
- _created: Date.now(),
|
|
|
- idString: "String",
|
|
|
+
|
|
|
+ const dbMatches = await Match.find()
|
|
|
+
|
|
|
+ const allMatches = await Promise.all(worksheet.slice(2, worksheet.length).map(async (data, key) => {
|
|
|
+ const fileMatch = {
|
|
|
+ created: fileDate,
|
|
|
+ fileLine: key,
|
|
|
+ category: normalize(data[3]),
|
|
|
place: normalize(data[0]),
|
|
|
date: data[1],
|
|
|
- category,
|
|
|
- player1: player1 ? player1._id : null,
|
|
|
- player2: player2 ? player2._id : null,
|
|
|
- result: normalize(data[8] || null),
|
|
|
- doubles: !!category.match(/DM.*|[MW]D.*/)
|
|
|
- })
|
|
|
+ result: normalize(data[8]),
|
|
|
+ }
|
|
|
+ fileMatch.doubles = !!fileMatch.category.match(/DM.*|[MW]D.*/)
|
|
|
+ const player1 = await Player.findOne({idString: `${fileMatch.category} % ${normalize(data[4])}`})
|
|
|
+ const player2 = await Player.findOne({idString: `${fileMatch.category} % ${normalize(data[6])}`})
|
|
|
+ fileMatch.idString = `${fileMatch.category} % ${player1 ? player1.idString : `${key}_1`} - ${player2 ? player2.idString : `${key}_2`}`
|
|
|
+ fileMatch.player1 = player1 ? player1._id : null
|
|
|
+ fileMatch.player2 = player2 ? player2._id : null
|
|
|
|
|
|
- match.save()
|
|
|
- return match
|
|
|
+ const dbMatch = dbMatches.filter(match => match.idString == fileMatch.idString).sort((a, b) =>
|
|
|
+ a.created > b.created ? 1 : a.created == b.created ? 0 : -1
|
|
|
+ )[0]
|
|
|
+
|
|
|
+ if (dbMatch && dbMatch.equal(fileMatch)) {
|
|
|
+ return dbMatch._id
|
|
|
+ } else {
|
|
|
+ const match = new Match(fileMatch)
|
|
|
+ match.save()
|
|
|
+ return match._id
|
|
|
+ }
|
|
|
}))
|
|
|
- res.json(calendar)
|
|
|
+ const matchList = new MatchList({
|
|
|
+ imported: fileDate,
|
|
|
+ file: req.params.filename,
|
|
|
+ fileSize: stat.size,
|
|
|
+ matches: allMatches
|
|
|
+ })
|
|
|
+ matchList.save()
|
|
|
+
|
|
|
+ return res.json({ matchList })
|
|
|
} catch (error) {
|
|
|
res.status(400).json({ msg: error.toString() })
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-swisstennis.get('/download/draw/:draw', async (req, res) => {
|
|
|
- const { draw } = req.params
|
|
|
-
|
|
|
- if (!draw) {
|
|
|
- return res.json({ msg: 'No draw given.' })
|
|
|
- }
|
|
|
+swisstennis.get('/download/draw', async (req, res) => {
|
|
|
try {
|
|
|
+ const { draw } = req.query
|
|
|
+
|
|
|
+ if (!draw) {
|
|
|
+ throw Error('No draw given.')
|
|
|
+ }
|
|
|
const fileName = `DisplayDraw${draw}-${fileDate(new Date())}.xls`
|
|
|
const drawFile = fs.createWriteStream(`swisstennis_files/${fileName}`)
|
|
|
const drawDisplay = await session.get(`https://comp.swisstennis.ch/advantage/servlet/DisplayDraw.xls?eventId=${draw}&lang=D`, {stream: true})
|
|
@@ -308,12 +359,4 @@ swisstennis.get('/download/draw/:draw', async (req, res) => {
|
|
|
}
|
|
|
})
|
|
|
|
|
|
-swisstennis.get('/schedule/generate/:id', async (req, res) => {
|
|
|
- return res.status(400).json({ msg: 'Not implemented' })
|
|
|
-})
|
|
|
-
|
|
|
-swisstennis.get('/paylist/generate/:id', async (req, res) => {
|
|
|
- return res.status(400).json({ msg: 'Not implemented' })
|
|
|
-})
|
|
|
-
|
|
|
export default swisstennis
|