11use proton_api_rs:: clientv2:: { ping, SessionType } ;
2- use proton_api_rs:: { http, Session } ;
2+ use proton_api_rs:: domain:: CaptchaErrorDetail ;
3+ use proton_api_rs:: { captcha_get, http, LoginError , Session } ;
34use std:: io:: { BufRead , Write } ;
45
56fn main ( ) {
@@ -16,7 +17,49 @@ fn main() {
1617
1718 ping ( & client) . unwrap ( ) ;
1819
19- let session = match Session :: login ( & client, & user_email, & user_password, None ) . unwrap ( ) {
20+ let login_result = Session :: login ( & client, & user_email, & user_password, None ) ;
21+ if let Err ( LoginError :: Request ( http:: Error :: API ( e) ) ) = & login_result {
22+ if e. api_code != 9001 {
23+ panic ! ( "{e}" )
24+ }
25+ let captcha_desc =
26+ serde_json:: from_value :: < CaptchaErrorDetail > ( e. details . clone ( ) . unwrap ( ) ) . unwrap ( ) ;
27+
28+ let captcha_body = captcha_get ( & client, & captcha_desc. human_verification_token ) . unwrap ( ) ;
29+ run_captcha ( captcha_body) ;
30+ // TODO: Start webview with the downloaded body - use https://github.com/tauri-apps/wry
31+ // Click
32+ // Handle postMessageToParent which has token & token type
33+ // repeat submission with x-pm-human-verification-token and x-pm-human-verification-token-type
34+ // Use the event below to catch this
35+ // window.addEventListener(
36+ // "message",
37+ // (event) => {
38+ // -> event.Data
39+ // },
40+ // false
41+ // );
42+ // On Success
43+ // postMessageToParent({
44+ // "type": "pm_captcha",
45+ // "token": response
46+ // });
47+ //
48+ // on expired
49+ // postMessageToParent({
50+ // "type": "pm_captcha_expired",
51+ // "token": response
52+ // });
53+ //
54+ // on height:
55+ // postMessageToParent({
56+ // 'type': 'pm_height',
57+ // 'height': height
58+ // });
59+ return ;
60+ }
61+
62+ let session = match login_result. unwrap ( ) {
2063 SessionType :: Authenticated ( s) => s,
2164 SessionType :: AwaitingTotp ( mut t) => {
2265 let mut line_reader = std:: io:: BufReader :: new ( std:: io:: stdin ( ) ) ;
@@ -65,3 +108,53 @@ fn main() {
65108
66109 session. logout ( & client) . unwrap ( ) ;
67110}
111+
112+ fn run_captcha ( html : String ) {
113+ std:: fs:: write ( "/tmp/captcha.html" , html) . unwrap ( ) ;
114+ use wry:: {
115+ application:: {
116+ event:: { Event , StartCause , WindowEvent } ,
117+ event_loop:: { ControlFlow , EventLoop } ,
118+ window:: WindowBuilder ,
119+ } ,
120+ webview:: WebViewBuilder ,
121+ } ;
122+
123+ let event_loop = EventLoop :: new ( ) ;
124+ let window = WindowBuilder :: new ( )
125+ . with_title ( "Proton API Captcha" )
126+ . build ( & event_loop)
127+ . unwrap ( ) ;
128+ let _webview = WebViewBuilder :: new ( window)
129+ . unwrap ( )
130+ . with_url ( "http://127.0.0.1:8000/captcha.html" )
131+ . unwrap ( )
132+ . with_devtools ( true )
133+ . with_ipc_handler ( |window, req| {
134+ println ! ( "Window IPC: {req}" ) ;
135+ } )
136+ . build ( )
137+ . unwrap ( ) ;
138+
139+ _webview
140+ . evaluate_script (
141+ "postMessageToParent = function(message) { window.ipc.postMessage(JSON.stringify(message), '*')}" ,
142+ )
143+ . unwrap ( ) ;
144+
145+ event_loop. run ( move |event, _, control_flow| {
146+ * control_flow = ControlFlow :: Wait ;
147+
148+ match event {
149+ Event :: NewEvents ( StartCause :: Init ) => println ! ( "Wry has started!" ) ,
150+ Event :: WindowEvent {
151+ event : WindowEvent :: CloseRequested ,
152+ ..
153+ } => {
154+ println ! ( "Close requested" ) ;
155+ * control_flow = ControlFlow :: Exit
156+ }
157+ _ => ( ) ,
158+ }
159+ } ) ;
160+ }
0 commit comments