number_station 0.3.0 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7074376c291002a254430a7f9d9126e4fd1004f77db7d3d063e8ab0cee401332
4
- data.tar.gz: d9262e7c76cf7c457835084e794ddb5d92816009a50cfbb6ec8bd88ba98daf1f
3
+ metadata.gz: 28bb32733b0cc2c4dd9a9258985a762e6cf558b9ec3a05d7438a5d4b53332dfe
4
+ data.tar.gz: dc4f7d34bd69879eb4eda6ac0774f2fa20c65433d6d841a98a7f97968562daf8
5
5
  SHA512:
6
- metadata.gz: e016902c9071daea7cee1fe57a367674638f81397dabc73b3b3ec8d1db77161cf905d0a8c84e51b6b5a95568967b274af00dacc19aa928fe932f6201a0481354
7
- data.tar.gz: 228de828a66a1fbd85878ff33487b85522d4e30a628fd64c0cf9098a3ac26610fcd1d9ceeac918aa46e64e3c15aa890fb7d800af839351d6e067e34f3205b39a
6
+ metadata.gz: a86c1b266dd7d5837bf99d1eafecb545fe36ebb86649013dee3bb9a5cff9d507021f257c8595452a0a0f2c91a96cbb579769cadf0245f3983bf9f31371e82891
7
+ data.tar.gz: a8be3d5d110b854ac1254c9fdfb38b062dbb7fbbdbc828617c7c63fdfc40426627a6d1f086c772dfe6c6360a4a88f9eefdaea111d0ec1e6d7e98c53d308d236d
data/README.asciidoc CHANGED
@@ -1,11 +1,15 @@
1
1
  == number_station ==
2
+
2
3
  This gem contains utilities to aid in the running of a number station.
3
4
 
4
5
  image:https://badge.fury.io/rb/number_station.svg["Gem Version", link="https://badge.fury.io/rb/number_station"]
5
6
 
6
7
  === Installation ===
7
8
 
8
- gem install number_station
9
+ [source,bash]
10
+ ----
11
+ gem install number_station
12
+ ----
9
13
 
10
14
  === Usage ===
11
15
 
@@ -13,7 +17,10 @@ image:https://badge.fury.io/rb/number_station.svg["Gem Version", link="https://b
13
17
 
14
18
  Create the initial configuration:
15
19
 
16
- number_station create_config
20
+ [source,bash]
21
+ ----
22
+ number_station create_config
23
+ ----
17
24
 
18
25
  This creates `~/number_station/conf.yaml` and copies template files (`intro_message.txt`, `outro_message.txt`, `repeat_message.txt`) to the same directory.
19
26
 
