pec_ruby 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec_status +109 -92
- data/CHANGELOG.md +36 -0
- data/Gemfile.lock +3 -1
- data/README.md +212 -45
- data/lib/pec_ruby/cli.rb +353 -111
- data/lib/pec_ruby/client.rb +77 -29
- data/lib/pec_ruby/message.rb +188 -38
- data/lib/pec_ruby/version.rb +2 -2
- data/lib/pec_ruby.rb +7 -6
- metadata +16 -2
data/lib/pec_ruby/cli.rb
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
begin
|
4
4
|
require 'tty-prompt'
|
5
|
+
require 'tty-screen'
|
5
6
|
require 'awesome_print'
|
6
7
|
rescue LoadError => e
|
7
|
-
raise LoadError,
|
8
|
+
raise LoadError, 'CLI dependencies not available. Install with: gem install tty-prompt tty-screen awesome_print'
|
8
9
|
end
|
9
10
|
|
10
11
|
module PecRuby
|
@@ -12,22 +13,29 @@ module PecRuby
|
|
12
13
|
def initialize
|
13
14
|
@client = nil
|
14
15
|
@prompt = TTY::Prompt.new
|
16
|
+
@screen_height = TTY::Screen.height
|
17
|
+
@screen_width = TTY::Screen.width
|
15
18
|
end
|
16
19
|
|
17
20
|
def run
|
18
|
-
puts banner
|
19
|
-
|
20
21
|
loop do
|
22
|
+
clear_screen
|
23
|
+
show_header
|
24
|
+
show_status
|
25
|
+
|
21
26
|
case main_menu
|
22
27
|
when :connect
|
23
28
|
connect_to_server
|
29
|
+
when :select_folder
|
30
|
+
select_folder_menu if connected?
|
24
31
|
when :list_messages
|
25
32
|
list_and_select_messages if connected?
|
26
33
|
when :disconnect
|
27
34
|
disconnect_from_server
|
28
35
|
when :exit
|
29
36
|
disconnect_from_server if connected?
|
30
|
-
|
37
|
+
clear_screen
|
38
|
+
puts center_text('Arrivederci!')
|
31
39
|
break
|
32
40
|
end
|
33
41
|
end
|
@@ -35,28 +43,56 @@ module PecRuby
|
|
35
43
|
|
36
44
|
private
|
37
45
|
|
46
|
+
def clear_screen
|
47
|
+
print "\033[2J\033[H"
|
48
|
+
end
|
49
|
+
|
50
|
+
def center_text(text)
|
51
|
+
padding = (@screen_width - text.length) / 2
|
52
|
+
' ' * [padding, 0].max + text
|
53
|
+
end
|
54
|
+
|
55
|
+
def show_header
|
56
|
+
puts banner
|
57
|
+
end
|
58
|
+
|
59
|
+
def show_status
|
60
|
+
if connected?
|
61
|
+
status = "CONNESSO: #{@client.username}"
|
62
|
+
folder = @client.current_folder ? " | FOLDER: #{@client.current_folder}" : ""
|
63
|
+
puts center_text("#{status}#{folder}")
|
64
|
+
else
|
65
|
+
puts center_text("NON CONNESSO")
|
66
|
+
end
|
67
|
+
puts "─" * @screen_width
|
68
|
+
puts
|
69
|
+
end
|
70
|
+
|
38
71
|
def banner
|
39
72
|
<<~BANNER
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
73
|
+
██████╗ ███████╗ ██████╗ ██████╗ ██╗ ██╗██████╗ ██╗ ██╗
|
74
|
+
██╔══██╗██╔════╝██╔════╝ ██╔══██╗██║ ██║██╔══██╗╚██╗ ██╔╝
|
75
|
+
██████╔╝█████╗ ██║ ██████╔╝██║ ██║██████╔╝ ╚████╔╝
|
76
|
+
██╔═══╝ ██╔══╝ ██║ ██╔══██╗██║ ██║██╔══██╗ ╚██╔╝
|
77
|
+
██║ ███████╗╚██████╗ ██║ ██║╚██████╔╝██████╔╝ ██║
|
78
|
+
╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝
|
79
|
+
|
80
|
+
PEC Ruby CLI v#{PecRuby::VERSION} | Italian PEC Email Manager
|
46
81
|
BANNER
|
47
82
|
end
|
48
83
|
|
49
84
|
def main_menu
|
50
85
|
choices = []
|
51
|
-
|
86
|
+
|
52
87
|
if connected?
|
53
|
-
choices << { name:
|
54
|
-
choices << { name:
|
88
|
+
choices << { name: 'Seleziona folder', value: :select_folder }
|
89
|
+
choices << { name: 'Lista e analizza messaggi', value: :list_messages }
|
90
|
+
choices << { name: 'Disconnetti dal server', value: :disconnect }
|
55
91
|
else
|
56
|
-
choices << { name:
|
92
|
+
choices << { name: 'Connetti al server PEC', value: :connect }
|
57
93
|
end
|
58
|
-
|
59
|
-
choices << { name:
|
94
|
+
|
95
|
+
choices << { name: 'Esci', value: :exit }
|
60
96
|
|
61
97
|
@prompt.select("Seleziona un'azione:", choices)
|
62
98
|
end
|
@@ -64,24 +100,35 @@ module PecRuby
|
|
64
100
|
def connect_to_server
|
65
101
|
return if connected?
|
66
102
|
|
67
|
-
|
68
|
-
|
103
|
+
clear_screen
|
104
|
+
show_header
|
105
|
+
puts
|
106
|
+
puts center_text("CONNESSIONE AL SERVER PEC")
|
107
|
+
puts "─" * @screen_width
|
108
|
+
puts
|
69
109
|
|
70
|
-
host = @prompt.ask(
|
71
|
-
username = @prompt.ask(
|
72
|
-
password = @prompt.mask(
|
110
|
+
host = @prompt.ask('Host IMAP:', default: 'imaps.pec.aruba.it')
|
111
|
+
username = @prompt.ask('Username/Email:')
|
112
|
+
password = @prompt.mask('Password:')
|
113
|
+
|
114
|
+
puts
|
115
|
+
puts center_text('[*] Connessione in corso...')
|
73
116
|
|
74
|
-
print "Connessione in corso..."
|
75
|
-
|
76
117
|
begin
|
77
118
|
@client = Client.new(host: host, username: username, password: password)
|
78
119
|
@client.connect
|
79
|
-
|
80
|
-
puts
|
120
|
+
|
121
|
+
puts center_text('[+] Connesso con successo!')
|
122
|
+
puts center_text("Utente: #{@client.username}")
|
123
|
+
puts center_text("Folder: INBOX")
|
124
|
+
|
125
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
81
126
|
rescue PecRuby::Error => e
|
82
|
-
puts
|
83
|
-
puts "
|
127
|
+
puts center_text('[-] Errore di connessione!')
|
128
|
+
puts center_text("Dettagli: #{e.message}")
|
84
129
|
@client = nil
|
130
|
+
|
131
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
85
132
|
end
|
86
133
|
end
|
87
134
|
|
@@ -91,22 +138,39 @@ module PecRuby
|
|
91
138
|
|
92
139
|
def disconnect_from_server
|
93
140
|
return unless connected?
|
141
|
+
|
142
|
+
clear_screen
|
143
|
+
show_header
|
144
|
+
puts
|
145
|
+
puts center_text('[*] Disconnessione in corso...')
|
94
146
|
|
95
147
|
@client.disconnect
|
96
148
|
@client = nil
|
97
|
-
|
149
|
+
|
150
|
+
puts center_text('[+] Disconnesso dal server')
|
151
|
+
|
152
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
98
153
|
end
|
99
154
|
|
100
155
|
def list_and_select_messages
|
101
|
-
|
156
|
+
current_folder = @client.current_folder || 'INBOX'
|
102
157
|
|
158
|
+
clear_screen
|
159
|
+
show_header
|
160
|
+
show_status
|
161
|
+
puts center_text("MESSAGGI DA #{current_folder.upcase}")
|
162
|
+
puts "─" * @screen_width
|
163
|
+
puts center_text("[*] Caricamento messaggi...")
|
164
|
+
|
103
165
|
begin
|
104
|
-
messages
|
105
|
-
|
106
|
-
messages = messages
|
107
|
-
|
166
|
+
# Get messages in reverse order (newest first) directly from server
|
167
|
+
start_time = Time.now
|
168
|
+
messages = @client.messages(limit: 50, reverse: true)
|
169
|
+
load_time = Time.now - start_time
|
170
|
+
|
108
171
|
if messages.empty?
|
109
|
-
puts "Nessun messaggio
|
172
|
+
puts center_text("[-] Nessun messaggio trovato in #{current_folder}")
|
173
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
110
174
|
return
|
111
175
|
end
|
112
176
|
|
@@ -115,112 +179,290 @@ module PecRuby
|
|
115
179
|
[label, msg]
|
116
180
|
end
|
117
181
|
|
118
|
-
puts "
|
119
|
-
puts
|
120
|
-
|
121
|
-
|
122
|
-
selected_message = @prompt.select("Seleziona un messaggio:", choices.to_h, per_page: 15, cycle: true)
|
182
|
+
puts center_text("[+] Trovati #{messages.size} messaggi (caricati in #{load_time.round(2)}s)")
|
183
|
+
puts
|
184
|
+
|
185
|
+
selected_message = @prompt.select('Seleziona un messaggio:', choices.to_h, per_page: 15, cycle: true)
|
123
186
|
display_message(selected_message)
|
124
|
-
|
125
187
|
rescue PecRuby::Error => e
|
126
|
-
puts "Errore nel recupero messaggi: #{e.message}"
|
188
|
+
puts center_text("[-] Errore nel recupero messaggi: #{e.message}")
|
189
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
190
|
+
rescue StandardError => e
|
191
|
+
puts center_text("[-] Errore imprevisto: #{e.message}")
|
192
|
+
puts center_text("Dettagli: #{e.class}")
|
193
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
127
194
|
end
|
128
195
|
end
|
129
196
|
|
130
197
|
def format_message_label(message)
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
198
|
+
# Use only original (envelope) data for performance - no postacert fetching
|
199
|
+
subject = message.original_subject || '(nessun oggetto)'
|
200
|
+
from = message.original_from || '(mittente sconosciuto)'
|
201
|
+
date = message.original_date ? message.original_date.strftime('%d/%m %H:%M') : 'N/A'
|
202
|
+
|
135
203
|
short_subject = subject.length > 60 ? "#{subject[0..56]}..." : subject
|
136
|
-
|
137
|
-
|
138
|
-
short_subject,
|
139
|
-
from.to_s[0..24],
|
204
|
+
|
205
|
+
format('%-60s | %-25s | %s',
|
206
|
+
short_subject,
|
207
|
+
from.to_s[0..24],
|
140
208
|
date)
|
141
209
|
end
|
142
210
|
|
143
211
|
def display_message(message)
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
puts
|
160
|
-
puts
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
content = body[:content].strip
|
172
|
-
|
173
|
-
# Clean up common formatting issues
|
174
|
-
content = content.gsub(/\r\n/, "\n") # Normalize line endings
|
175
|
-
content = content.gsub(/\u0093|\u0094/, '"') # Replace smart quotes
|
176
|
-
content = content.gsub(/\u0092/, "'") # Replace smart apostrophes
|
177
|
-
|
178
|
-
puts content
|
212
|
+
loop do
|
213
|
+
clear_screen
|
214
|
+
show_header
|
215
|
+
show_status
|
216
|
+
|
217
|
+
# Message header with visual separator
|
218
|
+
puts center_text("DETTAGLIO MESSAGGIO")
|
219
|
+
puts "═" * @screen_width
|
220
|
+
puts
|
221
|
+
|
222
|
+
# Message info in organized sections
|
223
|
+
display_message_info(message)
|
224
|
+
display_message_body(message, truncate: true)
|
225
|
+
display_message_attachments(message, show_download_option: false)
|
226
|
+
|
227
|
+
puts
|
228
|
+
puts "═" * @screen_width
|
229
|
+
|
230
|
+
# Show message menu
|
231
|
+
action = show_message_menu(message)
|
232
|
+
case action
|
233
|
+
when :full_body
|
234
|
+
display_full_body(message)
|
235
|
+
when :download_attachments
|
236
|
+
download_attachments(message.attachments) if message.attachments.any?
|
237
|
+
when :back
|
238
|
+
break
|
179
239
|
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def show_message_menu(message)
|
244
|
+
choices = []
|
245
|
+
|
246
|
+
# Add body option if message has body
|
247
|
+
body = message.raw_body
|
248
|
+
if body && body[:content] && !body[:content].strip.empty?
|
249
|
+
choices << { name: "Visualizza corpo completo", value: :full_body }
|
250
|
+
end
|
251
|
+
|
252
|
+
# Add attachments option if message has attachments
|
253
|
+
if message.attachments.any?
|
254
|
+
choices << { name: "Scarica allegati (#{message.attachments.size})", value: :download_attachments }
|
255
|
+
end
|
256
|
+
|
257
|
+
choices << { name: "← Torna alla lista", value: :back }
|
258
|
+
|
259
|
+
@prompt.select("Seleziona un'azione:", choices)
|
260
|
+
end
|
180
261
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
262
|
+
def display_full_body(message)
|
263
|
+
clear_screen
|
264
|
+
show_header
|
265
|
+
|
266
|
+
puts center_text("CORPO COMPLETO DEL MESSAGGIO")
|
267
|
+
puts "═" * @screen_width
|
268
|
+
puts
|
269
|
+
|
270
|
+
body = message.raw_body
|
271
|
+
if body && body[:content] && !body[:content].strip.empty?
|
272
|
+
content = body[:content].strip
|
273
|
+
content = content.gsub(/\r\n/, "\n")
|
274
|
+
content = content.gsub(/\u0093|\u0094/, '"')
|
275
|
+
content = content.gsub(/\u0092/, "'")
|
276
|
+
|
277
|
+
puts content
|
278
|
+
else
|
279
|
+
puts center_text("Nessun contenuto disponibile")
|
280
|
+
end
|
281
|
+
|
282
|
+
puts
|
283
|
+
puts "═" * @screen_width
|
284
|
+
@prompt.keypress(center_text("Premi un tasto per continuare..."), echo: false)
|
285
|
+
end
|
286
|
+
|
287
|
+
def display_message_info(message)
|
288
|
+
# Main information section
|
289
|
+
puts "[INFORMAZIONI PRINCIPALI]"
|
290
|
+
puts "─" * (@screen_width - 20)
|
291
|
+
|
292
|
+
info_lines = [
|
293
|
+
["Oggetto", message.subject || "(nessun oggetto)"],
|
294
|
+
["Mittente", message.from || "(sconosciuto)"],
|
295
|
+
["Destinatari", message.to.join(", ")],
|
296
|
+
["Data", message.date ? message.date.strftime("%d/%m/%Y %H:%M") : "(sconosciuta)"]
|
297
|
+
]
|
298
|
+
|
299
|
+
display_info_table(info_lines)
|
300
|
+
puts
|
301
|
+
|
302
|
+
# PEC container information
|
303
|
+
puts "[INFORMAZIONI CONTENITORE PEC]"
|
304
|
+
puts "─" * (@screen_width - 20)
|
305
|
+
|
306
|
+
pec_lines = [
|
307
|
+
["Oggetto PEC", message.original_subject || "(nessun oggetto)"],
|
308
|
+
["From PEC", message.original_from || "(sconosciuto)"],
|
309
|
+
["Data PEC", message.original_date ? message.original_date.strftime("%d/%m/%Y %H:%M") : "(sconosciuta)"]
|
310
|
+
]
|
311
|
+
|
312
|
+
display_info_table(pec_lines)
|
313
|
+
puts
|
314
|
+
end
|
315
|
+
|
316
|
+
def display_message_body(message, truncate: false)
|
317
|
+
body = message.raw_body
|
318
|
+
return unless body && body[:content] && !body[:content].strip.empty?
|
319
|
+
|
320
|
+
puts "[CORPO DEL MESSAGGIO]"
|
321
|
+
puts "─" * (@screen_width - 20)
|
322
|
+
|
323
|
+
# Format the body for better readability
|
324
|
+
content = body[:content].strip
|
325
|
+
content = content.gsub(/\r\n/, "\n")
|
326
|
+
content = content.gsub(/\u0093|\u0094/, '"')
|
327
|
+
content = content.gsub(/\u0092/, "'")
|
328
|
+
|
329
|
+
if truncate
|
330
|
+
# Truncate long messages for overview
|
331
|
+
max_lines = 10
|
332
|
+
lines = content.split("\n")
|
333
|
+
|
334
|
+
if lines.length > max_lines
|
335
|
+
puts lines.first(max_lines).join("\n")
|
336
|
+
puts
|
337
|
+
puts center_text("... (messaggio troncato, #{lines.length - max_lines} righe rimanenti)")
|
197
338
|
else
|
198
|
-
puts
|
339
|
+
puts content
|
340
|
+
end
|
341
|
+
else
|
342
|
+
puts content
|
343
|
+
end
|
344
|
+
puts
|
345
|
+
end
|
346
|
+
|
347
|
+
def display_message_attachments(message, show_download_option: true)
|
348
|
+
attachments = message.attachments
|
349
|
+
puts "[ALLEGATI - #{attachments.size}]"
|
350
|
+
puts "─" * (@screen_width - 20)
|
351
|
+
|
352
|
+
if attachments.any?
|
353
|
+
attachments.each_with_index do |att, i|
|
354
|
+
status = att.filename.include?('postacert') ? '[PEC]' : '[ATT]'
|
355
|
+
puts format("%s %2d. %-35s | %-20s | %8.1f KB",
|
356
|
+
status,
|
357
|
+
i + 1,
|
358
|
+
truncate_text(att.filename, 35),
|
359
|
+
truncate_text(att.mime_type, 20),
|
360
|
+
att.size_kb)
|
361
|
+
end
|
362
|
+
|
363
|
+
if show_download_option
|
364
|
+
puts
|
365
|
+
download_attachments(attachments) if @prompt.yes?("Vuoi scaricare gli allegati?")
|
199
366
|
end
|
200
367
|
else
|
201
|
-
puts "
|
368
|
+
puts center_text("Nessun allegato presente")
|
202
369
|
end
|
370
|
+
end
|
371
|
+
|
372
|
+
def display_info_table(lines)
|
373
|
+
max_label_width = lines.map { |line| line[0].length }.max
|
203
374
|
|
204
|
-
|
205
|
-
|
375
|
+
lines.each do |label, value|
|
376
|
+
formatted_label = label.ljust(max_label_width)
|
377
|
+
puts " #{formatted_label} : #{value}"
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
def truncate_text(text, max_length)
|
382
|
+
text.length > max_length ? "#{text[0..max_length-4]}..." : text
|
383
|
+
end
|
384
|
+
|
385
|
+
def select_folder_menu
|
386
|
+
clear_screen
|
387
|
+
show_header
|
388
|
+
show_status
|
389
|
+
puts center_text("SELEZIONE FOLDER")
|
390
|
+
puts "─" * @screen_width
|
391
|
+
puts
|
392
|
+
|
393
|
+
begin
|
394
|
+
folders = @client.available_folders
|
395
|
+
|
396
|
+
if folders.empty?
|
397
|
+
puts center_text('[-] Nessuna folder disponibile')
|
398
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
399
|
+
return
|
400
|
+
end
|
401
|
+
|
402
|
+
current_folder = @client.current_folder || 'INBOX'
|
403
|
+
puts center_text("Folder corrente: #{current_folder}")
|
404
|
+
puts
|
405
|
+
|
406
|
+
folder_choices = folders.map { |folder| { name: "#{folder == current_folder ? '[*]' : ' '} #{folder}", value: folder } }
|
407
|
+
folder_choices << { name: '← Torna al menu principale', value: :back }
|
408
|
+
|
409
|
+
selected_folder = @prompt.select('Seleziona una folder:', folder_choices)
|
410
|
+
|
411
|
+
return if selected_folder == :back
|
412
|
+
|
413
|
+
if selected_folder != current_folder
|
414
|
+
puts center_text("[*] Selezione folder #{selected_folder}...")
|
415
|
+
@client.select_folder(selected_folder)
|
416
|
+
puts center_text('[+] Folder selezionata con successo!')
|
417
|
+
puts center_text("Folder attiva: #{selected_folder}")
|
418
|
+
else
|
419
|
+
puts center_text("[*] Folder #{selected_folder} già selezionata")
|
420
|
+
end
|
421
|
+
|
422
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
423
|
+
rescue PecRuby::Error => e
|
424
|
+
puts center_text("[-] Errore nella selezione folder: #{e.message}")
|
425
|
+
@prompt.keypress("\n#{center_text('Premi un tasto per continuare...')}", echo: false)
|
426
|
+
end
|
206
427
|
end
|
207
428
|
|
208
429
|
def download_attachments(attachments)
|
209
|
-
|
430
|
+
clear_screen
|
431
|
+
show_header
|
432
|
+
show_status
|
433
|
+
|
434
|
+
puts center_text("DOWNLOAD ALLEGATI")
|
435
|
+
puts "═" * @screen_width
|
436
|
+
puts
|
437
|
+
|
438
|
+
download_dir = @prompt.ask('Directory di download:', default: './downloads')
|
439
|
+
|
440
|
+
puts center_text("[*] Creazione directory...")
|
210
441
|
|
211
442
|
begin
|
212
443
|
require 'fileutils'
|
213
444
|
FileUtils.mkdir_p(download_dir)
|
214
445
|
|
215
|
-
|
446
|
+
puts center_text("[+] Directory creata: #{download_dir}")
|
447
|
+
puts
|
448
|
+
|
449
|
+
attachments.each_with_index do |attachment, i|
|
450
|
+
puts center_text("[*] Salvando #{i+1}/#{attachments.size}: #{attachment.filename}")
|
216
451
|
file_path = attachment.save_to_dir(download_dir)
|
217
|
-
puts "Salvato: #{file_path}"
|
452
|
+
puts center_text("[+] Salvato: #{file_path}")
|
218
453
|
end
|
219
454
|
|
220
|
-
puts
|
221
|
-
|
222
|
-
puts "
|
455
|
+
puts
|
456
|
+
puts center_text("[+] Tutti gli allegati sono stati salvati!")
|
457
|
+
puts center_text("Directory: #{download_dir}")
|
458
|
+
|
459
|
+
rescue StandardError => e
|
460
|
+
puts center_text("[-] Errore nel salvataggio: #{e.message}")
|
223
461
|
end
|
462
|
+
|
463
|
+
puts
|
464
|
+
puts "═" * @screen_width
|
465
|
+
@prompt.keypress(center_text("Premi un tasto per continuare..."), echo: false)
|
224
466
|
end
|
225
467
|
end
|
226
|
-
end
|
468
|
+
end
|