mirror of
https://github.com/bytedream/untisbot-discord.git
synced 2025-05-09 12:15:09 +02:00
commit
64b28e9e93
0
Dockerfile
Normal file → Executable file
0
Dockerfile
Normal file → Executable file
23
README.md
Normal file → Executable file
23
README.md
Normal file → Executable file
@ -1,6 +1,7 @@
|
||||
### UntisBot
|
||||
|
||||
**UntisBot** is a java programmed discord bot, which uses the [WebUntis](https://webuntis.com/) timetable software / api to automatically sends messages when the timetable from a given account or class changes.
|
||||
**UntisBot** is a java programmed discord bot, which uses the [WebUntis](https://webuntis.com/) timetable software / api
|
||||
to receive the timetable for a specific date, automatically send messages when the timetable from a given account or class changes, displays absent teachers, and more!
|
||||
You can invite the bot right [here](https://discord.com/api/oauth2/authorize?client_id=768841979433451520&permissions=268437504&scope=bot) or [host it yourself](#Self-hosting).
|
||||
|
||||
<p align="center">
|
||||
@ -23,15 +24,19 @@ To see all available commands and get infos about it, simply type `help`.
|
||||
|
||||
| command | usage | example | default |
|
||||
| --- | --- | --- | --- |
|
||||
| `channel` | In the channel where this command is entered, the bot shows the timetable changes | `channel` | -
|
||||
| `clear` | Clears the given untis data, given from the `data` command | `clear` | -
|
||||
| `data <username> <password> <login page url> [class name]` | Sets the data with which the bot logs in to untis and checks for timetable changes. The data is stored encrypted on the server. `username` and `password` are the normal untis login data with which one also logs in to the untis website / app. To gain the login page url you have to go to webuntis.com, type in your school and choose it. Then you will be redirected to the untis login page, The url of this page is the login page url, for example `https://example.webuntis.com/WebUntis/?school=myschool#/basic/main`. `class name` is just the name of the class you want to check (eg. `12AB`). If `class name` is not specified, the bot tries to get the default class which is assigned to the given account. | `data myname secure https://example.webuntis.com/WebUntis/?school=example#/basic/main 12AB` | - |
|
||||
| `help` | Displays help to a given command | `help data` | - |
|
||||
| `channel` | In the channel where this command is entered, the bot shows the timetable changes | `channel` | - |
|
||||
| `clear` | Clears the given untis data, given from the `data` command | `clear` | - |
|
||||
| `data <username> <password> <login page url> [class name]` | Sets the data with which the bot logs in to untis and checks for timetable changes. The data is stored encrypted on the server. `username` and `password` are the normal untis login data with which one also logs in to the untis website / app. To gain the login page url you have to go to webuntis.com, type in your school and choose it. Then you will be redirected to the untis login page, The url of this page is the login page url, for example `https://example.webuntis.com/WebUntis/?school=myschool#/basic/main`. `class name` is just the name of the class you want to check (eg. `12AB`). As `class name` you can use any class from your school. If it isn't specified, the bot tries to get the default class which is assigned to the given account. | `data myname secure https://example.webuntis.com/WebUntis/?school=example#/basic/main 12AB` | - |
|
||||
| `info` | Displays information about the bot | `info` | - |
|
||||
| `help [command]` | Displays help to a given command | `help data` | - |
|
||||
| `language <language>` | Changes the language in which the timetable information are displayed. Currently only `de` (german) and `en` (english) are supported | `language de` | `en` |
|
||||
| `prefix <new prefix>` | Changes the prefix with which commands are called | `prefix $` | `!untis ` |
|
||||
| `stats` | Displays a message with some stats (total cancelled lessons, etc.) | `stats` | - |
|
||||
| `start` | Starts the stopped timetable listener. Only works if data was set with the `data` command | `start` | - |
|
||||
| `stop` | Stops timetable listening. Only works if data was set with the `data` command | `stop` | - |
|
||||
| `timetable [date] [class name]` | Displays the timetable for a specific date. As `date` you can use 3 formats. 1: Only the day (`12`); 2. Day and month (`13.04`); 3. Day, month and year (`31.12.2020`). Only works if data was set with the `data` command. If no date is given, the timetable for the current date is displayed. As `class name` you can use any class from your school. If class is not given, the class which was assigned in the `data` command is used | `timetable 11.11` | - |
|
||||
|
||||
Note: All commands except for `help <command>` and `<stats>` can only be executed by a member with admin rights.
|
||||
Note: All commands except for `help [command]`, `timetable [] [class]` and `<stats>` can only be executed by a member with admin rights.
|
||||
|
||||
## Self-hosting
|
||||
|
||||
@ -62,7 +67,7 @@ When you run the bot manually you can choose from 2 types of data storage:
|
||||
|
||||
### In-memory storage
|
||||
|
||||
In memory data storage is pretty simple: Just download the [jar](https://github.com/ByteDream/untisbot-discord/releases/tag/v1.0/UntisBot-1.0.jar) and run it with `java -jar UntisBot-1.0.jar token=<your discord bot token>`.
|
||||
In memory data storage is pretty simple: Just download the [jar](https://github.com/ByteDream/untisbot-discord/releases/tag/v1.1/UntisBot-1.0.jar) and run it with `java -jar UntisBot-1.0.jar token=<your discord bot token>`.
|
||||
The simple things have unfortunately also often disadvantages: The user data is only stored as long as the bot is running. If you shut it down, all data will be lost.
|
||||
If you want to keep the data even after a shutdown, you should use [database storage](#MariaDB).
|
||||
|
||||
@ -79,7 +84,7 @@ To set up the database, you have to execute the following command and replace `<
|
||||
mysql -u <user> -p -e "CREATE DATABASE Untis; USE Untis; $(wget -qO- https://raw.githubusercontent.com/ByteDream/untisbot-discord/master/files/database.sql)"
|
||||
```
|
||||
|
||||
Now you have set up the database and are ready to go. Download the [jar](https://github.com/ByteDream/untisbot-discord/releases/tag/v1.0/UntisBot-1.0.jar) and run it with `java -jar UntisBot-1.0.jar <your discord bot token> mariadb`.
|
||||
Now you have set up the database and are ready to go. Download the [jar](https://github.com/ByteDream/untisbot-discord/releases/tag/v1.1/UntisBot-1.0.jar) and run it with `java -jar UntisBot-1.0.jar <your discord bot token> mariadb`.
|
||||
|
||||
## Run options
|
||||
|
||||
@ -166,7 +171,7 @@ If you want to add a language which isn't supported you can
|
||||
- [Database client](https://github.com/mariadb-corporation/mariadb-connector-j) (mariadb java client)
|
||||
- [Logger](https://github.com/qos-ch/logback) (logback-core and logback-classic)
|
||||
|
||||
**_Note_: The [UntisBot jar file](https://github.com/ByteDream/untisbot-discord/releases/tag/v1.0/UntisBot-1.0.jar) and the [Dockerfile](Dockerfile) are containing all dependencies.**
|
||||
**_Note_: The [UntisBot jar file](https://github.com/ByteDream/untisbot-discord/releases/tag/v1.1/UntisBot-1.0.jar) and the [Dockerfile](Dockerfile) are containing all dependencies.**
|
||||
|
||||
|
||||
## License
|
||||
|
0
files/database.sql
Normal file → Executable file
0
files/database.sql
Normal file → Executable file
0
src/org/bytedream/untisbot/Crypt.java
Normal file → Executable file
0
src/org/bytedream/untisbot/Crypt.java
Normal file → Executable file
7
src/org/bytedream/untisbot/Main.java
Normal file → Executable file
7
src/org/bytedream/untisbot/Main.java
Normal file → Executable file
@ -1,3 +1,8 @@
|
||||
/**
|
||||
* @author ByteDream
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
package org.bytedream.untisbot;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
@ -21,6 +26,8 @@ import java.util.HashSet;
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static final String version = "1.1";
|
||||
|
||||
private static Logger logger;
|
||||
private static Connection connection;
|
||||
|
||||
|
0
src/org/bytedream/untisbot/Utils.java
Normal file → Executable file
0
src/org/bytedream/untisbot/Utils.java
Normal file → Executable file
6
src/org/bytedream/untisbot/data/Data.java
Normal file → Executable file
6
src/org/bytedream/untisbot/data/Data.java
Normal file → Executable file
@ -50,7 +50,7 @@ public class Data {
|
||||
public String getUsername() {
|
||||
try {
|
||||
return crypt.decrypt((String) (data[2]));
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException ignore) {
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | NullPointerException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -58,7 +58,7 @@ public class Data {
|
||||
public String getPassword() {
|
||||
try {
|
||||
return crypt.decrypt((String) (data[3]));
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException ignore) {
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | NullPointerException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -72,7 +72,7 @@ public class Data {
|
||||
}
|
||||
|
||||
public Short getKlasseId() {
|
||||
return (short) data[6];
|
||||
return (Short) data[6];
|
||||
}
|
||||
|
||||
public Long getChannelId() {
|
||||
|
10
src/org/bytedream/untisbot/data/DataConnector.java
Normal file → Executable file
10
src/org/bytedream/untisbot/data/DataConnector.java
Normal file → Executable file
@ -192,7 +192,7 @@ public class DataConnector {
|
||||
args.put("LANGUAGE", language);
|
||||
if (username != null) {
|
||||
if (username.isEmpty()) {
|
||||
args.put("USERNAME", "NULL");
|
||||
args.put("USERNAME", "");
|
||||
} else {
|
||||
try {
|
||||
args.put("USERNAME", crypt.encrypt(username));
|
||||
@ -205,12 +205,12 @@ public class DataConnector {
|
||||
}
|
||||
if (password != null) {
|
||||
if (password.isEmpty()) {
|
||||
args.put("PASSWORD", "NULL");
|
||||
args.put("PASSWORD", "");
|
||||
} else {
|
||||
try {
|
||||
args.put("PASSWORD", crypt.encrypt(password));
|
||||
} catch (GeneralSecurityException ignore) {
|
||||
args.put("PASSWORD", null);
|
||||
args.put("PASSWORD", "");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -218,7 +218,7 @@ public class DataConnector {
|
||||
}
|
||||
if (server != null) {
|
||||
if (server.isEmpty()) {
|
||||
args.put("SERVER", "NULL");
|
||||
args.put("SERVER", "");
|
||||
} else {
|
||||
args.put("SERVER", server);
|
||||
}
|
||||
@ -227,7 +227,7 @@ public class DataConnector {
|
||||
}
|
||||
if (school != null) {
|
||||
if (school.isEmpty()) {
|
||||
args.put("SCHOOL", "NULL");
|
||||
args.put("SCHOOL", "");
|
||||
} else {
|
||||
args.put("SCHOOL", school);
|
||||
}
|
||||
|
0
src/org/bytedream/untisbot/data/StoreType.java
Normal file → Executable file
0
src/org/bytedream/untisbot/data/StoreType.java
Normal file → Executable file
59
src/org/bytedream/untisbot/discord/Discord.java
Normal file → Executable file
59
src/org/bytedream/untisbot/discord/Discord.java
Normal file → Executable file
@ -1,11 +1,26 @@
|
||||
package org.bytedream.untisbot.discord;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
import org.bytedream.untisbot.Crypt;
|
||||
import org.bytedream.untisbot.Main;
|
||||
import org.bytedream.untisbot.data.StoreType;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Base class to start the bot
|
||||
@ -16,6 +31,7 @@ import javax.security.auth.login.LoginException;
|
||||
public class Discord {
|
||||
|
||||
private final JDABuilder jdaBuilder;
|
||||
private JDA jda = null;
|
||||
|
||||
/**
|
||||
* Configures the bot to make it ready to launch
|
||||
@ -27,9 +43,50 @@ public class Discord {
|
||||
*/
|
||||
public Discord(String token, StoreType storeType, String encryptPassword, JSONObject languages) {
|
||||
jdaBuilder = JDABuilder.createDefault(token);
|
||||
updateRichPresence();
|
||||
jdaBuilder.addEventListeners(new DiscordCommandListener(storeType, new Crypt(encryptPassword), languages));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show rich presence if a bot update was released within then last 24 hours
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
private void updateRichPresence() {
|
||||
try {
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/ByteDream/untisbot-discord/releases/tags/v" + Main.version).openConnection();
|
||||
connection.connect();
|
||||
|
||||
if (connection.getResponseCode() == 200) {
|
||||
JSONTokener jsonTokener = new JSONTokener(new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)));
|
||||
JSONObject releaseInfos = new JSONObject(jsonTokener);
|
||||
String releaseTime = releaseInfos.getString("published_at");
|
||||
LocalDateTime releaseDateTime = LocalDateTime.parse(releaseTime.substring(0, releaseTime.length() - 1));
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
if (ChronoUnit.DAYS.between(now, releaseDateTime) == 0) {
|
||||
if (jda != null) {
|
||||
jda.getPresence().setActivity(Activity.playing("update " + Main.version + " („\\(^_^)/“)"));
|
||||
} else {
|
||||
jdaBuilder.setActivity(Activity.playing("update " + Main.version + " („\\(^_^)/“)"));
|
||||
}
|
||||
new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (jda != null) {
|
||||
jda.getPresence().setActivity(null);
|
||||
} else {
|
||||
jdaBuilder.setActivity(null);
|
||||
}
|
||||
}
|
||||
}, TimeUnit.DAYS.toMillis(1) - ChronoUnit.MILLIS.between(now, releaseDateTime));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the bot
|
||||
*
|
||||
@ -37,7 +94,7 @@ public class Discord {
|
||||
* @since 1.0
|
||||
*/
|
||||
public void start() throws LoginException {
|
||||
jdaBuilder.build();
|
||||
jda = jdaBuilder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
955
src/org/bytedream/untisbot/discord/DiscordCommandListener.java
Normal file → Executable file
955
src/org/bytedream/untisbot/discord/DiscordCommandListener.java
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
46
src/org/bytedream/untisbot/language.json
Normal file → Executable file
46
src/org/bytedream/untisbot/language.json
Normal file → Executable file
@ -1,15 +1,20 @@
|
||||
{
|
||||
"de": {
|
||||
"language": "German",
|
||||
"title": "Stunden Ausfall Information für {weekday}, den {date}",
|
||||
"cancelled-title": "Ausfall {lesson-name}. Stunde ({start-time} Uhr - {end-time} Uhr)",
|
||||
"cancelled-body": "Ausfall bei {teachers}, in {subjects}, in der {lesson-name}. Stunde",
|
||||
"moved-title": "{from-lesson-name}. Stunde wird zur {to-lesson-name}. Stunde umverlegt",
|
||||
"moved-body": "Die {from-lesson-name}. Stunde bei {teachers} in {subjects} wird zur {to-lesson-name}. Stunde umverlegt",
|
||||
"not-cancelled-title": "KEIN Ausfall {lesson-name}. Stunde ({start-time} Uhr - {end-time} Uhr)",
|
||||
"not-cancelled-body": "KEIN Ausfall bei {teachers}, in {subjects}, in der {lesson-name}. Stunde",
|
||||
"not-moved-title": "{from-lesson-name}. Stunde wird NICHT zur {to-lesson-name}. Stunde umverlegt",
|
||||
"not-moved-body": "Die {from-lesson-name}. Stunde bei {teachers} wird NICHT zur {to-lesson-name}. Stunde umverlegt",
|
||||
"timetable-title": "Stundenplan für Klasse {class} am {date}",
|
||||
"timetable-lesson-title": "{lesson-number}. Stunde ({start-time} - {end-time})",
|
||||
"timetable-teachers": "_Lehrer_: {teachers}",
|
||||
"timetable-subjects": "_Unterricht_: {subjects}",
|
||||
"timetable-rooms": "_Raum_: {rooms}",
|
||||
"change-title": "Stunden Ausfall Information für {weekday}, den {date}",
|
||||
"cancelled-title": "Ausfall {lesson-number}. Stunde ({start-time} Uhr - {end-time} Uhr)",
|
||||
"cancelled-body": "Ausfall bei {teachers}, in {subjects}, in der {lesson-number}. Stunde",
|
||||
"moved-title": "{from-lesson-number}. Stunde wird zur {to-lesson-number}. Stunde umverlegt",
|
||||
"moved-body": "Die {from-lesson-number}. Stunde bei {teachers} in {subjects} wird zur {to-lesson-number}. Stunde umverlegt",
|
||||
"not-cancelled-title": "KEIN Ausfall {lesson-number}. Stunde ({start-time} Uhr - {end-time} Uhr)",
|
||||
"not-cancelled-body": "KEIN Ausfall bei {teachers}, in {subjects}, in der {lesson-number}. Stunde",
|
||||
"not-moved-title": "{from-lesson-number}. Stunde wird NICHT zur {to-lesson-number}. Stunde umverlegt",
|
||||
"not-moved-body": "Die {from-lesson-number}. Stunde bei {teachers} wird NICHT zur {to-lesson-number}. Stunde umverlegt",
|
||||
"monday": "Montag",
|
||||
"tuesday": "Dienstag",
|
||||
"wednesday": "Mittwoch",
|
||||
@ -20,15 +25,20 @@
|
||||
},
|
||||
"en": {
|
||||
"language": "English",
|
||||
"title": "Irregular lesson information for {weekday}, {date}",
|
||||
"cancelled-title": "Cancelled {lesson-name}. lesson ({start-time} - {end-time})",
|
||||
"cancelled-body": "The {lesson-name}. lesson with {teachers} in {subjects} is cancelled",
|
||||
"moved-title": "The {from-lesson-name}. lesson is moved to {to-lesson-name}. lesson",
|
||||
"moved-body": "The {from-lesson-name}. lesson with {teachers} in {subjects} is moved to the {to-lesson-name}. lesson",
|
||||
"not-cancelled-title": "{lesson-name}. lesson ({start-time} - {end-time}) is NO cancelled",
|
||||
"not-cancelled-body": "The {lesson-name}. lesson with {teachers} in {subjects} is NOT cancelled",
|
||||
"not-moved-title": "The {from-lesson-name}. lesson is NOT moved to {to-lesson-name}.",
|
||||
"not-moved-body": "The {from-lesson-name}. lesson with {teachers} in {subjects} is NOT moved to the {to-lesson-name}. lesson",
|
||||
"timetable-title": "Timetable for class {class} on {date}",
|
||||
"timetable-lesson-title": "{lesson-number}. lesson ({start-time} - {end-time})",
|
||||
"timetable-teachers": "_Teacher_: {teachers}",
|
||||
"timetable-subjects": "_Subject_: {subjects}",
|
||||
"timetable-rooms": "_Room_: {rooms}",
|
||||
"change-title": "Irregular lesson information for {weekday}, {date}",
|
||||
"cancelled-title": "Cancelled {lesson-number}. lesson ({start-time} - {end-time})",
|
||||
"cancelled-body": "The {lesson-number}. lesson with {teachers} in {subjects} is cancelled",
|
||||
"moved-title": "The {from-lesson-number}. lesson is moved to {to-lesson-number}. lesson",
|
||||
"moved-body": "The {from-lesson-number}. lesson with {teachers} in {subjects} is moved to the {to-lesson-number}. lesson",
|
||||
"not-cancelled-title": "{lesson-number}. lesson ({start-time} - {end-time}) is NO cancelled",
|
||||
"not-cancelled-body": "The {lesson-number}. lesson with {teachers} in {subjects} is NOT cancelled",
|
||||
"not-moved-title": "The {from-lesson-number}. lesson is NOT moved to {to-lesson-number}.",
|
||||
"not-moved-body": "The {from-lesson-number}. lesson with {teachers} in {subjects} is NOT moved to the {to-lesson-number}. lesson",
|
||||
"monday": "monday",
|
||||
"tuesday": "tuesday",
|
||||
"wednesday": "wednesday",
|
||||
|
0
src/org/bytedream/untisbot/resources/logback.xml
Normal file → Executable file
0
src/org/bytedream/untisbot/resources/logback.xml
Normal file → Executable file
0
src/org/bytedream/untisbot/untis/CheckCallback.java
Normal file → Executable file
0
src/org/bytedream/untisbot/untis/CheckCallback.java
Normal file → Executable file
17
src/org/bytedream/untisbot/untis/TimetableChecker.java
Normal file → Executable file
17
src/org/bytedream/untisbot/untis/TimetableChecker.java
Normal file → Executable file
@ -19,7 +19,7 @@ import java.util.HashSet;
|
||||
public class TimetableChecker {
|
||||
|
||||
private final Session session;
|
||||
private final int klasseId;
|
||||
private final int classId;
|
||||
private final LocalDate[] cancelledLessonsDay = new LocalDate[7];
|
||||
private final LocalDate[] ignoredLessonsDay = new LocalDate[7];
|
||||
private final LocalDate[] movedLessonsDay = new LocalDate[7];
|
||||
@ -30,16 +30,13 @@ public class TimetableChecker {
|
||||
/**
|
||||
* Sets all necessary configurations and connects to the untis account with the given untis credentials
|
||||
*
|
||||
* @param username username of the untis account
|
||||
* @param password user password of the untis account
|
||||
* @param server the server from the school as URL
|
||||
* @param schoolName name of the school
|
||||
* @throws IOException if any {@link IOException} while the login occurs
|
||||
* @param session user session
|
||||
* @param classId id of the class to check the timetable
|
||||
* @since 1.0
|
||||
*/
|
||||
public TimetableChecker(String username, String password, String server, String schoolName, int klasseId) throws IOException {
|
||||
session = Session.login(username, password, server, schoolName);
|
||||
this.klasseId = klasseId;
|
||||
public TimetableChecker(Session session, int classId) {
|
||||
this.session = session;
|
||||
this.classId = classId;
|
||||
|
||||
for (LocalDate[] localDates : new HashSet<LocalDate[]>() {{
|
||||
add(cancelledLessonsDay);
|
||||
@ -65,7 +62,7 @@ public class TimetableChecker {
|
||||
* @since 1.0
|
||||
*/
|
||||
public CheckCallback check(LocalDate dateToCheck) throws IOException {
|
||||
Timetable timetable = session.getTimetableFromKlasseId(dateToCheck, dateToCheck, klasseId);
|
||||
Timetable timetable = session.getTimetableFromKlasseId(dateToCheck, dateToCheck, classId);
|
||||
timetable.sortByStartTime();
|
||||
|
||||
int dayOfWeekInArray = dateToCheck.getDayOfWeek().getValue() - 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user