66from functools import partial
77from typing import Any , Callable , Dict , List , Mapping , Tuple
88
9- import click
10-
119from icloudpd .mfa_provider import MFAProvider
1210from icloudpd .status import Status , StatusExchange
1311from pyicloud_ipd .base import PyiCloudService
1614from pyicloud_ipd .raw_policy import RawTreatmentPolicy
1715
1816
17+ def prompt_int_range (message : str , default : str , min_val : int , max_val : int ) -> int :
18+ """Prompt user for integer input within a range, similar to click.IntRange"""
19+ while True :
20+ try :
21+ response = input (f"{ message } [{ default } ]: " ).strip () or default
22+ value = int (response )
23+ if min_val <= value <= max_val :
24+ return value
25+ else :
26+ print (f"Invalid input: { value } is not in the range { min_val } -{ max_val } " )
27+ except ValueError :
28+ print (f"Invalid input: '{ response } ' is not a valid integer" )
29+
30+
31+ def prompt_string (message : str ) -> str :
32+ """Prompt user for string input"""
33+ return input (f"{ message } : " )
34+
35+
36+ def echo (message : str ) -> None :
37+ """Print message to stdout, similar to click.echo"""
38+ print (message )
39+
40+
1941def authenticator (
2042 logger : logging .Logger ,
2143 domain : str ,
@@ -93,18 +115,16 @@ def request_2sa(icloud: PyiCloudService, logger: logging.Logger) -> None:
93115 number = device ["phoneNumber" ]
94116 alt_name = f"SMS to { number } "
95117 name = device .get ("deviceName" , alt_name )
96- click . echo (f" { i } : { name } " )
118+ echo (f" { i } : { name } " )
97119
98- device_index = click .prompt (
99- "Please choose an option:" , default = "0" , type = click .IntRange (0 , devices_count - 1 )
100- )
120+ device_index = prompt_int_range ("Please choose an option:" , "0" , 0 , devices_count - 1 )
101121
102122 device = devices [device_index ]
103123 if not icloud .send_verification_code (device ):
104124 logger .error ("Failed to send two-step authentication code" )
105125 sys .exit (1 )
106126
107- code = click . prompt ("Please enter two-step authentication code" )
127+ code = prompt_string ("Please enter two-step authentication code" )
108128 if not icloud .validate_verification_code (device , code ):
109129 logger .error ("Failed to verify two-step authentication code" )
110130 sys .exit (1 )
@@ -127,47 +147,47 @@ def request_2fa(icloud: PyiCloudService, logger: logging.Logger) -> None:
127147 raise PyiCloudFailedMFAException ("Too many trusted devices for authentication" )
128148
129149 for i , device in enumerate (devices ):
130- click . echo (f" { device_index_alphabet [i ]} : { device .obfuscated_number } " )
150+ echo (f" { device_index_alphabet [i ]} : { device .obfuscated_number } " )
131151
132152 index_str = f"..{ device_index_alphabet [devices_count - 1 ]} " if devices_count > 1 else ""
133153 index_or_code : str = ""
134154 while True :
135155 index_or_code = (
136- click . prompt (
137- f"Please enter two-factor authentication code or device index ({ device_index_alphabet [0 ]} { index_str } ) to send SMS with a code" ,
156+ prompt_string (
157+ f"Please enter two-factor authentication code or device index ({ device_index_alphabet [0 ]} { index_str } ) to send SMS with a code"
138158 )
139159 .strip ()
140160 .lower ()
141161 )
142162
143163 if index_or_code == "" :
144- click . echo ("Empty string. Try again" )
164+ echo ("Empty string. Try again" )
145165 continue
146166
147167 if len (index_or_code ) == 1 :
148168 if index_or_code in device_index_alphabet :
149169 if device_index_alphabet .index (index_or_code ) > devices_count - 1 :
150- click . echo (
151- f"Invalid index, should be ({ device_index_alphabet [0 ]} { index_str } ). Try again" ,
170+ echo (
171+ f"Invalid index, should be ({ device_index_alphabet [0 ]} { index_str } ). Try again"
152172 )
153173 continue
154174 else :
155175 break
156176 else :
157- click . echo (
158- f"Invalid index, should be ({ device_index_alphabet [0 ]} { index_str } ). Try again" ,
177+ echo (
178+ f"Invalid index, should be ({ device_index_alphabet [0 ]} { index_str } ). Try again"
159179 )
160180 continue
161181
162182 if len (index_or_code ) == 6 :
163183 if index_or_code .isdigit ():
164184 break
165185 else :
166- click . echo ("Invalid code, should be six digits. Try again" )
186+ echo ("Invalid code, should be six digits. Try again" )
167187 continue
168188
169- click . echo (
170- f"Should be index ({ device_index_alphabet [0 ]} { index_str } ) or six-digit code. Try again" ,
189+ echo (
190+ f"Should be index ({ device_index_alphabet [0 ]} { index_str } ) or six-digit code. Try again"
171191 )
172192
173193 if index_or_code in device_index_alphabet :
@@ -177,12 +197,12 @@ def request_2fa(icloud: PyiCloudService, logger: logging.Logger) -> None:
177197 if not icloud .send_2fa_code_sms (device .id ):
178198 raise PyiCloudFailedMFAException ("Failed to send two-factor authentication code" )
179199 while True :
180- code : str = click . prompt (
181- "Please enter two-factor authentication code that you received over SMS" ,
200+ code : str = prompt_string (
201+ "Please enter two-factor authentication code that you received over SMS"
182202 ).strip ()
183203 if len (code ) == 6 and code .isdigit ():
184204 break
185- click . echo ("Invalid code, should be six digits. Try again" )
205+ echo ("Invalid code, should be six digits. Try again" )
186206
187207 if not icloud .validate_2fa_code_sms (device .id , code ):
188208 raise PyiCloudFailedMFAException ("Failed to verify two-factor authentication code" )
@@ -191,12 +211,10 @@ def request_2fa(icloud: PyiCloudService, logger: logging.Logger) -> None:
191211 raise PyiCloudFailedMFAException ("Failed to verify two-factor authentication code" )
192212 else :
193213 while True :
194- code = click .prompt (
195- "Please enter two-factor authentication code" ,
196- ).strip ()
214+ code = prompt_string ("Please enter two-factor authentication code" ).strip ()
197215 if len (code ) == 6 and code .isdigit ():
198216 break
199- click . echo ("Invalid code, should be six digits. Try again" )
217+ echo ("Invalid code, should be six digits. Try again" )
200218 if not icloud .validate_2fa_code (code ):
201219 raise PyiCloudFailedMFAException ("Failed to verify two-factor authentication code" )
202220 logger .info (
0 commit comments