activityContext;
- private SyncCallback callback;
- private Exception e = null;
- private String apiResponse = null;
- private int profileId;
- private ProfileFull profile;
-
- public ProcessAsyncTask(App app, Context activityContext, SyncCallback callback, int profileId, ProfileFull profile) {
- //d(TAG, "Thread/ProcessAsyncTask/constructor/"+Thread.currentThread().getName());
- this.app = app;
- this.activityContext = new WeakReference<>(activityContext);
- this.callback = callback;
- this.profileId = profileId;
- this.profile = profile;
- }
-
- @Override
- protected Integer doInBackground(Void... voids) {
- Context activityContext = this.activityContext.get();
- //d(TAG, "Thread/ProcessAsyncTask/doInBackground/"+Thread.currentThread().getName());
- try {
-
- // UPDATE FCM TOKEN IF EMPTY
- if (app.appConfig.fcmToken == null || app.appConfig.fcmToken.equals("")) {
- FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
- app.appConfig.fcmToken = instanceIdResult.getToken();
- app.appConfig.savePending = true;
- });
- }
-
- callback.onProgress(1);
- if (profile.getSyncNotifications()) {
- new Handler(activityContext.getMainLooper()).post(() -> {
- callback.onActionStarted(R.string.sync_action_creating_notifications);
- });
-
- for (LessonFull change : app.db.lessonChangeDao().getNotNotifiedNow(profileId)) {
- String text = app.getContext().getString(R.string.notification_lesson_change_format, change.changeTypeStr(app.getContext()), change.lessonDate == null ? "" : change.lessonDate.getFormattedString(), change.subjectLongName);
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_TIMETABLE_LESSON_CHANGE)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_TIMETABLE)
- .withLongExtra("timetableDate", change.lessonDate.getValue())
- .withAddedDate(change.addedDate)
- );
- }
- for (EventFull event : app.db.eventDao().getNotNotifiedNow(profileId)) {
- String text;
- if (event.type == TYPE_HOMEWORK)
- text = app.getContext().getString(R.string.notification_homework_format, ns(app.getString(R.string.notification_event_no_subject), event.subjectLongName), event.eventDate.getFormattedString());
- else
- text = app.getContext().getString(R.string.notification_event_format, event.typeName, event.eventDate.getFormattedString(), ns(app.getString(R.string.notification_event_no_subject), event.subjectLongName));
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(event.type == TYPE_HOMEWORK ? Notification.TYPE_NEW_HOMEWORK : Notification.TYPE_NEW_EVENT)
- .withFragmentRedirect(event.type == TYPE_HOMEWORK ? MainActivity.DRAWER_ITEM_HOMEWORK : MainActivity.DRAWER_ITEM_AGENDA)
- .withLongExtra("eventId", event.id)
- .withLongExtra("eventDate", event.eventDate.getValue())
- .withAddedDate(event.addedDate)
- );
- // student's rights abuse - disabled, because this was useless
- /*if (!event.addedManually && event.type == RegisterEvent.TYPE_EXAM && event.eventDate.combineWith(event.startTime) - event.addedDate < 7 * 24 * 60 * 60 * 1000) {
- text = app.getContext().getString(R.string.notification_abuse_format, event.typeString(app, app.profile), event.subjectLongName, event.eventDate.getFormattedString());
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.id, profile.name)
- .withType(Notification.TYPE_GENERAL)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_NOTIFICATIONS)
- );
- }*/
- }
-
- Date today = Date.getToday();
- int todayValue = today.getValue();
- profile.setCurrentSemester(profile.dateToSemester(today));
-
- for (GradeFull grade : app.db.gradeDao().getNotNotifiedNow(profileId)) {
- String gradeName = grade.name;
- if (grade.type == TYPE_SEMESTER1_PROPOSED
- || grade.type == TYPE_SEMESTER2_PROPOSED) {
- gradeName = (app.getString(R.string.grade_semester_proposed_format_2, grade.name));
- } else if (grade.type == TYPE_SEMESTER1_FINAL
- || grade.type == TYPE_SEMESTER2_FINAL) {
- gradeName = (app.getString(R.string.grade_semester_final_format_2, grade.name));
- } else if (grade.type == TYPE_YEAR_PROPOSED) {
- gradeName = (app.getString(R.string.grade_year_proposed_format_2, grade.name));
- } else if (grade.type == TYPE_YEAR_FINAL) {
- gradeName = (app.getString(R.string.grade_year_final_format_2, grade.name));
- }
- String text = app.getContext().getString(R.string.notification_grade_format, gradeName, grade.subjectLongName);
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_NEW_GRADE)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_GRADES)
- .withLongExtra("gradesSubjectId", grade.subjectId)
- .withAddedDate(grade.addedDate)
- );
- }
- for (NoticeFull notice : app.db.noticeDao().getNotNotifiedNow(profileId)) {
- String noticeTypeStr = (notice.type == Notice.TYPE_POSITIVE ? app.getString(R.string.notification_notice_praise) : (notice.type == Notice.TYPE_NEGATIVE ? app.getString(R.string.notification_notice_warning) : app.getString(R.string.notification_notice_new)));
- String text = app.getContext().getString(R.string.notification_notice_format, noticeTypeStr, notice.teacherFullName, Date.fromMillis(notice.addedDate).getFormattedString());
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_NEW_NOTICE)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_BEHAVIOUR)
- .withLongExtra("noticeId", notice.id)
- .withAddedDate(notice.addedDate)
- );
- }
- for (AttendanceFull attendance : app.db.attendanceDao().getNotNotifiedNow(profileId)) {
- String attendanceTypeStr = app.getString(R.string.notification_type_attendance);
- switch (attendance.type) {
- case Attendance.TYPE_ABSENT:
- attendanceTypeStr = app.getString(R.string.notification_absence);
- break;
- case Attendance.TYPE_ABSENT_EXCUSED:
- attendanceTypeStr = app.getString(R.string.notification_absence_excused);
- break;
- case Attendance.TYPE_BELATED:
- attendanceTypeStr = app.getString(R.string.notification_belated);
- break;
- case Attendance.TYPE_BELATED_EXCUSED:
- attendanceTypeStr = app.getString(R.string.notification_belated_excused);
- break;
- case Attendance.TYPE_RELEASED:
- attendanceTypeStr = app.getString(R.string.notification_release);
- break;
- }
- String text = app.getContext().getString(R.string.notification_attendance_format, attendanceTypeStr, attendance.subjectLongName, attendance.lessonDate.getFormattedString());
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_NEW_ATTENDANCE)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_ATTENDANCE)
- .withLongExtra("attendanceId", attendance.id)
- .withAddedDate(attendance.addedDate)
- );
- }
- for (AnnouncementFull announcement : app.db.announcementDao().getNotNotifiedNow(profileId)) {
- String text = app.getContext().getString(R.string.notification_announcement_format, announcement.subject);
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_NEW_ANNOUNCEMENT)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_ANNOUNCEMENTS)
- .withLongExtra("announcementId", announcement.id)
- .withAddedDate(announcement.addedDate)
- );
- }
- for (MessageFull message : app.db.messageDao().getReceivedNotNotifiedNow(profileId)) {
- String text = app.getContext().getString(R.string.notification_message_format, message.senderFullName, message.subject);
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_NEW_MESSAGE)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_MESSAGES)
- .withLongExtra("messageType", Message.TYPE_RECEIVED)
- .withLongExtra("messageId", message.id)
- .withAddedDate(message.addedDate)
- );
- }
-
- if (profile.getLuckyNumber() != oldLuckyNumber
- && profile.getLuckyNumber() != -1
- && profile.getLuckyNumberDate() != null
- && profile.getLuckyNumberDate().getValue() >= todayValue) {
- String text;
- if (profile.getLuckyNumberDate().getValue() == todayValue) { // LN for today
- text = app.getString((profile.getStudentNumber() != -1 && profile.getStudentNumber() == profile.getLuckyNumber() ? R.string.notification_lucky_number_yours_format : R.string.notification_lucky_number_format), profile.getLuckyNumber());
- } else if (profile.getLuckyNumberDate().getValue() == todayValue + 1) { // LN for tomorrow
- text = app.getString((profile.getStudentNumber() != -1 && profile.getStudentNumber() == profile.getLuckyNumber() ? R.string.notification_lucky_number_yours_tomorrow_format : R.string.notification_lucky_number_tomorrow_format), profile.getLuckyNumber());
- } else { // LN for later
- text = app.getString((profile.getStudentNumber() != -1 && profile.getStudentNumber() == profile.getLuckyNumber() ? R.string.notification_lucky_number_yours_later_format : R.string.notification_lucky_number_later_format), profile.getLuckyNumberDate().getFormattedString(), profile.getLuckyNumber());
- }
- app.notifier.add(new Notification(app.getContext(), text)
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_LUCKY_NUMBER)
- .withFragmentRedirect(MainActivity.DRAWER_ITEM_HOME)
- );
- oldLuckyNumber = profile.getLuckyNumber();
- }
- }
-
-
- app.db.metadataDao().setAllNotified(profileId, true);
- callback.onProgress(1);
-
- // SEND WEB PUSH, if registration allowed
- // otherwise, UNREGISTER THE USER
- if (profile.getRegistration() == REGISTRATION_ENABLED) {
- new Handler(activityContext.getMainLooper()).post(() -> {
- callback.onActionStarted(R.string.sync_action_syncing_shared_events);
- });
- //if (profile.registrationUsername == null || profile.registrationUsername.equals("")) {
- //}
- ServerRequest syncRequest = new ServerRequest(app, app.requestScheme + APP_URL + "main.php?sync", "Edziennik/REG", profile);
-
- if (registerEmpty) {
- syncRequest.setBodyParameter("first_run", "true");
- }
-
- // ALSO SEND NEW DATA TO BROWSER *excluding* all Shared Events !!!
- // because they will be sent by the server, as soon as it's shared, by FCM
-
- if (app.appConfig.webPushEnabled) {
- int position = 0;
- for (Notification notification : app.appConfig.notifications) {
- //Log.d(TAG, notification.text);
- if (!notification.notified) {
- if (notification.type != Notification.TYPE_NEW_SHARED_EVENT
- && notification.type != Notification.TYPE_SERVER_MESSAGE
- && notification.type != Notification.TYPE_NEW_SHARED_HOMEWORK) // these are automatically sent to the browser by the server
- {
- //Log.d(TAG, "Adding notify[" + position + "]");
- syncRequest.setBodyParameter("notify[" + position + "][type]", Integer.toString(notification.type));
- syncRequest.setBodyParameter("notify[" + position + "][title]", notification.title);
- syncRequest.setBodyParameter("notify[" + position + "][text]", notification.text);
- position++;
- }
- }
- }
- }
-
- callback.onProgress(1);
-
- if (app.appConfig.webPushEnabled || profile.getEnableSharedEvents()) {
- JsonObject result = syncRequest.runSync();
- callback.onProgress(1);
- //Log.d(TAG, "Executed request");
- if (result == null) {
- return AppError.CODE_APP_SERVER_ERROR;
- }
- apiResponse = result.toString();
- if (!result.get("success").getAsString().equals("true")) {
- return AppError.CODE_APP_SERVER_ERROR;
- }
- // HERE PROCESS ALL THE RECEIVED EVENTS
- // add them to the profile and create appropriate notifications
- for (JsonElement jEventEl : result.getAsJsonArray("events")) {
- JsonObject jEvent = jEventEl.getAsJsonObject();
- String teamCode = jEvent.get("team").getAsString();
- //d(TAG, "An event is there! "+jEvent.toString());
- // get the target Team from teamCode
- Team team = app.db.teamDao().getByCodeNow(profile.getId(), teamCode);
- if (team != null) {
- //d(TAG, "The target team is "+team.name+", ID "+team.id);
- // create the event from Json. Add the missing teamId and !!profileId!!
- Event event = app.gson.fromJson(jEvent.toString(), Event.class);
- // proguard. disable for Event.class
- if (event.eventDate == null) {
- apiResponse += "\n\nEventDate == null\n" + jEvent.toString();
- throw new Exception("null eventDate");
- }
- event.profileId = profile.getId();
- event.teamId = team.id;
- event.addedManually = true;
- //d(TAG, "Created the event! "+event);
-
- if (event.sharedBy != null && event.sharedBy.equals(profile.getUsernameId())) {
- //d(TAG, "Shared by self! Changing name");
- event.sharedBy = "self";
- event.sharedByName = profile.getStudentNameLong();
- }
-
- EventType type = app.db.eventTypeDao().getByIdNow(profileId, event.type);
-
- //d(TAG, "Finishing adding event "+event);
- app.db.eventDao().add(event);
- Metadata metadata = new Metadata(profile.getId(), event.type == TYPE_HOMEWORK ? Metadata.TYPE_HOMEWORK : Metadata.TYPE_EVENT, event.id, registerEmpty, true, jEvent.get("addedDate").getAsLong());
- long metadataId = app.db.metadataDao().add(metadata);
- if (metadataId != -1 && !registerEmpty) {
- app.notifier.add(new Notification(app.getContext(), app.getString(R.string.notification_shared_event_format, event.sharedByName, type != null ? type.name : "wydarzenie", event.eventDate == null ? "nieznana data" : event.eventDate.getFormattedString(), event.topic))
- .withProfileData(profile.getId(), profile.getName())
- .withType(event.type == TYPE_HOMEWORK ? Notification.TYPE_NEW_SHARED_HOMEWORK : Notification.TYPE_NEW_SHARED_EVENT)
- .withFragmentRedirect(event.type == TYPE_HOMEWORK ? MainActivity.DRAWER_ITEM_HOMEWORK : MainActivity.DRAWER_ITEM_AGENDA)
- .withLongExtra("eventDate", event.eventDate.getValue())
- );
- }
- }
- }
- callback.onProgress(5);
- return CODE_OK;
- } else {
- callback.onProgress(6);
- return CODE_OK;
- }
- } else {
- // the user does not want to be registered
- callback.onProgress(7);
- return CODE_OK;
- }
- } catch (Exception e) {
- e.printStackTrace();
- this.e = e;
- return null;
- }
- //return null;
- }
-
- @Override
- protected void onPostExecute(Integer errorCode) {
- //d(TAG, "Thread/ProcessAsyncTask/onPostExecute/"+Thread.currentThread().getName());
- Context activityContext = this.activityContext.get();
- app.profileSaveFull(profile);
- if (app.profile != null && profile.getId() == app.profile.getId()) {
- app.profile = profile;
- }
- if (errorCode == null) {
- // this means an Exception was thrown
- callback.onError(activityContext, new AppError(TAG, 513, CODE_OTHER, e, apiResponse));
- return;
- }
- //Log.d(TAG, "Finishing");
-
-
- callback.onProgress(1);
-
- if (errorCode == CODE_OK)
- callback.onSuccess(activityContext, profile);
- else {
- try {
- // oh that's useless
- throw new RuntimeException(stringErrorCode(app, errorCode, ""));
- } catch (Exception e) {
- callback.onError(activityContext, new AppError(TAG, 528, errorCode, e, (String) null));
- }
- }
- super.onPostExecute(errorCode);
- }
- }
-
- public void notifyAndReload() {
- app.notifier.postAll(null);
- app.saveConfig();
- SyncJob.schedule(app);
- Intent i = new Intent(Intent.ACTION_MAIN)
- .putExtra("reloadProfileId", -1);
- app.sendBroadcast(i);
-
- Intent intent = new Intent(app.getContext(), WidgetTimetable.class);
- intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- int[] ids = AppWidgetManager.getInstance(app).getAppWidgetIds(new ComponentName(app, WidgetTimetable.class));
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
- app.sendBroadcast(intent);
-
- intent = new Intent(app.getContext(), WidgetNotifications.class);
- intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- ids = AppWidgetManager.getInstance(app).getAppWidgetIds(new ComponentName(app, WidgetNotifications.class));
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
- app.sendBroadcast(intent);
-
- intent = new Intent(app.getContext(), WidgetLuckyNumber.class);
- intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- ids = AppWidgetManager.getInstance(app).getAppWidgetIds(new ComponentName(app, WidgetLuckyNumber.class));
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
- app.sendBroadcast(intent);
- }
-
- /* _____
- / ____|
- | (___ _ _ _ __ ___
- \___ \| | | | '_ \ / __|
- ____) | |_| | | | | (__
- |_____/ \__, |_| |_|\___|
- __/ |
- |__*/
- // DataCallbacks that are *not* in Edziennik.sync need to be executed on the main thread.
- // EdziennikInterface.sync is executed on a worker thread
- // in Edziennik.sync/newCallback methods are called on a worker thread
-
- // callback passed to Edziennik.sync is executed on the main thread
- // thus, callback which is in guiSync is also on the main thread
-
- /**
- * Sync all Edziennik data.
- * Used in services, login form and {@code guiSync}
- *
- * May be ran on worker thread.
- * {@link EdziennikInterface}.sync is ran always on worker thread.
- * Every callback is ran on the UI thread.
- *
- * @param app
- * @param activityContext
- * @param callback
- * @param profileId
- */
- public void sync(@NonNull App app, @NonNull Context activityContext, @NonNull SyncCallback callback, int profileId) {
- sync(app, activityContext, callback, profileId, (int[])null);
- }
- public void sync(@NonNull App app, @NonNull Context activityContext, @NonNull SyncCallback callback, int profileId, @Nullable int ... featureList) {
- // empty: no unread notifications, all shared events (current+past)
- // only if there is no data, and we are not logged in yet
- SyncCallback newCallback = new SyncCallback() {
- @Override
- public void onLoginFirst(List profileList, LoginStore loginStore) {
- new Handler(activityContext.getMainLooper()).post(() -> {
- callback.onLoginFirst(profileList, loginStore);
- });
- }
-
- @Override
- public void onSuccess(Context activityContext, ProfileFull profileFull) {
- new Handler(activityContext.getMainLooper()).post(() -> {
- new ProcessAsyncTask(app, activityContext, callback, profileId, profileFull).execute();
- });
- }
-
- @Override
- public void onError(Context activityContext, AppError error) {
- new Handler(activityContext.getMainLooper()).post(() -> {
- callback.onError(activityContext, error);
- });
- }
-
- @Override
- public void onProgress(int progressStep) {
- new Handler(activityContext.getMainLooper()).post(() -> {
- callback.onProgress(progressStep);
- });
- }
-
- @Override
- public void onActionStarted(int stringResId) {
- new Handler(activityContext.getMainLooper()).post(() -> {
- callback.onActionStarted(stringResId);
- });
- }
- };
- AsyncTask.execute(() -> {
- ProfileFull profile = app.db.profileDao().getByIdNow(profileId);
- if (profile != null) {
-
- if (profile.getArchived()) {
- newCallback.onError(activityContext, new AppError(TAG, 678, CODE_PROFILE_ARCHIVED, profile.getName()));
- return;
- }
- else if (profile.getDateYearEnd() != null && Date.getToday().getValue() >= profile.getDateYearEnd().getValue()) {
- profile.setArchived(true);
- app.notifier.add(new Notification(app.getContext(), app.getString(R.string.profile_auto_archiving_format, profile.getName(), profile.getDateYearEnd().getFormattedString()))
- .withProfileData(profile.getId(), profile.getName())
- .withType(Notification.TYPE_AUTO_ARCHIVING)
- .withFragmentRedirect(DRAWER_ITEM_HOME)
- .withLongExtra("autoArchiving", 1L)
- );
- app.notifier.postAll(null);
- app.db.profileDao().add(profile);
- if (App.profileId == profile.getId()) {
- app.profile.setArchived(true);
- }
- newCallback.onSuccess(activityContext, profile);
- return;
- }
-
- registerEmpty = profile.getEmpty();
- oldLuckyNumber = profile.getLuckyNumber();
- getApi(app, profile.getLoginStoreType()).syncFeature(activityContext, newCallback, profile, featureList);
- } else {
- new Handler(activityContext.getMainLooper()).post(() -> callback.onError(activityContext, new AppError(TAG, 609, CODE_PROFILE_NOT_FOUND, (String) null)));
- }
- });
- }
-
- /* _____ _ _ _____
- / ____| | | |_ _|
- | | __| | | | | | __ ___ __ __ _ _ __ _ __ ___ _ __ ___
- | | |_ | | | | | | \ \ /\ / / '__/ _` | '_ \| '_ \ / _ \ '__/ __|
- | |__| | |__| |_| |_ \ V V /| | | (_| | |_) | |_) | __/ | \__ \
- \_____|\____/|_____| \_/\_/ |_| \__,_| .__/| .__/ \___|_| |___/
- | | | |
- |_| |*/
- /**
- * Sync all Edziennik data while showing a progress dialog.
- * A wrapper for {@code sync}
- *
- * Does not switch between threads.
- * All callbacks have to be executed on the UI thread.
- *
- * @param app an App singleton instance
- * @param activity a parent activity
- * @param profileId ID of the profile to sync
- * @param dialogTitle a title of the dialog to show
- * @param dialogText dialog's content
- * @param successText a toast to show on success
- */
- public void guiSync(@NonNull App app, @NonNull Activity activity, int profileId, @StringRes int dialogTitle, @StringRes int dialogText, @StringRes int successText) {
- guiSync(app, activity, profileId, dialogTitle, dialogText, successText, (int[])null);
- }
- public void guiSync(@NonNull App app, @NonNull Activity activity, int profileId, @StringRes int dialogTitle, @StringRes int dialogText, @StringRes int successText, int ... featureList) {
- MaterialDialog progressDialog = new MaterialDialog.Builder(activity)
- .title(dialogTitle)
- .content(dialogText)
- .progress(false, PROFILE_MAX_PROGRESS, false)
- .canceledOnTouchOutside(false)
- .show();
- SyncCallback guiSyncCallback = new SyncCallback() {
- @Override
- public void onLoginFirst(List profileList, LoginStore loginStore) {
-
- }
-
- @Override
- public void onSuccess(Context activityContext, ProfileFull profileFull) {
- progressDialog.dismiss();
- Toast.makeText(activityContext, successText, Toast.LENGTH_SHORT).show();
- notifyAndReload();
- // profiles are saved automatically, during app.saveConfig in processFinish
- /*if (activityContext instanceof MainActivity) {
- //((MainActivity) activityContext).reloadCurrentFragment("GuiSync");
- ((MainActivity) activityContext).accountHeaderAddProfiles();
- }*/
- }
-
- @Override
- public void onError(Context activityContext, AppError error) {
- progressDialog.dismiss();
- guiShowErrorDialog((Activity) activityContext, error, R.string.sync_error_dialog_title);
- }
-
- @Override
- public void onProgress(int progressStep) {
- progressDialog.incrementProgress(progressStep);
- }
-
- @Override
- public void onActionStarted(int stringResId) {
- progressDialog.setContent(activity.getString(R.string.sync_action_format, activity.getString(stringResId)));
- }
- };
- app.apiEdziennik.sync(app, activity, guiSyncCallback, profileId, featureList);
- }
- /**
- * Sync all Edziennik data in background.
- * A callback is executed on main thread.
- * A wrapper for {@code sync}
- *
- * @param app an App singleton instance
- * @param activity a parent activity
- * @param profileId ID of the profile to sync
- * @param syncCallback a callback
- * @param feature a feature to sync
- */
- public void guiSyncSilent(@NonNull App app, @NonNull Activity activity, int profileId, SyncCallback syncCallback, int feature) {
- SyncCallback guiSyncCallback = new SyncCallback() {
- @Override
- public void onLoginFirst(List profileList, LoginStore loginStore) {
-
- }
-
- @Override
- public void onSuccess(Context activityContext, ProfileFull profileFull) {
- notifyAndReload();
- syncCallback.onSuccess(activityContext, profileFull);
- }
-
- @Override
- public void onError(Context activityContext, AppError error) {
- syncCallback.onError(activityContext, error);
- }
-
- @Override
- public void onProgress(int progressStep) {
- syncCallback.onProgress(progressStep);
- }
-
- @Override
- public void onActionStarted(int stringResId) {
- syncCallback.onActionStarted(stringResId);
- }
- };
- app.apiEdziennik.sync(app, activity, guiSyncCallback, profileId, feature == FEATURE_ALL ? null : new int[]{feature});
- }
-
- /**
- * Show a dialog allowing the user to choose which features to sync.
- * Handles everything including pre-selecting the features basing on the current fragment.
- *
- * Will execute {@code sync} after the selection is made.
- *
- * A normal progress dialog is shown during the sync.
- *
- * @param app an App singleton instance
- * @param activity a parent activity
- * @param profileId ID of the profile to sync
- * @param dialogTitle a title of the dialog to show
- * @param dialogText dialog's content
- * @param successText a toast to show on success
- * @param currentFeature a feature id representing the currently opened fragment or caller
- */
- public void guiSyncFeature(@NonNull App app,
- @NonNull Activity activity,
- int profileId,
- @StringRes int dialogTitle,
- @StringRes int dialogText,
- @StringRes int successText,
- int currentFeature) {
-
- String[] items = new String[]{
- app.getString(R.string.menu_timetable),
- app.getString(R.string.menu_agenda),
- app.getString(R.string.menu_grades),
- app.getString(R.string.menu_homework),
- app.getString(R.string.menu_notices),
- app.getString(R.string.menu_attendance),
- app.getString(R.string.title_messages_inbox_single),
- app.getString(R.string.title_messages_sent_single),
- app.getString(R.string.menu_announcements)
- };
- int[] itemsIds = new int[]{
- FEATURE_TIMETABLE,
- FEATURE_AGENDA,
- FEATURE_GRADES,
- FEATURE_HOMEWORK,
- FEATURE_NOTICES,
- FEATURE_ATTENDANCE,
- FEATURE_MESSAGES_INBOX,
- FEATURE_MESSAGES_OUTBOX,
- FEATURE_ANNOUNCEMENTS
- };
- int[] selectedIndices;
- if (currentFeature == FEATURE_ALL) {
- selectedIndices = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8};
- }
- else {
- selectedIndices = new int[]{Arrays.binarySearch(itemsIds, currentFeature)};
- }
-
- MaterialDialog dialog = new MaterialDialog.Builder(activity)
- .title(R.string.sync_feature_title)
- .content(R.string.sync_feature_text)
- .positiveText(R.string.ok)
- .negativeText(R.string.cancel)
- .neutralText(R.string.sync_feature_all)
- .items(items)
- .itemsIds(itemsIds)
- .itemsCallbackMultiChoice(ArrayUtils.toWrapperArray(selectedIndices), (dialog1, which, text) -> {
- dialog1.getActionButton(DialogAction.POSITIVE).setEnabled(which.length > 0);
- return true;
- })
- .alwaysCallMultiChoiceCallback()
- .onPositive(((dialog1, which) -> {
- List featureList = new ArrayList<>();
- for (int i: dialog1.getSelectedIndices()) {
- featureList.add(itemsIds[i]);
- }
- guiSync(app, activity, profileId, dialogTitle, dialogText, successText, ArrayUtils.toPrimitiveArray(featureList));
- }))
- .onNeutral(((dialog1, which) -> {
- guiSync(app, activity, profileId, dialogTitle, dialogText, successText);
- }))
- .show();
-
-
-
- }
-
- public void guiShowArchivedDialog(Activity activity, String profileName) {
- new MaterialDialog.Builder(activity)
- .title(R.string.profile_archived_dialog_title)
- .content(activity.getString(R.string.profile_archived_dialog_text_format, profileName))
- .positiveText(R.string.ok)
- .onPositive(((dialog, which) -> dialog.dismiss()))
- .autoDismiss(false)
- .show();
- }
-
- /* _____ _ _ _____
- / ____| | | |_ _|
- | | __| | | | | | ___ _ __ _ __ ___ _ __ ___
- | | |_ | | | | | | / _ \ '__| '__/ _ \| '__/ __|
- | |__| | |__| |_| |_ | __/ | | | | (_) | | \__ \
- \_____|\____/|_____| \___|_| |_| \___/|_| |__*/
- /**
- * Used for reporting an exception somewhere in the code that is not part of Edziennik APIs.
- *
- * @param activity a parent activity
- * @param errorLine the line of code where the error occurred
- * @param e an Exception object
- */
- public void guiReportException(Activity activity, int errorLine, Exception e) {
- guiReportError(activity, new AppError(TAG, errorLine, CODE_OTHER, "Błąd wewnętrzny aplikacji ("+errorLine+")", null, null, e, null), null);
- }
-
- public void guiShowErrorDialog(Activity activity, @NonNull AppError error, @StringRes int dialogTitle) {
- if (error.errorCode == CODE_PROFILE_ARCHIVED) {
- guiShowArchivedDialog(activity, error.errorText);
- return;
- }
- error.changeIfCodeOther();
- new MaterialDialog.Builder(activity)
- .title(dialogTitle)
- .content(error.asReadableString(activity))
- .positiveText(R.string.ok)
- .onPositive(((dialog, which) -> dialog.dismiss()))
- .neutralText(R.string.sync_error_dialog_report_button)
- .onNeutral(((dialog, which) -> {
- guiReportError(activity, error, dialog);
- }))
- .autoDismiss(false)
- .show();
- }
- public void guiShowErrorSnackbar(MainActivity activity, @NonNull AppError error) {
- if (error.errorCode == CODE_PROFILE_ARCHIVED) {
- guiShowArchivedDialog(activity, error.errorText);
- return;
- }
-
- // TODO: 2019-08-28
- IconicsDrawable icon = new IconicsDrawable(activity)
- .icon(CommunityMaterial.Icon.cmd_alert_circle);
- sizeDp(icon, 20);
- colorInt(icon, Themes.INSTANCE.getPrimaryTextColor(activity));
-
- error.changeIfCodeOther();
- CafeBar.builder(activity)
- .to(activity.findViewById(R.id.coordinator))
- .content(error.asReadableString(activity))
- .icon(icon)
- .positiveText(R.string.more)
- .positiveColor(0xff4caf50)
- .negativeText(R.string.ok)
- .negativeColor(0x66ffffff)
- .onPositive((cafeBar -> guiReportError(activity, error, null)))
- .onNegative((cafeBar -> cafeBar.dismiss()))
- .autoDismiss(false)
- .swipeToDismiss(true)
- .floating(true)
- .show();
- }
- public void guiReportError(Activity activity, AppError error, @Nullable MaterialDialog parentDialogToDisableNeutral) {
- String errorDetails = error.getDetails(activity);
- String htmlErrorDetails = ""+errorDetails+" ";
- htmlErrorDetails = htmlErrorDetails.replaceAll(activity.getPackageName(), ""+activity.getPackageName()+" ");
- htmlErrorDetails = htmlErrorDetails.replaceAll("\n", " ");
-
- new MaterialDialog.Builder(activity)
- .title(R.string.sync_report_dialog_title)
- .content(Html.fromHtml(htmlErrorDetails))
- .typeface(null, "RobotoMono-Regular.ttf")
- .negativeText(R.string.close)
- .onNegative(((dialog1, which1) -> dialog1.dismiss()))
- .neutralText(R.string.copy_to_clipboard)
- .onNeutral((dialog1, which1) -> {
- ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(CLIPBOARD_SERVICE);
- if (clipboard != null) {
- ClipData clip = ClipData.newPlainText("Error report", errorDetails);
- clipboard.setPrimaryClip(clip);
- Toast.makeText(activity, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show();
- }
- })
- .autoDismiss(false)
- .positiveText(R.string.sync_report_dialog_button)
- .checkBoxPromptRes(R.string.sync_report_dialog_include_api_response, true, null)
- .onPositive(((dialog1, which1) -> AsyncTask.execute(() -> error.getApiResponse(activity, apiResponse -> {
- new ServerRequest(app, app.requestScheme + APP_URL + "main.php?report", "Edziennik/Report")
- .setBodyParameter("base64_encoded", Base64.encodeToString(errorDetails.getBytes(), Base64.DEFAULT))
- .setBodyParameter("api_response", dialog1.isPromptCheckBoxChecked() ? Base64.encodeToString(apiResponse.getBytes(), Base64.DEFAULT) : "VW5jaGVja2Vk"/*Unchecked*/)
- .run((e, result) -> {
- new Handler(activity.getMainLooper()).post(() -> {
- if (result != null)
- {
- if (result.get("success").getAsBoolean()) {
- Toast.makeText(activity, activity.getString(R.string.crash_report_sent), Toast.LENGTH_SHORT).show();
- dialog1.getActionButton(DialogAction.POSITIVE).setEnabled(false);
- if (parentDialogToDisableNeutral != null)
- parentDialogToDisableNeutral.getActionButton(DialogAction.NEUTRAL).setEnabled(false);
- }
- else {
- Toast.makeText(activity, activity.getString(R.string.crash_report_cannot_send) + ": " + result.get("reason").getAsString(), Toast.LENGTH_LONG).show();
- }
- }
- else
- {
- Toast.makeText(activity, activity.getString(R.string.crash_report_cannot_send)+" brak internetu", Toast.LENGTH_LONG).show();
- }
- });
- });
- }))))
- .show();
- }
-
- /**
- * A method that displays a dialog allowing the user to report an error that has occurred.
- *
- * @param activity a parent activity
- * @param errorCode self-explanatory
- * @param errorText additional error information, that replaces text based on {@code errorCode} if it's {@code CODE_OTHER}
- * @param throwable a {@link Throwable} containing the error details
- * @param apiResponse response of the Edziennik API
- * @param parentDialogToDisableNeutral if not null, an instance of {@link MaterialDialog} in which the neutral button should be disabled after submitting an error report
- */
- public void guiReportError(Activity activity, int errorCode, String errorText, Throwable throwable, String apiResponse, @Nullable MaterialDialog parentDialogToDisableNeutral) {
- // build a string containing the stack trace and the device name + user's registration data
- String contentPlain = "Application Internal Error "+stringErrorType(errorCode)+":\n"+stringErrorCode(activity, errorCode, "")+"\n"+errorText+"\n\n";
- contentPlain += Log.getStackTraceString(throwable);
- String content = ""+contentPlain+" ";
- content = content.replaceAll(activity.getPackageName(), ""+activity.getPackageName()+" ");
- content = content.replaceAll("\n", " ");
-
- contentPlain += "\n"+Build.MANUFACTURER+"\n"+Build.BRAND+"\n"+Build.MODEL+"\n"+Build.DEVICE+"\n";
- if (app.profile != null && app.profile.getRegistration() == REGISTRATION_ENABLED) {
- contentPlain += "U: "+app.profile.getUsernameId()+"\nS: "+ app.profile.getStudentNameLong() +"\nT: "+app.profile.loginStoreType()+"\n";
- }
- contentPlain += BuildConfig.VERSION_NAME+" "+BuildConfig.BUILD_TYPE+"\nAndroid "+Build.VERSION.RELEASE;
-
- d(TAG, contentPlain);
- d(TAG, apiResponse == null ? "API Response = null" : apiResponse);
-
-
- // show a dialog containing the error details in HTML
- String finalContentPlain = contentPlain;
- new MaterialDialog.Builder(activity)
- .title(R.string.sync_report_dialog_title)
- .content(Html.fromHtml(content))
- .typeface(null, "RobotoMono-Regular.ttf")
- .negativeText(R.string.close)
- .onNegative(((dialog1, which1) -> dialog1.dismiss()))
- .neutralText(R.string.copy_to_clipboard)
- .onNeutral((dialog1, which1) -> {
- ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(CLIPBOARD_SERVICE);
- if (clipboard != null) {
- ClipData clip = ClipData.newPlainText("Error report", finalContentPlain);
- clipboard.setPrimaryClip(clip);
- Toast.makeText(activity, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show();
- }
- })
- .autoDismiss(false)
- .positiveText(R.string.sync_report_dialog_button)
- .checkBoxPromptRes(R.string.sync_report_dialog_include_api_response, true, null)
- .onPositive(((dialog1, which1) -> {
- // send the error report
- new ServerRequest(app, app.requestScheme + APP_URL + "main.php?report", "Edziennik/Report")
- .setBodyParameter("base64_encoded", Base64.encodeToString(finalContentPlain.getBytes(), Base64.DEFAULT))
- .setBodyParameter("api_response", dialog1.isPromptCheckBoxChecked() ? apiResponse == null ? Base64.encodeToString("NULL XD".getBytes(), Base64.DEFAULT) : Base64.encodeToString(apiResponse.getBytes(), Base64.DEFAULT) : "VW5jaGVja2Vk"/*Unchecked*/)
- .run((e, result) -> {
- new Handler(Looper.getMainLooper()).post(() -> {
- if (result != null)
- {
- if (result.get("success").getAsBoolean()) {
- Toast.makeText(activity, activity.getString(R.string.crash_report_sent), Toast.LENGTH_SHORT).show();
- dialog1.getActionButton(DialogAction.POSITIVE).setEnabled(false);
- if (parentDialogToDisableNeutral != null)
- parentDialogToDisableNeutral.getActionButton(DialogAction.NEUTRAL).setEnabled(false);
- }
- else {
- Toast.makeText(activity, activity.getString(R.string.crash_report_cannot_send) + ": " + result.get("reason").getAsString(), Toast.LENGTH_LONG).show();
- }
- }
- else
- {
- Toast.makeText(activity, activity.getString(R.string.crash_report_cannot_send)+" JsonObject equals null", Toast.LENGTH_LONG).show();
- }
- });
- });
- }))
- .show();
- }
-
- /* _____ __ _ _ _
- | __ \ / _(_) | | |
- | |__) | __ ___ | |_ _| | ___ _ __ ___ _ __ ___ _____ ____ _| |
- | ___/ '__/ _ \| _| | |/ _ \ | '__/ _ \ '_ ` _ \ / _ \ \ / / _` | |
- | | | | | (_) | | | | | __/ | | | __/ | | | | | (_) \ V / (_| | |
- |_| |_| \___/|_| |_|_|\___| |_| \___|_| |_| |_|\___/ \_/ \__,_|*/
- public void guiRemoveProfile(MainActivity activity, int profileId, String profileName) {
- new MaterialDialog.Builder(activity)
- .title(R.string.profile_menu_remove_confirm)
- .content(activity.getString(R.string.profile_menu_remove_confirm_text_format, profileName, profileName))
- .positiveText(R.string.remove)
- .negativeText(R.string.cancel)
- .onPositive(((dialog, which) -> {
- AsyncTask.execute(() -> {
- removeProfile(profileId);
- activity.runOnUiThread(() -> {
- //activity.drawer.loadItem(DRAWER_ITEM_HOME, null, "ProfileRemoving");
- //activity.recreate(DRAWER_ITEM_HOME);
- activity.reloadTarget();
- Toast.makeText(activity, "Profil został usunięty.", Toast.LENGTH_LONG).show();
- });
- });
- }))
- .show();
- }
- public void removeProfile(int profileId) {
- Profile profileObject = app.db.profileDao().getByIdNow(profileId);
- if (profileObject == null)
- return;
- app.db.announcementDao().clear(profileId);
- app.db.attendanceDao().clear(profileId);
- app.db.eventDao().clear(profileId);
- app.db.eventTypeDao().clear(profileId);
- app.db.gradeDao().clear(profileId);
- app.db.gradeCategoryDao().clear(profileId);
- app.db.lessonDao().clear(profileId);
- app.db.lessonChangeDao().clear(profileId);
- app.db.luckyNumberDao().clear(profileId);
- app.db.noticeDao().clear(profileId);
- app.db.subjectDao().clear(profileId);
- app.db.teacherDao().clear(profileId);
- app.db.teamDao().clear(profileId);
- app.db.messageRecipientDao().clear(profileId);
- app.db.messageDao().clear(profileId);
-
- int loginStoreId = profileObject.getLoginStoreId();
- List profilesUsingLoginStore = app.db.profileDao().getIdsByLoginStoreIdNow(loginStoreId);
- if (profilesUsingLoginStore.size() == 1) {
- app.db.loginStoreDao().remove(loginStoreId);
- }
- app.db.profileDao().remove(profileId);
- app.db.metadataDao().deleteAll(profileId);
-
- List toRemove = new ArrayList<>();
- for (Notification notification: app.appConfig.notifications) {
- if (notification.profileId == profileId) {
- toRemove.add(notification);
- }
- }
- app.appConfig.notifications.removeAll(toRemove);
-
- app.profile = null;
- App.profileId = -1;
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EdziennikNotification.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EdziennikNotification.kt
new file mode 100644
index 00000000..a78f8ab1
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EdziennikNotification.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2019-10-1.
+ */
+
+package pl.szczodrzynski.edziennik.data.api
+
+import android.app.Notification
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationCompat.PRIORITY_MIN
+import pl.szczodrzynski.edziennik.R
+import kotlin.math.roundToInt
+
+
+class EdziennikNotification(val context: Context) {
+ companion object {
+ const val NOTIFICATION_ID = 20191001
+ }
+
+ private val notificationManager by lazy { context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager }
+
+ private val notificationBuilder: NotificationCompat.Builder by lazy {
+ NotificationCompat.Builder(context, ApiService.NOTIFICATION_API_CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_notification)
+ .setPriority(PRIORITY_MIN)
+ .setOngoing(true)
+ .setLocalOnly(true)
+ }
+
+ val notification: Notification
+ get() = notificationBuilder.build()
+
+ private var errorCount = 0
+ private var criticalErrorCount = 0
+
+ private fun cancelPendingIntent(taskId: Int): PendingIntent {
+ val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
+ intent.putExtra("task", "TaskCancelRequest")
+ intent.putExtra("taskId", taskId)
+ return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
+ }
+ private val closePendingIntent: PendingIntent
+ get() {
+ val intent = Intent("pl.szczodrzynski.edziennik.SZKOLNY_MAIN")
+ intent.putExtra("task", "ServiceCloseRequest")
+ return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) as PendingIntent
+ }
+
+ private fun errorCountText(): String? {
+ var result = ""
+ if (criticalErrorCount > 0) {
+ result += context.resources.getQuantityString(R.plurals.critical_errors_format, criticalErrorCount, criticalErrorCount)
+ }
+ if (criticalErrorCount > 0 && errorCount > 0) {
+ result += ", "
+ }
+ if (errorCount > 0) {
+ result += context.resources.getQuantityString(R.plurals.normal_errors_format, errorCount, errorCount)
+ }
+ return if (result.isEmpty()) null else result
+ }
+
+ fun setIdle(): EdziennikNotification {
+ notificationBuilder.setContentTitle(context.getString(R.string.edziennik_notification_api_title))
+ notificationBuilder.setProgress(0, 0, false)
+ notificationBuilder.apply {
+ val str = context.getString(R.string.edziennik_notification_api_text)
+ setStyle(NotificationCompat.BigTextStyle().bigText(str))
+ setContentText(str)
+ }
+ setCloseAction()
+ return this
+ }
+
+ fun addError(): EdziennikNotification {
+ errorCount++
+ return this
+ }
+ fun setCriticalError(): EdziennikNotification {
+ criticalErrorCount++
+ notificationBuilder.setContentTitle(context.getString(R.string.edziennik_notification_api_error_title))
+ notificationBuilder.setProgress(0, 0, false)
+ notificationBuilder.apply {
+ val str = errorCountText()
+ setStyle(NotificationCompat.BigTextStyle().bigText(str))
+ setContentText(str)
+ }
+ setCloseAction()
+ return this
+ }
+
+ fun setProgress(progress: Float): EdziennikNotification {
+ notificationBuilder.setProgress(100, progress.roundToInt(), progress < 0f)
+ return this
+ }
+ fun setProgressText(progressText: String?): EdziennikNotification {
+ notificationBuilder.setContentTitle(progressText)
+ return this
+ }
+
+ fun setCurrentTask(taskId: Int, progressText: String?): EdziennikNotification {
+ notificationBuilder.setProgress(100, 0, true)
+ notificationBuilder.setContentTitle(progressText)
+ notificationBuilder.apply {
+ val str = errorCountText()
+ setStyle(NotificationCompat.BigTextStyle().bigText(str))
+ setContentText(str)
+ }
+ setCancelAction(taskId)
+ return this
+ }
+
+ fun setCloseAction(): EdziennikNotification {
+ notificationBuilder.mActions.clear()
+ notificationBuilder.addAction(
+ NotificationCompat.Action(
+ R.drawable.ic_notification,
+ context.getString(R.string.edziennik_notification_api_close),
+ closePendingIntent
+ ))
+ return this
+ }
+ private fun setCancelAction(taskId: Int) {
+ notificationBuilder.mActions.clear()
+ notificationBuilder.addAction(
+ NotificationCompat.Action(
+ R.drawable.ic_notification,
+ context.getString(R.string.edziennik_notification_api_cancel),
+ cancelPendingIntent(taskId)
+ ))
+ }
+
+ fun post() {
+ notificationManager.notify(NOTIFICATION_ID, notification)
+ }
+
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EndpointChooser.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EndpointChooser.kt
new file mode 100644
index 00000000..9229950a
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EndpointChooser.kt
@@ -0,0 +1,112 @@
+package pl.szczodrzynski.edziennik.data.api
+
+import pl.szczodrzynski.edziennik.data.api.models.Data
+import pl.szczodrzynski.edziennik.data.api.models.Feature
+import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
+import pl.szczodrzynski.edziennik.data.db.modules.api.EndpointTimer
+import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_NEVER
+
+fun Data.prepare(loginMethods: List, features: List, featureIds: List, viewId: Int?) {
+ val data = this
+
+ val possibleLoginMethods = data.loginMethods.toMutableList()
+
+ for (loginMethod in loginMethods) {
+ if (loginMethod.isPossible(profile, loginStore))
+ possibleLoginMethods += loginMethod.loginMethodId
+ }
+
+ //var highestLoginMethod = 0
+ var endpointList = mutableListOf()
+ val requiredLoginMethods = mutableListOf()
+
+ data.targetEndpointIds.clear()
+ data.targetLoginMethodIds.clear()
+
+ // get all endpoints for every feature, only if possible to login and possible/necessary to sync
+ for (featureId in featureIds) {
+ features.filter {
+ it.featureId == featureId // feature ID matches
+ && possibleLoginMethods.containsAll(it.requiredLoginMethods) // is possible to login
+ && it.shouldSync?.invoke(data) ?: true // is necessary/possible to sync
+ }.let {
+ endpointList.addAll(it)
+ }
+ }
+
+ val timestamp = System.currentTimeMillis()
+
+ endpointList = endpointList
+ // sort the endpoint list by feature ID and priority
+ .sortedWith(compareBy(Feature::featureId, Feature::priority))
+ // select only the most important endpoint for each feature
+ .distinctBy { it.featureId }
+ .toMutableList()
+ // add all endpoint IDs and required login methods, filtering using timers
+ .onEach { feature ->
+ feature.endpointIds.forEach { endpoint ->
+ (data.endpointTimers
+ .singleOrNull { it.endpointId == endpoint.first } ?: EndpointTimer(data.profile?.id ?: -1, endpoint.first))
+ .let { timer ->
+ if (timer.nextSync == SYNC_ALWAYS ||
+ (viewId != null && timer.viewId == viewId) ||
+ (timer.nextSync != SYNC_NEVER && timer.nextSync < timestamp)) {
+ data.targetEndpointIds.add(endpoint.first)
+ requiredLoginMethods.add(endpoint.second)
+ }
+ }
+ }
+ }
+
+ // check every login method for any dependencies
+ for (loginMethodId in requiredLoginMethods) {
+ var requiredLoginMethod: Int? = loginMethodId
+ while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
+ loginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let { loginMethod ->
+ if (requiredLoginMethod != null)
+ data.targetLoginMethodIds.add(requiredLoginMethod!!)
+ requiredLoginMethod = loginMethod.requiredLoginMethod(data.profile, data.loginStore)
+ }
+ }
+ }
+
+ // sort and distinct every login method and endpoint
+ data.targetLoginMethodIds = data.targetLoginMethodIds.toHashSet().toMutableList()
+ data.targetLoginMethodIds.sort()
+
+ data.targetEndpointIds = data.targetEndpointIds.toHashSet().toMutableList()
+ data.targetEndpointIds.sort()
+
+ progressCount = targetLoginMethodIds.size + targetEndpointIds.size
+ progressStep = if (progressCount <= 0) 0f else 100f / progressCount.toFloat()
+}
+
+fun Data.prepareFor(loginMethods: List, loginMethodId: Int) {
+ val possibleLoginMethods = this.loginMethods.toMutableList()
+
+ loginMethods.forEach {
+ if (it.isPossible(profile, loginStore))
+ possibleLoginMethods += it.loginMethodId
+ }
+
+ targetEndpointIds.clear()
+ targetLoginMethodIds.clear()
+
+ // check the login method for any dependencies
+ var requiredLoginMethod: Int? = loginMethodId
+ while (requiredLoginMethod != LOGIN_METHOD_NOT_NEEDED) {
+ loginMethods.singleOrNull { it.loginMethodId == requiredLoginMethod }?.let {
+ if (requiredLoginMethod != null)
+ targetLoginMethodIds.add(requiredLoginMethod!!)
+ requiredLoginMethod = it.requiredLoginMethod(profile, loginStore)
+ }
+ }
+
+ // sort and distinct every login method
+ targetLoginMethodIds = targetLoginMethodIds.toHashSet().toMutableList()
+ targetLoginMethodIds.sort()
+
+ progressCount = 0
+ progressStep = 0f
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt
new file mode 100644
index 00000000..2dff48ec
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2019-9-21.
+ */
+
+package pl.szczodrzynski.edziennik.data.api
+
+/*const val CODE_OTHER = 0
+const val CODE_OK = 1
+const val CODE_NO_INTERNET = 10
+const val CODE_SSL_ERROR = 13
+const val CODE_ARCHIVED = 5
+const val CODE_MAINTENANCE = 6
+const val CODE_LOGIN_ERROR = 7
+const val CODE_ACCOUNT_MISMATCH = 8
+const val CODE_APP_SERVER_ERROR = 9
+const val CODE_MULTIACCOUNT_SETUP = 12
+const val CODE_TIMEOUT = 11
+const val CODE_PROFILE_NOT_FOUND = 14
+const val CODE_ATTACHMENT_NOT_AVAILABLE = 28
+const val CODE_INVALID_LOGIN = 2
+const val CODE_INVALID_SERVER_ADDRESS = 21
+const val CODE_INVALID_SCHOOL_NAME = 22
+const val CODE_INVALID_DEVICE = 23
+const val CODE_OLD_PASSWORD = 4
+const val CODE_INVALID_TOKEN = 24
+const val CODE_EXPIRED_TOKEN = 27
+const val CODE_INVALID_SYMBOL = 25
+const val CODE_INVALID_PIN = 26
+const val CODE_LIBRUS_NOT_ACTIVATED = 29
+const val CODE_SYNERGIA_NOT_ACTIVATED = 32
+const val CODE_LIBRUS_DISCONNECTED = 31
+const val CODE_PROFILE_ARCHIVED = 30*/
+
+const val ERROR_APP_CRASH = 1
+const val ERROR_MESSAGE_NOT_SENT = 10
+
+const val ERROR_REQUEST_FAILURE = 50
+const val ERROR_REQUEST_HTTP_400 = 51
+const val ERROR_REQUEST_HTTP_401 = 52
+const val ERROR_REQUEST_HTTP_403 = 53
+const val ERROR_REQUEST_HTTP_404 = 54
+const val ERROR_REQUEST_HTTP_405 = 55
+const val ERROR_REQUEST_HTTP_410 = 56
+const val ERROR_REQUEST_HTTP_424 = 57
+const val ERROR_REQUEST_HTTP_500 = 58
+const val ERROR_REQUEST_HTTP_503 = 59
+const val ERROR_REQUEST_FAILURE_HOSTNAME_NOT_FOUND = 60
+const val ERROR_REQUEST_FAILURE_TIMEOUT = 61
+const val ERROR_REQUEST_FAILURE_NO_INTERNET = 62
+const val ERROR_REQUEST_FAILURE_SSL_ERROR = 63
+const val ERROR_RESPONSE_EMPTY = 100
+const val ERROR_LOGIN_DATA_MISSING = 101
+const val ERROR_PROFILE_MISSING = 105
+const val ERROR_INVALID_LOGIN_MODE = 110
+const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
+const val ERROR_NOT_IMPLEMENTED = 112
+const val ERROR_FILE_DOWNLOAD = 113
+
+const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115
+
+const val CODE_INTERNAL_LIBRUS_ACCOUNT_410 = 120
+const val CODE_INTERNAL_LIBRUS_SYNERGIA_EXPIRED = 121
+const val ERROR_LOGIN_LIBRUS_API_CAPTCHA_NEEDED = 124
+const val ERROR_LOGIN_LIBRUS_API_CONNECTION_PROBLEMS = 125
+const val ERROR_LOGIN_LIBRUS_API_INVALID_CLIENT = 126
+const val ERROR_LOGIN_LIBRUS_API_REG_ACCEPT_NEEDED = 127
+const val ERROR_LOGIN_LIBRUS_API_CHANGE_PASSWORD_ERROR = 128
+const val ERROR_LOGIN_LIBRUS_API_PASSWORD_CHANGE_REQUIRED = 129
+const val ERROR_LOGIN_LIBRUS_API_INVALID_LOGIN = 130
+const val ERROR_LOGIN_LIBRUS_API_OTHER = 131
+const val ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING = 132
+const val ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED = 133
+const val ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR = 134
+const val ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_TOKEN_MISSING = 139
+const val ERROR_LIBRUS_API_TOKEN_EXPIRED = 140
+const val ERROR_LIBRUS_API_INSUFFICIENT_SCOPES = 141
+const val ERROR_LIBRUS_API_OTHER = 142
+const val ERROR_LIBRUS_API_ACCESS_DENIED = 143
+const val ERROR_LIBRUS_API_RESOURCE_NOT_FOUND = 144
+const val ERROR_LIBRUS_API_DATA_NOT_FOUND = 145
+const val ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC = 146
+const val ERROR_LIBRUS_API_RESOURCE_ACCESS_DENIED = 147
+const val ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS = 148
+const val ERROR_LIBRUS_API_INCORRECT_ENDPOINT = 149
+const val ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE = 150
+const val ERROR_LIBRUS_API_NOTES_NOT_ACTIVE = 151
+const val ERROR_LOGIN_LIBRUS_SYNERGIA_NO_TOKEN = 152
+const val ERROR_LOGIN_LIBRUS_SYNERGIA_TOKEN_INVALID = 153
+const val ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID = 154
+const val ERROR_LIBRUS_MESSAGES_ACCESS_DENIED = 155
+const val ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED = 156
+const val ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID = 157
+const val ERROR_LIBRUS_PORTAL_ACCESS_DENIED = 158
+const val ERROR_LIBRUS_PORTAL_API_DISABLED = 159
+const val ERROR_LIBRUS_PORTAL_SYNERGIA_DISCONNECTED = 160
+const val ERROR_LIBRUS_PORTAL_OTHER = 161
+const val ERROR_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND = 162
+const val ERROR_LOGIN_LIBRUS_PORTAL_OTHER = 163
+const val ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED = 164
+const val ERROR_LOGIN_LIBRUS_PORTAL_CODE_REVOKED = 165
+const val ERROR_LOGIN_LIBRUS_PORTAL_NO_CLIENT_ID = 166
+const val ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE = 167
+const val ERROR_LOGIN_LIBRUS_PORTAL_NO_REFRESH = 168
+const val ERROR_LOGIN_LIBRUS_PORTAL_NO_REDIRECT = 169
+const val ERROR_LOGIN_LIBRUS_PORTAL_UNSUPPORTED_GRANT = 170
+const val ERROR_LOGIN_LIBRUS_PORTAL_INVALID_CLIENT_ID = 171
+const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID = 172
+const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED = 173
+const val ERROR_LIBRUS_SYNERGIA_OTHER = 174
+const val ERROR_LIBRUS_SYNERGIA_MAINTENANCE = 175
+const val ERROR_LIBRUS_MESSAGES_MAINTENANCE = 176
+const val ERROR_LIBRUS_MESSAGES_ERROR = 177
+const val ERROR_LIBRUS_MESSAGES_OTHER = 178
+const val ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN = 179
+const val ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN = 180
+const val ERROR_LIBRUS_API_MAINTENANCE = 181
+const val ERROR_LIBRUS_PORTAL_MAINTENANCE = 182
+
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_DEVICE = 203
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_ARCHIVED = 204
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_MAINTENANCE = 205
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_ADDRESS = 206
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OTHER = 210
+const val ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED = 211
+const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY = 212
+const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE = 216
+const val ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID = 213
+const val ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE = 214
+const val ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID = 215
+
+const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301
+const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302
+const val ERROR_LOGIN_VULCAN_INVALID_PIN = 309
+const val ERROR_LOGIN_VULCAN_INVALID_PIN_0_REMAINING = 310
+const val ERROR_LOGIN_VULCAN_INVALID_PIN_1_REMAINING = 311
+const val ERROR_LOGIN_VULCAN_INVALID_PIN_2_REMAINING = 312
+const val ERROR_LOGIN_VULCAN_EXPIRED_TOKEN = 321
+const val ERROR_LOGIN_VULCAN_OTHER = 322
+const val ERROR_LOGIN_VULCAN_ONLY_KINDERGARTEN = 330
+const val ERROR_LOGIN_VULCAN_NO_PUPILS = 331
+const val ERROR_VULCAN_API_MAINTENANCE = 340
+const val ERROR_VULCAN_API_BAD_REQUEST = 341
+const val ERROR_VULCAN_API_OTHER = 342
+
+const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_LOGIN = 401
+const val ERROR_LOGIN_IDZIENNIK_WEB_INVALID_SCHOOL_NAME = 402
+const val ERROR_LOGIN_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED = 403
+const val ERROR_LOGIN_IDZIENNIK_WEB_MAINTENANCE = 404
+const val ERROR_LOGIN_IDZIENNIK_WEB_SERVER_ERROR = 405
+const val ERROR_LOGIN_IDZIENNIK_WEB_OTHER = 410
+const val ERROR_LOGIN_IDZIENNIK_WEB_API_NO_ACCESS = 411 /* {"d":{"__type":"mds.Web.mod_komunikator.WS_mod_wiadomosci+detailWiadomosci","Wiadomosc":{"_recordId":0,"DataNadania":null,"DataOdczytania":null,"Nadawca":null,"ListaOdbiorcow":[],"Tytul":null,"Text":null,"ListaZal":[]},"Bledy":{"__type":"mds.Module.Globalne+sBledy","CzyJestBlad":true,"ListaBledow":["Nie masz dostępu do tych zasobów!"],"ListaKodowBledow":[]},"czyJestWiecej":false}} */
+const val ERROR_LOGIN_IDZIENNIK_WEB_NO_SESSION = 420
+const val ERROR_LOGIN_IDZIENNIK_WEB_NO_AUTH = 421
+const val ERROR_LOGIN_IDZIENNIK_WEB_NO_BEARER = 422
+const val ERROR_IDZIENNIK_WEB_ACCESS_DENIED = 430
+const val ERROR_IDZIENNIK_WEB_OTHER = 431
+const val ERROR_IDZIENNIK_WEB_MAINTENANCE = 432
+const val ERROR_IDZIENNIK_WEB_SERVER_ERROR = 433
+const val ERROR_IDZIENNIK_WEB_PASSWORD_CHANGE_NEEDED = 434
+const val ERROR_LOGIN_IDZIENNIK_FIRST_NO_SCHOOL_YEAR = 440
+const val ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA = 441
+const val ERROR_IDZIENNIK_API_ACCESS_DENIED = 450
+const val ERROR_IDZIENNIK_API_OTHER = 451
+const val ERROR_IDZIENNIK_API_NO_REGISTER = 452
+
+const val ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN = 501
+const val ERROR_LOGIN_EDUDZIENNIK_WEB_OTHER = 510
+const val ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID = 511
+const val ERROR_EDUDZIENNIK_WEB_TIMETABLE_NOT_PUBLIC = 520
+const val ERROR_EDUDZIENNIK_WEB_LIMITED_ACCESS = 521
+const val ERROR_EDUDZIENNIK_WEB_SESSION_EXPIRED = 522
+const val ERROR_EDUDZIENNIK_WEB_TEAM_MISSING = 530
+
+const val ERROR_TEMPLATE_WEB_OTHER = 801
+
+const val EXCEPTION_API_TASK = 900
+const val EXCEPTION_LOGIN_LIBRUS_API_TOKEN = 901
+const val EXCEPTION_LOGIN_LIBRUS_PORTAL_TOKEN = 902
+const val EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN = 903
+const val EXCEPTION_LIBRUS_API_REQUEST = 904
+const val EXCEPTION_LIBRUS_SYNERGIA_REQUEST = 905
+const val EXCEPTION_MOBIDZIENNIK_WEB_REQUEST = 906
+const val EXCEPTION_VULCAN_API_REQUEST = 907
+const val EXCEPTION_MOBIDZIENNIK_WEB_FILE_REQUEST = 908
+const val EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST = 909
+const val EXCEPTION_NOTIFY = 910
+const val EXCEPTION_LIBRUS_MESSAGES_REQUEST = 911
+const val EXCEPTION_IDZIENNIK_WEB_REQUEST = 912
+const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913
+const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
+const val EXCEPTION_EDUDZIENNIK_WEB_REQUEST = 920
+const val EXCEPTION_EDUDZIENNIK_FILE_REQUEST = 921
+
+const val LOGIN_NO_ARGUMENTS = 1201
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt
new file mode 100644
index 00000000..40f24048
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2019-9-29.
+ */
+
+package pl.szczodrzynski.edziennik.data.api
+
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ANNOUNCEMENTS
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ATTENDANCE
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_BEHAVIOUR
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_GRADES
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOME
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
+import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
+import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
+import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT
+
+internal const val FEATURE_TIMETABLE = 1
+internal const val FEATURE_AGENDA = 2
+internal const val FEATURE_GRADES = 3
+internal const val FEATURE_HOMEWORK = 4
+internal const val FEATURE_BEHAVIOUR = 5
+internal const val FEATURE_ATTENDANCE = 6
+internal const val FEATURE_MESSAGES_INBOX = 7
+internal const val FEATURE_MESSAGES_SENT = 8
+internal const val FEATURE_ANNOUNCEMENTS = 9
+
+internal const val FEATURE_ALWAYS_NEEDED = 100
+internal const val FEATURE_STUDENT_INFO = 101
+internal const val FEATURE_STUDENT_NUMBER = 109
+internal const val FEATURE_SCHOOL_INFO = 102
+internal const val FEATURE_CLASS_INFO = 103
+internal const val FEATURE_TEAM_INFO = 104
+internal const val FEATURE_LUCKY_NUMBER = 105
+internal const val FEATURE_TEACHERS = 106
+internal const val FEATURE_SUBJECTS = 107
+internal const val FEATURE_CLASSROOMS = 108
+internal const val FEATURE_PUSH_CONFIG = 120
+
+object Features {
+ private fun getAllNecessary(): List = listOf(
+ FEATURE_ALWAYS_NEEDED,
+ FEATURE_STUDENT_INFO,
+ FEATURE_STUDENT_NUMBER,
+ FEATURE_SCHOOL_INFO,
+ FEATURE_CLASS_INFO,
+ FEATURE_TEAM_INFO,
+ FEATURE_LUCKY_NUMBER,
+ FEATURE_TEACHERS,
+ FEATURE_SUBJECTS,
+ FEATURE_CLASSROOMS)
+
+ private fun getAllFeatures(): List = listOf(
+ FEATURE_TIMETABLE,
+ FEATURE_AGENDA,
+ FEATURE_GRADES,
+ FEATURE_HOMEWORK,
+ FEATURE_BEHAVIOUR,
+ FEATURE_ATTENDANCE,
+ FEATURE_MESSAGES_INBOX,
+ FEATURE_MESSAGES_SENT,
+ FEATURE_ANNOUNCEMENTS)
+
+ fun getAllIds(): List = getAllFeatures() + getAllNecessary()
+
+ fun getIdsByView(targetId: Int, targetType: Int): List {
+ return (when (targetId) {
+ DRAWER_ITEM_HOME -> getAllFeatures()
+ DRAWER_ITEM_TIMETABLE -> listOf(FEATURE_TIMETABLE)
+ DRAWER_ITEM_AGENDA -> listOf(FEATURE_AGENDA)
+ DRAWER_ITEM_GRADES -> listOf(FEATURE_GRADES)
+ DRAWER_ITEM_MESSAGES -> when (targetType) {
+ TYPE_RECEIVED -> listOf(FEATURE_MESSAGES_INBOX)
+ TYPE_SENT -> listOf(FEATURE_MESSAGES_SENT)
+ else -> listOf(FEATURE_MESSAGES_INBOX, FEATURE_MESSAGES_SENT)
+ }
+ DRAWER_ITEM_HOMEWORK -> listOf(FEATURE_HOMEWORK)
+ DRAWER_ITEM_BEHAVIOUR -> listOf(FEATURE_BEHAVIOUR)
+ DRAWER_ITEM_ATTENDANCE -> listOf(FEATURE_ATTENDANCE)
+ DRAWER_ITEM_ANNOUNCEMENTS -> listOf(FEATURE_ANNOUNCEMENTS)
+ else -> getAllFeatures()
+ } + getAllNecessary()).sorted()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Iuczniowie.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Iuczniowie.java
deleted file mode 100644
index 33c69671..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Iuczniowie.java
+++ /dev/null
@@ -1,1710 +0,0 @@
-package pl.szczodrzynski.edziennik.data.api;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.util.Pair;
-
-import com.crashlytics.android.Crashlytics;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonNull;
-import com.google.gson.JsonObject;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import im.wangchao.mhttp.Request;
-import im.wangchao.mhttp.Response;
-import im.wangchao.mhttp.body.MediaTypeUtils;
-import im.wangchao.mhttp.callback.JsonArrayCallbackHandler;
-import im.wangchao.mhttp.callback.JsonCallbackHandler;
-import im.wangchao.mhttp.callback.TextCallbackHandler;
-import okhttp3.Cookie;
-import okhttp3.HttpUrl;
-import pl.szczodrzynski.edziennik.App;
-import pl.szczodrzynski.edziennik.BuildConfig;
-import pl.szczodrzynski.edziennik.R;
-import pl.szczodrzynski.edziennik.data.api.interfaces.AttachmentGetCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface;
-import pl.szczodrzynski.edziennik.data.api.interfaces.LoginCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.MessageGetCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.RecipientListGetCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.SyncCallback;
-import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement;
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance;
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event;
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade;
-import pl.szczodrzynski.edziennik.data.db.modules.lessons.Lesson;
-import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange;
-import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore;
-import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull;
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata;
-import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice;
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
-import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject;
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher;
-import pl.szczodrzynski.edziennik.data.db.modules.teams.Team;
-import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeInfo;
-import pl.szczodrzynski.edziennik.utils.models.Date;
-import pl.szczodrzynski.edziennik.utils.models.Endpoint;
-import pl.szczodrzynski.edziennik.utils.models.Time;
-import pl.szczodrzynski.edziennik.utils.models.Week;
-
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_INVALID_LOGIN;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_INVALID_SCHOOL_NAME;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_MAINTENANCE;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_OTHER;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_ABSENT;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_ABSENT_EXCUSED;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_BELATED;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_PRESENT;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_RELEASED;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_FINAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_FINAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED;
-import static pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CANCELLED;
-import static pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CHANGE;
-import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_DELETED;
-import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED;
-import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT;
-import static pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.TYPE_NEGATIVE;
-import static pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.TYPE_NEUTRAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.TYPE_POSITIVE;
-import static pl.szczodrzynski.edziennik.utils.Utils.crc16;
-import static pl.szczodrzynski.edziennik.utils.Utils.crc32;
-import static pl.szczodrzynski.edziennik.utils.Utils.d;
-import static pl.szczodrzynski.edziennik.utils.Utils.getWordGradeValue;
-
-public class Iuczniowie implements EdziennikInterface {
- public Iuczniowie(App app) {
- this.app = app;
- }
-
- private static final String TAG = "api.Iuczniowie";
- private static String IDZIENNIK_URL = "https://iuczniowie.progman.pl/idziennik";
- private static final String userAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36";
-
- private App app;
- private Context activityContext = null;
- private SyncCallback callback = null;
- private int profileId = -1;
- private Profile profile = null;
- private LoginStore loginStore = null;
- private boolean fullSync = true;
- private Date today = Date.getToday();
- private List targetEndpoints = new ArrayList<>();
-
- // PROGRESS
- private static final int PROGRESS_LOGIN = 10;
- private int PROGRESS_COUNT = 1;
- private int PROGRESS_STEP = (90/PROGRESS_COUNT);
-
- private int onlyFeature = FEATURE_ALL;
-
- private List teamList;
- private List teacherList;
- private List subjectList;
- private List lessonList;
- private List lessonChangeList;
- private List gradeList;
- private List eventList;
- private List noticeList;
- private List attendanceList;
- private List announcementList;
- private List messageList;
- private List messageRecipientList;
- private List messageRecipientIgnoreList;
- private List metadataList;
- private List messageMetadataList;
-
- private static boolean fakeLogin = false;
- private String lastLogin = "";
- private long lastLoginTime = -1;
- private String lastResponse = null;
- private String loginSchoolName = null;
- private String loginUsername = null;
- private String loginPassword = null;
- private String loginBearerToken = null;
- private int loginRegisterId = -1;
- private int loginSchoolYearId = -1;
- private String loginStudentId = null;
- private int teamClassId = -1;
-
- private boolean prepare(@NonNull Context activityContext, @NonNull SyncCallback callback, int profileId, @Nullable Profile profile, @NonNull LoginStore loginStore) {
- this.activityContext = activityContext;
- this.callback = callback;
- this.profileId = profileId;
- // here we must have a login store: either with a correct ID or -1
- // there may be no profile and that's when onLoginFirst happens
- this.profile = profile;
- this.loginStore = loginStore;
- this.fullSync = profile == null || profile.getEmpty() || profile.shouldFullSync(activityContext);
- this.today = Date.getToday();
-
- this.loginSchoolName = loginStore.getLoginData("schoolName", "");
- this.loginUsername = loginStore.getLoginData("username", "");
- this.loginPassword = loginStore.getLoginData("password", "");
- if (loginSchoolName.equals("") || loginUsername.equals("") || loginPassword.equals("")) {
- finishWithError(new AppError(TAG, 162, CODE_INVALID_LOGIN, "Login field is empty"));
- return false;
- }
- fakeLogin = BuildConfig.DEBUG && loginUsername.startsWith("FAKE");
- IDZIENNIK_URL = fakeLogin ? "http://szkolny.eu/idziennik" : "https://iuczniowie.progman.pl/idziennik";
-
- teamList = profileId == -1 ? new ArrayList<>() : app.db.teamDao().getAllNow(profileId);
- teacherList = profileId == -1 ? new ArrayList<>() : app.db.teacherDao().getAllNow(profileId);
- subjectList = profileId == -1 ? new ArrayList<>() : app.db.subjectDao().getAllNow(profileId);
- lessonList = new ArrayList<>();
- lessonChangeList = new ArrayList<>();
- gradeList = new ArrayList<>();
- eventList = new ArrayList<>();
- noticeList = new ArrayList<>();
- attendanceList = new ArrayList<>();
- announcementList = new ArrayList<>();
- messageList = new ArrayList<>();
- messageRecipientList = new ArrayList<>();
- messageRecipientIgnoreList = new ArrayList<>();
- metadataList = new ArrayList<>();
- messageMetadataList = new ArrayList<>();
-
- return true;
- }
-
- @Override
- public void sync(@NonNull Context activityContext, @NonNull SyncCallback callback, int profileId, @Nullable Profile profile, @NonNull LoginStore loginStore) {
- if (!prepare(activityContext, callback, profileId, profile, loginStore))
- return;
-
- login(() -> {
- targetEndpoints = new ArrayList<>();
- targetEndpoints.add("LuckyNumberAndSemesterDates");
- targetEndpoints.add("Timetable");
- targetEndpoints.add("Grades");
- targetEndpoints.add("PropositionGrades");
- targetEndpoints.add("Exams");
- targetEndpoints.add("Notices");
- targetEndpoints.add("Announcements");
- targetEndpoints.add("Attendance");
- targetEndpoints.add("MessagesInbox");
- targetEndpoints.add("MessagesOutbox");
- targetEndpoints.add("Finish");
- PROGRESS_COUNT = targetEndpoints.size()-1;
- PROGRESS_STEP = (90/PROGRESS_COUNT);
- begin();
- });
- }
- @Override
- public void syncFeature(@NonNull Context activityContext, @NonNull SyncCallback callback, @NonNull ProfileFull profile, int ... featureList) {
- if (featureList == null) {
- sync(activityContext, callback, profile.getId(), profile, LoginStore.fromProfileFull(profile));
- return;
- }
- if (!prepare(activityContext, callback, profile.getId(), profile, LoginStore.fromProfileFull(profile)))
- return;
-
- login(() -> {
- targetEndpoints = new ArrayList<>();
- if (featureList.length == 1)
- onlyFeature = featureList[0];
- targetEndpoints.add("LuckyNumberAndSemesterDates");
- for (int feature: featureList) {
- switch (feature) {
- case FEATURE_TIMETABLE:
- targetEndpoints.add("Timetable");
- break;
- case FEATURE_AGENDA:
- targetEndpoints.add("Exams");
- break;
- case FEATURE_GRADES:
- targetEndpoints.add("Grades");
- targetEndpoints.add("PropositionGrades");
- break;
- case FEATURE_HOMEWORK:
- targetEndpoints.add("Homework");
- break;
- case FEATURE_NOTICES:
- targetEndpoints.add("Notices");
- break;
- case FEATURE_ATTENDANCE:
- targetEndpoints.add("Attendance");
- break;
- case FEATURE_MESSAGES_INBOX:
- targetEndpoints.add("MessagesInbox");
- break;
- case FEATURE_MESSAGES_OUTBOX:
- targetEndpoints.add("MessagesOutbox");
- break;
- case FEATURE_ANNOUNCEMENTS:
- targetEndpoints.add("Announcements");
- break;
- }
- }
- targetEndpoints.add("Finish");
- PROGRESS_COUNT = targetEndpoints.size()-1;
- PROGRESS_STEP = (90/PROGRESS_COUNT);
- begin();
- });
- }
-
- private void begin() {
- List cookieList = app.cookieJar.loadForRequest(HttpUrl.get(IDZIENNIK_URL));
- for (Cookie cookie: cookieList) {
- if (cookie.name().equalsIgnoreCase("Bearer")) {
- loginBearerToken = cookie.value();
- }
- }
- loginStudentId = profile.getStudentData("studentId", null);
- loginSchoolYearId = profile.getStudentData("schoolYearId", -1);
- loginRegisterId = profile.getStudentData("registerId", -1);
-
- if (loginRegisterId == -1) {
- finishWithError(new AppError(TAG, 212, CODE_OTHER, app.getString(R.string.error_register_id_not_found), "loginRegisterId == -1"));
- return;
- }
- if (loginSchoolYearId == -1) {
- finishWithError(new AppError(TAG, 216, CODE_OTHER, app.getString(R.string.error_school_year_not_found), "loginSchoolYearId == -1"));
- return;
- }
- if (loginStudentId == null) {
- if (lastResponse == null) {
- lastLoginTime = -1;
- lastLogin = "";
- finishWithError(new AppError(TAG, 223, CODE_OTHER, app.getString(R.string.error_student_id_not_found), "loginStudentId == null && lastResponse == null"));
- return;
- }
- Matcher selectMatcher = Pattern.compile("", Pattern.DOTALL).matcher(lastResponse);
- if (!selectMatcher.find()) {
- finishWithError(new AppError(TAG, 228, CODE_OTHER, app.getString(R.string.error_register_id_not_found), lastResponse));
- return;
- }
- Matcher idMatcher = Pattern.compile(".*?", Pattern.DOTALL).matcher(selectMatcher.group(0));
- while (idMatcher.find()) {
- loginStudentId = idMatcher.group(1);
- profile.putStudentData("studentId", loginStudentId);
- }
- }
-
- this.attendanceMonth = today.month;
- this.attendanceYear = today.year;
- this.attendancePrevMonthChecked = false;
- this.examsMonth = today.month;
- this.examsYear = today.year;
- this.examsMonthsChecked = 0;
- this.examsNextMonthChecked = false;
-
- callback.onProgress(PROGRESS_LOGIN);
-
- r("get", null);
- }
-
- private void r(String type, String endpoint) {
- // endpoint == null when beginning
- if (endpoint == null)
- endpoint = targetEndpoints.get(0);
- int index = -1;
- for (String request: targetEndpoints) {
- index++;
- if (request.equals(endpoint)) {
- break;
- }
- }
- if (type.equals("finish")) {
- // called when finishing the action
- callback.onProgress(PROGRESS_STEP);
- index++;
- }
- d(TAG, "Called r("+type+", "+endpoint+"). Getting "+targetEndpoints.get(index));
- switch (targetEndpoints.get(index)) {
- case "LuckyNumberAndSemesterDates":
- getLuckyNumberAndSemesterDates();
- break;
- case "Timetable":
- getTimetable();
- break;
- case "Grades":
- getGrades();
- break;
- case "PropositionGrades":
- getPropositionGrades();
- break;
- case "Exams":
- getExams();
- break;
- case "Notices":
- getNotices();
- break;
- case "Announcements":
- getAnnouncements();
- break;
- case "Attendance":
- getAttendance();
- break;
- case "MessagesInbox":
- getMessagesInbox();
- break;
- case "MessagesOutbox":
- getMessagesOutbox();
- break;
- case "Finish":
- finish();
- break;
- }
- }
- private void saveData() {
- if (teamList.size() > 0) {
- //app.db.teamDao().clear(profileId);
- app.db.teamDao().addAll(teamList);
- }
- if (teacherList.size() > 0)
- app.db.teacherDao().addAll(teacherList);
- if (subjectList.size() > 0)
- app.db.subjectDao().addAll(subjectList);
- if (lessonList.size() > 0) {
- app.db.lessonDao().clear(profileId);
- app.db.lessonDao().addAll(lessonList);
- }
- if (lessonChangeList.size() > 0)
- app.db.lessonChangeDao().addAll(lessonChangeList);
- if (gradeList.size() > 0) {
- app.db.gradeDao().clear(profileId);
- app.db.gradeDao().addAll(gradeList);
- }
- if (eventList.size() > 0) {
- app.db.eventDao().removeFuture(profileId, today);
- app.db.eventDao().addAll(eventList);
- }
- if (noticeList.size() > 0) {
- app.db.noticeDao().clear(profileId);
- app.db.noticeDao().addAll(noticeList);
- }
- if (attendanceList.size() > 0)
- app.db.attendanceDao().addAll(attendanceList);
- if (announcementList.size() > 0)
- app.db.announcementDao().addAll(announcementList);
- if (messageList.size() > 0)
- app.db.messageDao().addAllIgnore(messageList);
- if (messageRecipientList.size() > 0)
- app.db.messageRecipientDao().addAll(messageRecipientList);
- if (messageRecipientIgnoreList.size() > 0)
- app.db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList);
- if (metadataList.size() > 0)
- app.db.metadataDao().addAllIgnore(metadataList);
- if (messageMetadataList.size() > 0)
- app.db.metadataDao().setSeen(messageMetadataList);
- }
- private void finish() {
- try {
- saveData();
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 363, CODE_OTHER, app.getString(R.string.sync_error_saving_data), null, null, e, null));
- }
- if (fullSync) {
- profile.setLastFullSync(System.currentTimeMillis());
- fullSync = false;
- }
- profile.setEmpty(false);
- callback.onSuccess(activityContext, new ProfileFull(profile, loginStore));
- }
- private void finishWithError(AppError error) {
- try {
- saveData();
- }
- catch (Exception e) {
- Crashlytics.logException(e);
- }
- callback.onError(activityContext, error);
- }
-
- /* _ _
- | | (_)
- | | ___ __ _ _ _ __
- | | / _ \ / _` | | '_ \
- | |___| (_) | (_| | | | | |
- |______\___/ \__, |_|_| |_|
- __/ |
- |__*/
- private void login(@NonNull LoginCallback loginCallback) {
- if (lastLogin.equals(loginSchoolName +":"+ loginUsername)
- && System.currentTimeMillis() - lastLoginTime < 5 * 60 * 1000
- && profile != null) { // less than 5 minutes, use the already logged in account
- loginCallback.onSuccess();
- return;
- }
- app.cookieJar.clearForDomain("iuczniowie.progman.pl");
- callback.onActionStarted(R.string.sync_action_logging_in);
- Request.builder()
- .url(IDZIENNIK_URL +"/login.aspx")
- .userAgent(userAgent)
- .callback(new TextCallbackHandler() {
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 389, CODE_OTHER, response, throwable));
- }
-
- @Override
- public void onSuccess(String data1, Response response1) {
- if (data1 == null || data1.equals("")) { // for safety
- finishWithError(new AppError(TAG, 395, CODE_MAINTENANCE, response1));
- return;
- }
- //Log.d(TAG, "r:"+data);
- Request.Builder builder = Request.builder()
- .url(IDZIENNIK_URL +"/login.aspx")
- .userAgent(userAgent)
- //.withClient(app.httpLazy)
- .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/png,*/*;q=0.8")
- .addHeader("Cache-Control", "max-age=0")
- .addHeader("Origin", "https://iuczniowie.progman.pl")
- .addHeader("Referer", "https://iuczniowie.progman.pl/idziennik/login.aspx")
- .addHeader("Upgrade-Insecure-Requests", "1")
- .contentType(MediaTypeUtils.APPLICATION_FORM)
- .addParameter("ctl00$ContentPlaceHolder$nazwaPrzegladarki", userAgent)
- .addParameter("ctl00$ContentPlaceHolder$NazwaSzkoly", loginSchoolName)
- .addParameter("ctl00$ContentPlaceHolder$UserName", loginUsername)
- .addParameter("ctl00$ContentPlaceHolder$Password", loginPassword)
- .addParameter("ctl00$ContentPlaceHolder$captcha", "")
- .addParameter("ctl00$ContentPlaceHolder$Logowanie", "Zaloguj")
- .post();
-
- // extract hidden form fields __VIEWSTATE __VIEWSTATEGENERATOR __EVENTVALIDATION
- //Pattern pattern = Pattern.compile("<.+?name=\"__VIEWSTATE\".+?value=\"([A-z0-9+/=]+)\".+?name=\"__VIEWSTATEGENERATOR\".+?value=\"([A-z0-9+/=]+)\".+?name=\"__EVENTVALIDATION\".+?value=\"([A-z0-9+/=]+)\".+?>", Pattern.DOTALL);
- //Pattern pattern = Pattern.compile(" ]* name=[\"']([^'\"]*)|)(?=[^>]* value=[\"']([^'\"]*)|)", Pattern.DOTALL);
- Pattern pattern = Pattern.compile(" ", Pattern.DOTALL);
- Matcher matcher = pattern.matcher(data1);
- while (matcher.find()) {
- //Log.d(TAG, "Match: "+matcher.group(1)+"="+matcher.group(2));
- builder.addParameter(matcher.group(1), matcher.group(2));
- }
-
- builder.callback(new TextCallbackHandler() {
- @Override
- public void onSuccess(String data2, Response response2) {
- callback.onProgress(PROGRESS_LOGIN);
- Pattern errorPattern = Pattern.compile("id=\"spanErrorMessage\">(.*?)", Pattern.DOTALL);
- Matcher errorMatcher = errorPattern.matcher(data2);
- if (errorMatcher.find()) {
- String error = errorMatcher.group(1);
- d(TAG, errorMatcher.group(0));
- if (error.equals("")) {
- finishWithError(new AppError(TAG, 443, CODE_MAINTENANCE, error, response2, data2));
- return;
- }
- if (error.contains("nieprawidłową nazwę szkoły")) {
- finishWithError(new AppError(TAG, 447, CODE_INVALID_SCHOOL_NAME, error, response2, data2));
- return;
- }
- if (error.contains("nieprawidłowy login lub hasło")) {
- finishWithError(new AppError(TAG, 451, AppError.CODE_INVALID_LOGIN, error, response2, data2));
- return;
- }
- finishWithError(new AppError(TAG, 454, CODE_OTHER, error, response2, data2));
- return;
- }
-
- // a successful login
-
- lastLogin = loginSchoolName +":"+ loginUsername;
- lastLoginTime = System.currentTimeMillis();
- lastResponse = data2;
-
- // HERE we decide if it's the first login
- // if it is, let's search for students and return them in onLoginFirst
- // else, let's continue syncing having the profile object
- if (profile != null) {
- loginRegisterId = profile.getStudentData("registerId", -1);
- loginSchoolYearId = profile.getStudentData("schoolYearId", -1);
- loginStudentId = profile.getStudentData("studentId", null);
- Matcher selectMatcher = Pattern.compile("", Pattern.DOTALL).matcher(data2);
- if (!selectMatcher.find()) {
- finishWithError(new AppError(TAG, 473, CODE_OTHER, app.getString(R.string.error_register_id_not_found), response2, data2));
- return;
- }
- Log.d(TAG, "g" + selectMatcher.group(0));
- Matcher idMatcher = Pattern.compile("(.+?)\\s(.+?)\\s*\\((.+?),\\s*(.+?)\\)", Pattern.DOTALL).matcher(selectMatcher.group(0));
- while (idMatcher.find()) {
- if (loginRegisterId != Integer.parseInt(idMatcher.group(1)))
- continue;
- String teamClassName = idMatcher.group(4) + " " + idMatcher.group(5);
- teamClassId = crc16(teamClassName.getBytes());
- app.db.teamDao().add(new Team(
- profileId,
- teamClassId,
- teamClassName,
- 1,
- loginSchoolName+":"+teamClassName,
- -1
- ));
- }
- loginCallback.onSuccess();
- return;
- }
- try {
- Matcher yearMatcher = Pattern.compile("name=\"ctl00\\$dxComboRokSzkolny\".+?selected=\"selected\".*?value=\"([0-9]+)\"", Pattern.DOTALL).matcher(data2);
- if (yearMatcher.find()) {
- try {
- loginSchoolYearId = Integer.parseInt(yearMatcher.group(1));
- } catch (Exception ex) {
- finishWithError(new AppError(TAG, 501, CODE_OTHER, response2, ex, data2));
- return;
- }
- } else {
- if (data2.contains("Hasło dostępu do systemu wygasło")) {
- finishWithError(new AppError(TAG, 504, CODE_OTHER, app.getString(R.string.error_must_change_password), response2, data2));
- return;
- }
- finishWithError(new AppError(TAG, 507, CODE_OTHER, app.getString(R.string.error_school_year_not_found), response2, data2));
- return;
- }
-
- List studentIds = new ArrayList<>();
- List registerIds = new ArrayList<>();
- List studentNamesLong = new ArrayList<>();
- List studentNamesShort = new ArrayList<>();
- List studentTeams = new ArrayList<>();
-
- Matcher selectMatcher = Pattern.compile("", Pattern.DOTALL).matcher(data2);
- if (!selectMatcher.find()) {
- finishWithError(new AppError(TAG, 519, CODE_OTHER, app.getString(R.string.error_register_id_not_found), response2, data2));
- return;
- }
- Log.d(TAG, "g" + selectMatcher.group(0));
- Matcher idMatcher = Pattern.compile("(.+?)\\s(.+?)\\s*\\((.+?),\\s*(.+?)\\)", Pattern.DOTALL).matcher(selectMatcher.group(0));
- while (idMatcher.find()) {
- registerIds.add(Integer.parseInt(idMatcher.group(1)));
- String studentId = idMatcher.group(2);
- String studentFirstName = idMatcher.group(3);
- String studentLastName = idMatcher.group(4);
- String teamClassName = idMatcher.group(5) + " " + idMatcher.group(6);
- studentIds.add(studentId);
- studentNamesLong.add(studentFirstName + " " + studentLastName);
- studentNamesShort.add(studentFirstName + " " + studentLastName.charAt(0) + ".");
- studentTeams.add(teamClassName);
- }
- Collections.reverse(studentIds);
- Collections.reverse(registerIds);
- Collections.reverse(studentNamesLong);
- Collections.reverse(studentNamesShort);
- Collections.reverse(studentTeams);
-
- List profileList = new ArrayList<>();
- for (int index = 0; index < registerIds.size(); index++) {
- Profile newProfile = new Profile();
- newProfile.setStudentNameLong(studentNamesLong.get(index));
- newProfile.setStudentNameShort(studentNamesShort.get(index));
- newProfile.setName(newProfile.getStudentNameLong());
- newProfile.setSubname(loginUsername);
- newProfile.setEmpty(true);
- newProfile.setLoggedIn(true);
- newProfile.putStudentData("studentId", studentIds.get(index));
- newProfile.putStudentData("registerId", registerIds.get(index));
- newProfile.putStudentData("schoolYearId", loginSchoolYearId);
- profileList.add(newProfile);
- }
-
- callback.onLoginFirst(profileList, loginStore);
- } catch (Exception ex) {
- finishWithError(new AppError(TAG, 557, CODE_OTHER, response2, ex, data2));
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 563, CODE_OTHER, response, throwable, data1));
- }
- }).build().enqueue();
- }
- }).build().enqueue();
- }
-
- /* _ _ _ _ _ _ _
- | | | | | | ___ | | | | | |
- | |__| | ___| |_ __ ___ _ __ ___ ( _ ) ___ __ _| | | |__ __ _ ___| | _____
- | __ |/ _ \ | '_ \ / _ \ '__/ __| / _ \/\ / __/ _` | | | '_ \ / _` |/ __| |/ / __|
- | | | | __/ | |_) | __/ | \__ \ | (_> < | (_| (_| | | | |_) | (_| | (__| <\__ \
- |_| |_|\___|_| .__/ \___|_| |___/ \___/\/ \___\__,_|_|_|_.__/ \__,_|\___|_|\_\___/
- | |
- |*/
- private interface ApiRequestCallback {
- void onSuccess(JsonObject result, Response response);
- }
- private void apiRequest(Request.Builder requestBuilder, ApiRequestCallback apiRequestCallback) {
- requestBuilder.callback(new JsonCallbackHandler() {
- @Override
- public void onSuccess(JsonObject data, Response response) {
- if (data == null) {
- finishWithError(new AppError(TAG, 578, CODE_MAINTENANCE, response));
- return;
- }
- try {
- apiRequestCallback.onSuccess(data, response);
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 583, CODE_OTHER, response, e, data));
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 592, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
- private interface ApiRequestArrayCallback {
- void onSuccess(JsonArray result, Response response);
- }
- private void apiRequestArray(Request.Builder requestBuilder, ApiRequestArrayCallback apiRequestArrayCallback) {
- requestBuilder.callback(new JsonArrayCallbackHandler() {
- @Override
- public void onSuccess(JsonArray data, Response response) {
- if (data == null) {
- finishWithError(new AppError(TAG, 603, CODE_MAINTENANCE, response));
- return;
- }
- try {
- apiRequestArrayCallback.onSuccess(data, response);
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 610, CODE_OTHER, response, e, data.toString()));
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 616, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- private Subject searchSubject(String name, long id, String shortName) {
- Subject subject;
- if (id == -1)
- subject = Subject.getByName(subjectList, name);
- else
- subject = Subject.getById(subjectList, id);
-
- if (subject == null) {
- subject = new Subject(profileId, (id == -1 ? crc16(name.getBytes()) : id), name, shortName);
- subjectList.add(subject);
- }
- return subject;
- }
-
- private Teacher searchTeacher(String firstName, String lastName) {
- Teacher teacher = Teacher.getByFullName(teacherList, firstName+" "+lastName);
- return validateTeacher(teacher, firstName, lastName);
- }
- private Teacher searchTeacher(char firstNameChar, String lastName) {
- Teacher teacher = Teacher.getByShortName(teacherList, firstNameChar+"."+lastName);
- return validateTeacher(teacher, String.valueOf(firstNameChar), lastName);
- }
- @NonNull
- private Teacher validateTeacher(Teacher teacher, String firstName, String lastName) {
- if (teacher == null) {
- teacher = new Teacher(profileId, -1, firstName, lastName);
- teacher.id = crc16(teacher.getShortName().getBytes());
- teacherList.add(teacher);
- }
- if (firstName.length() > 1)
- teacher.name = firstName;
- teacher.surname = lastName;
- return teacher;
- }
-
- private Teacher searchTeacherByLastFirst(String nameLastFirst) {
- String[] nameParts = nameLastFirst.split(" ", Integer.MAX_VALUE);
- if (nameParts.length == 1)
- return searchTeacher(nameParts[0], "");
- return searchTeacher(nameParts[1], nameParts[0]);
- }
- private Teacher searchTeacherByFirstLast(String nameFirstLast) {
- String[] nameParts = nameFirstLast.split(" ", Integer.MAX_VALUE);
- if (nameParts.length == 1)
- return searchTeacher(nameParts[0], "");
- return searchTeacher(nameParts[0], nameParts[1]);
- }
- private Teacher searchTeacherByFDotLast(String nameFDotLast) {
- String[] nameParts = nameFDotLast.split("\\.", Integer.MAX_VALUE);
- if (nameParts.length == 1)
- return searchTeacher(nameParts[0], "");
- return searchTeacher(nameParts[0].charAt(0), nameParts[1]);
- }
- private Teacher searchTeacherByFDotSpaceLast(String nameFDotSpaceLast) {
- String[] nameParts = nameFDotSpaceLast.split("\\. ", Integer.MAX_VALUE);
- if (nameParts.length == 1)
- return searchTeacher(nameParts[0], "");
- return searchTeacher(nameParts[0].charAt(0), nameParts[1]);
- }
-
- /* _____ _ _____ _
- | __ \ | | | __ \ | |
- | | | | __ _| |_ __ _ | |__) |___ __ _ _ _ ___ ___| |_ ___
- | | | |/ _` | __/ _` | | _ // _ \/ _` | | | |/ _ \/ __| __/ __|
- | |__| | (_| | || (_| | | | \ \ __/ (_| | |_| | __/\__ \ |_\__ \
- |_____/ \__,_|\__\__,_| |_| \_\___|\__, |\__,_|\___||___/\__|___/
- | |
- |*/
- private void getTimetable() {
- callback.onActionStarted(R.string.sync_action_syncing_timetable);
- Date weekStart = Week.getWeekStart();
- if (Date.getToday().getWeekDay() > 4) {
- weekStart.stepForward(0, 0, 7);
- }
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_panelRodzica/plan/WS_Plan.asmx/pobierzPlanZajec")
- .userAgent(userAgent)
- .addParameter("idPozDziennika", loginRegisterId)
- .addParameter("pidRokSzkolny", loginSchoolYearId)
- .addParameter("data", weekStart.getStringY_m_d()+"T10:00:00.000Z")
- .postJson(), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 697, CODE_MAINTENANCE, response, result));
- return;
- }
- List> lessonHours = new ArrayList<>();
- for (JsonElement jLessonHourEl : data.getAsJsonArray("GodzinyLekcyjne")) {
- JsonObject jLessonHour = jLessonHourEl.getAsJsonObject();
- // jLessonHour
- lessonHours.add(new Pair<>(Time.fromH_m(jLessonHour.get("Poczatek").getAsString()), Time.fromH_m(jLessonHour.get("Koniec").getAsString())));
- }
-
- for (JsonElement jLessonEl : data.getAsJsonArray("Przedmioty")) {
- JsonObject jLesson = jLessonEl.getAsJsonObject();
- // jLesson
- Subject rSubject = searchSubject(jLesson.get("Nazwa").getAsString(), jLesson.get("Id").getAsInt(), jLesson.get("Skrot").getAsString());
- Teacher rTeacher = searchTeacherByFDotLast(jLesson.get("Nauczyciel").getAsString());
-
- int weekDay = jLesson.get("DzienTygodnia").getAsInt() - 1;
- Pair lessonHour = lessonHours.get(jLesson.get("Godzina").getAsInt());
- if (lessonHour == null || lessonHour.first == null || lessonHour.second == null)
- continue;
- Lesson lessonObject = new Lesson(
- profileId,
- weekDay,
- lessonHour.first,
- lessonHour.second
- );
- lessonObject.subjectId = rSubject.id;
- lessonObject.teacherId = rTeacher.id;
- lessonObject.teamId = teamClassId;
- lessonObject.classroomName = jLesson.get("NazwaSali").getAsString();
-
- lessonList.add(lessonObject);
-
- int type = jLesson.get("TypZastepstwa").getAsInt();
- if (type != -1) {
- // we have a lesson change to process
- LessonChange lessonChangeObject = new LessonChange(
- profileId,
- weekStart.clone().stepForward(0, 0, weekDay),
- lessonObject.startTime,
- lessonObject.endTime
- );
-
- lessonChangeObject.teamId = lessonObject.teamId;
- lessonChangeObject.teacherId = lessonObject.teacherId;
- lessonChangeObject.subjectId = lessonObject.subjectId;
- lessonChangeObject.classroomName = lessonObject.classroomName;
- switch (type) {
- case 0:
- lessonChangeObject.type = TYPE_CANCELLED;
- break;
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- lessonChangeObject.type = TYPE_CHANGE;
- String newTeacher = jLesson.get("NauZastepujacy").getAsString();
- String newSubject = jLesson.get("PrzedmiotZastepujacy").getAsString();
- if (!newTeacher.equals("")) {
- lessonChangeObject.teacherId = searchTeacherByFDotLast(newTeacher).id;
- }
- if (!newSubject.equals("")) {
- lessonChangeObject.subjectId = searchSubject(newSubject, -1, "").id;
- }
- break;
- }
-
- lessonChangeList.add(lessonChangeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_LESSON_CHANGE, lessonChangeObject.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
- }
- r("finish", "Timetable");
- });
- }
-
- private void getGrades() {
- callback.onActionStarted(R.string.sync_action_syncing_grades);
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_panelRodzica/oceny/WS_ocenyUcznia.asmx/pobierzOcenyUcznia")
- .userAgent(userAgent)
- .addParameter("idPozDziennika", loginRegisterId)
- .postJson(), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 782, CODE_MAINTENANCE, response, result));
- return;
- }
- JsonArray jSubjects = data.getAsJsonArray("Przedmioty");
- for (JsonElement jSubjectEl : jSubjects) {
- JsonObject jSubject = jSubjectEl.getAsJsonObject();
- // jSubject
- Subject rSubject = searchSubject(jSubject.get("Przedmiot").getAsString(), jSubject.get("IdPrzedmiotu").getAsInt(), jSubject.get("Przedmiot").getAsString());
- for (JsonElement jGradeEl : jSubject.getAsJsonArray("Oceny")) {
- JsonObject jGrade = jGradeEl.getAsJsonObject();
- // jGrade
- Teacher rTeacher = searchTeacherByLastFirst(jGrade.get("Wystawil").getAsString());
-
- boolean countToTheAverage = jGrade.get("DoSredniej").getAsBoolean();
- float value = jGrade.get("WartoscDoSred").getAsFloat();
-
- String gradeColor = jGrade.get("Kolor").getAsString();
- int colorInt = 0xff2196f3;
- if (!gradeColor.isEmpty()) {
- colorInt = Color.parseColor("#"+gradeColor);
- }
-
- Grade gradeObject = new Grade(
- profileId,
- jGrade.get("idK").getAsLong(),
- jGrade.get("Kategoria").getAsString(),
- colorInt,
- "",
- jGrade.get("Ocena").getAsString(),
- value,
- value > 0 && countToTheAverage ? jGrade.get("Waga").getAsFloat() : 0,
- jGrade.get("Semestr").getAsInt(),
- rTeacher.id,
- rSubject.id);
-
- switch (jGrade.get("Typ").getAsInt()) {
- case 0:
- JsonElement historyEl = jGrade.get("Historia");
- JsonArray history;
- if (historyEl instanceof JsonArray && (history = historyEl.getAsJsonArray()).size() > 0) {
- float sum = gradeObject.value * gradeObject.weight;
- float count = gradeObject.weight;
- for (JsonElement historyItemEl: history) {
- JsonObject historyItem = historyItemEl.getAsJsonObject();
-
- countToTheAverage = historyItem.get("DoSredniej").getAsBoolean();
- value = historyItem.get("WartoscDoSred").getAsFloat();
- float weight = historyItem.get("Waga").getAsFloat();
-
- if (value > 0 && countToTheAverage) {
- sum += value * weight;
- count += weight;
- }
-
- Grade historyObject = new Grade(
- profileId,
- gradeObject.id * -1,
- historyItem.get("Kategoria").getAsString(),
- Color.parseColor("#"+historyItem.get("Kolor").getAsString()),
- historyItem.get("Uzasadnienie").getAsString(),
- historyItem.get("Ocena").getAsString(),
- value,
- value > 0 && countToTheAverage ? weight * -1 : 0,
- historyItem.get("Semestr").getAsInt(),
- rTeacher.id,
- rSubject.id);
- historyObject.parentId = gradeObject.id;
-
- gradeList.add(historyObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, historyObject.id, true, true, Date.fromY_m_d(historyItem.get("Data_wystaw").getAsString()).getInMillis()));
- }
- // update the current grade's value with an average of all historical grades and itself
- if (sum > 0 && count > 0) {
- gradeObject.value = sum / count;
- }
- gradeObject.isImprovement = true; // gradeObject is the improved grade. Originals are historyObjects
- }
- break;
- case 1:
- gradeObject.type = TYPE_SEMESTER1_FINAL;
- gradeObject.name = Integer.toString((int) gradeObject.value);
- gradeObject.weight = 0;
- break;
- case 2:
- gradeObject.type = TYPE_YEAR_FINAL;
- gradeObject.name = Integer.toString((int) gradeObject.value);
- gradeObject.weight = 0;
- break;
- }
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), Date.fromY_m_d(jGrade.get("Data_wystaw").getAsString()).getInMillis()));
- }
- }
- r("finish", "Grades");
- });
- }
-
- private void getPropositionGrades() {
- callback.onActionStarted(R.string.sync_action_syncing_proposition_grades);
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_panelRodzica/brak_ocen/WS_BrakOcenUcznia.asmx/pobierzBrakujaceOcenyUcznia")
- .userAgent(userAgent)
- .addParameter("idPozDziennika", loginRegisterId)
- .postJson(), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 836, CODE_MAINTENANCE, response, result));
- return;
- }
- JsonArray jSubjects = data.getAsJsonArray("Przedmioty");
- for (JsonElement jSubjectEl : jSubjects) {
- JsonObject jSubject = jSubjectEl.getAsJsonObject();
- // jSubject
- Subject rSubject = searchSubject(jSubject.get("Przedmiot").getAsString(), -1, jSubject.get("Przedmiot").getAsString());
- String semester1Proposed = jSubject.get("OcenaSem1").getAsString();
- String semester2Proposed = jSubject.get("OcenaSem2").getAsString();
- int semester1Value = getWordGradeValue(semester1Proposed);
- int semester2Value = getWordGradeValue(semester2Proposed);
- long semester1Id = rSubject.id * -100 - 1;
- long semester2Id = rSubject.id * -100 - 2;
-
- if (!semester1Proposed.equals("")) {
- Grade gradeObject = new Grade(
- profileId,
- semester1Id,
- "",
- -1,
- "",
- Integer.toString(semester1Value),
- semester1Value,
- 0,
- 1,
- -1,
- rSubject.id);
-
- gradeObject.type = TYPE_SEMESTER1_PROPOSED;
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
-
- if (!semester2Proposed.equals("")) {
- Grade gradeObject = new Grade(
- profileId,
- semester2Id,
- "",
- -1,
- "",
- Integer.toString(semester2Value),
- semester2Value,
- 0,
- 2,
- -1,
- rSubject.id);
-
- gradeObject.type = TYPE_YEAR_PROPOSED;
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
- }
- r("finish", "PropositionGrades");
- });
- }
-
- private int examsYear = Date.getToday().year;
- private int examsMonth = Date.getToday().month;
- private int examsMonthsChecked = 0;
- private boolean examsNextMonthChecked = false; // TO DO temporary // no more // idk
- private void getExams() {
- callback.onActionStarted(R.string.sync_action_syncing_exams);
- JsonObject postData = new JsonObject();
- postData.addProperty("idP", loginRegisterId);
- postData.addProperty("rok", examsYear);
- postData.addProperty("miesiac", examsMonth);
- JsonObject param = new JsonObject();
- param.addProperty("strona", 1);
- param.addProperty("iloscNaStrone", "99");
- param.addProperty("iloscRekordow", -1);
- param.addProperty("kolumnaSort", "ss.Nazwa,sp.Data_sprawdzianu");
- param.addProperty("kierunekSort", 0);
- param.addProperty("maxIloscZaznaczonych", 0);
- param.addProperty("panelFiltrow", 0);
- postData.add("param", param);
-
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_panelRodzica/sprawdziany/mod_sprawdzianyPanel.asmx/pobierzListe")
- .userAgent(userAgent)
- .setJsonBody(postData), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 921, CODE_MAINTENANCE, response, result));
- return;
- }
- for (JsonElement jExamEl : data.getAsJsonArray("ListK")) {
- JsonObject jExam = jExamEl.getAsJsonObject();
- // jExam
- long eventId = jExam.get("_recordId").getAsLong();
- Subject rSubject = searchSubject(jExam.get("przedmiot").getAsString(), -1, "");
- Teacher rTeacher = searchTeacherByLastFirst(jExam.get("wpisal").getAsString());
- Date examDate = Date.fromY_m_d(jExam.get("data").getAsString());
- Lesson lessonObject = Lesson.getByWeekDayAndSubject(lessonList, examDate.getWeekDay(), rSubject.id);
- Time examTime = lessonObject == null ? null : lessonObject.startTime;
-
- int eventType = (jExam.get("rodzaj").getAsString().equals("sprawdzian/praca klasowa") ? Event.TYPE_EXAM : Event.TYPE_SHORT_QUIZ);
- Event eventObject = new Event(
- profileId,
- eventId,
- examDate,
- examTime,
- jExam.get("zakres").getAsString(),
- -1,
- eventType,
- false,
- rTeacher.id,
- rSubject.id,
- teamClassId
- );
-
- eventList.add(eventObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_EVENT, eventObject.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
-
- if (profile.getEmpty() && examsMonthsChecked < 3 /* how many months backwards to check? */) {
- examsMonthsChecked++;
- examsMonth--;
- if (examsMonth < 1) {
- examsMonth = 12;
- examsYear--;
- }
- r("get", "Exams");
- } else if (!examsNextMonthChecked /* get also one month forward */) {
- Date showDate = Date.getToday().stepForward(0, 1, 0);
- examsYear = showDate.year;
- examsMonth = showDate.month;
- examsNextMonthChecked = true;
- r("get", "Exams");
- } else {
- r("finish", "Exams");
- }
- });
- }
-
- private void getNotices() {
- callback.onActionStarted(R.string.sync_action_syncing_notices);
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_panelRodzica/uwagi/WS_uwagiUcznia.asmx/pobierzUwagiUcznia")
- .userAgent(userAgent)
- .addParameter("idPozDziennika", loginRegisterId)
- .postJson(), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 982, CODE_MAINTENANCE, response, result));
- return;
- }
- for (JsonElement jNoticeEl : data.getAsJsonArray("SUwaga")) {
- JsonObject jNotice = jNoticeEl.getAsJsonObject();
- // jExam
- long noticeId = crc16(jNotice.get("id").getAsString().getBytes());
-
- Teacher rTeacher = searchTeacherByLastFirst(jNotice.get("Nauczyciel").getAsString());
- Date addedDate = Date.fromY_m_d(jNotice.get("Data").getAsString());
-
- int nType = TYPE_NEUTRAL;
- String jType = jNotice.get("Typ").getAsString();
- if (jType.equals("n")) {
- nType = TYPE_NEGATIVE;
- } else if (jType.equals("p")) {
- nType = TYPE_POSITIVE;
- }
-
- Notice noticeObject = new Notice(
- profileId,
- noticeId,
- jNotice.get("Tresc").getAsString(),
- jNotice.get("Semestr").getAsInt(),
- nType,
- rTeacher.id);
- noticeList.add(noticeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_NOTICE, noticeObject.id, profile.getEmpty(), profile.getEmpty(), addedDate.getInMillis()));
- }
- r("finish", "Notices");
- });
- }
-
- private void getAnnouncements() {
- callback.onActionStarted(R.string.sync_action_syncing_announcements);
- if (loginStudentId == null) {
- r("finish", "Announcements");
- return;
- }
- JsonObject postData = new JsonObject();
- postData.addProperty("uczenId", loginStudentId);
- JsonObject param = new JsonObject();
- param.add("parametryFiltrow", new JsonArray());
- postData.add("param", param);
-
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_panelRodzica/tabOgl/WS_tablicaOgloszen.asmx/GetOgloszenia")
- .userAgent(userAgent)
- .setJsonBody(postData), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 1033, CODE_MAINTENANCE, response, result));
- return;
- }
- for (JsonElement jAnnouncementEl : data.getAsJsonArray("ListK")) {
- JsonObject jAnnouncement = jAnnouncementEl.getAsJsonObject();
- // jAnnouncement
- long announcementId = jAnnouncement.get("Id").getAsLong();
-
- Teacher rTeacher = searchTeacherByFirstLast(jAnnouncement.get("Autor").getAsString());
- long addedDate = Long.parseLong(jAnnouncement.get("DataDodania").getAsString().replaceAll("[^\\d]", ""));
- Date startDate = Date.fromMillis(Long.parseLong(jAnnouncement.get("DataWydarzenia").getAsString().replaceAll("[^\\d]", "")));
-
- Announcement announcementObject = new Announcement(
- profileId,
- announcementId,
- jAnnouncement.get("Temat").getAsString(),
- jAnnouncement.get("Tresc").getAsString(),
- startDate,
- null,
- rTeacher.id
- );
- announcementList.add(announcementObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_ANNOUNCEMENT, announcementObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- r("finish", "Announcements");
- });
- }
-
- private int attendanceYear;
- private int attendanceMonth;
- private boolean attendancePrevMonthChecked = false;
- private void getAttendance() {
- callback.onActionStarted(R.string.sync_action_syncing_attendance);
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_panelRodzica/obecnosci/WS_obecnosciUcznia.asmx/pobierzObecnosciUcznia")
- .userAgent(userAgent)
- .addParameter("idPozDziennika", loginRegisterId)
- .addParameter("mc", attendanceMonth)
- .addParameter("rok", attendanceYear)
- .addParameter("dataTygodnia", "")
- .postJson(), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 1076, CODE_MAINTENANCE, response, result));
- return;
- }
- for (JsonElement jAttendanceEl : data.getAsJsonArray("Obecnosci")) {
- JsonObject jAttendance = jAttendanceEl.getAsJsonObject();
- // jAttendance
- int attendanceTypeIdziennik = jAttendance.get("TypObecnosci").getAsInt();
- if (attendanceTypeIdziennik == 5 || attendanceTypeIdziennik == 7)
- continue;
- Date attendanceDate = Date.fromY_m_d(jAttendance.get("Data").getAsString());
- Time attendanceTime = Time.fromH_m(jAttendance.get("OdDoGodziny").getAsString());
- if (attendanceDate.combineWith(attendanceTime) > System.currentTimeMillis())
- continue;
-
- long attendanceId = crc16(jAttendance.get("IdLesson").getAsString().getBytes());
- Subject rSubject = searchSubject(jAttendance.get("Przedmiot").getAsString(), jAttendance.get("IdPrzedmiot").getAsLong(), "");
- Teacher rTeacher = searchTeacherByFDotSpaceLast(jAttendance.get("PrzedmiotNauczyciel").getAsString());
-
- String attendanceName = "obecność";
- int attendanceType = Attendance.TYPE_CUSTOM;
-
- switch (attendanceTypeIdziennik) {
- case 1: /* nieobecność usprawiedliwiona */
- attendanceName = "nieobecność usprawiedliwiona";
- attendanceType = TYPE_ABSENT_EXCUSED;
- break;
- case 2: /* spóźnienie */
- attendanceName = "spóźnienie";
- attendanceType = TYPE_BELATED;
- break;
- case 3: /* nieobecność nieusprawiedliwiona */
- attendanceName = "nieobecność nieusprawiedliwiona";
- attendanceType = TYPE_ABSENT;
- break;
- case 4: /* zwolnienie */
- case 9: /* zwolniony / obecny */
- attendanceType = TYPE_RELEASED;
- if (attendanceTypeIdziennik == 4)
- attendanceName = "zwolnienie";
- if (attendanceTypeIdziennik == 9)
- attendanceName = "zwolnienie / obecność";
- break;
- case 0: /* obecny */
- case 8: /* Wycieczka */
- attendanceType = TYPE_PRESENT;
- if (attendanceTypeIdziennik == 8)
- attendanceName = "wycieczka";
- break;
- }
-
- int semester = profile.dateToSemester(attendanceDate);
-
- Attendance attendanceObject = new Attendance(
- profileId,
- attendanceId,
- rTeacher.id,
- rSubject.id,
- semester,
- attendanceName,
- attendanceDate,
- attendanceTime,
- attendanceType
- );
-
- attendanceList.add(attendanceObject);
- if (attendanceObject.type != TYPE_PRESENT) {
- metadataList.add(new Metadata(profileId, Metadata.TYPE_ATTENDANCE, attendanceObject.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
- }
-
- int attendanceDateValue = attendanceYear *10000 + attendanceMonth *100;
- if (profile.getEmpty() && attendanceDateValue > profile.getSemesterStart(1).getValue()) {
- attendancePrevMonthChecked = true; // do not need to check prev month later
- attendanceMonth--;
- if (attendanceMonth < 1) {
- attendanceMonth = 12;
- attendanceYear--;
- }
- r("get", "Attendance");
- } else if (!attendancePrevMonthChecked /* get also the previous month */) {
- attendanceMonth--;
- if (attendanceMonth < 1) {
- attendanceMonth = 12;
- attendanceYear--;
- }
- attendancePrevMonthChecked = true;
- r("get", "Attendance");
- } else {
- r("finish", "Attendance");
- }
- });
- }
-
- private void getLuckyNumberAndSemesterDates() {
- if (profile.getLuckyNumberDate() != null && profile.getLuckyNumber() != -1 && profile.getLuckyNumberDate().getValue() == Date.getToday().getValue()) {
- r("finish", "LuckyNumberAndSemesterDates");
- return;
- }
- if (loginBearerToken == null || loginStudentId == null) {
- r("finish", "LuckyNumberAndSemesterDates");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_lucky_number);
- apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/api/Uczniowie/"+loginStudentId+"/AktualnyDziennik")
- .header("Authorization", "Bearer "+loginBearerToken)
- .userAgent(userAgent), (data, response) -> {
- JsonObject settings = data.getAsJsonObject("ustawienia");
- if (settings == null) {
- finishWithError(new AppError(TAG, 1188, CODE_MAINTENANCE, response, data));
- return;
- }
- // data, settings
- profile.setLuckyNumber(-1);
- profile.setLuckyNumberDate(today);
- JsonElement luckyNumberEl = data.get("szczesliwyNumerek");
- if (luckyNumberEl != null && !(luckyNumberEl instanceof JsonNull)) {
- profile.setLuckyNumber(luckyNumberEl.getAsInt());
- Time publishTime = Time.fromH_m(settings.get("godzinaPublikacjiSzczesliwegoLosu").getAsString());
- if (Time.getNow().getValue() > publishTime.getValue()) {
- profile.getLuckyNumberDate().stepForward(0, 0, 1); // the lucky number is already for tomorrow
- }
- app.db.luckyNumberDao().add(new LuckyNumber(profileId, profile.getLuckyNumberDate(), profile.getLuckyNumber()));
- }
-
- profile.setDateSemester1Start(Date.fromY_m_d(settings.get("poczatekSemestru1").getAsString()));
- profile.setDateSemester2Start(Date.fromY_m_d(settings.get("koniecSemestru1").getAsString()).stepForward(0, 0, 1));
- profile.setDateYearEnd(Date.fromY_m_d(settings.get("koniecSemestru2").getAsString()));
-
- r("finish", "LuckyNumberAndSemesterDates");
- });
- }
-
- private void getMessagesInbox() {
- if (loginBearerToken == null) {
- r("finish", "MessagesInbox");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_messages);
- apiRequestArray(Request.builder()
- .url(IDZIENNIK_URL +"/api/Wiadomosci/Odebrane")
- .header("Authorization", "Bearer "+loginBearerToken)
- .userAgent(userAgent), (data, response) -> {
- for (JsonElement jMessageEl: data) {
- JsonObject jMessage = jMessageEl.getAsJsonObject();
-
- String subject = jMessage.get("tytul").getAsString();
- if (subject.contains("(") && subject.startsWith("iDziennik - "))
- continue;
- if (subject.startsWith("Uwaga dla ucznia (klasa:"))
- continue;
-
- String messageIdStr = jMessage.get("id").getAsString();
- long messageId = crc32((messageIdStr+"0").getBytes());
-
- String body = "[META:"+messageIdStr+";-1]";
- body += jMessage.get("tresc").getAsString().replaceAll("\n", " ");
-
- long readDate = jMessage.get("odczytana").getAsBoolean() ? Date.fromIso(jMessage.get("wersjaRekordu").getAsString()) : 0;
- long sentDate = Date.fromIso(jMessage.get("dataWyslania").getAsString());
-
- JsonObject sender = jMessage.getAsJsonObject("nadawca");
- Teacher rTeacher = searchTeacher(sender.get("imie").getAsString(), sender.get("nazwisko").getAsString());
- rTeacher.loginId = sender.get("id").getAsString()+":"+sender.get("usr").getAsString();
-
- Message message = new Message(
- profileId,
- messageId,
- subject,
- body,
- jMessage.get("rekordUsuniety").getAsBoolean() ? TYPE_DELETED : TYPE_RECEIVED,
- rTeacher.id,
- -1
- );
-
- MessageRecipient messageRecipient = new MessageRecipient(
- profileId,
- -1 /* me */,
- -1,
- readDate,
- /*messageId*/ messageId
- );
-
- messageList.add(message);
- messageRecipientList.add(messageRecipient);
- messageMetadataList.add(new Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, readDate > 0, readDate > 0 || profile.getEmpty(), sentDate));
- }
-
- r("finish", "MessagesInbox");
- });
- }
-
- private void getMessagesOutbox() {
- if (loginBearerToken == null) {
- r("finish", "MessagesOutbox");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_messages);
- apiRequestArray(Request.builder()
- .url(IDZIENNIK_URL +"/api/Wiadomosci/Wyslane")
- .header("Authorization", "Bearer "+loginBearerToken)
- .userAgent(userAgent), (data, response) -> {
- for (JsonElement jMessageEl: data) {
- JsonObject jMessage = jMessageEl.getAsJsonObject();
-
- String messageIdStr = jMessage.get("id").getAsString();
- long messageId = crc32((messageIdStr+"1").getBytes());
-
- String subject = jMessage.get("tytul").getAsString();
-
- String body = "[META:"+messageIdStr+";-1]";
- body += jMessage.get("tresc").getAsString().replaceAll("\n", " ");
-
- long sentDate = Date.fromIso(jMessage.get("dataWyslania").getAsString());
-
- Message message = new Message(
- profileId,
- messageId,
- subject,
- body,
- TYPE_SENT,
- -1,
- -1
- );
-
- for (JsonElement recipientEl: jMessage.getAsJsonArray("odbiorcy")) {
- JsonObject recipient = recipientEl.getAsJsonObject();
- String firstName = recipient.get("imie").getAsString();
- String lastName = recipient.get("nazwisko").getAsString();
- if (firstName.isEmpty() || lastName.isEmpty()) {
- firstName = "usunięty";
- lastName = "użytkownik";
- }
- Teacher rTeacher = searchTeacher(firstName, lastName);
- rTeacher.loginId = recipient.get("id").getAsString()+":"+recipient.get("usr").getAsString();
-
- MessageRecipient messageRecipient = new MessageRecipient(
- profileId,
- rTeacher.id,
- -1,
- -1,
- /*messageId*/ messageId
- );
- messageRecipientIgnoreList.add(messageRecipient);
- }
-
- messageList.add(message);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate));
- }
-
- r("finish", "MessagesOutbox");
- });
- }
-
- @Override
- public Map getConfigurableEndpoints(Profile profile) {
- return null;
- }
-
- @Override
- public boolean isEndpointEnabled(Profile profile, boolean defaultActive, String name) {
- return defaultActive;
- }
-
- @Override
- public void syncMessages(@NonNull Context activityContext, @NonNull SyncCallback errorCallback, @NonNull ProfileFull profile)
- {
- }
-
- /* __ __
- | \/ |
- | \ / | ___ ___ ___ __ _ __ _ ___ ___
- | |\/| |/ _ \/ __/ __|/ _` |/ _` |/ _ \/ __|
- | | | | __/\__ \__ \ (_| | (_| | __/\__ \
- |_| |_|\___||___/___/\__,_|\__, |\___||___/
- __/ |
- |__*/
- @Override
- public void getMessage(@NonNull Context activityContext, @NonNull SyncCallback errorCallback, @NonNull ProfileFull profile, @NonNull MessageFull message, @NonNull MessageGetCallback messageCallback) {
- if (message.body == null)
- return;
- String messageIdStr = null;
- long messageIdBefore = -1;
- Matcher matcher = Pattern.compile("\\[META:([A-z0-9]+);([0-9-]+)]").matcher(message.body);
- if (matcher.find()) {
- messageIdStr = matcher.group(1);
- messageIdBefore = Long.parseLong(matcher.group(2));
- }
- if (messageIdBefore != -1) {
- boolean readByAll = true;
- // load this message's recipient(s) data
- message.recipients = app.db.messageRecipientDao().getAllByMessageId(profile.getId(), message.id);
- for (MessageRecipientFull recipient: message.recipients) {
- if (recipient.id == -1)
- recipient.fullName = profile.getStudentNameLong();
- if (message.type == TYPE_SENT && recipient.readDate < 1)
- readByAll = false;
- }
- if (!message.seen) {
- app.db.metadataDao().setSeen(profile.getId(), message, true);
- }
- if (readByAll) {
- // if a sent msg is not read by everyone, download it again to check the read status
- new Handler(activityContext.getMainLooper()).post(() -> messageCallback.onSuccess(message));
- return;
- }
- }
-
- if (!prepare(activityContext, errorCallback, profile.getId(), profile, LoginStore.fromProfileFull(profile)))
- return;
-
- String finalMessageIdStr = messageIdStr;
- login(() -> apiRequest(Request.builder()
- .url(IDZIENNIK_URL +"/mod_komunikator/WS_wiadomosci.asmx/PobierzWiadomosc")
- .userAgent(userAgent)
- .addParameter("idWiadomosci", finalMessageIdStr)
- .addParameter("typWiadomosci", message.type == TYPE_SENT ? 1 : 0)
- .postJson(), (result, response) -> {
- JsonObject data = result.getAsJsonObject("d");
- if (data == null) {
- finishWithError(new AppError(TAG, 1418, CODE_MAINTENANCE, response, result));
- return;
- }
- JsonObject jMessage = data.getAsJsonObject("Wiadomosc");
- if (jMessage == null) {
- finishWithError(new AppError(TAG, 1423, CODE_MAINTENANCE, response, result));
- return;
- }
-
- List messageRecipientList = new ArrayList<>();
-
- long messageId = jMessage.get("_recordId").getAsLong();
-
- message.body = message.body.replaceAll("\\[META:[A-z0-9]+;[0-9-]+]", "[META:"+ finalMessageIdStr +";"+ messageId +"]");
-
- message.clearAttachments();
- for (JsonElement jAttachmentEl: jMessage.getAsJsonArray("ListaZal")) {
- JsonObject jAttachment = jAttachmentEl.getAsJsonObject();
- message.addAttachment(jAttachment.get("Id").getAsLong(), jAttachment.get("Nazwa").getAsString(), -1);
- }
-
- if (message.type == TYPE_RECEIVED) {
- MessageRecipientFull recipient = new MessageRecipientFull(profileId, -1, message.id);
-
- String readDateStr = jMessage.get("DataOdczytania").getAsString();
- recipient.readDate = readDateStr.isEmpty() ? System.currentTimeMillis() : Date.fromIso(readDateStr);
-
- recipient.fullName = profile.getStudentNameLong();
- messageRecipientList.add(recipient);
- }
- else if (message.type == TYPE_SENT) {
- teacherList = app.db.teacherDao().getAllNow(profileId);
- for (JsonElement jReceiverEl: jMessage.getAsJsonArray("ListaOdbiorcow")) {
- JsonObject jReceiver = jReceiverEl.getAsJsonObject();
- String receiverLastFirstName = jReceiver.get("NazwaOdbiorcy").getAsString();
-
- Teacher teacher = searchTeacherByLastFirst(receiverLastFirstName);
-
- MessageRecipientFull recipient = new MessageRecipientFull(profileId, teacher.id, message.id);
-
- recipient.readDate = jReceiver.get("Status").getAsInt();
-
- recipient.fullName = teacher.getFullName();
- messageRecipientList.add(recipient);
- }
- }
-
- if (!message.seen) {
- app.db.metadataDao().setSeen(profileId, message, true);
- }
- app.db.messageDao().add(message);
- app.db.messageRecipientDao().addAll((List)(List>) messageRecipientList); // not addAllIgnore
-
- message.recipients = messageRecipientList;
-
- new Handler(activityContext.getMainLooper()).post(() -> messageCallback.onSuccess(message));
- }));
- }
-
- @Override
- public void getAttachment(@NonNull Context activityContext, @NonNull SyncCallback errorCallback, @NonNull ProfileFull profile, @NonNull MessageFull message, long attachmentId, @NonNull AttachmentGetCallback attachmentCallback) {
- if (message.body == null)
- return;
- if (!prepare(activityContext, errorCallback, profile.getId(), profile, LoginStore.fromProfileFull(profile)))
- return;
-
- login(() -> {
- String fileName = message.attachmentNames.get(message.attachmentIds.indexOf(attachmentId));
-
- long messageId = -1;
- Matcher matcher = Pattern.compile("\\[META:([A-z0-9]+);([0-9-]+)]").matcher(message.body);
- if (matcher.find()) {
- messageId = Long.parseLong(matcher.group(2));
- }
-
- Request.Builder builder = Request.builder()
- .url("https://iuczniowie.progman.pl/idziennik/mod_komunikator/Download.ashx")
- .post()
- .contentType(MediaTypeUtils.APPLICATION_FORM)
- .addParameter("id", messageId)
- .addParameter("fileName", fileName);
-
- new Handler(activityContext.getMainLooper()).post(() -> attachmentCallback.onSuccess(builder));
- });
- }
-
- @Override
- public void getRecipientList(@NonNull Context activityContext, @NonNull SyncCallback errorCallback, @NonNull ProfileFull profile, @NonNull RecipientListGetCallback recipientListGetCallback) {
- if (!prepare(activityContext, errorCallback, profile.getId(), profile, LoginStore.fromProfileFull(profile)))
- return;
-
- if (System.currentTimeMillis() - profile.getLastReceiversSync() < 24 * 60 * 60 * 1000) {
- AsyncTask.execute(() -> {
- List teacherList = app.db.teacherDao().getAllNow(profileId);
- new Handler(activityContext.getMainLooper()).post(() -> recipientListGetCallback.onSuccess(teacherList));
- });
- return;
- }
-
- login(() -> {
- List cookieList = app.cookieJar.loadForRequest(HttpUrl.get(IDZIENNIK_URL));
- for (Cookie cookie: cookieList) {
- if (cookie.name().equalsIgnoreCase("Bearer")) {
- loginBearerToken = cookie.value();
- }
- }
- loginStudentId = profile.getStudentData("studentId", null);// TODO: 2019-06-12 temporary duplicated token & ID extraction
-
- apiRequestArray(Request.builder()
- .url(IDZIENNIK_URL + "/api/Wiadomosci/Odbiorcy?idUcznia="+loginStudentId)
- .header("Authorization", "Bearer " + loginBearerToken)
- .userAgent(userAgent), (result, response) -> {
- teacherList = app.db.teacherDao().getAllNow(profileId);
- for (JsonElement recipientEl: result) {
- JsonObject recipient = recipientEl.getAsJsonObject();
- String name = recipient.get("nazwaKontaktu").getAsString();
- String loginId = recipient.get("idUzytkownika").getAsString();
- JsonArray typesArray = recipient.getAsJsonArray("typOsoby");
- List types = new ArrayList<>();
- for (JsonElement typeEl: typesArray) {
- types.add(typeEl.getAsInt());
- }
- String delimiter;
- if (types.size() == 1 && types.get(0) >= 6) /* parent or student */
- delimiter = " (";
- else
- delimiter = ": ";
- String nameFirstLast = name.substring(0, name.indexOf(delimiter));
- Teacher teacher = searchTeacherByFirstLast(nameFirstLast);
- teacher.loginId = loginId;
- teacher.type = 0;
- for (int type: types) {
- switch (type) {
- case 0:
- teacher.setType(Teacher.TYPE_SCHOOL_ADMIN);
- break;
- case 1:
- teacher.setType(Teacher.TYPE_SECRETARIAT);
- break;
- case 2:
- teacher.setType(Teacher.TYPE_TEACHER);
- teacher.typeDescription = name.substring(name.indexOf(": ")+2);
- break;
- case 3:
- teacher.setType(Teacher.TYPE_PRINCIPAL);
- break;
- case 4:
- teacher.setType(Teacher.TYPE_EDUCATOR);
- break;
- case 5:
- teacher.setType(Teacher.TYPE_PEDAGOGUE);
- break;
- case 6:
- teacher.setType(Teacher.TYPE_PARENT);
- teacher.typeDescription = name.substring(name.indexOf(" (")+2, name.lastIndexOf(" ("));
- break;
- case 7:
- teacher.setType(Teacher.TYPE_STUDENT);
- break;
- }
- }
- }
- app.db.teacherDao().addAll(teacherList);
-
- profile.setLastReceiversSync(System.currentTimeMillis());
- app.db.profileDao().add(profile);
-
- new Handler(activityContext.getMainLooper()).post(() -> recipientListGetCallback.onSuccess(new ArrayList<>(teacherList)));
- });
- });
- }
-
- @Override
- public MessagesComposeInfo getComposeInfo(@NonNull ProfileFull profile) {
- return new MessagesComposeInfo(0, 0, 180, 1983);
- }
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Librus.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Librus.java
deleted file mode 100644
index 5c7356e2..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Librus.java
+++ /dev/null
@@ -1,3872 +0,0 @@
-package pl.szczodrzynski.edziennik.data.api;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.util.Base64;
-import android.util.Pair;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.crashlytics.android.Crashlytics;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonNull;
-import com.google.gson.JsonObject;
-import com.google.gson.reflect.TypeToken;
-
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Parser;
-import org.jsoup.select.Elements;
-
-import java.text.DateFormat;
-import java.text.DecimalFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import im.wangchao.mhttp.Request;
-import im.wangchao.mhttp.Response;
-import im.wangchao.mhttp.body.MediaTypeUtils;
-import im.wangchao.mhttp.callback.JsonCallbackHandler;
-import im.wangchao.mhttp.callback.TextCallbackHandler;
-import pl.szczodrzynski.edziennik.App;
-import pl.szczodrzynski.edziennik.BuildConfig;
-import pl.szczodrzynski.edziennik.R;
-import pl.szczodrzynski.edziennik.data.api.interfaces.AttachmentGetCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface;
-import pl.szczodrzynski.edziennik.data.api.interfaces.LoginCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.MessageGetCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.RecipientListGetCallback;
-import pl.szczodrzynski.edziennik.data.api.interfaces.SyncCallback;
-import pl.szczodrzynski.edziennik.data.api.v2.models.DataStore;
-import pl.szczodrzynski.edziennik.data.db.modules.announcements.Announcement;
-import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance;
-import pl.szczodrzynski.edziennik.data.db.modules.events.Event;
-import pl.szczodrzynski.edziennik.data.db.modules.events.EventType;
-import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade;
-import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory;
-import pl.szczodrzynski.edziennik.data.db.modules.lessons.Lesson;
-import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange;
-import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore;
-import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.Message;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient;
-import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull;
-import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata;
-import pl.szczodrzynski.edziennik.data.db.modules.notices.Notice;
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
-import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull;
-import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject;
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher;
-import pl.szczodrzynski.edziennik.data.db.modules.teachers.TeacherAbsence;
-import pl.szczodrzynski.edziennik.data.db.modules.teams.Team;
-import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeInfo;
-import pl.szczodrzynski.edziennik.utils.models.Date;
-import pl.szczodrzynski.edziennik.utils.models.Endpoint;
-import pl.szczodrzynski.edziennik.utils.models.Time;
-import pl.szczodrzynski.edziennik.utils.models.Week;
-import pl.szczodrzynski.edziennik.utils.Utils;
-
-import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
-import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
-import static java.net.HttpURLConnection.HTTP_GONE;
-import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
-import static java.net.HttpURLConnection.HTTP_OK;
-import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_INVALID_LOGIN;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_LIBRUS_DISCONNECTED;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_LIBRUS_NOT_ACTIVATED;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_MAINTENANCE;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_OTHER;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_PROFILE_NOT_FOUND;
-import static pl.szczodrzynski.edziennik.data.api.AppError.CODE_SYNERGIA_NOT_ACTIVATED;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_ABSENT;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_ABSENT_EXCUSED;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_BELATED;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_PRESENT;
-import static pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance.TYPE_RELEASED;
-import static pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_PT_MEETING;
-import static pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_TEACHER_ABSENCE;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_NORMAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_FINAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER2_FINAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER2_PROPOSED;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_FINAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED;
-import static pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CANCELLED;
-import static pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CHANGE;
-import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED;
-import static pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_SENT;
-import static pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.TYPE_NEGATIVE;
-import static pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.TYPE_NEUTRAL;
-import static pl.szczodrzynski.edziennik.data.db.modules.notices.Notice.TYPE_POSITIVE;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_EDUCATOR;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_LIBRARIAN;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_OTHER;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_PARENTS_COUNCIL;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_PEDAGOGUE;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_SCHOOL_ADMIN;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_SCHOOL_PARENTS_COUNCIL;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_SECRETARIAT;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_SUPER_ADMIN;
-import static pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher.TYPE_TEACHER;
-import static pl.szczodrzynski.edziennik.utils.Utils.bs;
-import static pl.szczodrzynski.edziennik.utils.Utils.c;
-import static pl.szczodrzynski.edziennik.utils.Utils.contains;
-import static pl.szczodrzynski.edziennik.utils.Utils.crc16;
-import static pl.szczodrzynski.edziennik.utils.Utils.d;
-import static pl.szczodrzynski.edziennik.utils.Utils.getGradeValue;
-import static pl.szczodrzynski.edziennik.utils.Utils.strToInt;
-
-public class Librus implements EdziennikInterface {
- public Librus(App app) {
- this.app = app;
- }
-
- private static final String TAG = "api.Librus";
- private static final String CLIENT_ID = "wmSyUMo8llDAs4y9tJVYY92oyZ6h4lAt7KCuy0Gv";
- private static final String REDIRECT_URL = "http://localhost/bar";
- private static final String AUTHORIZE_URL = "https://portal.librus.pl/oauth2/authorize?client_id="+CLIENT_ID+"&redirect_uri="+REDIRECT_URL+"&response_type=code";
- private static final String LOGIN_URL = "https://portal.librus.pl/rodzina/login/action";
- private static final String TOKEN_URL = "https://portal.librus.pl/oauth2/access_token";
- private static final String ACCOUNTS_URL = "https://portal.librus.pl/api/v2/SynergiaAccounts";
- private static final String ACCOUNT_URL = "https://portal.librus.pl/api/v2/SynergiaAccounts/fresh/"; // + login
- private static final String API_URL = "https://api.librus.pl/2.0/";
- private static final String SYNERGIA_URL = "https://wiadomosci.librus.pl/module/";
- private static final String SYNERGIA_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action=";
- private static final String userAgent = "Dalvik/2.1.0 Android LibrusMobileApp";
- private static final String synergiaUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/62.0";
-
- private App app;
- private Context activityContext = null;
- private SyncCallback callback = null;
- private int profileId = -1;
- private Profile profile = null;
- private LoginStore loginStore = null;
- private boolean fullSync = true;
- private Date today;
- private List targetEndpoints = new ArrayList<>();
-
- // PROGRESS
- private static final int PROGRESS_LOGIN = 10;
- private int PROGRESS_COUNT = 1;
- private int PROGRESS_STEP = (90/PROGRESS_COUNT);
-
- private int onlyFeature = FEATURE_ALL;
-
- private List teamList;
- private List teacherList;
- private List teacherAbsenceList;
- private List subjectList;
- private List lessonList;
- private List lessonChangeList;
- private List gradeCategoryList;
- private List gradeList;
- private List eventList;
- private List eventTypeList;
- private List noticeList;
- private List attendanceList;
- private List announcementList;
- private List messageList;
- private List messageRecipientList;
- private List messageRecipientIgnoreList;
- private List metadataList;
- private List messageMetadataList;
-
- private static boolean fakeLogin = false;
- private String librusEmail = null;
- private String librusPassword = null;
- private String synergiaLogin = null;
- private String synergiaPassword = null;
- private String synergiaLastLogin = null;
- private long synergiaLastLoginTime = -1;
- private boolean premium = false;
- private boolean enableStandardGrades = true;
- private boolean enablePointGrades = false;
- private boolean enableDescriptiveGrades = false;
- private boolean enableTextGrades = false;
- private boolean enableBehaviourGrades = true;
- private long unitId = -1;
- private int startPointsSemester1 = 0;
- private int startPointsSemester2 = 0;
-
- private boolean prepare(@NonNull Context activityContext, @NonNull SyncCallback callback, int profileId, @Nullable Profile profile, @NonNull LoginStore loginStore) {
- this.activityContext = activityContext;
- this.callback = callback;
- this.profileId = profileId;
- // here we must have a login store: either with a correct ID or -1
- // there may be no profile and that's when onLoginFirst happens
- this.profile = profile;
- this.loginStore = loginStore;
- this.fullSync = profile == null || profile.getEmpty() || profile.shouldFullSync(activityContext);
- this.today = Date.getToday();
-
- DataStore ds = new DataStore(app.db, profileId);
-
- this.librusEmail = loginStore.getLoginData("email", "");
- this.librusPassword = loginStore.getLoginData("password", "");
- if (profile == null) {
- this.synergiaLogin = null;
- this.synergiaPassword = null;
- }
- else {
- this.synergiaLogin = profile.getStudentData("accountLogin", null);
- this.synergiaPassword = profile.getStudentData("accountPassword", null);
- }
- if (librusEmail.equals("") || librusPassword.equals("")) {
- finishWithError(new AppError(TAG, 214, AppError.CODE_INVALID_LOGIN, "Login field is empty"));
- return false;
- }
- this.premium = profile != null && profile.getStudentData("isPremium", false);
- this.failed = 0;
- fakeLogin = BuildConfig.DEBUG && librusEmail.toLowerCase().startsWith("fake");
- this.synergiaLastLogin = null;
- this.synergiaLastLoginTime = -1;
-
- this.refreshTokenFailed = false;
-
- teamList = profileId == -1 ? new ArrayList<>() : app.db.teamDao().getAllNow(profileId);
- teacherList = profileId == -1 ? new ArrayList<>() : app.db.teacherDao().getAllNow(profileId);
- teacherAbsenceList = new ArrayList<>();
- subjectList = new ArrayList<>();
- lessonList = new ArrayList<>();
- lessonChangeList = new ArrayList<>();
- gradeCategoryList = new ArrayList<>();
- gradeList = new ArrayList<>();
- eventList = new ArrayList<>();
- eventTypeList = new ArrayList<>();
- noticeList = new ArrayList<>();
- attendanceList = new ArrayList<>();
- announcementList = new ArrayList<>();
- messageList = new ArrayList<>();
- messageRecipientList = new ArrayList<>();
- messageRecipientIgnoreList = new ArrayList<>();
- metadataList = new ArrayList<>();
- messageMetadataList = new ArrayList<>();
-
- return true;
- }
-
- @Override
- public void sync(@NonNull Context activityContext, @NonNull SyncCallback callback, int profileId, @Nullable Profile profile, @NonNull LoginStore loginStore) {
- if (!prepare(activityContext, callback, profileId, profile, loginStore))
- return;
-
- login(() -> {
- targetEndpoints = new ArrayList<>();
- targetEndpoints.add("Me");
- targetEndpoints.add("Schools");
- targetEndpoints.add("Classes");
- targetEndpoints.add("VirtualClasses");
- targetEndpoints.add("Units");
- targetEndpoints.add("Users");
- targetEndpoints.add("Subjects");
- targetEndpoints.add("Classrooms");
- targetEndpoints.add("Substitutions");
- targetEndpoints.add("Timetables");
- targetEndpoints.add("Colors");
-
- targetEndpoints.add("SavedGradeCategories");
- targetEndpoints.add("GradesCategories");
- targetEndpoints.add("PointGradesCategories");
- targetEndpoints.add("DescriptiveGradesCategories");
- //targetEndpoints.add("TextGradesCategories");
- targetEndpoints.add("BehaviourGradesCategories"); // TODO: 2019-04-30
- targetEndpoints.add("SaveGradeCategories");
-
- targetEndpoints.add("Grades");
- targetEndpoints.add("PointGrades");
- targetEndpoints.add("DescriptiveGrades");
- targetEndpoints.add("TextGrades");
- targetEndpoints.add("BehaviourGrades");
- targetEndpoints.add("GradesComments");
-
- targetEndpoints.add("Events");
- targetEndpoints.add("TeacherFreeDays");
- targetEndpoints.add("CustomTypes");
- targetEndpoints.add("Homework");
- targetEndpoints.add("LuckyNumbers");
- targetEndpoints.add("Notices");
- targetEndpoints.add("AttendanceTypes");
- targetEndpoints.add("Attendance");
- targetEndpoints.add("Announcements");
- targetEndpoints.add("PtMeetings");
-
- /*if (isEndpointEnabled(profile, true, "SchoolFreeDays"))
- targetEndpoints.add("SchoolFreeDays");
- if (isEndpointEnabled(profile, true, "ClassFreeDays"))
- targetEndpoints.add("ClassFreeDays");*/
- targetEndpoints.add("MessagesLogin");
- targetEndpoints.add("MessagesInbox");
- targetEndpoints.add("MessagesOutbox");
- targetEndpoints.add("Finish");
- PROGRESS_COUNT = targetEndpoints.size()-1;
- PROGRESS_STEP = (90/PROGRESS_COUNT);
- begin();
- });
- }
- @Override
- public void syncFeature(@NonNull Context activityContext, @NonNull SyncCallback callback, @NonNull ProfileFull profile, int ... featureList) {
- if (featureList == null) {
- sync(activityContext, callback, profile.getId(), profile, LoginStore.fromProfileFull(profile));
- return;
- }
- if (!prepare(activityContext, callback, profile.getId(), profile, LoginStore.fromProfileFull(profile)))
- return;
-
- login(() -> {
- targetEndpoints = new ArrayList<>();
- if (featureList.length == 1)
- onlyFeature = featureList[0];
- targetEndpoints.add("Me");
- targetEndpoints.add("Schools");
- targetEndpoints.add("Classes");
- targetEndpoints.add("VirtualClasses");
- targetEndpoints.add("Units");
- targetEndpoints.add("Users");
- targetEndpoints.add("Subjects");
- targetEndpoints.add("Colors");
- boolean hasMessagesLogin = false;
- for (int feature: featureList) {
- switch (feature) {
- case FEATURE_TIMETABLE:
- targetEndpoints.add("Classrooms");
- targetEndpoints.add("Substitutions");
- targetEndpoints.add("Timetables");
- break;
- case FEATURE_AGENDA:
- targetEndpoints.add("Events");
- targetEndpoints.add("CustomTypes");
- targetEndpoints.add("PtMeetings");
- targetEndpoints.add("SchoolFreeDays");
- targetEndpoints.add("TeacherFreeDays");
- break;
- case FEATURE_GRADES:
- targetEndpoints.add("SavedGradeCategories");
- targetEndpoints.add("GradesCategories");
- targetEndpoints.add("PointGradesCategories");
- targetEndpoints.add("DescriptiveGradesCategories");
- //targetEndpoints.add("TextGradesCategories");
- targetEndpoints.add("BehaviourGradesCategories"); // TODO: 2019-04-30
- targetEndpoints.add("SaveGradeCategories");
-
- targetEndpoints.add("Grades");
- targetEndpoints.add("PointGrades");
- targetEndpoints.add("DescriptiveGrades");
- targetEndpoints.add("TextGrades");
- targetEndpoints.add("BehaviourGrades");
-
- targetEndpoints.add("GradesComments");
- break;
- case FEATURE_HOMEWORK:
- targetEndpoints.add("Homework");
- break;
- case FEATURE_NOTICES:
- targetEndpoints.add("Notices");
- break;
- case FEATURE_ATTENDANCE:
- targetEndpoints.add("AttendanceTypes");
- targetEndpoints.add("Attendance");
- break;
- case FEATURE_MESSAGES_INBOX:
- if (!hasMessagesLogin) {
- hasMessagesLogin = true;
- targetEndpoints.add("MessagesLogin");
- }
- targetEndpoints.add("MessagesInbox");
- break;
- case FEATURE_MESSAGES_OUTBOX:
- if (!hasMessagesLogin) {
- hasMessagesLogin = true;
- targetEndpoints.add("MessagesLogin");
- }
- targetEndpoints.add("MessagesOutbox");
- break;
- case FEATURE_ANNOUNCEMENTS:
- targetEndpoints.add("Announcements");
- break;
- }
- }
- targetEndpoints.add("LuckyNumbers");
-
- /*if (isEndpointEnabled(profile, true, "SchoolFreeDays"))
- targetEndpoints.add("SchoolFreeDays");
- if (isEndpointEnabled(profile, true, "ClassFreeDays"))
- targetEndpoints.add("ClassFreeDays");*/
- targetEndpoints.add("Finish");
- PROGRESS_COUNT = targetEndpoints.size()-1;
- PROGRESS_STEP = (90/PROGRESS_COUNT);
- begin();
- });
- }
-
- private void begin() {
- if (profile == null) {
- finishWithError(new AppError(TAG, 214, AppError.CODE_PROFILE_NOT_FOUND, "Profile == null WTF???"));
- return;
- }
- String accountToken = profile.getStudentData("accountToken", null);
- d(TAG, "Beginning account "+ profile.getStudentNameLong() +" sync with token "+accountToken+". Full sync enabled "+fullSync);
- synergiaAccessToken = accountToken;
-
- callback.onProgress(PROGRESS_LOGIN);
-
- r("get", null);
- }
-
- private void r(String type, String endpoint) {
- // endpoint == null when beginning
- if (endpoint == null)
- endpoint = targetEndpoints.get(0);
- int index = -1;
- for (String request: targetEndpoints) {
- index++;
- if (request.equals(endpoint)) {
- break;
- }
- }
- if (type.equals("finish")) {
- // called when finishing the action
- callback.onProgress(PROGRESS_STEP);
- index++;
- }
- if (index > targetEndpoints.size()) {
- finish();
- return;
- }
- d(TAG, "Called r("+type+", "+endpoint+"). Getting "+targetEndpoints.get(index));
- switch (targetEndpoints.get(index)) {
- case "Me":
- getMe();
- break;
- case "Schools":
- getSchools();
- break;
- case "Classes":
- getClasses();
- break;
- case "VirtualClasses":
- getVirtualClasses();
- break;
- case "Units":
- getUnits();
- break;
- case "Users":
- getUsers();
- break;
- case "Subjects":
- getSubjects();
- break;
- case "Classrooms":
- getClassrooms();
- break;
- case "Timetables":
- getTimetables();
- break;
- case "Substitutions":
- getSubstitutions();
- break;
- case "Colors":
- getColors();
- break;
- case "SavedGradeCategories":
- getSavedGradeCategories();
- break;
- case "GradesCategories":
- getGradesCategories();
- break;
- case "PointGradesCategories":
- getPointGradesCategories();
- break;
- case "DescriptiveGradesCategories":
- getDescriptiveGradesSkills();
- break;
- case "TextGradesCategories":
- getTextGradesCategories();
- break;
- case "BehaviourGradesCategories":
- getBehaviourGradesCategories();
- break;
- case "SaveGradeCategories":
- saveGradeCategories();
- break;
- case "Grades":
- getGrades();
- break;
- case "PointGrades":
- getPointGrades();
- break;
- case "DescriptiveGrades":
- getDescriptiveGrades();
- break;
- case "TextGrades":
- getTextGrades();
- break;
- case "GradesComments":
- getGradesComments();
- break;
- case "BehaviourGrades":
- getBehaviourGrades();
- break;
- case "Events":
- getEvents();
- break;
- case "CustomTypes":
- getCustomTypes();
- break;
- case "Homework":
- getHomework();
- break;
- case "LuckyNumbers":
- getLuckyNumbers();
- break;
- case "Notices":
- getNotices();
- break;
- case "AttendanceTypes":
- getAttendanceTypes();
- break;
- case "Attendance":
- getAttendance();
- break;
- case "Announcements":
- getAnnouncements();
- break;
- case "PtMeetings":
- getPtMeetings();
- break;
- case "TeacherFreeDaysTypes":
- getTeacherFreeDaysTypes();
- break;
- case "TeacherFreeDays":
- getTeacherFreeDays();
- break;
- case "SchoolFreeDays":
- getSchoolFreeDays();
- break;
- case "MessagesLogin":
- getMessagesLogin();
- break;
- case "MessagesInbox":
- getMessagesInbox();
- break;
- case "MessagesOutbox":
- getMessagesOutbox();
- break;
- case "Finish":
- finish();
- break;
- }
- }
- private void saveData() {
- if (teamList.size() > 0) {
- //app.db.teamDao().clear(profileId);
- app.db.teamDao().addAll(teamList);
- }
- if (teacherList.size() > 0 && teacherListChanged)
- app.db.teacherDao().addAllIgnore(teacherList);
- if (subjectList.size() > 0)
- app.db.subjectDao().addAll(subjectList);
- if (lessonList.size() > 0) {
- app.db.lessonDao().clear(profileId);
- app.db.lessonDao().addAll(lessonList);
- }
- if (lessonChangeList.size() > 0)
- app.db.lessonChangeDao().addAll(lessonChangeList);
- if (gradeCategoryList.size() > 0 && gradeCategoryListChanged)
- app.db.gradeCategoryDao().addAll(gradeCategoryList);
- if (gradeList.size() > 0) {
- app.db.gradeDao().clear(profileId);
- app.db.gradeDao().addAll(gradeList);
- }
- if (eventList.size() > 0) {
- app.db.eventDao().removeFuture(profileId, Date.getToday());
- app.db.eventDao().addAll(eventList);
- }
- if (eventTypeList.size() > 0)
- app.db.eventTypeDao().addAll(eventTypeList);
- if (teacherAbsenceList.size() > 0)
- app.db.teacherAbsenceDao().addAll(teacherAbsenceList);
- if (noticeList.size() > 0) {
- app.db.noticeDao().clear(profileId);
- app.db.noticeDao().addAll(noticeList);
- }
- if (attendanceList.size() > 0)
- app.db.attendanceDao().addAll(attendanceList);
- if (announcementList.size() > 0)
- app.db.announcementDao().addAll(announcementList);
- if (messageList.size() > 0)
- app.db.messageDao().addAllIgnore(messageList);
- if (messageRecipientList.size() > 0)
- app.db.messageRecipientDao().addAll(messageRecipientList);
- if (messageRecipientIgnoreList.size() > 0)
- app.db.messageRecipientDao().addAllIgnore(messageRecipientIgnoreList);
- if (metadataList.size() > 0)
- app.db.metadataDao().addAllIgnore(metadataList);
- if (messageMetadataList.size() > 0)
- app.db.metadataDao().setSeen(messageMetadataList);
- }
- private void finish() {
- try {
- saveData();
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 480, CODE_OTHER, app.getString(R.string.sync_error_saving_data), null, null, e, null));
- }
- if (fullSync) {
- profile.setLastFullSync(System.currentTimeMillis());
- fullSync = false;
- }
- profile.setEmpty(false);
- callback.onSuccess(activityContext, new ProfileFull(profile, loginStore));
- }
- private void finishWithError(AppError error) {
- try {
- saveData();
- }
- catch (Exception e) {
- Crashlytics.logException(e);
- }
- callback.onError(activityContext, error);
- }
-
- /* _ _
- | | (_)
- | | ___ __ _ _ _ __
- | | / _ \ / _` | | '_ \
- | |___| (_) | (_| | | | | |
- |______\___/ \__, |_|_| |_|
- __/ |
- |__*/
- public void login(@NonNull LoginCallback loginCallback)
- {
-
- authorizeCallback = new AuthorizeCallback() {
- @Override
- public void onCsrfToken(String csrfToken) {
- d(TAG, "Found CSRF token: "+csrfToken);
- login(csrfToken, librusEmail, librusPassword, librusLoginCallback);
- }
-
- @Override
- public void onAuthorizationCode(String code) {
- d(TAG, "Found auth code: "+code);
- accessToken(code, null, accessTokenCallback);
- }
- };
-
- librusLoginCallback = redirectUrl -> {
- fakeAuthorize = "authorize";
- authorize(AUTHORIZE_URL, authorizeCallback);
- };
-
- accessTokenCallback = new AccessTokenCallback() {
- @Override
- public void onSuccess(String tokenType, String accessToken, String refreshToken, int expiresIn) {
- d(TAG, "Got tokens: "+tokenType+" "+accessToken);
- d(TAG, "Got tokens: "+refreshToken);
- loginStore.putLoginData("tokenType", tokenType);
- loginStore.putLoginData("accessToken", accessToken);
- loginStore.putLoginData("refreshToken", refreshToken);
- loginStore.putLoginData("tokenExpiryTime", System.currentTimeMillis()/1000 + expiresIn);
- getSynergiaToken(tokenType, accessToken, refreshToken, System.currentTimeMillis()/1000 + expiresIn);
- }
-
- @Override
- public void onError() {
- d(TAG, "Beginning login (authorize)");
- authorize(AUTHORIZE_URL, authorizeCallback);
- }
- };
-
- synergiaAccountsCallback = data -> {
- d(TAG, "Accounts: "+data.toString());
- JsonArray accounts = data.getAsJsonArray("accounts");
- if (accounts.size() == 0) {
- finishWithError(new AppError(TAG, 1237, CODE_OTHER, app.getString(R.string.sync_error_register_no_students), data));
- return;
- }
- long accountDataTime;
- List accountIds = new ArrayList<>();
- List accountLogins = new ArrayList<>();
- List accountTokens = new ArrayList<>();
- List accountNamesLong = new ArrayList<>();
- List accountNamesShort = new ArrayList<>();
- accountIds.clear();
- accountLogins.clear();
- accountTokens.clear();
- accountNamesLong.clear();
- accountNamesShort.clear();
- accountDataTime = data.get("lastModification").getAsLong();
- for (JsonElement accountEl: accounts) {
- JsonObject account = accountEl.getAsJsonObject();
-
- JsonElement state = account.get("state");
- if (state != null && !(state instanceof JsonNull)) {
- if (state.getAsString().equals("requiring_an_action")) {
- finishWithError(new AppError(TAG, 694, CODE_LIBRUS_DISCONNECTED, data));
- return;
- }
- if (state.getAsString().equals("need-activation")) {
- finishWithError(new AppError(TAG, 701, CODE_SYNERGIA_NOT_ACTIVATED, data));
- return;
- }
- }
-
- accountIds.add(account.get("id").getAsInt());
- accountLogins.add(account.get("login").getAsString());
- accountTokens.add(account.get("accessToken").getAsString());
- accountNamesLong.add(account.get("studentName").getAsString());
- String[] nameParts = account.get("studentName").getAsString().split(" ");
- accountNamesShort.add(nameParts[0]+" "+nameParts[1].charAt(0)+".");
- }
-
- List profileList = new ArrayList<>();
- for (int index = 0; index < accountIds.size(); index++) {
- Profile newProfile = new Profile();
- newProfile.setStudentNameLong(accountNamesLong.get(index));
- newProfile.setStudentNameShort(accountNamesShort.get(index));
- newProfile.setName(newProfile.getStudentNameLong());
- newProfile.setSubname(librusEmail);
- newProfile.setEmpty(true);
- newProfile.setLoggedIn(true);
- newProfile.putStudentData("accountId", accountIds.get(index));
- newProfile.putStudentData("accountLogin", accountLogins.get(index));
- newProfile.putStudentData("accountToken", accountTokens.get(index));
- newProfile.putStudentData("accountTokenTime", accountDataTime);
- profileList.add(newProfile);
- }
-
- callback.onLoginFirst(profileList, loginStore);
- };
-
- synergiaAccountCallback = data -> {
- if (data == null) {
- // 410 Gone
- app.cookieJar.clearForDomain("portal.librus.pl");
- authorize(AUTHORIZE_URL, authorizeCallback);
- return;
- }
- if (profile == null) {
- // this cannot be run on a fresh login
- finishWithError(new AppError(TAG, 1290, CODE_PROFILE_NOT_FOUND, "Profile == null", data));
- return;
- }
- d(TAG, "Account: "+data.toString());
- // synergiaAccount is executed when a synergia token needs a refresh
- JsonElement id = data.get("id");
- JsonElement login = data.get("login");
- JsonElement accessToken = data.get("accessToken");
- if (id == null || login == null || accessToken == null) {
- finishWithError(new AppError(TAG, 1284, CODE_OTHER, data));
- return;
- }
- profile.putStudentData("accountId", id.getAsInt());
- profile.putStudentData("accountLogin", login.getAsString());
- profile.putStudentData("accountToken", accessToken.getAsString());
- profile.putStudentData("accountTokenTime", System.currentTimeMillis() / 1000);
- profile.setStudentNameLong(data.get("studentName").getAsString());
- String[] nameParts = data.get("studentName").getAsString().split(" ");
- profile.setStudentNameShort(nameParts[0] + " " + nameParts[1].charAt(0) + ".");
- loginCallback.onSuccess();
- };
-
- String tokenType = loginStore.getLoginData("tokenType", "Bearer");
- String accessToken = loginStore.getLoginData("accessToken", null);
- String refreshToken = loginStore.getLoginData("refreshToken", null);
- long tokenExpiryTime = loginStore.getLoginData("tokenExpiryTime", (long)0);
- String accountToken;
-
- if (profile != null
- && (accountToken = profile.getStudentData("accountToken", null)) != null
- && !accountToken.equals("")
- && (System.currentTimeMillis() / 1000) - profile.getStudentData("accountTokenTime", (long)0) < 3 * 60 * 60) {
- c(TAG, "synergia token should be valid");
- loginCallback.onSuccess();
- }
- else {
- getSynergiaToken(tokenType, accessToken, refreshToken, tokenExpiryTime);
- }
- }
- private String synergiaAccessToken = "";
- private void getSynergiaToken(String tokenType, String accessToken, String refreshToken, long tokenExpiryTime) {
- c(TAG, "we have no synergia token or it expired");
- if (!tokenType.equals("")
- && refreshToken != null
- && accessToken != null
- && tokenExpiryTime-30 > System.currentTimeMillis() / 1000) {
- c(TAG, "we have a valid librus token, so we can use the API");
- // we have to decide whether we can already proceed getting the synergiaToken
- // or a list of students
- if (profile != null) {
- app.cookieJar.clearForDomain("portal.librus.pl");
- c(TAG, "user is logged in, refreshing synergia token");
- d(TAG, "Librus token: "+accessToken);
- synergiaAccount(tokenType, accessToken, profile.getStudentData("accountLogin", null), synergiaAccountCallback);
- }
- else {
- // this *should* be executed only once. ever.
- c(TAG, "user is not logged in, getting all the accounts");
- synergiaAccounts(tokenType, accessToken, synergiaAccountsCallback);
- }
- } else if (refreshToken != null) {
- c(TAG, "we don't have a valid token or it expired");
- c(TAG, "but we have a refresh token");
- d(TAG, "Token expired at " + tokenExpiryTime + ", " + (System.currentTimeMillis() / 1000 - tokenExpiryTime) + " seconds ago");
- app.cookieJar.clearForDomain("portal.librus.pl");
- accessToken(null, refreshToken, accessTokenCallback);
- } else {
- c(TAG, "we don't have any of the needed librus tokens");
- c(TAG, "we need to log in and generate");
- app.cookieJar.clearForDomain("portal.librus.pl");
- authorize(AUTHORIZE_URL, authorizeCallback);
- }
- }
- public boolean loginSynergia(@NonNull LoginCallback loginCallback)
- {
- if (profile == null) {
- return false;
- }
- if (synergiaLogin == null || synergiaPassword == null || synergiaLogin.equals("") || synergiaPassword.equals("")) {
- finishWithError(new AppError(TAG, 1152, CODE_INVALID_LOGIN, "Login field is empty"));
- return false;
- }
- if (System.currentTimeMillis() - synergiaLastLoginTime < 10 * 60 * 1000 && synergiaLogin.equals(synergiaLastLogin)) {// 10 minutes
- loginCallback.onSuccess();
- return true;
- }
-
- String escapedPassword = synergiaPassword.replace("&", "&");// TODO: 2019-05-07 check other chars to escape
-
- String body =
- "\n" +
- " \n" +
- " \n" +
- " "+synergiaLogin+" \n" +
- " "+escapedPassword+" \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " ";
- synergiaRequest("Login", body, data -> {
- if (data == null) {
- finishWithError(new AppError(TAG, 1176, AppError.CODE_MAINTENANCE, "data == null (975)"));
- return;
- }
- String error = data.select("response Login status").text();
- if (error.equals("ok")) {
- synergiaLastLoginTime = System.currentTimeMillis();
- synergiaLastLogin = synergiaLogin;
- loginCallback.onSuccess();
- }
- else {
- finishWithError(new AppError(TAG, 1186, CODE_INVALID_LOGIN, (Response) null, data.outerHtml()));
- }
- });
- return true;
- }
-
- /* _ _ _ _ _ _ _
- | | | | | | ___ | | | | | |
- | |__| | ___| |_ __ ___ _ __ ___ ( _ ) ___ __ _| | | |__ __ _ ___| | _____
- | __ |/ _ \ | '_ \ / _ \ '__/ __| / _ \/\ / __/ _` | | | '_ \ / _` |/ __| |/ / __|
- | | | | __/ | |_) | __/ | \__ \ | (_> < | (_| (_| | | | |_) | (_| | (__| <\__ \
- |_| |_|\___|_| .__/ \___|_| |___/ \___/\/ \___\__,_|_|_|_.__/ \__,_|\___|_|\_\___/
- | |
- |*/
- private String fakeAuthorize = "authorize";
- private void authorize(String url, AuthorizeCallback authorizeCallback) {
- callback.onActionStarted(R.string.sync_action_authorizing);
- Request.builder()
- .url(fakeLogin ? "http://szkolny.eu/librus/"+fakeAuthorize+".php" : url)
- .userAgent(userAgent)
- .withClient(app.httpLazy)
- .callback(new TextCallbackHandler() {
- @Override
- public void onSuccess(String data, Response response) {
- //d("headers "+response.headers().toString());
- String location = response.headers().get("Location");
- if (location != null) {
- Matcher authMatcher = Pattern.compile(REDIRECT_URL+"\\?code=([A-z0-9]+?)$", Pattern.DOTALL | Pattern.MULTILINE).matcher(location);
- if (authMatcher.find()) {
- authorizeCallback.onAuthorizationCode(authMatcher.group(1));
- }
- else {
- //callback.onError(activityContext, Edziennik.CODE_OTHER, "Auth code not found: "+location);
- authorize(location, authorizeCallback);
- }
- }
- else {
- Matcher csrfMatcher = Pattern.compile("name=\"csrf-token\" content=\"([A-z0-9=+/\\-_]+?)\"", Pattern.DOTALL).matcher(data);
- if (csrfMatcher.find()) {
- authorizeCallback.onCsrfToken(csrfMatcher.group(1));
- }
- else {
- finishWithError(new AppError(TAG, 463, CODE_OTHER, "CSRF token not found.", response, data));
- }
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 207, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- private void login(String csrfToken, String email, String password, LibrusLoginCallback librusLoginCallback) {
- callback.onActionStarted(R.string.sync_action_logging_in);
- Request.builder()
- .url(fakeLogin ? "http://szkolny.eu/librus/login_action.php" : LOGIN_URL)
- .userAgent(userAgent)
- .addParameter("email", email)
- .addParameter("password", password)
- .addHeader("X-CSRF-TOKEN", csrfToken)
- .contentType(MediaTypeUtils.APPLICATION_JSON)
- .post()
- .callback(new JsonCallbackHandler() {
- @Override
- public void onSuccess(JsonObject data, Response response) {
- if (data == null) {
- if (response.parserErrorBody != null && response.parserErrorBody.contains("link aktywacyjny")) {
- finishWithError(new AppError(TAG, 487, CODE_LIBRUS_NOT_ACTIVATED, response));
- return;
- }
- finishWithError(new AppError(TAG, 489, CODE_MAINTENANCE, response));
- return;
- }
- if (data.get("errors") != null) {
- finishWithError(new AppError(TAG, 490, CODE_OTHER, data.get("errors").getAsJsonArray().get(0).getAsString(), response, data));
- return;
- }
- librusLoginCallback.onLogin(data.get("redirect") != null ? data.get("redirect").getAsString() : "");
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- if (response.code() == 403
- || response.code() == 401) {
- finishWithError(new AppError(TAG, 248, AppError.CODE_INVALID_LOGIN, response, throwable));
- return;
- }
- finishWithError(new AppError(TAG, 251, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- private boolean refreshTokenFailed = false;
- private void accessToken(String code, String refreshToken, AccessTokenCallback accessTokenCallback) {
- callback.onActionStarted(R.string.sync_action_getting_token);
- List> params = new ArrayList<>();
- params.add(new Pair<>("client_id", CLIENT_ID));
- if (code != null) {
- params.add(new Pair<>("grant_type", "authorization_code"));
- params.add(new Pair<>("code", code));
- params.add(new Pair<>("redirect_uri", REDIRECT_URL));
- }
- else if (refreshToken != null) {
- params.add(new Pair<>("grant_type", "refresh_token"));
- params.add(new Pair<>("refresh_token", refreshToken));
- }
- Request.builder()
- .url(fakeLogin ? "http://szkolny.eu/librus/access_token.php" : TOKEN_URL)
- .userAgent(userAgent)
- .addParams(params)
- .allowErrorCode(HTTP_UNAUTHORIZED)
- .post()
- .callback(new JsonCallbackHandler() {
- @Override
- public void onSuccess(JsonObject data, Response response) {
- if (data == null) {
- finishWithError(new AppError(TAG, 539, CODE_MAINTENANCE, response));
- return;
- }
- if (data.get("error") != null) {
- JsonElement message = data.get("message");
- JsonElement hint = data.get("hint");
- if (!refreshTokenFailed && refreshToken != null && hint != null && (hint.getAsString().equals("Token has been revoked") || hint.getAsString().equals("Token has expired"))) {
- c(TAG, "refreshing the token failed. Trying to log in again.");
- refreshTokenFailed = true;
- accessTokenCallback.onError();
- return;
- }
- String errorText = data.get("error").getAsString()+" "+(message == null ? "" : message.getAsString())+" "+(hint == null ? "" : hint.getAsString());
- finishWithError(new AppError(TAG, 552, CODE_OTHER, errorText, response, data));
- return;
- }
- try {
- accessTokenCallback.onSuccess(
- data.get("token_type").getAsString(),
- data.get("access_token").getAsString(),
- data.get("refresh_token").getAsString(),
- data.get("expires_in").getAsInt());
- }
- catch (NullPointerException e) {
- finishWithError(new AppError(TAG, 311, CODE_OTHER, response, e, data));
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 317, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- private void synergiaAccounts(String tokenType, String accessToken, SynergiaAccountsCallback synergiaAccountsCallback) {
- callback.onActionStarted(R.string.sync_action_getting_accounts);
- Request.builder()
- .url(fakeLogin ? "http://szkolny.eu/librus/synergia_accounts.php" : ACCOUNTS_URL)
- .userAgent(userAgent)
- .addHeader("Authorization", tokenType+" "+accessToken)
- .get()
- .allowErrorCode(HTTP_FORBIDDEN)
- .allowErrorCode(HTTP_UNAUTHORIZED)
- .allowErrorCode(HTTP_BAD_REQUEST)
- .callback(new JsonCallbackHandler() {
- @Override
- public void onSuccess(JsonObject data, Response response) {
- if (data == null) {
- finishWithError(new AppError(TAG, 590, CODE_MAINTENANCE, response));
- return;
- }
- if (data.get("error") != null) {
- JsonElement message = data.get("message");
- JsonElement hint = data.get("hint");
- String errorText = data.get("error").getAsString()+" "+(message == null ? "" : message.getAsString())+" "+(hint == null ? "" : hint.getAsString());
- finishWithError(new AppError(TAG, 597, CODE_OTHER, errorText, response, data));
- return;
- }
- try {
- synergiaAccountsCallback.onSuccess(data);
- }
- catch (NullPointerException e) {
- e.printStackTrace();
- finishWithError(new AppError(TAG, 358, CODE_OTHER, response, e, data));
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 364, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- private boolean error410 = false;
-
- private void synergiaAccount(String tokenType, String accessToken, String accountLogin, SynergiaAccountCallback synergiaAccountCallback) {
- callback.onActionStarted(R.string.sync_action_getting_account);
- d(TAG, "Requesting "+(fakeLogin ? "http://szkolny.eu/librus/synergia_accounts_fresh.php?login="+accountLogin : ACCOUNT_URL+accountLogin));
- if (accountLogin == null) { // just for safety
- synergiaAccounts(tokenType, accessToken, synergiaAccountsCallback);
- return;
- }
- Request.builder()
- .url(fakeLogin ? "http://szkolny.eu/librus/synergia_accounts_fresh.php?login="+accountLogin : ACCOUNT_URL+accountLogin)
- .userAgent(userAgent)
- .addHeader("Authorization", tokenType+" "+accessToken)
- .get()
- .allowErrorCode(HTTP_NOT_FOUND)
- .allowErrorCode(HTTP_FORBIDDEN)
- .allowErrorCode(HTTP_UNAUTHORIZED)
- .allowErrorCode(HTTP_BAD_REQUEST)
- .allowErrorCode(HTTP_GONE)
- .callback(new JsonCallbackHandler() {
- @Override
- public void onSuccess(JsonObject data, Response response) {
- if (data == null) {
- finishWithError(new AppError(TAG, 641, CODE_MAINTENANCE, response));
- return;
- }
- if (response.code() == 410 && !error410) {
- JsonElement reason = data.get("reason");
- if (reason != null && !(reason instanceof JsonNull) && reason.getAsString().equals("requires_an_action")) {
- finishWithError(new AppError(TAG, 1078, CODE_LIBRUS_DISCONNECTED, response, data));
- return;
- }
- error410 = true;
- synergiaAccountCallback.onSuccess(null);
- return;
- }
- if (data.get("message") != null) {
- String message = data.get("message").getAsString();
- if (message.equals("Account not found")) {
- finishWithError(new AppError(TAG, 651, CODE_OTHER, app.getString(R.string.sync_error_register_student_not_associated_format, profile.getStudentNameLong(), accountLogin), response, data));
- return;
- }
- finishWithError(new AppError(TAG, 654, CODE_OTHER, message+"\n\n"+accountLogin, response, data));
- return;
- }
- if (response.code() == HTTP_OK) {
- try {
- synergiaAccountCallback.onSuccess(data);
- } catch (NullPointerException e) {
- e.printStackTrace();
- finishWithError(new AppError(TAG, 662, CODE_OTHER, response, e, data));
- }
- }
- else {
- finishWithError(new AppError(TAG, 425, CODE_OTHER, response, data));
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 432, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- private int failed = 0;
-
- private void apiRequest(String endpoint, ApiRequestCallback apiRequestCallback) {
- d(TAG, "Requesting "+API_URL+endpoint);
- Request.builder()
- .url(fakeLogin ? "http://szkolny.eu/librus/api/"+endpoint : API_URL+endpoint)
- .userAgent(userAgent)
- .addHeader("Authorization", "Bearer "+synergiaAccessToken)
- .get()
- .allowErrorCode(HTTP_FORBIDDEN)
- .allowErrorCode(HTTP_UNAUTHORIZED)
- .allowErrorCode(HTTP_BAD_REQUEST)
- .callback(new JsonCallbackHandler() {
- @Override
- public void onSuccess(JsonObject data, Response response) {
- if (data == null) {
- if (response.parserErrorBody != null && response.parserErrorBody.equals("Nieprawidłowy węzeł.")) {
- apiRequestCallback.onSuccess(null);
- return;
- }
- finishWithError(new AppError(TAG, 453, CODE_MAINTENANCE, response));
- return;
- }
- if (data.get("Status") != null) {
- JsonElement message = data.get("Message");
- JsonElement code = data.get("Code");
- d(TAG, "apiRequest Error "+data.get("Status").getAsString()+" "+(message == null ? "" : message.getAsString())+" "+(code == null ? "" : code.getAsString())+"\n\n"+response.request().url().toString());
- if (message != null && !(message instanceof JsonNull) && message.getAsString().equals("Student timetable is not public")) {
- try {
- apiRequestCallback.onSuccess(null);
- }
- catch (NullPointerException e) {
- e.printStackTrace();
- d(TAG, "apiRequest exception "+e.getMessage());
- finishWithError(new AppError(TAG, 503, CODE_OTHER, response, e, data));
- }
- return;
- }
- if (code != null
- && !(code instanceof JsonNull)
- && (code.getAsString().equals("LuckyNumberIsNotActive")
- || code.getAsString().equals("NotesIsNotActive")
- || code.getAsString().equals("AccessDeny"))
- ) {
- try {
- apiRequestCallback.onSuccess(null);
- }
- catch (NullPointerException e) {
- e.printStackTrace();
- d(TAG, "apiRequest exception "+e.getMessage());
- finishWithError(new AppError(TAG, 504, CODE_OTHER, response, e, data));
- }
- return;
- }
- String errorText = data.get("Status").getAsString()+" "+(message == null ? "" : message.getAsString())+" "+(code == null ? "" : code.getAsString());
- if (code != null && !(code instanceof JsonNull) && code.getAsString().equals("TokenIsExpired")) {
- failed++;
- d(TAG, "Trying to refresh synergia token, api request failed "+failed+" times now");
- if (failed > 1) {
- d(TAG, "Giving up, failed "+failed+" times");
- finishWithError(new AppError(TAG, 485, CODE_OTHER, errorText, response, data));
- return;
- }
- String tokenType = loginStore.getLoginData("tokenType", "Bearer");
- String accessToken = loginStore.getLoginData("accessToken", null);
- String refreshToken = loginStore.getLoginData("refreshToken", null);
- long tokenExpiryTime = loginStore.getLoginData("tokenExpiryTime", (long)0);
- getSynergiaToken(tokenType, accessToken, refreshToken, tokenExpiryTime);
- return;
- }
- finishWithError(new AppError(TAG, 497, CODE_OTHER, errorText, response, data));
- return;
- }
- try {
- apiRequestCallback.onSuccess(data);
- }
- catch (NullPointerException e) {
- e.printStackTrace();
- d(TAG, "apiRequest exception "+e.getMessage());
- finishWithError(new AppError(TAG, 505, CODE_OTHER, response, e, data));
- }
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- if (response.code() == 405) {
- // method not allowed
- finishWithError(new AppError(TAG, 511, CODE_OTHER, response, throwable));
- return;
- }
- if (response.code() == 500) {
- // TODO: 2019-09-10 dirty hotfix
- if ("Classrooms".equals(endpoint)) {
- apiRequestCallback.onSuccess(null);
- return;
- }
- finishWithError(new AppError(TAG, 516, CODE_MAINTENANCE, response, throwable));
- return;
- }
- finishWithError(new AppError(TAG, 520, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- private void synergiaRequest(String endpoint, String body, SynergiaRequestCallback synergiaRequestCallback) {
- d(TAG, "Requesting "+SYNERGIA_URL+endpoint);
- Request.builder()
- .url(SYNERGIA_URL+endpoint)
- .userAgent(synergiaUserAgent)
- .setTextBody(body, MediaTypeUtils.APPLICATION_XML)
- .callback(new TextCallbackHandler() {
- @Override
- public void onSuccess(String data, Response response) {
- if ((data.contains("error ") || data.contains("")) && !data.contains("Niepoprawny")) {
- finishWithError(new AppError(TAG, 541, AppError.CODE_MAINTENANCE, response, data));
- return;
- }
- synergiaRequestCallback.onSuccess(Jsoup.parse(data, "", Parser.xmlParser()));
- }
-
- @Override
- public void onFailure(Response response, Throwable throwable) {
- finishWithError(new AppError(TAG, 556, CODE_OTHER, response, throwable));
- }
- })
- .build()
- .enqueue();
- }
-
- // CALLBACKS & INTERFACES
- private interface AuthorizeCallback {
- void onCsrfToken(String csrfToken);
- void onAuthorizationCode(String code);
- }
- private interface LibrusLoginCallback {
- void onLogin(String redirectUrl);
- }
- private interface AccessTokenCallback {
- void onSuccess(String tokenType, String accessToken, String refreshToken, int expiresIn);
- void onError();
- }
- private interface SynergiaAccountsCallback {
- void onSuccess(JsonObject data);
- }
- private interface SynergiaAccountCallback {
- void onSuccess(JsonObject data);
- }
- private interface ApiRequestCallback {
- void onSuccess(JsonObject data);
- }
- private interface SynergiaRequestCallback {
- void onSuccess(Document data);
- }
-
- private AuthorizeCallback authorizeCallback;
- private LibrusLoginCallback librusLoginCallback;
- private AccessTokenCallback accessTokenCallback;
- private SynergiaAccountsCallback synergiaAccountsCallback;
- private SynergiaAccountCallback synergiaAccountCallback;
-
- /* _____ _ _____ _
- | __ \ | | | __ \ | |
- | | | | __ _| |_ __ _ | |__) |___ __ _ _ _ ___ ___| |_ ___
- | | | |/ _` | __/ _` | | _ // _ \/ _` | | | |/ _ \/ __| __/ __|
- | |__| | (_| | || (_| | | | \ \ __/ (_| | |_| | __/\__ \ |_\__ \
- |_____/ \__,_|\__\__,_| |_| \_\___|\__, |\__,_|\___||___/\__|___/
- | |
- |*/
- private void getMe() {
- if (!fullSync) {
- r("finish", "Me");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_account_info);
- apiRequest("Me", data -> {
- JsonObject me = data.get("Me").getAsJsonObject();
- me = me.get("Account").getAsJsonObject();
- //d("Got School: "+school.toString());
- try {
- boolean premium = me.get("IsPremium").getAsBoolean();
- boolean premiumDemo = me.get("IsPremiumDemo").getAsBoolean();
- this.premium = premium || premiumDemo;
- profile.putStudentData("isPremium", premium || premiumDemo);
- r("finish", "Me");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1316, CODE_OTHER, e, data));
- }
- });
- }
-
- private Map> lessonRanges = new HashMap<>();
- private String schoolName = "";
- private void getSchools() {
- if (!fullSync) {
- try {
- lessonRanges = app.gson.fromJson(profile.getStudentData("lessonRanges", "{}"), new TypeToken>>() {
- }.getType());
- if (lessonRanges != null && lessonRanges.size() > 0) {
- r("finish", "Schools");
- return;
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- lessonRanges = new HashMap<>();
- callback.onActionStarted(R.string.sync_action_syncing_school_info);
- apiRequest("Schools", data -> {
- //d("Got School: "+school.toString());
- try {
- JsonObject school = data.get("School").getAsJsonObject();
- int schoolId = school.get("Id").getAsInt();
- String schoolNameLong = school.get("Name").getAsString();
- StringBuilder schoolNameShort = new StringBuilder();
- for (String schoolNamePart: schoolNameLong.split(" ")) {
- if (schoolNamePart.isEmpty())
- continue;
- schoolNameShort.append(Character.toLowerCase(schoolNamePart.charAt(0)));
- }
- String schoolTown = school.get("Town").getAsString();
- schoolName = schoolId+schoolNameShort.toString()+"_"+schoolTown.toLowerCase();
- profile.putStudentData("schoolName", schoolName);
-
- lessonRanges.clear();
- int index = 0;
- for (JsonElement lessonRangeEl: school.get("LessonsRange").getAsJsonArray()) {
- JsonObject lr = lessonRangeEl.getAsJsonObject();
- JsonElement from = lr.get("From");
- JsonElement to = lr.get("To");
- if (from != null && to != null && !(from instanceof JsonNull) && !(to instanceof JsonNull)) {
- lessonRanges.put(index, new Pair<>(Time.fromH_m(from.getAsString()), Time.fromH_m(to.getAsString())));
- }
- index++;
- }
- profile.putStudentData("lessonRanges", app.gson.toJson(lessonRanges));
- r("finish", "Schools");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1364, CODE_OTHER, e, data));
- }
- });
- }
-
- private long teamClassId = -1;
- private void getClasses() {
- if (!fullSync) {
- r("finish", "Classes");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_class);
- apiRequest("Classes", data -> {
- //d("Got Class: "+myClass.toString());
- try {
- JsonObject myClass = data.get("Class").getAsJsonObject();
- String teamName = myClass.get("Number").getAsString()
- + myClass.get("Symbol").getAsString();
- teamClassId = myClass.get("Id").getAsLong();
- teamList.add(new Team(
- profileId,
- teamClassId,
- teamName,
- 1,
- schoolName+":"+teamName,
- myClass.get("ClassTutor").getAsJsonObject().get("Id").getAsLong()));
- JsonElement semester1Begin = myClass.get("BeginSchoolYear");
- JsonElement semester2Begin = myClass.get("EndFirstSemester");
- JsonElement yearEnd = myClass.get("EndSchoolYear");
- if (semester1Begin != null
- && semester2Begin != null
- && yearEnd != null
- && !(semester1Begin instanceof JsonNull)
- && !(semester2Begin instanceof JsonNull)
- && !(yearEnd instanceof JsonNull)) {
- profile.setDateSemester1Start(Date.fromY_m_d(semester1Begin.getAsString()));
- profile.setDateSemester2Start(Date.fromY_m_d(semester2Begin.getAsString()));
- profile.setDateYearEnd(Date.fromY_m_d(yearEnd.getAsString()));
- }
- JsonElement unit = myClass.get("Unit");
- if (unit != null && !(unit instanceof JsonNull)) {
- unitId = unit.getAsJsonObject().get("Id").getAsLong();
- profile.putStudentData("unitId", unitId);
- }
- r("finish", "Classes");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1411, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getVirtualClasses() {
- if (!fullSync) {
- r("finish", "VirtualClasses");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_teams);
- apiRequest("VirtualClasses", data -> {
- if (data == null) {
- r("finish", "VirtualClasses");
- return;
- }
- try {
- JsonArray classes = data.get("VirtualClasses").getAsJsonArray();
- for (JsonElement myClassEl: classes) {
- JsonObject myClass = myClassEl.getAsJsonObject();
- String teamName = myClass.get("Name").getAsString();
- long teamId = myClass.get("Id").getAsLong();
- long teacherId = -1;
- JsonElement el;
- if ((el = myClass.get("Teacher")) != null) {
- teacherId = el.getAsJsonObject().get("Id").getAsLong();
- }
- teamList.add(new Team(
- profileId,
- teamId,
- teamName,
- 2,
- schoolName + ":" + teamName,
- teacherId));
- }
- r("finish", "VirtualClasses");
- } catch (Exception e) {
- finishWithError(new AppError(TAG, 1449, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getUnits() {
- if (!fullSync) {
- enableStandardGrades = profile.getStudentData("enableStandardGrades", true);
- enablePointGrades = profile.getStudentData("enablePointGrades", false);
- enableDescriptiveGrades = profile.getStudentData("enableDescriptiveGrades", false);
- enableTextGrades = profile.getStudentData("enableTextGrades", false);
- enableBehaviourGrades = profile.getStudentData("enableBehaviourGrades", true);
- startPointsSemester1 = profile.getStudentData("startPointsSemester1", 0);
- startPointsSemester2 = profile.getStudentData("startPointsSemester2", 0);
- r("finish", "Units");
- return;
- }
- d(TAG, "Grades settings: "+enableStandardGrades+", "+enablePointGrades+", "+enableDescriptiveGrades);
- callback.onActionStarted(R.string.sync_action_syncing_school_info);
- apiRequest("Units", data -> {
- if (data == null) {
- r("finish", "Units");
- return;
- }
- JsonArray units = data.getAsJsonArray("Units");
- try {
- long unitId = profile.getStudentData("unitId", (long)-1);
- enableStandardGrades = true; // once a week or two (during a full sync) force getting the standard grade list. If there aren't any, disable it again later.
- enableBehaviourGrades = true;
- enableTextGrades = true; // TODO: 2019-05-13 if "DescriptiveGradesEnabled" are also TextGrades
- profile.putStudentData("enableStandardGrades", true);
- profile.putStudentData("enableBehaviourGrades", true);
- profile.putStudentData("enableTextGrades", true);
- for (JsonElement unitEl: units) {
- JsonObject unit = unitEl.getAsJsonObject();
-
- if (unit.get("Id").getAsLong() == unitId) {
- JsonObject gradesSettings = unit.getAsJsonObject("GradesSettings");
- enablePointGrades = gradesSettings.get("PointGradesEnabled").getAsBoolean();
- enableDescriptiveGrades = gradesSettings.get("DescriptiveGradesEnabled").getAsBoolean();
-
- JsonObject behaviourGradesSettings = unit.getAsJsonObject("BehaviourGradesSettings");
- JsonObject startPoints = behaviourGradesSettings.getAsJsonObject("StartPoints");
-
- startPointsSemester1 = startPoints.get("Semester1").getAsInt();
- JsonElement startPointsSemester2El;
- if ((startPointsSemester2El = startPoints.get("Semester2")) != null) {
- startPointsSemester2 = startPointsSemester2El.getAsInt();
- }
- else {
- startPointsSemester2 = startPointsSemester1;
- }
-
- profile.putStudentData("enablePointGrades", enablePointGrades);
- profile.putStudentData("enableDescriptiveGrades", enableDescriptiveGrades);
- profile.putStudentData("startPointsSemester1", startPointsSemester1);
- profile.putStudentData("startPointsSemester2", startPointsSemester2);
- break;
- }
- }
- d(TAG, "Grades settings: "+enableStandardGrades+", "+enablePointGrades+", "+enableDescriptiveGrades);
- r("finish", "Units");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1506, CODE_OTHER, e, data));
- }
- });
- }
-
- private boolean teacherListChanged = false;
- private void getUsers() {
- if (!fullSync) {
- r("finish", "Users");
- teacherList = app.db.teacherDao().getAllNow(profileId);
- teacherListChanged = false;
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_users);
- apiRequest("Users", data -> {
- if (data == null) {
- r("finish", "Users");
- return;
- }
- JsonArray users = data.get("Users").getAsJsonArray();
- //d("Got Users: "+users.toString());
- try {
- teacherListChanged = true;
- for (JsonElement userEl : users) {
- JsonObject user = userEl.getAsJsonObject();
- JsonElement firstName = user.get("FirstName");
- JsonElement lastName = user.get("LastName");
- teacherList.add(new Teacher(
- profileId,
- user.get("Id").getAsLong(),
- firstName instanceof JsonNull ? "" : firstName.getAsString(),
- lastName instanceof JsonNull ? "" : lastName.getAsString()
- ));
- }
- r("finish", "Users");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1544, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getSubjects() {
- if (!fullSync) {
- r("finish", "Subjects");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_subjects);
- apiRequest("Subjects", data -> {
- if (data == null) {
- r("finish", "Subjects");
- return;
- }
- JsonArray subjects = data.get("Subjects").getAsJsonArray();
- //d("Got Subjects: "+subjects.toString());
- try {
- for (JsonElement subjectEl : subjects) {
- JsonObject subject = subjectEl.getAsJsonObject();
- JsonElement longName = subject.get("Name");
- JsonElement shortName = subject.get("Short");
- subjectList.add(new Subject(
- profileId,
- subject.get("Id").getAsLong(),
- longName instanceof JsonNull ? "" : longName.getAsString(),
- shortName instanceof JsonNull ? "" : shortName.getAsString()
- ));
- }
- subjectList.add(new Subject(
- profileId,
- 1,
- "Zachowanie",
- "zach"
- ));
- r("finish", "Subjects");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1588, CODE_OTHER, e, data));
- }
- });
- }
-
- private SparseArray classrooms = new SparseArray<>();
- private void getClassrooms() {
- //if (!fullSync)
- // r("finish", "Classrooms");
- callback.onActionStarted(R.string.sync_action_syncing_classrooms);
- apiRequest("Classrooms", data -> {
- if (data == null) {
- r("finish", "Classrooms");
- return;
- }
- if (data.get("Classrooms") == null) {
- r("finish", "Classrooms");
- return;
- }
- JsonArray jClassrooms = data.get("Classrooms").getAsJsonArray();
- //d("Got Classrooms: "+jClassrooms.toString());
- classrooms.clear();
- try {
- for (JsonElement classroomEl : jClassrooms) {
- JsonObject classroom = classroomEl.getAsJsonObject();
- classrooms.put(classroom.get("Id").getAsInt(), classroom.get("Name").getAsString());
- }
- r("finish", "Classrooms");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1617, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getTimetables() {
- callback.onActionStarted(R.string.sync_action_syncing_timetable);
- Date weekStart = Week.getWeekStart();
- if (Date.getToday().getWeekDay() > 4) {
- weekStart.stepForward(0, 0, 7);
- }
- apiRequest("Timetables?weekStart="+weekStart.getStringY_m_d(), data -> {
- if (data == null) {
- r("finish", "Timetables");
- return;
- }
- JsonObject timetables = data.get("Timetable").getAsJsonObject();
- try {
- for (Map.Entry dayEl: timetables.entrySet()) {
- JsonArray day = dayEl.getValue().getAsJsonArray();
- Date lessonDate = Date.fromY_m_d(dayEl.getKey());
- for (JsonElement lessonGroupEl: day) {
- if ((lessonGroupEl instanceof JsonArray && ((JsonArray) lessonGroupEl).size() == 0) || lessonGroupEl instanceof JsonNull || lessonGroupEl == null) {
- continue;
- }
- JsonArray lessonGroup = lessonGroupEl.getAsJsonArray();
- for (JsonElement lessonEl: lessonGroup) {
- if ((lessonEl instanceof JsonArray && ((JsonArray) lessonEl).size() == 0) || lessonEl instanceof JsonNull || lessonEl == null) {
- continue;
- }
- JsonObject lesson = lessonEl.getAsJsonObject();
-
- boolean substitution = false;
- boolean cancelled = false;
- JsonElement isSubstitutionClass;
- if ((isSubstitutionClass = lesson.get("IsSubstitutionClass")) != null) {
- substitution = isSubstitutionClass.getAsBoolean();
- }
- JsonElement isCanceled;
- if ((isCanceled = lesson.get("IsCanceled")) != null) {
- cancelled = isCanceled.getAsBoolean();
- }
-
- if (substitution && cancelled) {
- // the lesson is probably shifted. Skip this one
- continue;
- }
-
- Time startTime = null;
- Time endTime = null;
- try {
- startTime = Time.fromH_m(lesson.get(substitution && !cancelled ? "OrgHourFrom" : "HourFrom").getAsString());
- endTime = Time.fromH_m(lesson.get(substitution && !cancelled ? "OrgHourTo" : "HourTo").getAsString());
- }
- catch (Exception ignore) {
- try {
- JsonElement lessonNo;
- if (!((lessonNo = lesson.get("LessonNo")) instanceof JsonNull)) {
- Pair timePair = lessonRanges.get(strToInt(lessonNo.getAsString()));
- if (timePair != null) {
- startTime = timePair.first;
- endTime = timePair.second;
- }
- }
- }
- catch (Exception ignore2) { }
- }
-
-
- Lesson lessonObject = new Lesson(
- profileId,
- lesson.get("DayNo").getAsInt() - 1,
- startTime,
- endTime
- );
-
- JsonElement subject;
- if ((subject = lesson.get(substitution && !cancelled ? "OrgSubject" : "Subject")) != null) {
- lessonObject.subjectId = subject.getAsJsonObject().get("Id").getAsLong();
- }
-
- JsonElement teacher;
- if ((teacher = lesson.get(substitution && !cancelled ? "OrgTeacher" : "Teacher")) != null) {
- lessonObject.teacherId = teacher.getAsJsonObject().get("Id").getAsLong();
- }
-
- JsonElement myClass;
- if ((myClass = lesson.get("Class")) != null) {
- lessonObject.teamId = myClass.getAsJsonObject().get("Id").getAsLong();
- }
- if (myClass == null && (myClass = lesson.get("VirtualClass")) != null) {
- lessonObject.teamId = myClass.getAsJsonObject().get("Id").getAsLong();
- }
-
- JsonElement classroom;
- JsonElement substitutionClassroom;
- if (substitution && !cancelled) {
- classroom = lesson.get("OrgClassroom");
- substitutionClassroom = lesson.get("Classroom");
-
- if (classroom != null)
- lessonObject.classroomName = classrooms.get(classroom.getAsJsonObject().get("Id").getAsInt());
-
- if (substitutionClassroom != null) {
- for (LessonChange lessonChange : lessonChangeList) {
- if(lessonChange.lessonDate.compareTo(lessonDate) == 0) {
- lessonChange.classroomName
- = classrooms.get(substitutionClassroom.getAsJsonObject().get("Id").getAsInt());
- break;
- }
- }
- }
- } else {
- classroom = lesson.get("Classroom");
- if (classroom != null)
- lessonObject.classroomName = classrooms.get(classroom.getAsJsonObject().get("Id").getAsInt());
- }
-
- lessonList.add(lessonObject);
- }
- }
- }
- r("finish", "Timetables");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1704, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getSubstitutions() {
- callback.onActionStarted(R.string.sync_action_syncing_timetable_changes);
- apiRequest("Calendars/Substitutions", data -> {
- if (data == null) {
- r("finish", "Substitutions");
- return;
- }
-
- JsonArray substitutions = data.get("Substitutions").getAsJsonArray();
- try {
- List ignoreList = new ArrayList<>();
- for (JsonElement substitutionEl : substitutions) {
- JsonObject substitution = substitutionEl.getAsJsonObject();
-
- String str_date = substitution.get("OrgDate").getAsString();
- Date lessonDate = Date.fromY_m_d(str_date);
-
- Time startTime = Time.getNow();
- JsonElement lessonNo;
- if (!((lessonNo = substitution.get("OrgLessonNo")) instanceof JsonNull)) {
- Pair timePair = lessonRanges.get(lessonNo.getAsInt());
- if (timePair != null)
- startTime = timePair.first;
- }
-
- JsonElement isShifted;
- JsonElement isCancelled;
- if ((isShifted = substitution.get("IsShifted")) != null && isShifted.getAsBoolean()) {
- // a lesson is shifted
- // add a TYPE_CANCELLED for the source lesson and a TYPE_CHANGE for the destination lesson
-
- // source lesson: cancel
- LessonChange lessonCancelled = new LessonChange(profileId, lessonDate, startTime, startTime.clone().stepForward(0, 45, 0));
- lessonCancelled.type = TYPE_CANCELLED;
- lessonChangeList.add(lessonCancelled);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_LESSON_CHANGE, lessonCancelled.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
-
- // target lesson: change
- startTime = Time.getNow();
- if (!((lessonNo = substitution.get("LessonNo")) instanceof JsonNull)) {
- Pair timePair = lessonRanges.get(lessonNo.getAsInt());
- if (timePair != null)
- startTime = timePair.first;
- }
-
- LessonChange lessonChanged = new LessonChange(profileId, lessonDate, startTime, startTime.clone().stepForward(0, 45, 0));
- lessonChanged.type = TYPE_CHANGE;
- JsonElement subject;
- if ((subject = substitution.get("Subject")) != null) {
- lessonChanged.subjectId = subject.getAsJsonObject().get("Id").getAsLong();
- }
- JsonElement teacher;
- if ((teacher = substitution.get("Teacher")) != null) {
- lessonChanged.teacherId = teacher.getAsJsonObject().get("Id").getAsLong();
- }
- JsonElement myClass;
- if ((myClass = substitution.get("Class")) != null) {
- lessonChanged.teamId = myClass.getAsJsonObject().get("Id").getAsLong();
- }
- if (myClass == null && (myClass = substitution.get("VirtualClass")) != null) {
- lessonChanged.teamId = myClass.getAsJsonObject().get("Id").getAsLong();
- }
- lessonChangeList.add(lessonChanged);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_LESSON_CHANGE, lessonChanged.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
-
- // ignore the target lesson in further array elements - it's already changed
- ignoreList.add(lessonChanged.lessonDate.combineWith(lessonChanged.startTime));
- }
- else if ((isCancelled = substitution.get("IsCancelled")) != null && isCancelled.getAsBoolean()) {
- LessonChange lessonChange = new LessonChange(profileId, lessonDate, startTime, startTime.clone().stepForward(0, 45, 0));
- // if it's actually a lesson shift - ignore the target lesson cancellation
- if (ignoreList.size() > 0 && ignoreList.contains(lessonChange.lessonDate.combineWith(lessonChange.startTime)))
- continue;
- lessonChange.type = TYPE_CANCELLED;
- lessonChangeList.add(lessonChange);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_LESSON_CHANGE, lessonChange.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
- else {
- LessonChange lessonChange = new LessonChange(profileId, lessonDate, startTime, startTime.clone().stepForward(0, 45, 0));
-
- lessonChange.type = TYPE_CHANGE;
-
- JsonElement subject;
- if ((subject = substitution.get("Subject")) != null) {
- lessonChange.subjectId = subject.getAsJsonObject().get("Id").getAsLong();
- }
- JsonElement teacher;
- if ((teacher = substitution.get("Teacher")) != null) {
- lessonChange.teacherId = teacher.getAsJsonObject().get("Id").getAsLong();
- }
-
- JsonElement myClass;
- if ((myClass = substitution.get("Class")) != null) {
- lessonChange.teamId = myClass.getAsJsonObject().get("Id").getAsLong();
- }
- if (myClass == null && (myClass = substitution.get("VirtualClass")) != null) {
- lessonChange.teamId = myClass.getAsJsonObject().get("Id").getAsLong();
- }
-
- lessonChangeList.add(lessonChange);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_LESSON_CHANGE, lessonChange.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
-
- }
- r("finish", "Substitutions");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1822, CODE_OTHER, e, data));
- }
- });
- }
-
- private SparseIntArray colors = new SparseIntArray();
- private void getColors() {
- colors.put( 1, 0xFFF0E68C);
- colors.put( 2, 0xFF87CEFA);
- colors.put( 3, 0xFFB0C4DE);
- colors.put( 4, 0xFFF0F8FF);
- colors.put( 5, 0xFFF0FFFF);
- colors.put( 6, 0xFFF5F5DC);
- colors.put( 7, 0xFFFFEBCD);
- colors.put( 8, 0xFFFFF8DC);
- colors.put( 9, 0xFFA9A9A9);
- colors.put(10, 0xFFBDB76B);
- colors.put(11, 0xFF8FBC8F);
- colors.put(12, 0xFFDCDCDC);
- colors.put(13, 0xFFDAA520);
- colors.put(14, 0xFFE6E6FA);
- colors.put(15, 0xFFFFA07A);
- colors.put(16, 0xFF32CD32);
- colors.put(17, 0xFF66CDAA);
- colors.put(18, 0xFF66CDAA);
- colors.put(19, 0xFFC0C0C0);
- colors.put(20, 0xFFD2B48C);
- colors.put(21, 0xFF3333FF);
- colors.put(22, 0xFF7B68EE);
- colors.put(23, 0xFFBA55D3);
- colors.put(24, 0xFFFFB6C1);
- colors.put(25, 0xFFFF1493);
- colors.put(26, 0xFFDC143C);
- colors.put(27, 0xFFFF0000);
- colors.put(28, 0xFFFF8C00);
- colors.put(29, 0xFFFFD700);
- colors.put(30, 0xFFADFF2F);
- colors.put(31, 0xFF7CFC00);
- r("finish", "Colors");
- /*
- apiRequest("Colors", data -> {
- JsonArray jColors = data.get("Colors").getAsJsonArray();
- d("Got Colors: "+jColors.toString());
- colors.clear();
- try {
- for (JsonElement colorEl : jColors) {
- JsonObject color = colorEl.getAsJsonObject();
- colors.put(color.get("Id").getAsInt(), Color.parseColor("#"+color.get("RGB").getAsString()));
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- getGrades();
- });*/
- }
-
- private boolean gradeCategoryListChanged = false;
- private void getSavedGradeCategories() {
- gradeCategoryList = app.db.gradeCategoryDao().getAllNow(profileId);
- gradeCategoryListChanged = false;
- r("finish", "SavedGradeCategories");
- }
-
- private void saveGradeCategories() {
- r("finish", "SaveGradeCategories");
- }
-
- private void getGradesCategories() {
- if (!fullSync && false) {
- // cancel every not-full sync; no need to download categories again
- // every full sync it'll be enabled to make sure there are no grades - by getUnits
- r("finish", "GradesCategories");
- return;
- }
- // not a full sync. Will get all grade categories. Clear the current list.
- //gradeCategoryList.clear();
-
- callback.onActionStarted(R.string.sync_action_syncing_grade_categories);
- apiRequest("Grades/Categories", data -> {
- if (data == null) {
- r("finish", "GradesCategories");
- return;
- }
- JsonArray categories = data.get("Categories").getAsJsonArray();
- enableStandardGrades = categories.size() > 0;
- profile.putStudentData("enableStandardGrades", enableStandardGrades);
- if (!enableStandardGrades) {
- r("finish", "GradesCategories");
- return;
- }
- gradeCategoryListChanged = true;
- //d("Got Grades/Categories: "+categories.toString());
- try {
- for (JsonElement categoryEl : categories) {
- JsonObject category = categoryEl.getAsJsonObject();
- JsonElement name = category.get("Name");
- JsonElement weight = category.get("Weight");
- JsonElement color = category.get("Color");
- JsonElement countToTheAverage = category.get("CountToTheAverage");
- int colorInt = Color.BLUE;
- if (!(color instanceof JsonNull) && color != null) {
- colorInt = colors.get(color.getAsJsonObject().get("Id").getAsInt());
- }
- boolean countToTheAverageBool = !(countToTheAverage instanceof JsonNull) && countToTheAverage != null && countToTheAverage.getAsBoolean();
- int weightInt = weight instanceof JsonNull || weight == null || !countToTheAverageBool ? 0 : weight.getAsInt();
- int categoryId = category.get("Id").getAsInt();
- gradeCategoryList.add(new GradeCategory(
- profileId,
- categoryId,
- weightInt,
- colorInt,
- name instanceof JsonNull || name == null ? "" : name.getAsString()
- ));
- }
- r("finish", "GradesCategories");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 1954, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getGradesComments() {
- callback.onActionStarted(R.string.sync_action_syncing_grade_comments);
- apiRequest("Grades/Comments", data -> {
- if (data == null) {
- r("finish", "GradesComments");
- return;
- }
-
- JsonArray comments = data.get("Comments").getAsJsonArray();
- for (JsonElement commentEl : comments) {
- JsonObject comment = commentEl.getAsJsonObject();
- long gradeId = comment.get("Grade").getAsJsonObject().get("Id").getAsLong();
- String text = comment.get("Text").getAsString();
-
- for (Grade grade : gradeList) {
- if (grade.id == gradeId) {
- grade.description = text;
- break;
- }
- }
- }
-
- r("finish", "GradesComments");
- });
- }
-
- private void getPointGradesCategories() {
- if (!fullSync || !enablePointGrades) {
- // cancel every not-full sync; no need to download categories again
- // or
- // if it's a full sync, point grades may have already been disabled in getUnits
- r("finish", "PointGradesCategories");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_point_grade_categories);
- apiRequest("PointGrades/Categories", data -> {
- if (data == null) {
- r("finish", "PointGradesCategories");
- return;
- }
- JsonArray categories = data.get("Categories").getAsJsonArray();
- enablePointGrades = categories.size() > 0;
- profile.putStudentData("enablePointGrades", enablePointGrades);
- if (!enablePointGrades) {
- r("finish", "PointGradesCategories");
- return;
- }
- gradeCategoryListChanged = true;
- //d("Got Grades/Categories: "+categories.toString());
- for (JsonElement categoryEl : categories) {
- JsonObject category = categoryEl.getAsJsonObject();
- JsonElement name = category.get("Name");
- JsonElement weight = category.get("Weight");
- JsonElement color = category.get("Color");
- JsonElement countToTheAverage = category.get("CountToTheAverage");
- JsonElement valueFrom = category.get("ValueFrom");
- JsonElement valueTo = category.get("ValueTo");
- int colorInt = Color.BLUE;
- if (!(color instanceof JsonNull) && color != null) {
- colorInt = colors.get(color.getAsJsonObject().get("Id").getAsInt());
- }
- boolean countToTheAverageBool = !(countToTheAverage instanceof JsonNull) && countToTheAverage != null && countToTheAverage.getAsBoolean();
- int weightInt = weight instanceof JsonNull || weight == null || !countToTheAverageBool ? 0 : weight.getAsInt();
- int categoryId = category.get("Id").getAsInt();
- float valueFromFloat = valueFrom.getAsFloat();
- float valueToFloat = valueTo.getAsFloat();
- gradeCategoryList.add(
- new GradeCategory(
- profileId,
- categoryId,
- weightInt,
- colorInt,
- name instanceof JsonNull || name == null ? "" : name.getAsString()
- ).setValueRange(valueFromFloat, valueToFloat)
- );
- }
- r("finish", "PointGradesCategories");
- });
- }
-
- private void getDescriptiveGradesSkills() {
- if (!fullSync || !enableDescriptiveGrades) {
- // cancel every not-full sync; no need to download categories again
- // or
- // if it's a full sync, descriptive grades may have already been disabled in getUnits
- r("finish", "DescriptiveGradesCategories");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_descriptive_grade_categories);
- apiRequest("DescriptiveTextGrades/Skills", data -> {
- if (data == null) {
- r("finish", "DescriptiveGradesCategories");
- return;
- }
- JsonArray categories = data.get("Skills").getAsJsonArray();
- enableDescriptiveGrades = categories.size() > 0;
- profile.putStudentData("enableDescriptiveGrades", enableDescriptiveGrades);
- if (!enableDescriptiveGrades) {
- r("finish", "DescriptiveGradesCategories");
- return;
- }
- gradeCategoryListChanged = true;
- //d("Got Grades/Categories: "+categories.toString());
- for (JsonElement categoryEl : categories) {
- JsonObject category = categoryEl.getAsJsonObject();
- JsonElement name = category.get("Name");
- JsonElement color = category.get("Color");
- int colorInt = Color.BLUE;
- if (!(color instanceof JsonNull) && color != null) {
- colorInt = colors.get(color.getAsJsonObject().get("Id").getAsInt());
- }
- int weightInt = -1;
- int categoryId = category.get("Id").getAsInt();
- gradeCategoryList.add(new GradeCategory(
- profileId,
- categoryId,
- weightInt,
- colorInt,
- name instanceof JsonNull || name == null ? "" : name.getAsString()
- ));
- }
- r("finish", "DescriptiveGradesCategories");
- });
- }
-
- private void getTextGradesCategories() {
- if (!fullSync || !enableTextGrades) {
- // cancel every not-full sync; no need to download categories again
- // or
- // if it's a full sync, text grades may have already been disabled in getUnits
- r("finish", "TextGradesCategories");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_descriptive_grade_categories);
- apiRequest("TextGrades/Categories", data -> {
- if (data == null) {
- r("finish", "TextGradesCategories");
- return;
- }
- JsonArray categories = data.get("Categories").getAsJsonArray();
- enableTextGrades = categories.size() > 0;
- profile.putStudentData("enableTextGrades", enableTextGrades);
- if (!enableTextGrades) {
- r("finish", "TextGradesCategories");
- return;
- }
- gradeCategoryListChanged = true;
- //d("Got Grades/Categories: "+categories.toString());
- for (JsonElement categoryEl : categories) {
- JsonObject category = categoryEl.getAsJsonObject();
- JsonElement name = category.get("Name");
- JsonElement color = category.get("Color");
- int colorInt = Color.BLUE;
- if (!(color instanceof JsonNull) && color != null) {
- colorInt = colors.get(color.getAsJsonObject().get("Id").getAsInt());
- }
- int weightInt = -1;
- int categoryId = category.get("Id").getAsInt();
- gradeCategoryList.add(new GradeCategory(
- profileId,
- categoryId,
- weightInt,
- colorInt,
- name instanceof JsonNull || name == null ? "" : name.getAsString()
- ));
- }
- r("finish", "TextGradesCategories");
- });
- }
-
- private void getBehaviourGradesCategories() {
- if (!fullSync || !enableBehaviourGrades) {
- // cancel every not-full sync; no need to download categories again
- // or
- // if it's a full sync, descriptive grades may have already been disabled in getUnits
- r("finish", "BehaviourGradesCategories");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_behaviour_grade_categories);
- apiRequest("BehaviourGrades/Points/Categories", data -> {
- if (data == null) {
- r("finish", "BehaviourGradesCategories");
- return;
- }
- JsonArray categories = data.get("Categories").getAsJsonArray();
- enableBehaviourGrades = categories.size() > 0;
- profile.putStudentData("enableBehaviourGrades", enableBehaviourGrades);
- if (!enableBehaviourGrades) {
- r("finish", "BehaviourGradesCategories");
- return;
- }
- gradeCategoryListChanged = true;
- //d("Got Grades/Categories: "+categories.toString());
- for (JsonElement categoryEl : categories) {
- JsonObject category = categoryEl.getAsJsonObject();
- JsonElement name = category.get("Name");
- JsonElement valueFrom = category.get("ValueFrom");
- JsonElement valueTo = category.get("ValueTo");
- int colorInt = Color.BLUE;
- int categoryId = category.get("Id").getAsInt();
- float valueFromFloat = valueFrom.getAsFloat();
- float valueToFloat = valueTo.getAsFloat();
- gradeCategoryList.add(
- new GradeCategory(
- profileId,
- categoryId,
- -1,
- colorInt,
- name instanceof JsonNull || name == null ? "" : name.getAsString()
- ).setValueRange(valueFromFloat, valueToFloat)
- );
- }
- r("finish", "BehaviourGradesCategories");
- });
- }
-
- private void getGrades() {
- d(TAG, "Grades settings: "+enableStandardGrades+", "+enablePointGrades+", "+enableDescriptiveGrades);
- if (!enableStandardGrades && false) {
- // cancel only if grades have been disabled before
- // TODO do not cancel. this does not show any grades until a full sync happens. wtf
- // in KOTLIN api, maybe this will be forced when user synchronises this feature exclusively
- r("finish", "Grades");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_grades);
- apiRequest("Grades", data -> {
- if (data == null) {
- r("finish", "Grades");
- return;
- }
- JsonArray grades = data.get("Grades").getAsJsonArray();
- enableStandardGrades = grades.size() > 0;
- profile.putStudentData("enableStandardGrades", enableStandardGrades);
- if (!enableStandardGrades) {
- r("finish", "Grades");
- return;
- }
- //d("Got Grades: "+grades.toString());
- for (JsonElement gradeEl : grades) {
- JsonObject grade = gradeEl.getAsJsonObject();
- long id = grade.get("Id").getAsLong();
- long teacherId = grade.get("AddedBy").getAsJsonObject().get("Id").getAsLong();
- int semester = grade.get("Semester").getAsInt();
- long categoryId = grade.get("Category").getAsJsonObject().get("Id").getAsLong();
- long subjectId = grade.get("Subject").getAsJsonObject().get("Id").getAsLong();
- String name = grade.get("Grade").getAsString();
- float value = getGradeValue(name);
-
- String str_date = grade.get("AddDate").getAsString();
- long addedDate = Date.fromIso(str_date);
-
- float weight = 0.0f;
- String category = "";
- int color = -1;
- GradeCategory gradeCategory = GradeCategory.search(gradeCategoryList, categoryId);
- if (gradeCategory != null) {
- weight = gradeCategory.weight;
- category = gradeCategory.text;
- color = gradeCategory.color;
- }
-
- if (name.equals("-") || name.equals("+") || name.equalsIgnoreCase("np") || name.equalsIgnoreCase("bz")) {
- // fix for + and - grades that lower the average
- weight = 0;
- }
-
- Grade gradeObject = new Grade(
- profileId,
- id,
- category,
- color,
- "",
- name,
- value,
- weight,
- semester,
- teacherId,
- subjectId
- );
-
- if (grade.get("IsConstituent").getAsBoolean()) {
- // normal grade
- gradeObject.type = TYPE_NORMAL;
- }
- if (grade.get("IsSemester").getAsBoolean()) {
- // semester final
- gradeObject.type = (gradeObject.semester == 1 ? TYPE_SEMESTER1_FINAL : TYPE_SEMESTER2_FINAL);
- }
- else if (grade.get("IsSemesterProposition").getAsBoolean()) {
- // semester proposed
- gradeObject.type = (gradeObject.semester == 1 ? TYPE_SEMESTER1_PROPOSED : TYPE_SEMESTER2_PROPOSED);
- }
- else if (grade.get("IsFinal").getAsBoolean()) {
- // year final
- gradeObject.type = TYPE_YEAR_FINAL;
- }
- else if (grade.get("IsFinalProposition").getAsBoolean()) {
- // year final
- gradeObject.type = TYPE_YEAR_PROPOSED;
- }
-
- JsonElement historyEl = grade.get("Improvement");
- if (historyEl != null) {
- JsonObject history = historyEl.getAsJsonObject();
- long historicalId = history.get("Id").getAsLong();
- for (Grade historicalGrade: gradeList) {
- if (historicalGrade.id != historicalId)
- continue;
- // historicalGrade
- historicalGrade.parentId = gradeObject.id;
- if (historicalGrade.name.equals("nb")) {
- historicalGrade.weight = 0;
- }
- break;
- }
- gradeObject.isImprovement = true;
- }
-
- /*if (RegisterGradeCategory.getById(app.register, registerGrade.categoryId, -1) == null) {
- getGradesCategories = true;
- }*/
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- r("finish", "Grades");
- });
- }
-
- private void getPointGrades() {
- d(TAG, "Grades settings: "+enableStandardGrades+", "+enablePointGrades+", "+enableDescriptiveGrades);
- if (!enablePointGrades) {
- // cancel only if grades have been disabled before
- r("finish", "PointGrades");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_point_grades);
- apiRequest("PointGrades", data -> {
- if (data == null) {
- r("finish", "PointGrades");
- return;
- }
- JsonArray grades = data.get("Grades").getAsJsonArray();
- enablePointGrades = grades.size() > 0;
- profile.putStudentData("enablePointGrades", enablePointGrades);
- if (!enablePointGrades) {
- r("finish", "PointGrades");
- return;
- }
- //d("Got Grades: "+grades.toString());
- for (JsonElement gradeEl : grades) {
- JsonObject grade = gradeEl.getAsJsonObject();
- long id = grade.get("Id").getAsLong();
- long teacherId = grade.get("AddedBy").getAsJsonObject().get("Id").getAsLong();
- int semester = grade.get("Semester").getAsInt();
- long categoryId = grade.get("Category").getAsJsonObject().get("Id").getAsLong();
- long subjectId = grade.get("Subject").getAsJsonObject().get("Id").getAsLong();
- String name = grade.get("Grade").getAsString();
- float originalValue = grade.get("GradeValue").getAsFloat();
-
- String str_date = grade.get("AddDate").getAsString();
- long addedDate = Date.fromIso(str_date);
-
- float weight = 0.0f;
- String category = "";
- int color = -1;
- float value = 0.0f;
- float maxPoints = 0.0f;
- GradeCategory gradeCategory = GradeCategory.search(gradeCategoryList, categoryId);
- if (gradeCategory != null) {
- weight = gradeCategory.weight;
- category = gradeCategory.text;
- color = gradeCategory.color;
- maxPoints = gradeCategory.valueTo;
- value = originalValue;
- }
-
- Grade gradeObject = new Grade(
- profileId,
- id,
- category,
- color,
- "",
- name,
- value,
- weight,
- semester,
- teacherId,
- subjectId
- );
- gradeObject.type = Grade.TYPE_POINT;
- gradeObject.valueMax = maxPoints;
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- r("finish", "PointGrades");
- });
- }
-
- private void getDescriptiveGrades() {
- d(TAG, "Grades settings: "+enableStandardGrades+", "+enablePointGrades+", "+enableDescriptiveGrades);
- if (!enableDescriptiveGrades && !enableTextGrades) {
- // cancel only if grades have been disabled before
- r("finish", "DescriptiveGrades");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_descriptive_grades);
- apiRequest("BaseTextGrades", data -> {
- if (data == null) {
- r("finish", "DescriptiveGrades");
- return;
- }
- JsonArray grades = data.get("Grades").getAsJsonArray();
- int descriptiveGradesCount = 0;
- int textGradesCount = 0;
- //d("Got Grades: "+grades.toString());
- for (JsonElement gradeEl : grades) {
- JsonObject grade = gradeEl.getAsJsonObject();
- long id = grade.get("Id").getAsLong();
- long teacherId = grade.get("AddedBy").getAsJsonObject().get("Id").getAsLong();
- int semester = grade.get("Semester").getAsInt();
- long subjectId = grade.get("Subject").getAsJsonObject().get("Id").getAsLong();
- String description = grade.get("Grade").getAsString();
-
- long categoryId = -1;
- JsonElement categoryEl = grade.get("Category");
- JsonElement skillEl = grade.get("Skill");
- if (categoryEl != null) {
- categoryId = categoryEl.getAsJsonObject().get("Id").getAsLong();
- textGradesCount++;
- }
- if (skillEl != null) {
- categoryId = skillEl.getAsJsonObject().get("Id").getAsLong();
- descriptiveGradesCount++;
- }
-
- String str_date = grade.get("AddDate").getAsString();
- long addedDate = Date.fromIso(str_date);
-
- String category = "";
- int color = -1;
- GradeCategory gradeCategory = GradeCategory.search(gradeCategoryList, categoryId);
- if (gradeCategory != null) {
- category = gradeCategory.text;
- color = gradeCategory.color;
- }
-
- Grade gradeObject = new Grade(
- profileId,
- id,
- category,
- color,
- description,
- " ",
- 0.0f,
- 0,
- semester,
- teacherId,
- subjectId
- );
- gradeObject.type = Grade.TYPE_DESCRIPTIVE;
- if (categoryEl != null) {
- gradeObject.type = Grade.TYPE_TEXT;
- }
- if (skillEl != null) {
- gradeObject.type = Grade.TYPE_DESCRIPTIVE;
- }
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- enableDescriptiveGrades = descriptiveGradesCount > 0;
- enableTextGrades = textGradesCount > 0;
- profile.putStudentData("enableDescriptiveGrades", enableDescriptiveGrades);
- profile.putStudentData("enableTextGrades", enableTextGrades);
- r("finish", "DescriptiveGrades");
- });
- }
-
- private void getTextGrades() {
- callback.onActionStarted(R.string.sync_action_syncing_descriptive_grades);
- apiRequest("DescriptiveGrades", data -> {
- if (data == null) {
- r("finish", "TextGrades");
- return;
- }
- JsonArray grades = data.get("Grades").getAsJsonArray();
- //d("Got Grades: "+grades.toString());
- for (JsonElement gradeEl : grades) {
- JsonObject grade = gradeEl.getAsJsonObject();
- long id = grade.get("Id").getAsLong();
- long teacherId = grade.get("AddedBy").getAsJsonObject().get("Id").getAsLong();
- int semester = grade.get("Semester").getAsInt();
- long subjectId = grade.get("Subject").getAsJsonObject().get("Id").getAsLong();
- JsonElement map = grade.get("Map");
- JsonElement realGrade = grade.get("RealGradeValue");
- String description = "";
- if (map != null) {
- description = map.getAsString();
- }
- else if (realGrade != null) {
- description = realGrade.getAsString();
- }
-
- long categoryId = -1;
- JsonElement skillEl = grade.get("Skill");
- if (skillEl != null) {
- categoryId = skillEl.getAsJsonObject().get("Id").getAsLong();
- }
-
- String str_date = grade.get("AddDate").getAsString();
- long addedDate = Date.fromIso(str_date);
-
- String category = "";
- int color = -1;
- GradeCategory gradeCategory = GradeCategory.search(gradeCategoryList, categoryId);
- if (gradeCategory != null) {
- category = gradeCategory.text;
- color = gradeCategory.color;
- }
-
- Grade gradeObject = new Grade(
- profileId,
- id,
- category,
- color,
- "",
- description,
- 0.0f,
- 0,
- semester,
- teacherId,
- subjectId
- );
- gradeObject.type = Grade.TYPE_DESCRIPTIVE;
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- r("finish", "TextGrades");
- });
- }
-
- private void getBehaviourGrades() {
- d(TAG, "Grades settings: "+enableStandardGrades+", "+enablePointGrades+", "+enableDescriptiveGrades);
- if (!enableBehaviourGrades) {
- // cancel only if grades have been disabled before
- r("finish", "BehaviourGrades");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_behaviour_grades);
- apiRequest("BehaviourGrades/Points", data -> {
- if (data == null) {
- r("finish", "BehaviourGrades");
- return;
- }
- JsonArray grades = data.get("Grades").getAsJsonArray();
- enableBehaviourGrades = grades.size() > 0;
- profile.putStudentData("enableBehaviourGrades", enableBehaviourGrades);
- if (!enableBehaviourGrades) {
- r("finish", "BehaviourGrades");
- return;
- }
- //d("Got Grades: "+grades.toString());
- DecimalFormat nameFormat = new DecimalFormat("#.##");
-
- Grade gradeStartSemester1 = new Grade(
- profileId,
- -1,
- app.getString(R.string.grade_start_points),
- 0xffbdbdbd,
- app.getString(R.string.grade_start_points_format, 1),
- nameFormat.format(startPointsSemester1),
- startPointsSemester1,
- -1,
- 1,
- -1,
- 1
- );
- gradeStartSemester1.type = Grade.TYPE_BEHAVIOUR;
- Grade gradeStartSemester2 = new Grade(
- profileId,
- -2,
- app.getString(R.string.grade_start_points),
- 0xffbdbdbd,
- app.getString(R.string.grade_start_points_format, 2),
- nameFormat.format(startPointsSemester2),
- startPointsSemester2,
- -1,
- 2,
- -1,
- 1
- );
- gradeStartSemester2.type = Grade.TYPE_BEHAVIOUR;
-
- gradeList.add(gradeStartSemester1);
- gradeList.add(gradeStartSemester2);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, -1, true, true, profile.getSemesterStart(1).getInMillis()));
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, -2, true, true, profile.getSemesterStart(2).getInMillis()));
-
- for (JsonElement gradeEl : grades) {
- JsonObject grade = gradeEl.getAsJsonObject();
- long id = grade.get("Id").getAsLong();
- long teacherId = grade.get("AddedBy").getAsJsonObject().get("Id").getAsLong();
- int semester = grade.get("Semester").getAsInt();
- long categoryId = grade.get("Category").getAsJsonObject().get("Id").getAsLong();
- long subjectId = 1;
-
- float value = 0.0f;
- String name = "?";
- JsonElement nameValue;
- if ((nameValue = grade.get("Value")) != null) {
- value = nameValue.getAsFloat();
- name = value < 0 ? nameFormat.format(value) : "+"+nameFormat.format(value);
- }
- else if ((nameValue = grade.get("ShortName")) != null) {
- name = nameValue.getAsString();
- }
-
- String str_date = grade.get("AddDate").getAsString();
- long addedDate = Date.fromIso(str_date);
-
- int color = value > 0 ? 16 : value < 0 ? 26 : 12;
- color = colors.get(color);
-
- String category = "";
- float maxPoints = 0.0f;
- GradeCategory gradeCategory = GradeCategory.search(gradeCategoryList, categoryId);
- if (gradeCategory != null) {
- category = gradeCategory.text;
- maxPoints = gradeCategory.valueTo;
- }
-
- Grade gradeObject = new Grade(
- profileId,
- id,
- category,
- color,
- "",
- name,
- value,
- -1,
- semester,
- teacherId,
- subjectId
- );
- gradeObject.type = Grade.TYPE_BEHAVIOUR;
- gradeObject.valueMax = maxPoints;
-
- gradeList.add(gradeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_GRADE, gradeObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- r("finish", "BehaviourGrades");
- });
- }
-
- //private boolean eventTypeListChanged = false;
- private void getEvents() {
- //eventTypeList = app.db.eventTypeDao().getAllNow(profileId);
- // eventTypeListChanged = false;
- callback.onActionStarted(R.string.sync_action_syncing_events);
- apiRequest("HomeWorks", data -> {
- if (data == null) {
- r("finish", "Events");
- return;
- }
- JsonArray events = data.get("HomeWorks").getAsJsonArray();
- //d("Got Grades: "+events.toString());
- boolean getCustomTypes = false;
- try {
- for (JsonElement eventEl : events) {
- JsonObject event = eventEl.getAsJsonObject();
-
- JsonElement el;
- JsonObject obj;
-
- long id = event.get("Id").getAsLong();
- long teacherId = -1;
- long subjectId = -1;
- int type = -1;
-
- if ((el = event.get("CreatedBy")) != null
- && (obj = el.getAsJsonObject()) != null
- && (el = obj.get("Id")) != null) {
- teacherId = el.getAsLong();
- }
- if ((el = event.get("Subject")) != null
- && (obj = el.getAsJsonObject()) != null
- && (el = obj.get("Id")) != null) {
- subjectId = el.getAsLong();
- }
- String topic = event.get("Content").getAsString();
-
- if ((el = event.get("Category")) != null
- && (obj = el.getAsJsonObject()) != null
- && (el = obj.get("Id")) != null) {
- type = el.getAsInt();
- }
- /*EventType typeObject = app.db.eventTypeDao().getByIdNow(profileId, type);
- if (typeObject == null) {
- getCustomTypes = true;
- }*/
-
- JsonElement myClass = event.get("Class");
- long teamId = myClass == null ? -1 : myClass.getAsJsonObject().get("Id").getAsLong();
-
- String str_date = event.get("AddDate").getAsString();
- long addedDate = Date.fromIso(str_date);
-
- str_date = event.get("Date").getAsString();
- Date eventDate = Date.fromY_m_d(str_date);
-
-
- Time startTime = null;
- JsonElement lessonNo;
- JsonElement timeFrom;
- if (!((lessonNo = event.get("LessonNo")) instanceof JsonNull)) {
- Pair timePair = lessonRanges.get(lessonNo.getAsInt());
- if(timePair != null)
- startTime = timePair.first;
- }
- if (startTime == null && !((timeFrom = event.get("TimeFrom")) instanceof JsonNull)) {
- startTime = Time.fromH_m(timeFrom.getAsString());
- }
-
- Event eventObject = new Event(
- profileId,
- id,
- eventDate,
- startTime,
- topic,
- -1,
- type,
- false,
- teacherId,
- subjectId,
- teamId
- );
-
- eventList.add(eventObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_EVENT, eventObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- r("finish", "Events");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2541, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getCustomTypes() {
- if (!fullSync) {
- r("finish", "CustomTypes");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_event_categories);
- apiRequest("HomeWorks/Categories", data -> {
- if (data == null) {
- r("finish", "CustomTypes");
- return;
- }
- JsonArray jCategories = data.get("Categories").getAsJsonArray();
- //d("Got Classrooms: "+jClassrooms.toString());
- try {
- for (JsonElement categoryEl : jCategories) {
- JsonObject category = categoryEl.getAsJsonObject();
- eventTypeList.add(new EventType(profileId, category.get("Id").getAsInt(), category.get("Name").getAsString(), colors.get(category.get("Color").getAsJsonObject().get("Id").getAsInt())));
- }
- r("finish", "CustomTypes");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2573, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getHomework() {
- if (!premium) {
- r("finish", "Homework");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_homework);
- apiRequest("HomeWorkAssignments", data -> {
- if (data == null) {
- r("finish", "Homework");
- return;
- }
- JsonArray homeworkList = data.get("HomeWorkAssignments").getAsJsonArray();
- //d("Got Grades: "+events.toString());
- try {
- for (JsonElement homeworkEl : homeworkList) {
- JsonObject homework = homeworkEl.getAsJsonObject();
-
- JsonElement el;
- JsonObject obj;
-
- long id = homework.get("Id").getAsLong();
- long teacherId = -1;
- long subjectId = -1;
-
- if ((el = homework.get("Teacher")) != null
- && (obj = el.getAsJsonObject()) != null
- && (el = obj.get("Id")) != null) {
- teacherId = el.getAsLong();
- }
-
- String topic = "";
- try {
- topic = homework.get("Topic").getAsString() + "\n";
- topic += homework.get("Text").getAsString();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
-
- String str_date = homework.get("Date").getAsString();
- Date addedDate = Date.fromY_m_d(str_date);
-
- str_date = homework.get("DueDate").getAsString();
- Date eventDate = Date.fromY_m_d(str_date);
-
-
- Time startTime = null;
-
- Event eventObject = new Event(
- profileId,
- id,
- eventDate,
- startTime,
- topic,
- -1,
- -1,
- false,
- teacherId,
- subjectId,
- -1
- );
-
- eventList.add(eventObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_EVENT, eventObject.id, profile.getEmpty(), profile.getEmpty(), addedDate.getInMillis()));
- }
- r("finish", "Homework");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2648, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getLuckyNumbers() {
- if (!profile.getLuckyNumberEnabled() || (profile.getLuckyNumberDate() != null && profile.getLuckyNumberDate().getValue() == Date.getToday().getValue())) {
- r("finish", "LuckyNumbers");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_lucky_number);
- apiRequest("LuckyNumbers", data -> {
- if (data == null) {
- profile.setLuckyNumberEnabled(false);
- }
- else {
- profile.setLuckyNumber(-1);
- profile.setLuckyNumberDate(Date.getToday());
- try {
- JsonElement luckyNumberEl = data.get("LuckyNumber");
- if (luckyNumberEl != null) {
- JsonObject luckyNumber = luckyNumberEl.getAsJsonObject();
- profile.setLuckyNumber(luckyNumber.get("LuckyNumber").getAsInt());
- profile.setLuckyNumberDate(Date.fromY_m_d(luckyNumber.get("LuckyNumberDay").getAsString()));
- }
- } catch (Exception e) {
- finishWithError(new AppError(TAG, 2678, CODE_OTHER, e, data));
- }
- finally {
- app.db.luckyNumberDao().add(new LuckyNumber(profileId, profile.getLuckyNumberDate(), profile.getLuckyNumber()));
- }
- }
- r("finish", "LuckyNumbers");
- });
- }
-
- private void getNotices() {
- callback.onActionStarted(R.string.sync_action_syncing_notices);
- apiRequest("Notes", data -> {
- if (data == null) {
- r("finish", "Notices");
- return;
- }
- try {
- JsonArray jNotices = data.get("Notes").getAsJsonArray();
-
- for (JsonElement noticeEl : jNotices) {
- JsonObject notice = noticeEl.getAsJsonObject();
-
- int type = notice.get("Positive").getAsInt();
- switch (type) {
- case 0:
- type = TYPE_NEGATIVE;
- break;
- case 1:
- type = TYPE_POSITIVE;
- break;
- case 2:
- type = TYPE_NEUTRAL;
- break;
- }
-
- long id = notice.get("Id").getAsLong();
-
- Date addedDate = Date.fromY_m_d(notice.get("Date").getAsString());
-
- int semester = profile.dateToSemester(addedDate);
-
- JsonElement el;
- JsonObject obj;
- long teacherId = -1;
- if ((el = notice.get("Teacher")) != null
- && (obj = el.getAsJsonObject()) != null
- && (el = obj.get("Id")) != null) {
- teacherId = el.getAsLong();
- }
-
- Notice noticeObject = new Notice(
- profileId,
- id,
- notice.get("Text").getAsString(),
- semester,
- type,
- teacherId
- );
-
- noticeList.add(noticeObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_NOTICE, noticeObject.id, profile.getEmpty(), profile.getEmpty(), addedDate.getInMillis()));
- }
- r("finish", "Notices");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2750, CODE_OTHER, e, data));
- }
- });
- }
-
- private SparseArray> attendanceTypes = new SparseArray<>();
- private void getAttendanceTypes() {
- callback.onActionStarted(R.string.sync_action_syncing_attendance_types);
- apiRequest("Attendances/Types", data -> {
- if (data == null) {
- r("finish", "AttendanceTypes");
- return;
- }
- try {
- JsonArray jTypes = data.get("Types").getAsJsonArray();
- for (JsonElement typeEl : jTypes) {
- JsonObject type = typeEl.getAsJsonObject();
- int id = type.get("Id").getAsInt();
- attendanceTypes.put(id,
- new Pair<>(
- type.get("Standard").getAsBoolean() ? id : type.getAsJsonObject("StandardType").get("Id").getAsInt(),
- type.get("Name").getAsString()
- )
- );
- }
- r("finish", "AttendanceTypes");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2782, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getAttendance() {
- callback.onActionStarted(R.string.sync_action_syncing_attendance);
- apiRequest("Attendances"+(fullSync ? "" : "?dateFrom="+ Date.getToday().stepForward(0, -1, 0).getStringY_m_d()), data -> {
- if (data == null) {
- r("finish", "Attendance");
- return;
- }
-
- try {
- JsonArray jAttendance = data.get("Attendances").getAsJsonArray();
-
- for (JsonElement attendanceEl : jAttendance) {
- JsonObject attendance = attendanceEl.getAsJsonObject();
-
- int type = attendance.getAsJsonObject("Type").get("Id").getAsInt();
- Pair attendanceType;
- if ((attendanceType = attendanceTypes.get(type)) != null) {
- type = attendanceType.first;
- }
- switch (type) {
- case 1:
- type = TYPE_ABSENT;
- break;
- case 2:
- type = TYPE_BELATED;
- break;
- case 3:
- type = TYPE_ABSENT_EXCUSED;
- break;
- case 4:
- type = TYPE_RELEASED;
- break;
- default:
- case 100:
- type = TYPE_PRESENT;
- break;
- }
-
- String idStr = attendance.get("Id").getAsString();
- int id = strToInt(idStr.replaceAll("[^\\d.]", ""));
-
- long addedDate = Date.fromIso(attendance.get("AddDate").getAsString());
-
- Time startTime = Time.getNow();
- Pair timePair = lessonRanges.get(attendance.get("LessonNo").getAsInt());
- if (timePair != null)
- startTime = timePair.first;
- Date lessonDate = Date.fromY_m_d(attendance.get("Date").getAsString());
- int lessonWeekDay = lessonDate.getWeekDay();
- long subjectId = -1;
- String topic = "";
- if (attendanceType != null) {
- topic = attendanceType.second;
- }
-
- for (Lesson lesson: lessonList) {
- if (lesson.weekDay == lessonWeekDay && lesson.startTime.getValue() == startTime.getValue()) {
- subjectId = lesson.subjectId;
- }
- }
-
- Attendance attendanceObject = new Attendance(
- profileId,
- id,
- attendance.getAsJsonObject("AddedBy").get("Id").getAsLong(),
- subjectId,
- attendance.get("Semester").getAsInt(),
- topic,
- lessonDate,
- startTime,
- type);
-
- attendanceList.add(attendanceObject);
- if (attendanceObject.type != TYPE_PRESENT) {
- metadataList.add(new Metadata(profileId, Metadata.TYPE_ATTENDANCE, attendanceObject.id, profile.getEmpty(), profile.getEmpty(), addedDate));
- }
- }
- r("finish", "Attendance");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2872, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getAnnouncements() {
- callback.onActionStarted(R.string.sync_action_syncing_announcements);
- apiRequest("SchoolNotices", data -> {
- if (data == null) {
- r("finish", "Announcements");
- return;
- }
- try {
- JsonArray jAnnouncements = data.get("SchoolNotices").getAsJsonArray();
-
- for (JsonElement announcementEl : jAnnouncements) {
- JsonObject announcement = announcementEl.getAsJsonObject();
-
- String idStr = announcement.get("Id").getAsString();
- long id = crc16(idStr.getBytes());
-
- long addedDate = Date.fromIso(announcement.get("CreationDate").getAsString());
-
- boolean read = announcement.get("WasRead").getAsBoolean();
-
- String subject = "";
- String text = "";
- Date startDate = null;
- Date endDate = null;
- try {
- subject = announcement.get("Subject").getAsString();
- text = announcement.get("Content").getAsString();
- startDate = Date.fromY_m_d(announcement.get("StartDate").getAsString());
- endDate = Date.fromY_m_d(announcement.get("EndDate").getAsString());
- }
- catch (Exception e) {
- e.printStackTrace();
- }
-
- JsonElement el;
- JsonObject obj;
- long teacherId = -1;
- if ((el = announcement.get("AddedBy")) != null
- && (obj = el.getAsJsonObject()) != null
- && (el = obj.get("Id")) != null) {
- teacherId = el.getAsLong();
- }
-
- Announcement announcementObject = new Announcement(
- profileId,
- id,
- subject,
- text,
- startDate,
- endDate,
- teacherId
- );
-
- announcementList.add(announcementObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_ANNOUNCEMENT, announcementObject.id, read, read, addedDate));
- }
- r("finish", "Announcements");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2944, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getPtMeetings() {
- if (!fullSync) {
- r("finish", "PtMeetings");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_pt_meetings);
- apiRequest("ParentTeacherConferences", data -> {
- if (data == null) {
- r("finish", "PtMeetings");
- return;
- }
- try {
- JsonArray jMeetings = data.get("ParentTeacherConferences").getAsJsonArray();
- for (JsonElement meetingEl: jMeetings) {
- JsonObject meeting = meetingEl.getAsJsonObject();
-
- long id = meeting.get("Id").getAsLong();
- Event eventObject = new Event(
- profileId,
- id,
- Date.fromY_m_d(meeting.get("Date").getAsString()),
- Time.fromH_m(meeting.get("Time").getAsString()),
- meeting.get("Topic").getAsString(),
- -1,
- TYPE_PT_MEETING,
- false,
- meeting.getAsJsonObject("Teacher").get("Id").getAsLong(),
- -1,
- teamClassId
- );
- eventList.add(eventObject);
- metadataList.add(new Metadata(profileId, Metadata.TYPE_EVENT, eventObject.id, profile.getEmpty(), profile.getEmpty(), System.currentTimeMillis()));
- }
- r("finish", "PtMeetings");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 2996, CODE_OTHER, e, data));
- }
- });
- }
-
- private SparseArray teacherFreeDaysTypes = new SparseArray<>();
- private void getTeacherFreeDaysTypes() {
- if (!fullSync) {
- r("finish", "TeacherFreeDaysTypes");
- return;
- }
- callback.onActionStarted(R.string.sync_action_syncing_teacher_free_days_types);
- apiRequest("TeacherFreeDays/Types", data -> {
- if (data == null) {
- r("finish", "TeacherFreeDays");
- return;
- }
- try {
- JsonArray jTypes = data.get("Types").getAsJsonArray();
- for (JsonElement typeEl : jTypes) {
- JsonObject type = typeEl.getAsJsonObject();
- int id = type.get("Id").getAsInt();
- teacherFreeDaysTypes.put(id, type.get("Name").getAsString());
- }
- r("finish", "TeacherFreeDaysTypes");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 3019, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getTeacherFreeDays() {
- callback.onActionStarted(R.string.sync_action_syncing_teacher_free_days);
- apiRequest("TeacherFreeDays", data -> {
- if (data == null) {
- r("finish", "TeacherFreeDays");
- return;
- }
- try {
- JsonArray jFreeDays = data.get("TeacherFreeDays").getAsJsonArray();
- for (JsonElement freeDayEl: jFreeDays) {
- JsonObject freeDay = freeDayEl.getAsJsonObject();
-
- long id = freeDay.get("Id").getAsLong();
- long teacherId = freeDay.getAsJsonObject("Teacher").get("Id").getAsLong();
-
- Date dateFrom = Date.fromY_m_d(freeDay.get("DateFrom").getAsString());
- Date dateTo = Date.fromY_m_d(freeDay.get("DateTo").getAsString());
-
- Time timeFrom = null;
- Time timeTo = null;
-
- if (freeDay.get("TimeFrom") != null && freeDay.get("TimeTo") != null) {
- timeFrom = Time.fromH_m_s(freeDay.get("TimeFrom").getAsString());
- timeTo = Time.fromH_m_s(freeDay.get("TimeTo").getAsString());
- }
-
- long type = freeDay.getAsJsonObject("Type").get("Id").getAsLong();
-
- //String topic = teacherFreeDaysTypes.get(type)+"\n"+(dateFrom.getValue() != dateTo.getValue() ? dateFrom.getFormattedString()+" - "+dateTo.getFormattedString() : "");
-
- TeacherAbsence teacherAbsence = new TeacherAbsence(
- profileId,
- id,
- teacherId,
- type,
- dateFrom,
- dateTo,
- timeFrom,
- timeTo
- );
-
- teacherAbsenceList.add(teacherAbsence);
- metadataList.add(
- new Metadata(
- profileId,
- Metadata.TYPE_TEACHER_ABSENCE,
- teacherAbsence.getId(),
- true,
- true,
- System.currentTimeMillis())
- );
-
- }
- r("finish", "TeacherFreeDays");
- }
- catch (Exception e) {
- finishWithError(new AppError(TAG, 3069, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getSchoolFreeDays() {
- callback.onActionStarted(R.string.sync_action_syncing_school_free_days);
- apiRequest("SchoolFreeDays" + (unitId != -1 ? "?unit=" + unitId : ""), data -> {
- if (data == null) {
- r("finish", "SchoolFreeDays");
- return;
- }
- try {
- JsonArray jFreeDays = data.get("SchoolFreeDays").getAsJsonArray();
-
- for (JsonElement freeDayEl: jFreeDays) {
- continue;
- }
- r("finish", "SchoolFreeDays");
- } catch (Exception e) {
- finishWithError(new AppError(TAG, 3069, CODE_OTHER, e, data));
- }
- });
- }
-
- private void getMessagesLogin() {
- if (synergiaPassword == null) {
- // skip messages
- r("finish", "MessagesOutbox");
- return;
- }
- loginSynergia(() -> {
- r("finish", "MessagesLogin");
- });
- }
-
- private void getMessagesInbox() {
- String body =
- "