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.

190 lines
5.0 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 } from '../config'
  21. import { wrapCrawler } from '../crawlutil'
  22. import { InstitutionElement } from '../element'
  23. import { generateId } from '../generate-id'
  24. import { crawl, isConfigured } from './crawler'
  25. export function cwgElementCreator (): InstitutionElement | null {
  26. if (!isConfigured) {
  27. return null
  28. }
  29. const crawlUtil = wrapCrawler(() => crawl())
  30. const router = Router()
  31. router.get('/config/default', (_, res) => {
  32. res.json({
  33. config: [
  34. {
  35. param: 'userType',
  36. type: 'radio',
  37. value: 'student',
  38. label: 'Schüler',
  39. visibilityConditionId: '_true'
  40. },
  41. {
  42. param: 'userType',
  43. type: 'radio',
  44. value: 'teacher',
  45. label: 'Lehrer',
  46. visibilityConditionId: '_true'
  47. },
  48. {
  49. param: 'studentPassword',
  50. type: 'password',
  51. visibilityConditionId: 'isStudent',
  52. value: '',
  53. label: 'Schüler-Passwort'
  54. },
  55. {
  56. param: 'teacherPassword',
  57. type: 'password',
  58. visibilityConditionId: 'isTeacher',
  59. value: '',
  60. label: 'Lehrer-Passwort'
  61. }
  62. ],
  63. configValidationConditionId: 'hasValidUserType',
  64. contentBucketSets: [
  65. {
  66. id: 'student',
  67. passwordParam: 'studentPassword',
  68. usageConditionId: 'isStudent',
  69. type: 'content'
  70. },
  71. {
  72. id: 'teacher',
  73. passwordParam: 'teacherPassword',
  74. usageConditionId: 'isTeacher',
  75. type: 'content'
  76. },
  77. {
  78. id: 'default',
  79. usageConditionId: '_true',
  80. type: 'content'
  81. }
  82. ],
  83. conditionSets: [
  84. {
  85. id: 'isStudent',
  86. type: 'paramIs',
  87. left: 'userType',
  88. right: 'student'
  89. },
  90. {
  91. id: 'isTeacher',
  92. type: 'paramIs',
  93. left: 'userType',
  94. right: 'teacher'
  95. },
  96. {
  97. id: 'hasValidUserType',
  98. type: 'or',
  99. left: 'isStudent',
  100. right: 'isTeacher'
  101. }
  102. ]
  103. })
  104. })
  105. router.get('/content/default', (_, res, next) => {
  106. crawlUtil.getLastSuccessPromise().then((data) => {
  107. res.json({
  108. file: data.downloads.map((item) => ({
  109. type: 'download',
  110. mimeType: item.mimeType,
  111. lastModified: item.lastModified,
  112. title: item.title,
  113. file: item.file,
  114. id: generateId('download_' + item.title),
  115. notify: false
  116. })),
  117. message: data.messages.map((item) => ({
  118. id: generateId(item.content),
  119. title: item.title,
  120. content: item.content,
  121. notify: false
  122. }))
  123. })
  124. }).catch((ex) => next(ex))
  125. })
  126. router.get('/content/student', (req, res, next) => {
  127. const authData = auth(req)
  128. if ((!authData) || authData.pass !== config.cwg.password.student) {
  129. res.setHeader('WWW-Authenticate', 'Basic realm="Login"')
  130. res.sendStatus(401)
  131. return
  132. }
  133. crawlUtil.getLastSuccessPromise().then((data) => {
  134. res.json({
  135. file: data.studentPlans.map((item) => ({
  136. type: 'plan',
  137. mimeType: item.mimeType,
  138. lastModified: item.lastModified,
  139. title: item.title,
  140. file: item.file,
  141. id: generateId('plan_' + item.title),
  142. notify: true
  143. })),
  144. message: []
  145. })
  146. }).catch((ex) => next(ex))
  147. })
  148. router.get('/content/teacher', (req, res, next) => {
  149. const authData = auth(req)
  150. if ((!authData) || authData.pass !== config.cwg.password.teacher) {
  151. res.setHeader('WWW-Authenticate', 'Basic realm="Login"')
  152. res.sendStatus(401)
  153. return
  154. }
  155. crawlUtil.getLastSuccessPromise().then((data) => {
  156. res.json({
  157. file: data.teacherPlans.map((item) => ({
  158. type: 'plan',
  159. mimeType: item.mimeType,
  160. lastModified: item.lastModified,
  161. title: item.title,
  162. file: item.file,
  163. id: generateId('plan_' + item.title),
  164. notify: true
  165. })),
  166. message: []
  167. })
  168. }).catch((ex) => next(ex))
  169. })
  170. return {
  171. id: 'cwg-halle',
  172. title: 'Christian-Wolff-Gymnasium',
  173. router,
  174. getStatus: () => crawlUtil.getLastPromise()
  175. }
  176. }