@@ -22,64 +29,112 @@ This creates `~/number_station/conf.yaml` and copies template files (`intro_mess
22
29
  Manage agents using the `agents` subcommand:
23
30
 
24
31
  *Create an agent:*
25
- number_station agents create NAME [--location LOCATION] [--handler HANDLER]
32
+
33
+ [source,bash]
34
+ ----
35
+ number_station agents create NAME [--location LOCATION] [--handler HANDLER]
36
+ ----
26
37
 
27
38
  *Activate/Deactivate:*
28
- number_station agents activate NAME [--start-date DATE]
29
- number_station agents deactivate NAME [--end-date DATE]
39
+
40
+ [source,bash]
41
+ ----
42
+ number_station agents activate NAME [--start-date DATE]
43
+ number_station agents deactivate NAME [--end-date DATE]
44
+ ----
30
45
 
31
46
  *Update handler codeword:*
32
- number_station agents update-handler NAME HANDLER
47
+
48
+ [source,bash]
49
+ ----
50
+ number_station agents update-handler NAME HANDLER
51
+ ----
33
52
 
34
53
  *View agents:*
35
- number_station agents list # Active agents only
36
- number_station agents list-all # All agents with history
37
- number_station agents stats # Detailed statistics
54
+
55
+ [source,bash]
56
+ ----
57
+ number_station agents list # Active agents only
58
+ number_station agents list-all # All agents with history
59
+ number_station agents stats # Detailed statistics
60
+ ----
38
61
 
39
62
  ==== One-Time Pads ====
40
63
 
41
64
  *Create pads:*
42
- number_station pad create [--name AGENT] [--numpads NUM] [--length LENGTH]
65
+
66
+ [source,bash]
67
+ ----
68
+ number_station pad create [--name AGENT] [--numpads NUM] [--length LENGTH]
69
+ ----
43
70
 
44
71
  If `--name` is provided, creates pad in `~/number_station/pads/AGENT/` directory.
45
72
  Defaults: 500 pads, 500 characters (rounded up to nearest multiple of 5).
46
73
 
47
74
  *View pad statistics:*
48
- number_station pad stats [--path PATH]
75
+
76
+ [source,bash]
77
+ ----
78
+ number_station pad stats [--path PATH]
79
+ ----
49
80
 
50
81
  Shows pad statistics grouped by agent, including unconsumed pad counts.
51
82
 
52
83
  ==== Message Encryption/Decryption ====
53
84
 
54
85
  *Encrypt:*
55
- number_station encrypt [MESSAGE] [--file FILE] [--agent AGENT] [--padpath PADPATH] [--numpad NUMPAD]
86
+
87
+ [source,bash]
88
+ ----
89
+ number_station encrypt [MESSAGE] [--file FILE] [--agent AGENT] [--padpath PADPATH] [--numpad NUMPAD]
90
+ ----
56
91
 
57
92
  If `--agent` is provided, searches for oldest pad in agent-specific directory.
58
93
  Only active agents can encrypt messages.
59
94
 
60
95
  *Decrypt:*
61
- number_station decrypt [MESSAGE] [--file FILE] [--padpath PADPATH] [--numpad NUMPAD]
96
+
97
+ [source,bash]
98
+ ----
99
+ number_station decrypt [MESSAGE] [--file FILE] [--padpath PADPATH] [--numpad NUMPAD]
100
+ ----
62
101
 
63
102
  ==== Phonetic Conversion ====
64
103
 
65
104
  *Convert to phonetic:*
66
- number_station convert_to_phonetic FILE [--intro INTRO_FILE] [--outro OUTRO_FILE] [--repeat REPEAT_FILE]
105
+
106
+ [source,bash]
107
+ ----
108
+ number_station convert_to_phonetic FILE [--intro INTRO_FILE] [--outro OUTRO_FILE] [--repeat REPEAT_FILE]
109
+ ----
67
110
 
68
111
  Converts encrypted message to phonetic alphabet. Output saved as `FILENAME_phonetic.txt`.
69
112
  Intro, outro, and repeat messages are included as-is (not converted).
70
113
 
71
114
  *Convert to espeak XML:*
72
- number_station convert_to_espeak PHONETIC_FILE
115
+
116
+ [source,bash]
117
+ ----
118
+ number_station convert_to_espeak PHONETIC_FILE
119
+ ----
73
120
 
74
121
  Generates GLaDOS-style espeak XML file. Output saved as `FILENAME.xml`.
75
122
 
76
123
  *Generate MP3:*
77
- number_station convert_to_mp3 XML_FILE
124
+
125
+ [source,bash]
126
+ ----
127
+ number_station convert_to_mp3 XML_FILE
128
+ ----
78
129
 
79
130
  Converts XML to MP3 using espeak and ffmpeg. Output saved as `FILENAME.mp3`.
80
131
 
81
132
  *Play audio:*
82
- number_station espeak XML_FILE
133
+
134
+ [source,bash]
135
+ ----
136
+ number_station espeak XML_FILE
137
+ ----
83
138
 
84
139
  Plays the XML file using espeak with GLaDOS voice settings.
85
140
 
@@ -22,6 +22,7 @@
22
22
  require 'thor'
23
23
  require 'fileutils'
24
24
  require 'date'
25
+ require 'json'
25
26
 
26
27
  module NumberStation
27
28
  class Pad < Thor
@@ -676,6 +677,120 @@ module NumberStation
676
677
  puts "Generated GLaDOS espeak XML: #{output_path}"
677
678
  end
678
679
 
680
+ desc "convert_pad_to_asciidoc --padpath PADPATH", "Convert a pad file to AsciiDoc format"
681
+ long_desc <<-CONVERT_PAD_TO_ASCIIDOC_LONG_DESC
682
+ Convert a one-time pad file to AsciiDoc format with each pad as a chapter.
683
+
684
+ Parameters:
685
+ --padpath PADPATH - Path to pad file (e.g., ~/number_station/pads/Shadow/Shadow-2026-01-12.json)
686
+
687
+ Each pad in the file is converted to groups of 5 characters, separated by spaces.
688
+ Output saved as FILENAME.asciidoc in the same directory.
689
+
690
+ Example:
691
+ number_station convert_pad_to_asciidoc --padpath ~/number_station/pads/Shadow/Shadow-2026-01-12.json
692
+ CONVERT_PAD_TO_ASCIIDOC_LONG_DESC
693
+ option :padpath, type: :string, required: true
694
+ def convert_pad_to_asciidoc
695
+ ensure_config_loaded
696
+
697
+ pad_path = options[:padpath]
698
+ unless File.exist?(pad_path)
699
+ raise Thor::Error, "Pad file not found: #{pad_path}"
700
+ end
701
+
702
+ # Read pad file
703
+ pad_data = JSON.parse(File.read(pad_path))
704
+ pad_id = pad_data["id"]
705
+ pads_hash = pad_data["pads"]
706
+
707
+ if pads_hash.nil? || pads_hash.empty?
708
+ raise Thor::Error, "No pads found in file: #{pad_path}"
709
+ end
710
+
711
+ # Generate output filename: replace .json extension with .asciidoc
712
+ input_basename = File.basename(pad_path, File.extname(pad_path))
713
+ output_filename = "#{input_basename}.asciidoc"
714
+ output_path = File.join(File.dirname(pad_path), output_filename)
715
+
716
+ # Build AsciiDoc content
717
+ asciidoc_content = []
718
+ asciidoc_content << "= One-Time Pad: #{input_basename}"
719
+ asciidoc_content << ""
720
+
721
+ # Process each pad
722
+ pads_hash.sort_by { |k, v| k.to_i }.each do |pad_num, pad_info|
723
+ hex_key = pad_info["key"]
724
+
725
+ # Convert hex string to groups of 5 characters, separated by spaces
726
+ # Remove any existing formatting and group by 5
727
+ cleaned_hex = hex_key.gsub(/[\s\n\r]/, '')
728
+ grouped_hex = cleaned_hex.chars.each_slice(5).map(&:join).join(' ')
729
+
730
+ # Add chapter heading for this pad
731
+ asciidoc_content << "== Pad #{pad_num}"
732
+ asciidoc_content << ""
733
+ asciidoc_content << "[source]"
734
+ asciidoc_content << "----"
735
+ asciidoc_content << grouped_hex
736
+ asciidoc_content << "----"
737
+ asciidoc_content << ""
738
+
739
+ # Add page break after every 2nd pad (after pad 1, 3, 5, etc.)
740
+ if pad_num.to_i % 2 == 1
741
+ asciidoc_content << "<<<"
742
+ asciidoc_content << ""
743
+ end
744
+ end
745
+
746
+ # Write AsciiDoc file
747
+ File.write(output_path, asciidoc_content.join("\n"))
748
+ puts "Generated AsciiDoc file: #{output_path}"
749
+ end
750
+
751
+ desc "convert_to_pdf ASCIIDOC_FILE", "Convert an AsciiDoc file to PDF using asciidoctor-pdf"
752
+ long_desc <<-CONVERT_TO_PDF_LONG_DESC
753
+ Convert an AsciiDoc file (typically generated by convert_pad_to_asciidoc) to PDF format.
754
+
755
+ Parameters:
756
+ ASCIIDOC_FILE - Path to AsciiDoc file (e.g., Shadow-2026-01-12.asciidoc)
757
+
758
+ The command checks if asciidoctor-pdf is available before executing.
759
+ Output saved as FILENAME.pdf in the same directory.
760
+
761
+ Example:
762
+ number_station convert_to_pdf Shadow-2026-01-12.asciidoc
763
+ CONVERT_TO_PDF_LONG_DESC
764
+ def convert_to_pdf(asciidoc_file)
765
+ ensure_config_loaded
766
+
767
+ unless File.exist?(asciidoc_file)
768
+ raise Thor::Error, "File not found: #{asciidoc_file}"
769
+ end
770
+
771
+ # Check if asciidoctor-pdf is available
772
+ # Check if command exists first (most reliable)
773
+ unless NumberStation.command?('asciidoctor-pdf')
774
+ raise Thor::Error, "asciidoctor-pdf is not available. Please install it with: gem install asciidoctor-pdf"
775
+ end
776
+
777
+ # Generate output filename: replace .asciidoc extension with .pdf
778
+ input_basename = File.basename(asciidoc_file, File.extname(asciidoc_file))
779
+ output_filename = "#{input_basename}.pdf"
780
+ output_path = File.join(File.dirname(asciidoc_file), output_filename)
781
+
782
+ # Convert using asciidoctor-pdf command
783
+ cmd = "asciidoctor-pdf #{asciidoc_file} -o #{output_path}"
784
+ NumberStation.log.info "Running: #{cmd}"
785
+ system(cmd)
786
+
787
+ unless $?.success?
788
+ raise Thor::Error, "PDF conversion failed with exit code #{$?.exitstatus}"
789
+ end
790
+
791
+ puts "Generated PDF file: #{output_path}"
792
+ end
793
+
679
794
  desc "espeak XML_FILE", "Use espeak to read an XML file"
680
795
  long_desc <<-ESPEAK_LONG_DESC
681
796
  Use the espeak utility to read an XML file with GLaDOS-style voice settings.
@@ -20,5 +20,5 @@
20
20
  =end
21
21
 
22
22
  module NumberStation
23
- VERSION = "0.3.0"
23
+ VERSION = "0.4.0"
24
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: number_station
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Kirwan