1- use crate :: args:: { AddArgs , EditArgs , ExportArgs , ImportArgs } ;
1+ use crate :: args:: { AddArgs , EditArgs , ExportArgs , ExtractArgs , ImportArgs } ;
22use crate :: exporters:: do_export;
33use crate :: exporters:: otp_uri:: OtpUriList ;
44use crate :: importers:: aegis:: AegisJson ;
@@ -8,7 +8,7 @@ use crate::importers::converted::ConvertedJsonList;
88use crate :: importers:: freeotp_plus:: FreeOTPPlusJson ;
99use crate :: importers:: importer:: import_from_path;
1010use crate :: otp:: otp_element:: { OTPDatabase , OTPElement } ;
11- use crate :: utils;
11+ use crate :: { clipboard , utils} ;
1212use color_eyre:: eyre:: { eyre, ErrReport } ;
1313use zeroize:: Zeroize ;
1414
@@ -158,6 +158,27 @@ pub fn export(matches: ExportArgs, database: OTPDatabase) -> color_eyre::Result<
158158 . map_err ( |e| eyre ! ( "An error occurred while exporting database: {e}" ) )
159159}
160160
161+ pub fn extract ( args : ExtractArgs , database : OTPDatabase ) -> color_eyre:: Result < OTPDatabase > {
162+ let first_with_filters = database
163+ . elements
164+ . iter ( )
165+ . enumerate ( )
166+ . find ( |( index, code) | filter_extract ( & args, index, code) )
167+ . map ( |( _, code) | code) ;
168+
169+ if let Some ( otp) = first_with_filters {
170+ let code = otp. get_otp_code ( ) ?;
171+ println ! ( "{}" , code) ;
172+ if args. copy_to_clipboard {
173+ let _ = clipboard:: copy_string_to_clipboard ( code. as_str ( ) ) ?;
174+ println ! ( "Copied to clipboard" ) ;
175+ }
176+ Ok ( database)
177+ } else {
178+ Err ( eyre ! ( "No such code found with these fields" ) )
179+ }
180+ }
181+
161182pub fn change_password ( mut database : OTPDatabase ) -> color_eyre:: Result < OTPDatabase > {
162183 let mut new_password = utils:: verified_password ( "New password: " , 8 ) ;
163184 database
@@ -166,3 +187,17 @@ pub fn change_password(mut database: OTPDatabase) -> color_eyre::Result<OTPDatab
166187 new_password. zeroize ( ) ;
167188 Ok ( database)
168189}
190+
191+ fn filter_extract ( args : & ExtractArgs , index : & usize , code : & OTPElement ) -> bool {
192+ let match_by_index = args. index . map_or ( true , |i| i == * index) ;
193+
194+ let match_by_issuer = args. issuer . as_ref ( ) . map_or ( true , |issuer| {
195+ code. issuer . to_lowercase ( ) == issuer. to_lowercase ( )
196+ } ) ;
197+
198+ let match_by_label = args. label . as_ref ( ) . map_or ( true , |label| {
199+ code. label . to_lowercase ( ) == label. to_lowercase ( )
200+ } ) ;
201+
202+ match_by_index && match_by_issuer && match_by_label
203+ }
0 commit comments