@@ -33,6 +33,11 @@ class OutlookPoolResetRequest(BaseModel):
3333 scope : str | None = None
3434
3535
36+ class OutlookPoolRetryRequest (BaseModel ):
37+ provider_id : str = Field (min_length = 1 , max_length = 128 )
38+ mailbox_ids : list [str ] = Field (min_length = 1 )
39+
40+
3641class GptMailStatusRequest (BaseModel ):
3742 provider : dict | None = None
3843 force : bool | None = None
@@ -55,6 +60,11 @@ class GrokAccountChatTestRequest(BaseModel):
5560 model : str | None = Field (default = None , max_length = 128 )
5661
5762
63+ class GrokAccountExportRequest (BaseModel ):
64+ ids : list [str ] = Field (default_factory = list )
65+ format : Literal ["sub2api" , "cpa" ] = "sub2api"
66+
67+
5868def _grok_account_ids (values : list [str ]) -> list [str ]:
5969 return list (dict .fromkeys (str (value or "" ).strip () for value in values if str (value or "" ).strip ()))
6070
@@ -102,6 +112,22 @@ async def reset_outlook_pool(body: OutlookPoolResetRequest, authorization: str |
102112 require_admin (authorization )
103113 return {"register" : register_service .reset_outlook_pool (body .scope or "all" )}
104114
115+ @router .post ("/api/register/outlook-pool/retry-selected" )
116+ async def retry_selected_outlook_mailboxes (
117+ body : OutlookPoolRetryRequest ,
118+ authorization : str | None = Header (default = None ),
119+ ):
120+ require_admin (authorization )
121+ try :
122+ return {
123+ "register" : register_service .retry_outlook_failed (
124+ body .provider_id ,
125+ body .mailbox_ids ,
126+ )
127+ }
128+ except ValueError as exc :
129+ raise HTTPException (status_code = 400 , detail = str (exc )) from exc
130+
105131 @router .post ("/api/register/gptmail/status" )
106132 async def get_gptmail_status (body : GptMailStatusRequest , authorization : str | None = Header (default = None )):
107133 require_admin (authorization )
@@ -147,6 +173,11 @@ async def list_grok_accounts(
147173 "runtime_error" : str (view .get ("runtime_error" ) or "" ),
148174 }
149175
176+ @router .post ("/api/register/grok/accounts/runtime/snapshot" )
177+ async def refresh_grok_runtime_snapshot (authorization : str | None = Header (default = None )):
178+ require_admin (authorization )
179+ return await run_in_threadpool (register_service .refresh_grok_runtime_snapshot )
180+
150181 @router .get ("/api/register/grok/accounts/{account_id}/credentials" )
151182 async def get_grok_account_login_credentials (
152183 account_id : str ,
@@ -174,6 +205,17 @@ async def sync_grok_accounts(
174205 raise HTTPException (status_code = 400 , detail = {"error" : "ids is required" })
175206 return await run_in_threadpool (register_service .sync_grok_accounts , ids )
176207
208+ @router .post ("/api/register/grok/accounts/oauth/authorize" )
209+ async def authorize_grok_accounts_oauth (
210+ body : GrokAccountIdsRequest ,
211+ authorization : str | None = Header (default = None ),
212+ ):
213+ require_admin (authorization )
214+ ids = _grok_account_ids (body .ids )
215+ if not ids :
216+ raise HTTPException (status_code = 400 , detail = {"error" : "ids is required" })
217+ return await run_in_threadpool (register_service .authorize_grok_accounts_oauth , ids )
218+
177219 @router .post ("/api/register/grok/accounts/runtime/refresh" )
178220 async def refresh_grok_accounts_runtime (
179221 body : GrokAccountIdsRequest ,
@@ -244,26 +286,60 @@ async def delete_grok_accounts(
244286
245287 @router .get ("/api/register/grok/accounts/export" )
246288 async def export_grok_accounts (
247- format : Literal ["json " , "txt " ] = "json " ,
289+ format : Literal ["sub2api " , "cpa " ] = "sub2api " ,
248290 authorization : str | None = Header (default = None ),
249291 ):
250292 require_admin (authorization )
251293 timestamp = datetime .now (timezone .utc ).strftime ("%Y%m%d-%H%M%S" )
252- if format == "txt" :
253- return Response (
254- register_service .export_grok_accounts_text (),
255- media_type = "text/plain; charset=utf-8" ,
256- headers = {
257- "Cache-Control" : "no-store" ,
258- "Content-Disposition" : f'attachment; filename="grok-accounts-{ timestamp } .txt"' ,
259- },
260- )
294+ try :
295+ if format == "cpa" :
296+ return Response (
297+ register_service .export_grok_accounts_cpa (),
298+ media_type = "application/zip" ,
299+ headers = {
300+ "Cache-Control" : "no-store" ,
301+ "Content-Disposition" : f'attachment; filename="grok-accounts-cpa-{ timestamp } .zip"' ,
302+ },
303+ )
304+ payload = register_service .export_grok_accounts_sub2api ()
305+ except ValueError as exc :
306+ raise HTTPException (status_code = 400 , detail = str (exc )) from exc
307+ return Response (
308+ json .dumps (payload , ensure_ascii = False , indent = 2 ) + "\n " ,
309+ media_type = "application/json" ,
310+ headers = {
311+ "Cache-Control" : "no-store" ,
312+ "Content-Disposition" : f'attachment; filename="grok-accounts-sub2api-{ timestamp } .json"' ,
313+ },
314+ )
315+
316+ @router .post ("/api/register/grok/accounts/export" )
317+ async def export_selected_grok_accounts (
318+ body : GrokAccountExportRequest ,
319+ authorization : str | None = Header (default = None ),
320+ ):
321+ require_admin (authorization )
322+ ids = _grok_account_ids (body .ids )
323+ timestamp = datetime .now (timezone .utc ).strftime ("%Y%m%d-%H%M%S" )
324+ try :
325+ if body .format == "cpa" :
326+ return Response (
327+ register_service .export_grok_accounts_cpa (ids or None ),
328+ media_type = "application/zip" ,
329+ headers = {
330+ "Cache-Control" : "no-store" ,
331+ "Content-Disposition" : f'attachment; filename="grok-accounts-cpa-{ timestamp } .zip"' ,
332+ },
333+ )
334+ payload = register_service .export_grok_accounts_sub2api (ids or None )
335+ except ValueError as exc :
336+ raise HTTPException (status_code = 400 , detail = str (exc )) from exc
261337 return Response (
262- json .dumps (register_service . export_grok_accounts () , ensure_ascii = False , indent = 2 ) + "\n " ,
338+ json .dumps (payload , ensure_ascii = False , indent = 2 ) + "\n " ,
263339 media_type = "application/json" ,
264340 headers = {
265341 "Cache-Control" : "no-store" ,
266- "Content-Disposition" : f'attachment; filename="grok-accounts-{ timestamp } .json"' ,
342+ "Content-Disposition" : f'attachment; filename="grok-accounts-sub2api- { timestamp } .json"' ,
267343 },
268344 )
269345
0 commit comments