From 0f0e5debefe17e9f54594b5fc8c675b3a84ff8ea Mon Sep 17 00:00:00 2001 From: Daniel Bulant Date: Sat, 23 Oct 2021 16:19:56 +0200 Subject: [PATCH] test --- index.js | 5 ++- package.json | 2 + utils/api.js | 3 ++ utils/db/import.js | 74 +++++++++++++++++++++++++++++++++ utils/models/class.js | 33 +++++++++++++++ utils/models/event.js | 31 ++++++++++++++ utils/models/event_group.js | 36 ++++++++++++++++ utils/models/event_student.js | 36 ++++++++++++++++ utils/models/group.js | 29 +++++++++++++ utils/models/group_student.js | 36 ++++++++++++++++ utils/models/rickroll.js | 42 +++++++++++++++++++ utils/models/room.js | 14 +++++++ utils/models/student.js | 37 +++++++++++++++++ utils/models/subject.js | 25 +++++++++++ utils/models/supplementation.js | 69 ++++++++++++++++++++++++++++++ utils/models/teacher.js | 25 +++++++++++ utils/models/timetable.js | 72 ++++++++++++++++++++++++++++++++ utils/sequelize.js | 22 ++++++++++ utils/ssps-server.js | 2 + 19 files changed, 592 insertions(+), 1 deletion(-) create mode 100644 utils/db/import.js create mode 100644 utils/models/class.js create mode 100644 utils/models/event.js create mode 100644 utils/models/event_group.js create mode 100644 utils/models/event_student.js create mode 100644 utils/models/group.js create mode 100644 utils/models/group_student.js create mode 100644 utils/models/rickroll.js create mode 100644 utils/models/room.js create mode 100644 utils/models/student.js create mode 100644 utils/models/subject.js create mode 100644 utils/models/supplementation.js create mode 100644 utils/models/teacher.js create mode 100644 utils/models/timetable.js create mode 100644 utils/sequelize.js diff --git a/index.js b/index.js index 9ec3805..1038efa 100644 --- a/index.js +++ b/index.js @@ -10,6 +10,9 @@ luxon.Settings.defaultLocale = "cs"; luxon.Settings.defaultZone = new luxon.IANAZone("Europe/Prague"); const config = yaml.load(fs.readFileSync("./config.yml", { encoding: "utf-8" })); +global.config = config; + +require("./utils/sequelize"); const client = new Commando.Client({ owner: '820696421912412191', @@ -17,7 +20,7 @@ const client = new Commando.Client({ presence: { activity: { type: "WATCHING", - name: "Prestiž" + name: "prestiž" } } }); diff --git a/package.json b/package.json index db20530..1c643ea 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "fs-extra": "^10.0.0", "js-yaml": "^4.1.0", "luxon": "^2.0.2", + "mariadb": "^2.5.5", "node-fetch": "2", + "sequelize": "^6.7.0", "sqlite": "^4.0.23", "sqlite3": "^5.0.2", "turndown": "^7.1.1" diff --git a/utils/api.js b/utils/api.js index 2b7360e..d529a2f 100644 --- a/utils/api.js +++ b/utils/api.js @@ -141,6 +141,9 @@ class API { return new Supplementations(res); } + /** + * @returns {Promise} + */ async getSchedule(className) { const res = await request(`wp-content/themes/ssps-wordpress-theme/schedule.php/?class=${className}`); diff --git a/utils/db/import.js b/utils/db/import.js new file mode 100644 index 0000000..6602c5c --- /dev/null +++ b/utils/db/import.js @@ -0,0 +1,74 @@ +const isMain = require.main === module; +if(isMain) { + const yaml = require("js-yaml"); + const fs = require("fs-extra"); + const config = yaml.load(fs.readFileSync("./config.yml", { encoding: "utf-8" })); + global.config = config; +} + +const sequelize = require("../sequelize"); +const api = require("../api"); +const server = require("../ssps-server"); +const Class = require("../models/class"); +const Group = require("../models/group"); +const Subject = require("../models/subject"); +const Teacher = require("../models/teacher"); +const Room = require("../models/room"); +const Timetable = require("../models/timetable"); + +sequelize.afterBulkSync(async () => { + console.log("Sync in progress"); + + if(isMain) { + console.log("Syncing timetable"); + const classes = Object.values(api.map); + await Promise.all(classes.map(async id => { + const name = api.demap[id]; + await Class.create({ + id, + year: (2021 - parseInt(name[0]-1)), + type: name[1], + discord: server.reverseRoles[name] + }).catch(console.error); + const timetable = await api.getSchedule(id); + for(const day in timetable.schedule) { + for(let hour in timetable.schedule[day]) { + let lessons = timetable.schedule[day][hour]; + if(!Array.isArray(lessons)) lessons = [lessons]; + for(const item of lessons) { + await Group.create({ + id: item.Group.Id, + abbrev: item.Group.Abbrev, + name: item.Group.Name, + class: id + }).catch(console.error); + await Subject.create({ + id: item.Subject.Id, + abrev: item.Subject.Abbrev, + name: item.Subject.Name + }).catch(console.error); + await Teacher.create({ + id: item.Teacher.Id, + abbrev: item.Teacher.Abbrev, + name: item.Teacher.Name + }); + await Room.create({ id: item.Room.Abbrev }); + const cycle = item.Cycles[0].Id === "1" && item.Cycles[1].Id === "2" ? "always" : item.Cycles[0].Id === "1" ? "even" : item.Cycles[0].Id === "2" ? "odd" : null; + await Timetable.create({ + day, + hour, + class: id, + group: item.Group.Id, + subject: item.Subject.Id, + teacher: item.Teacher.Id, + room: item.Room.Abbrev, + cycles: cycle + }); + console.log("Done", day, hour, item.Subject.Id); + } + } + } + })); + console.log("Sync done"); + } +}); \ No newline at end of file diff --git a/utils/models/class.js b/utils/models/class.js new file mode 100644 index 0000000..9420a35 --- /dev/null +++ b/utils/models/class.js @@ -0,0 +1,33 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); + +const Class = sequelize.define( + "classes", + { + id: { + type: DataTypes.CHAR(2), + allowNull: false, + primaryKey: true + }, + year: { + type: DataTypes.INTEGER, + allowNull: false + }, + type: { + type: DataTypes.ENUM, + allowNull: false, + values: ["A", "B", "C", "K", "G", "L"] + }, + discord: { + type: DataTypes.STRING + }, + displayName: { + type: "CHAR(2) GENERATED ALWAYS AS concat(`year` - year(curdate()) + 1,`type`) STORED", + set() { + throw new Error('displayName is read-only') + } + } + } +); + +module.exports = Class; \ No newline at end of file diff --git a/utils/models/event.js b/utils/models/event.js new file mode 100644 index 0000000..c420fe9 --- /dev/null +++ b/utils/models/event.js @@ -0,0 +1,31 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); + +const Event = sequelize.define( + "events", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + date: { + type: DataTypes.DATE, + defaultValue: "CURRENT_TIMESTAMP()", + allowNull: false + }, + type: { + type: DataTypes.ENUM, + values: ["test", "homework", "action"] + }, + title: { + type: DataTypes.STRING(255), + allowNull: false + }, + description: { + type: DataTypes.TEXT + } + } +); + +module.exports = Event; \ No newline at end of file diff --git a/utils/models/event_group.js b/utils/models/event_group.js new file mode 100644 index 0000000..225955a --- /dev/null +++ b/utils/models/event_group.js @@ -0,0 +1,36 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Event = require("./event"); +const Group = require("./group"); + +const EventGroup = sequelize.define( + "event_groups", + { + event: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: Event, + key: "id" + } + }, + group: { + type: DataTypes.STRING(16), + allowNull: false, + references: { + model: Group, + key: "id" + } + } + }, + { + indexes: [{ + fields: ["event", "group"], + type: "UNIQUE" + }] + } +); +EventGroup.belongsTo(Event, { as: "event" }); +EventGroup.belongsTo(Group, { as: "group" }); + +module.exports = EventGroup; \ No newline at end of file diff --git a/utils/models/event_student.js b/utils/models/event_student.js new file mode 100644 index 0000000..888c3ca --- /dev/null +++ b/utils/models/event_student.js @@ -0,0 +1,36 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Event = require("./event"); +const Student = require("./student"); + +const EventStudent = sequelize.define( + "event_students", + { + event: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: Event, + key: "id" + } + }, + student: { + type: DataTypes.STRING(45), + allowNull: false, + references: { + model: Student, + key: "id" + } + } + }, + { + indexes: [{ + fields: ["event", "student"], + type: "UNIQUE" + }] + } +); +EventStudent.belongsTo(Event, { as: "event" }); +EventStudent.belongsTo(Student, { as: "student" }); + +module.exports = EventStudent; \ No newline at end of file diff --git a/utils/models/group.js b/utils/models/group.js new file mode 100644 index 0000000..726a372 --- /dev/null +++ b/utils/models/group.js @@ -0,0 +1,29 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Class = require("./class"); + +const Group = sequelize.define( + "groups", + { + id: { + type: DataTypes.STRING(16), + primaryKey: true + }, + abbrev: { + type: DataTypes.STRING + }, + name: { + type: DataTypes.STRING + }, + class: { + type: DataTypes.CHAR(2), + references: { + model: Class, + key: "id" + } + } + } +); +Group.belongsTo(Class, { as: "class" }); + +module.exports = Group; \ No newline at end of file diff --git a/utils/models/group_student.js b/utils/models/group_student.js new file mode 100644 index 0000000..a5ba8f0 --- /dev/null +++ b/utils/models/group_student.js @@ -0,0 +1,36 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Group = require("./group"); +const Student = require("./student"); + +const GroupStudent = sequelize.define( + "group_students", + { + group: { + type: DataTypes.STRING(16), + allowNull: false, + references: { + model: Group, + key: "id" + } + }, + student: { + type: DataTypes.STRING(45), + allowNull: false, + references: { + model: Student, + key: "id" + } + } + }, + { + indexes: [{ + fields: ["group", "student"], + type: "UNIQUE" + }] + } +); +EventStudent.belongsTo(Student, { as: "student" }); +EventStudent.belongsTo(Group, { as: "group" }); + +module.exports = GroupStudent; \ No newline at end of file diff --git a/utils/models/rickroll.js b/utils/models/rickroll.js new file mode 100644 index 0000000..af4960f --- /dev/null +++ b/utils/models/rickroll.js @@ -0,0 +1,42 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Student = require("./student"); + +const Rickroll = sequelize.define( + "rickrolls", + { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true + }, + source: { + type: DataTypes.STRING(45), + allowNull: false, + references: { + key: "id", + model: Student + } + }, + target: { + type: DataTypes.STRING(45), + allowNull: false, + references: { + key: "id", + model: Student + } + }, + date: { + type: DataTypes.DATE, + defaultValue: "CURRENT_TIMESTAMP()" + }, + link: { + type: DataTypes.STRING(255), + defaultValue: "'https://www.youtube.com/watch?v=dQw4w9WgXcQ'" + } + } +); +EventGroup.belongsTo(Student, { as: "source" }); +EventGroup.belongsTo(Student, { as: "target" }); + +module.exports = Rickroll; \ No newline at end of file diff --git a/utils/models/room.js b/utils/models/room.js new file mode 100644 index 0000000..4a6fdad --- /dev/null +++ b/utils/models/room.js @@ -0,0 +1,14 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); + +const Room = sequelize.define( + "rooms", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true + } + } +); + +module.exports = Room; \ No newline at end of file diff --git a/utils/models/student.js b/utils/models/student.js new file mode 100644 index 0000000..3332f0e --- /dev/null +++ b/utils/models/student.js @@ -0,0 +1,37 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Class = require("./class"); + +const Student = sequelize.define( + "students", + { + id: { + type: DataTypes.STRING(45), + primaryKey: true, + allowNull: false + }, + class: { + type: DataTypes.CHAR(2), + allowNull: false, + references: { + model: Class, + key: "id" + } + }, + name: { + type: DataTypes.STRING(45), + allowNull: false + }, + born: { + type: DataTypes.DATEONLY + }, + discord: { + type: DataTypes.BIGINT + }, + flags: { + type: DataTypes.INTEGER + } + } +); + +module.exports = Student; \ No newline at end of file diff --git a/utils/models/subject.js b/utils/models/subject.js new file mode 100644 index 0000000..656961b --- /dev/null +++ b/utils/models/subject.js @@ -0,0 +1,25 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); + +const Subject = sequelize.define( + "subjects", + { + id: { + type: DataTypes.CHAR(3), + primaryKey: true + }, + abbrev: { + type: DataTypes.STRING, + }, + name: { + type: DataTypes.STRING + } + }, { + indexes: [{ + fields: ["abbrev"], + type: "UNIQUE" + }] + } +); + +module.exports = Subject; \ No newline at end of file diff --git a/utils/models/supplementation.js b/utils/models/supplementation.js new file mode 100644 index 0000000..5e62766 --- /dev/null +++ b/utils/models/supplementation.js @@ -0,0 +1,69 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Class = require("./class"); +const Group = require("./group"); +const Room = require("./room"); +const Subject = require("./subject"); +const Teacher = require("./teacher"); + +const Supplementation = sequelize.define( + "supplementations", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + date: { + type: DataTypes.DATEONLY, + allowNull: false + }, + class: { + type: DataTypes.CHAR(2), + references: { + model: Class, + key: "id" + } + }, + type: { + type: DataTypes.ENUM, + values: ["substitutes", "move-src", "move-target", "join"] + }, + hour: { + type: DataTypes.TINYINT + }, + subject: { + type: DataTypes.CHAR(3), + references: { + model: Subject, + key: "id" + } + }, + group: { + type: DataTypes.STRING(16), + references: { + model: Group, + key: "id" + } + }, + room: { + type: DataTypes.INTEGER, + references: { + model: Room, + key: "id" + } + }, + teacher: { + type: DataTypes.STRING(16), + references: { + model: Teacher, + key: "abbrev" + } + }, + notes: { + type: DataTypes.STRING(255) + } + } +); + +module.exports = Supplementation; \ No newline at end of file diff --git a/utils/models/teacher.js b/utils/models/teacher.js new file mode 100644 index 0000000..356c151 --- /dev/null +++ b/utils/models/teacher.js @@ -0,0 +1,25 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); + +const Teacher = sequelize.define( + "teachers", + { + id: { + type: DataTypes.STRING(16), + primaryKey: true + }, + abbrev: { + type: DataTypes.STRING, + }, + name: { + type: DataTypes.STRING + } + }, { + indexes: [{ + fields: ["abbrev"], + type: "UNIQUE" + }] + } +); + +module.exports = Teacher; \ No newline at end of file diff --git a/utils/models/timetable.js b/utils/models/timetable.js new file mode 100644 index 0000000..78a31bd --- /dev/null +++ b/utils/models/timetable.js @@ -0,0 +1,72 @@ +const { Sequelize, Op, Model, DataTypes } = require("sequelize"); +const sequelize = require("../sequelize"); +const Class = require("./class"); +const Group = require("./group"); +const Room = require("./room"); +const Subject = require("./subject"); +const Teacher = require("./teacher"); + +const Timetable = sequelize.define( + "timetable", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + day: { + type: DataTypes.TINYINT, + allowNull: false + }, + hour: { + type: DataTypes.TINYINT, + allowNull: false + }, + class: { + type: DataTypes.CHAR(2), + references: { + model: Class, + key: "id" + }, + allowNull: false + }, + group: { + type: DataTypes.STRING(16), + references: { + model: Group, + key: "id" + }, + allowNull: false + }, + subject: { + type: DataTypes.CHAR(3), + references: { + model: Subject, + key: "id" + }, + allowNull: false + }, + teacher: { + type: DataTypes.STRING(16), + references: { + model: Teacher, + key: "id" + }, + allowNull: false + }, + room: { + type: DataTypes.INTEGER, + references: { + models: Room, + key: "id" + }, + allowNull: false + }, + cycles: { + type: DataTypes.ENUM, + values: ["always", "odd", "even"] + } + } +); + +module.exports = Timetable; \ No newline at end of file diff --git a/utils/sequelize.js b/utils/sequelize.js new file mode 100644 index 0000000..7ca7a29 --- /dev/null +++ b/utils/sequelize.js @@ -0,0 +1,22 @@ +const { Sequelize } = require("sequelize"); +const sequelize = new Sequelize("prestiz", config.user, config.password, { + host: config.host, + dialect: "mariadb", + define: { + freezeTableName: true + } +}); + +module.exports = sequelize; + +require("./models/class"); +require("./models/student"); +require("./models/room"); +require("./models/group"); +require("./models/teacher"); +require("./models/subject"); +require("./models/timetable"); +require("./models/rickroll"); +require("./models/supplementation"); + +sequelize.sync(); \ No newline at end of file diff --git a/utils/ssps-server.js b/utils/ssps-server.js index 2d3866b..11cc4bc 100644 --- a/utils/ssps-server.js +++ b/utils/ssps-server.js @@ -21,6 +21,7 @@ const roles = { "887339039533957151": "4C", "887339044961406996": "4L" }; +const reverseRoles = Object.fromEntries(Object.entries(roles).map(([t1,t2]) => [t2,t1])); /** * @@ -38,6 +39,7 @@ const server = "882560404167995443"; module.exports = { roles, + reverseRoles, server, getClass } \ No newline at end of file