1
1
use 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 } ;
3
4
use std:: io:: { BufRead , Write } ;
4
5
5
6
fn main ( ) {
@@ -16,7 +17,49 @@ fn main() {
16
17
17
18
ping ( & client) . unwrap ( ) ;
18
19
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 ( ) {
20
63
SessionType :: Authenticated ( s) => s,
21
64
SessionType :: AwaitingTotp ( mut t) => {
22
65
let mut line_reader = std:: io:: BufReader :: new ( std:: io:: stdin ( ) ) ;
@@ -65,3 +108,53 @@ fn main() {
65
108
66
109
session. logout ( & client) . unwrap ( ) ;
67
110
}
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