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(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 ? TYPE_NEW_HOMEWORK : 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(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(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(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(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(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(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 != TYPE_NEW_SHARED_EVENT
- && notification.type != TYPE_SERVER_MESSAGE
- && notification.type != 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 ? TYPE_NEW_SHARED_HOMEWORK : 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() {
- // TODO \/
-
- 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().getFullByIdNow(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(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, 110, 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);
- app.db.endpointTimerDao().clear(profileId);
- app.db.attendanceTypeDao().clear(profileId);
- app.db.classroomDao().clear(profileId);
- app.db.lessonRangeDao().clear(profileId);
- app.db.noticeTypeDao().clear(profileId);
- app.db.teacherAbsenceDao().clear(profileId);
- app.db.teacherAbsenceTypeDao().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/Iuczniowie.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Iuczniowie.java
deleted file mode 100644
index 6d1beed8..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Iuczniowie.java
+++ /dev/null
@@ -1,1709 +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.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