@@ -8,6 +8,7 @@ const Teacher = require("./Teacher");
8
8
const User = require ( "./User" ) ;
9
9
const { btoa, iterate} = require ( "../lib/utils" ) ;
10
10
const { ENDPOINT , API_STATUS , TIMELINE_ITEM_TYPE } = require ( "./enums" ) ;
11
+ const { SESSION_PING_INTERVAL_MS } = require ( "./constants" ) ;
11
12
const Class = require ( "./Class" ) ;
12
13
const Classroom = require ( "./Classroom" ) ;
13
14
const Parent = require ( "./Parent" ) ;
@@ -147,6 +148,12 @@ class Edupage extends RawData {
147
148
* @type {string }
148
149
*/
149
150
this . baseUrl = null ;
151
+
152
+ //Used internally to keep track of Timeout object for session pinging
153
+ Object . defineProperty ( this , "_sessionPingTimeout" , {
154
+ enumerable : false ,
155
+ writable : true
156
+ } ) ;
150
157
}
151
158
152
159
/**
@@ -168,6 +175,8 @@ class Edupage extends RawData {
168
175
//Update edupage data
169
176
await this . refresh ( ) . catch ( reject ) ;
170
177
178
+ this . scheduleSessionPing ( ) ;
179
+
171
180
resolve ( this . user ) ;
172
181
} ) . catch ( reject ) ;
173
182
} ) ;
@@ -440,7 +449,10 @@ class Edupage extends RawData {
440
449
const _html = await this . api ( { url : ENDPOINT . DASHBOARD_GET_CLASSBOOK , method : "GET" , type : "text" } ) ;
441
450
const ids = [ ..._html . matchAll ( / g p i d = " ? ( \d + ) " ? / gi) ] . map ( e => e [ 1 ] ) ;
442
451
443
- if ( ids . length ) this . ASC . gpid = ids [ ids . length - 1 ] ;
452
+ if ( ids . length ) {
453
+ this . ASC . gpids = ids ;
454
+ this . ASC . gpid = ids [ ids . length - 1 ] ;
455
+ }
444
456
else throw new Error ( "Cannot find gpid value" ) ;
445
457
} catch ( err ) {
446
458
debug ( `[Timetable] Could not get 'gpid' property` , err ) ;
@@ -631,6 +643,91 @@ class Edupage extends RawData {
631
643
} ) ;
632
644
}
633
645
646
+ /**
647
+ * Sends a session ping request
648
+ * @returns {Promise<boolean> } Whether the ping was successful
649
+ */
650
+ async pingSession ( ) {
651
+ debug ( `[Login] Sening a session ping request...` ) ;
652
+
653
+ const gpids = this . ASC . gpids ;
654
+ const success = await this . api ( {
655
+ url : ENDPOINT . SESSION_PING ,
656
+ method : "POST" ,
657
+ type : "text" ,
658
+ data : {
659
+ gpids : gpids . join ( ";" )
660
+ }
661
+ } ) . then ( data => {
662
+ if ( data == "notlogged" ) return false ;
663
+ else if ( data == "OK" ) return true ;
664
+
665
+ try {
666
+ const obj = JSON . parse ( data ) ;
667
+ if ( obj . status == "notlogged" ) return false ;
668
+ else return true ;
669
+ } catch ( err ) {
670
+ FatalError . throw ( new ParseError ( `Failed to parse session ping response as JSON: ${ err . message } ` ) , { data, gpids} ) ;
671
+ }
672
+ } ) . catch ( err => {
673
+ FatalError . warn ( new APIError ( `Failed to ping session: ${ err . message } ` ) , { err, gpids} ) ;
674
+ return null ;
675
+ } ) ;
676
+
677
+ this . scheduleSessionPing ( ) ;
678
+
679
+ //Failed to ping session
680
+ if ( success === null ) {
681
+ error ( `[Login] Failed to ping session` ) ;
682
+ return false ;
683
+ }
684
+
685
+ //Successfully pinged session
686
+ if ( success ) {
687
+ debug ( `[Login] Successfully pinged session` ) ;
688
+ return true ;
689
+ }
690
+
691
+ //Session is not logged in
692
+ if ( ! success ) {
693
+ warn ( `[Login] Session is not logged in, trying to log in...` ) ;
694
+ const loggedIn = await this . user . login ( this . user . credentials . username , this . user . credentials . password )
695
+ . then ( ( ) => {
696
+ debug ( `[Login] Successfully logged in` ) ;
697
+ return true ;
698
+ } )
699
+ . catch ( err => {
700
+ error ( `[Login] Failed to log in:` , err ) ;
701
+ return false ;
702
+ } ) ;
703
+
704
+ return loggedIn ;
705
+ }
706
+ }
707
+
708
+ /**
709
+ * Schedules a session ping request
710
+ */
711
+ scheduleSessionPing ( ) {
712
+ if ( this . _sessionPingTimeout ) {
713
+ clearTimeout ( this . _sessionPingTimeout ) ;
714
+ this . _sessionPingTimeout = null ;
715
+ }
716
+
717
+ this . _sessionPingTimeout = setTimeout ( ( ) => this . pingSession ( ) , SESSION_PING_INTERVAL_MS ) ;
718
+ debug ( `[Login] Scheduled session ping in ${ SESSION_PING_INTERVAL_MS } ms` ) ;
719
+ }
720
+
721
+ /**
722
+ * Stops internal timers to prevent process from hanging infinitely.
723
+ */
724
+ exit ( ) {
725
+ if ( this . _sessionPingTimeout ) {
726
+ clearTimeout ( this . _sessionPingTimeout ) ;
727
+ this . _sessionPingTimeout = null ;
728
+ }
729
+ }
730
+
634
731
/**
635
732
*
636
733
* @param {Date|number|string } date1
@@ -696,6 +793,7 @@ class Edupage extends RawData {
696
793
if ( endpoint == ENDPOINT . ELEARNING_TEST_RESULTS ) url = `/elearning/?cmd=EtestCreator&akcia=getResultsData` ;
697
794
if ( endpoint == ENDPOINT . ELEARNING_CARDS_DATA ) url = `/elearning/?cmd=EtestCreator&akcia=getCardsData` ;
698
795
if ( endpoint == ENDPOINT . GRADES_DATA ) url = `/znamky/?barNoSkin=1` ;
796
+ if ( endpoint == ENDPOINT . SESSION_PING ) url = this . _data ?. _edubar ?. sessionPingUrl || `/login/eauth?portalping` ;
699
797
700
798
if ( ! url ) throw new TypeError ( `Invalid API endpoint '${ endpoint } '` ) ;
701
799
else return this . baseUrl + url ;
0 commit comments