You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
4.6 KiB

  1. /*
  2. * vertretungsplan.io custom crawler
  3. * Copyright (C) 2019 Jonas Lochmann
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, version 3 of the
  8. * License.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. import * as auth from 'basic-auth'
  19. import { Router } from 'express'
  20. import { config as baseConfig } from '../config'
  21. import { wrapCrawler } from '../crawlutil'
  22. import { InstitutionElement } from '../element'
  23. import { crawlCategories } from './crawl'
  24. export function lbzElementCreator (): InstitutionElement | null {
  25. const configData = baseConfig.lbzBlindeHalle
  26. if (!(configData.studentPassword && configData.teacherPassword)) {
  27. return null
  28. }
  29. const id = 'lbz-fur-blinde-und-sehbehinderte'
  30. const crawlUtil = wrapCrawler(() => crawlCategories())
  31. const router = Router()
  32. router.get('/file/:hash', (req, res, next) => {
  33. const hash: string = req.params.hash
  34. crawlUtil.getLastSuccessPromise().then((data) => {
  35. const files = [data.student, data.teacher]
  36. const file = files.find((file) => file.sha512 === hash)
  37. if (file) {
  38. res.type('html').end(file.content)
  39. } else {
  40. res.sendStatus(404)
  41. }
  42. }).catch((ex) => next(ex))
  43. })
  44. ;(['student', 'teacher'] as Array<'student' | 'teacher'>).forEach((type) => {
  45. const password = type === 'student' ? configData.studentPassword : configData.teacherPassword
  46. router.get('/content/' + type, (req, res, next) => {
  47. const authData = auth(req)
  48. if ((!authData) || authData.pass !== password) {
  49. res.setHeader('WWW-Authenticate', 'Basic realm="Login"')
  50. res.sendStatus(401)
  51. return
  52. }
  53. crawlUtil.getLastSuccessPromise().then((data) => {
  54. const item = type === 'student' ? data.student : data.teacher
  55. res.json({
  56. file: [
  57. {
  58. type: 'plan',
  59. mimeType: 'text/html',
  60. // this does not work because the server does not report it
  61. // lastModified: item.lastModified,
  62. title: item.title,
  63. file: [
  64. {
  65. url: baseConfig.publicUrl + '/vp-institution/' + id + '/file/' + item.sha512,
  66. size: item.size,
  67. sha512: item.sha512
  68. }
  69. ],
  70. id: 'plan',
  71. notify: true
  72. }
  73. ],
  74. message: []
  75. })
  76. }).catch((ex) => next(ex))
  77. })
  78. })
  79. router.get('/config/default', (_, res) => {
  80. res.json({
  81. config: [
  82. {
  83. param: 'userType',
  84. type: 'radio',
  85. value: 'student',
  86. label: 'Schüler',
  87. visibilityConditionId: '_true'
  88. },
  89. {
  90. param: 'userType',
  91. type: 'radio',
  92. value: 'teacher',
  93. label: 'Lehrer',
  94. visibilityConditionId: '_true'
  95. },
  96. {
  97. param: 'studentPassword',
  98. type: 'password',
  99. visibilityConditionId: 'isStudent',
  100. value: '',
  101. label: 'Schüler-Passwort'
  102. },
  103. {
  104. param: 'teacherPassword',
  105. type: 'password',
  106. visibilityConditionId: 'isTeacher',
  107. value: '',
  108. label: 'Lehrer-Passwort'
  109. }
  110. ],
  111. configValidationConditionId: 'hasValidUserType',
  112. contentBucketSets: [
  113. {
  114. id: 'student',
  115. passwordParam: 'studentPassword',
  116. usageConditionId: 'isStudent',
  117. type: 'content'
  118. },
  119. {
  120. id: 'teacher',
  121. passwordParam: 'teacherPassword',
  122. usageConditionId: 'isTeacher',
  123. type: 'content'
  124. }
  125. ],
  126. conditionSets: [
  127. {
  128. id: 'isStudent',
  129. type: 'paramIs',
  130. left: 'userType',
  131. right: 'student'
  132. },
  133. {
  134. id: 'isTeacher',
  135. type: 'paramIs',
  136. left: 'userType',
  137. right: 'teacher'
  138. },
  139. {
  140. id: 'hasValidUserType',
  141. type: 'or',
  142. left: 'isStudent',
  143. right: 'isTeacher'
  144. }
  145. ]
  146. })
  147. })
  148. return {
  149. id,
  150. title: 'LBZ für Blinde und Sehbehinderte Halle',
  151. router,
  152. getStatus: () => crawlUtil.getLastPromise()
  153. }
  154. }