11package com .rtm516 .mcxboxbroadcast .core ;
22
3- import com .fasterxml .jackson .core .JsonProcessingException ;
43import com .rtm516 .mcxboxbroadcast .core .exceptions .SessionCreationException ;
54import com .rtm516 .mcxboxbroadcast .core .exceptions .SessionUpdateException ;
65import com .rtm516 .mcxboxbroadcast .core .models .CreateSessionRequest ;
7- import com .rtm516 .mcxboxbroadcast .core .models .JoinSessionRequest ;
86import org .java_websocket .util .NamedThreadFactory ;
97
8+ import java .io .File ;
109import java .io .FileWriter ;
1110import java .io .IOException ;
1211import java .net .URI ;
1312import java .net .http .HttpRequest ;
1413import java .net .http .HttpResponse ;
14+ import java .nio .file .Files ;
15+ import java .nio .file .Path ;
16+ import java .nio .file .Paths ;
17+ import java .util .ArrayList ;
18+ import java .util .Arrays ;
19+ import java .util .HashMap ;
20+ import java .util .List ;
21+ import java .util .Map ;
1522import java .util .concurrent .Executors ;
1623import java .util .concurrent .ScheduledExecutorService ;
24+ import java .util .stream .Stream ;
1725
1826/**
1927 * Simple manager to authenticate and create sessions on Xbox
2028 */
2129public class SessionManager extends SessionManagerCore {
2230 private final ScheduledExecutorService scheduledThreadPool ;
31+ private final Map <String , SubSessionManager > subSessionManagers ;
2332
2433 /**
2534 * Create an instance of SessionManager
2635 *
27- * @param cache The directory to store the cached tokens in
36+ * @param cache The directory to store the cached tokens in
2837 * @param logger The logger to use for outputting messages
2938 */
3039 public SessionManager (String cache , Logger logger ) {
3140 super (cache , logger .prefixed ("Primary Session" ));
3241 this .scheduledThreadPool = Executors .newScheduledThreadPool (5 , new NamedThreadFactory ("MCXboxBroadcast Thread" ));
42+ this .subSessionManagers = new HashMap <>();
3343 }
3444
3545 @ Override
@@ -63,6 +73,19 @@ public void init(SessionInfo sessionInfo) throws SessionCreationException, Sessi
6373 this .sessionInfo = new ExpandedSessionInfo ("" , "" , sessionInfo );
6474
6575 super .init ();
76+
77+ // Load sub-sessions from cache
78+ List <String > subSessions = new ArrayList <>();
79+ try {
80+ subSessions = Arrays .asList (Constants .OBJECT_MAPPER .readValue (Paths .get (cache , "sub_sessions.json" ).toFile (), String [].class ));
81+ } catch (IOException ignored ) { }
82+
83+ // Create the sub-session manager for each sub-session
84+ for (String subSession : subSessions ) {
85+ SubSessionManager subSessionManager = new SubSessionManager (subSession , this , Paths .get (cache , subSession ).toString (), logger );
86+ subSessionManager .init ();
87+ subSessionManagers .put (subSession , subSessionManager );
88+ }
6689 }
6790
6891 /**
@@ -88,8 +111,13 @@ protected void updateSession() throws SessionUpdateException {
88111 * Stop the current session and close the websocket
89112 */
90113 public void shutdown () {
114+ // Shutdown all sub-sessions
115+ for (SubSessionManager subSessionManager : subSessionManagers .values ()) {
116+ subSessionManager .shutdown ();
117+ }
118+
119+ // Shutdown self
91120 super .shutdown ();
92- this .sessionInfo .setSessionId (null ); // TODO I don't think this is needed
93121 scheduledThreadPool .shutdown ();
94122 }
95123
@@ -126,4 +154,96 @@ public void dumpSession() {
126154
127155 logger .info ("Dumped session responses to 'lastSessionResponse.json' and 'currentSessionResponse.json'" );
128156 }
157+
158+ /**
159+ * Create a sub-session for the given ID
160+ *
161+ * @param id The ID of the sub-session to create
162+ */
163+ public void addSubSession (String id ) {
164+ // Make sure we don't already have that ID
165+ if (subSessionManagers .containsKey (id )) {
166+ coreLogger .error ("Sub-session already exists with that ID" );
167+ return ;
168+ }
169+
170+ // Create the sub-session manager
171+ try {
172+ SubSessionManager subSessionManager = new SubSessionManager (id , this , Paths .get (cache , id ).toString (), logger );
173+ subSessionManager .init ();
174+ subSessionManagers .put (id , subSessionManager );
175+ } catch (SessionCreationException | SessionUpdateException e ) {
176+ coreLogger .error ("Failed to create sub-session" , e );
177+ return ;
178+ }
179+
180+ // Update the list of sub-sessions
181+ try {
182+ Files .write (Paths .get (cache , "sub_sessions.json" ), Constants .OBJECT_MAPPER .writeValueAsBytes (subSessionManagers .keySet ()));
183+ } catch (IOException e ) {
184+ coreLogger .error ("Failed to update sub-session list" , e );
185+ }
186+ }
187+
188+ /**
189+ * Remove a sub-session for the given ID
190+ *
191+ * @param id The ID of the sub-session to remove
192+ */
193+ public void removeSubSession (String id ) {
194+ // Make sure we have that ID
195+ if (!subSessionManagers .containsKey (id )) {
196+ coreLogger .error ("Sub-session does not exist with that ID" );
197+ return ;
198+ }
199+
200+ // Remove the sub-session manager
201+ subSessionManagers .get (id ).shutdown ();
202+ subSessionManagers .remove (id );
203+
204+ // Delete the sub-session cache folder and its contents
205+ try (Stream <Path > files = Files .walk (Paths .get (cache , id ))) {
206+ files .map (Path ::toFile )
207+ .forEach (File ::delete );
208+ Paths .get (cache , id ).toFile ().delete ();
209+ } catch (IOException e ) {
210+ coreLogger .error ("Failed to delete sub-session cache folder" , e );
211+ }
212+
213+ // Update the list of sub-sessions
214+ try {
215+ Files .write (Paths .get (cache , "sub_sessions.json" ), Constants .OBJECT_MAPPER .writeValueAsBytes (subSessionManagers .keySet ()));
216+ } catch (IOException e ) {
217+ coreLogger .error ("Failed to update sub-session list" , e );
218+ }
219+
220+ coreLogger .info ("Removed sub-session with ID " + id );
221+ }
222+
223+ /**
224+ * List all sessions and their information
225+ */
226+ public void listSessions () {
227+ List <String > messages = new ArrayList <>();
228+ coreLogger .info ("Loading status of sessions..." );
229+
230+ messages .add ("Primary Session:" );
231+ messages .add (" - Gamertag: " + getXboxToken ().gamertag ());
232+ messages .add (" Following: " + socialSummary ().targetFollowingCount () + "/1000" );
233+
234+ if (subSessionManagers .isEmpty ()) {
235+ messages .add ("Sub-sessions:" );
236+ for (Map .Entry <String , SubSessionManager > subSession : subSessionManagers .entrySet ()) {
237+ messages .add (" - ID: " + subSession .getKey ());
238+ messages .add (" Gamertag: " + subSession .getValue ().getXboxToken ().gamertag ());
239+ messages .add (" Following: " + subSession .getValue ().socialSummary ().targetFollowingCount () + "/1000" );
240+ }
241+ } else {
242+ messages .add ("No sub-sessions" );
243+ }
244+
245+ for (String message : messages ) {
246+ coreLogger .info (message );
247+ }
248+ }
129249}
0 commit comments