number_station 0.1.1 → 0.3.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 +4 -4
- data/README.asciidoc +81 -3
- data/Rakefile +58 -4
- data/lib/number_station/GLaDOS_espeak.rb +79 -0
- data/lib/number_station/cli.rb +1447 -133
- data/lib/number_station/config_reader.rb +91 -14
- data/lib/number_station/decrypt_message.rb +75 -31
- data/lib/number_station/encrypt_message.rb +112 -41
- data/lib/number_station/examine_pads.rb +171 -0
- data/lib/number_station/make_onetime_pad.rb +58 -23
- data/lib/number_station/phonetic_conversion.rb +39 -42
- data/lib/number_station/version.rb +1 -1
- data/lib/number_station.rb +37 -7
- data/number_station.gemspec +3 -4
- data/resources/conf.yaml +415 -0
- data/resources/intro_message.txt +1 -1
- data/resources/outro_message.txt +1 -1
- data/resources/repeat_message.txt +1 -0
- metadata +17 -29
- data/config/conf.json +0 -12
- data/resources/body_message.txt +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7074376c291002a254430a7f9d9126e4fd1004f77db7d3d063e8ab0cee401332
|
|
4
|
+
data.tar.gz: d9262e7c76cf7c457835084e794ddb5d92816009a50cfbb6ec8bd88ba98daf1f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e016902c9071daea7cee1fe57a367674638f81397dabc73b3b3ec8d1db77161cf905d0a8c84e51b6b5a95568967b274af00dacc19aa928fe932f6201a0481354
|
|
7
|
+
data.tar.gz: 228de828a66a1fbd85878ff33487b85522d4e30a628fd64c0cf9098a3ac26610fcd1d9ceeac918aa46e64e3c15aa890fb7d800af839351d6e067e34f3205b39a
|
data/README.asciidoc
CHANGED
|
@@ -1,8 +1,88 @@
|
|
|
1
1
|
== number_station ==
|
|
2
|
-
This gem
|
|
2
|
+
This gem contains utilities to aid in the running of a number station.
|
|
3
3
|
|
|
4
4
|
image:https://badge.fury.io/rb/number_station.svg["Gem Version", link="https://badge.fury.io/rb/number_station"]
|
|
5
5
|
|
|
6
|
+
=== Installation ===
|
|
7
|
+
|
|
8
|
+
gem install number_station
|
|
9
|
+
|
|
10
|
+
=== Usage ===
|
|
11
|
+
|
|
12
|
+
==== Configuration ====
|
|
13
|
+
|
|
14
|
+
Create the initial configuration:
|
|
15
|
+
|
|
16
|
+
number_station create_config
|
|
17
|
+
|
|
18
|
+
This creates `~/number_station/conf.yaml` and copies template files (`intro_message.txt`, `outro_message.txt`, `repeat_message.txt`) to the same directory.
|
|
19
|
+
|
|
20
|
+
==== Agent Management ====
|
|
21
|
+
|
|
22
|
+
Manage agents using the `agents` subcommand:
|
|
23
|
+
|
|
24
|
+
*Create an agent:*
|
|
25
|
+
number_station agents create NAME [--location LOCATION] [--handler HANDLER]
|
|
26
|
+
|
|
27
|
+
*Activate/Deactivate:*
|
|
28
|
+
number_station agents activate NAME [--start-date DATE]
|
|
29
|
+
number_station agents deactivate NAME [--end-date DATE]
|
|
30
|
+
|
|
31
|
+
*Update handler codeword:*
|
|
32
|
+
number_station agents update-handler NAME HANDLER
|
|
33
|
+
|
|
34
|
+
*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
|
|
38
|
+
|
|
39
|
+
==== One-Time Pads ====
|
|
40
|
+
|
|
41
|
+
*Create pads:*
|
|
42
|
+
number_station pad create [--name AGENT] [--numpads NUM] [--length LENGTH]
|
|
43
|
+
|
|
44
|
+
If `--name` is provided, creates pad in `~/number_station/pads/AGENT/` directory.
|
|
45
|
+
Defaults: 500 pads, 500 characters (rounded up to nearest multiple of 5).
|
|
46
|
+
|
|
47
|
+
*View pad statistics:*
|
|
48
|
+
number_station pad stats [--path PATH]
|
|
49
|
+
|
|
50
|
+
Shows pad statistics grouped by agent, including unconsumed pad counts.
|
|
51
|
+
|
|
52
|
+
==== Message Encryption/Decryption ====
|
|
53
|
+
|
|
54
|
+
*Encrypt:*
|
|
55
|
+
number_station encrypt [MESSAGE] [--file FILE] [--agent AGENT] [--padpath PADPATH] [--numpad NUMPAD]
|
|
56
|
+
|
|
57
|
+
If `--agent` is provided, searches for oldest pad in agent-specific directory.
|
|
58
|
+
Only active agents can encrypt messages.
|
|
59
|
+
|
|
60
|
+
*Decrypt:*
|
|
61
|
+
number_station decrypt [MESSAGE] [--file FILE] [--padpath PADPATH] [--numpad NUMPAD]
|
|
62
|
+
|
|
63
|
+
==== Phonetic Conversion ====
|
|
64
|
+
|
|
65
|
+
*Convert to phonetic:*
|
|
66
|
+
number_station convert_to_phonetic FILE [--intro INTRO_FILE] [--outro OUTRO_FILE] [--repeat REPEAT_FILE]
|
|
67
|
+
|
|
68
|
+
Converts encrypted message to phonetic alphabet. Output saved as `FILENAME_phonetic.txt`.
|
|
69
|
+
Intro, outro, and repeat messages are included as-is (not converted).
|
|
70
|
+
|
|
71
|
+
*Convert to espeak XML:*
|
|
72
|
+
number_station convert_to_espeak PHONETIC_FILE
|
|
73
|
+
|
|
74
|
+
Generates GLaDOS-style espeak XML file. Output saved as `FILENAME.xml`.
|
|
75
|
+
|
|
76
|
+
*Generate MP3:*
|
|
77
|
+
number_station convert_to_mp3 XML_FILE
|
|
78
|
+
|
|
79
|
+
Converts XML to MP3 using espeak and ffmpeg. Output saved as `FILENAME.mp3`.
|
|
80
|
+
|
|
81
|
+
*Play audio:*
|
|
82
|
+
number_station espeak XML_FILE
|
|
83
|
+
|
|
84
|
+
Plays the XML file using espeak with GLaDOS voice settings.
|
|
85
|
+
|
|
6
86
|
=== Contributing ===
|
|
7
87
|
Contributions are welcome, please fork the repo, create a branch, add your code, and make a PR
|
|
8
88
|
against master on this repo. For more information see _CONTRIBUTING.asciidoc_
|
|
@@ -14,5 +94,3 @@ file.
|
|
|
14
94
|
=== Number Station Resources ===
|
|
15
95
|
|
|
16
96
|
- https://linuxcoffee.com/numbers/
|
|
17
|
-
- http://users.telenet.be/d.rijmenants/en/onetimepad.htm
|
|
18
|
-
- https://www.numbers-stations.com/
|
data/Rakefile
CHANGED
|
@@ -21,20 +21,74 @@
|
|
|
21
21
|
|
|
22
22
|
require 'bundler'
|
|
23
23
|
require 'fileutils'
|
|
24
|
+
|
|
25
|
+
# Ensure we load from local lib directory, not installed gem
|
|
26
|
+
# This must happen before requiring number_station/version
|
|
27
|
+
lib = File.expand_path('lib', __FILE__)
|
|
28
|
+
# Remove gem paths that might interfere
|
|
29
|
+
gem_paths = $LOAD_PATH.select { |p| p.include?('gems') && p.include?('number_station') }
|
|
30
|
+
gem_paths.each { |p| $LOAD_PATH.delete(p) }
|
|
31
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
32
|
+
|
|
33
|
+
# Load version from local source
|
|
34
|
+
require_relative 'lib/number_station/version'
|
|
35
|
+
|
|
24
36
|
Bundler::GemHelper.install_tasks
|
|
25
37
|
|
|
26
38
|
task :default => :menu
|
|
27
39
|
|
|
40
|
+
desc "Show available rake tasks"
|
|
28
41
|
task :menu do
|
|
29
|
-
puts
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
rake
|
|
42
|
+
puts <<-MSG
|
|
43
|
+
Available tasks:
|
|
44
|
+
|
|
45
|
+
rake build # Build number_station-x.x.x.gem into the pkg directory
|
|
46
|
+
rake install # Build and install number_station-x.x.x.gem into system gems
|
|
47
|
+
rake release # Create tag vx.x.x and build and push number_station-x.x.x.gem to http://rubygems.org/
|
|
48
|
+
rake clean # Clean up build artifacts (.gem files and pkg directory)
|
|
49
|
+
rake version # Show the current version
|
|
50
|
+
rake validate # Validate the gemspec
|
|
51
|
+
rake console # Start an interactive console with the gem loaded
|
|
52
|
+
|
|
33
53
|
MSG
|
|
34
54
|
end
|
|
35
55
|
|
|
36
56
|
desc "Clean up build artifacts"
|
|
37
57
|
task :clean do
|
|
38
58
|
FileUtils.rm_rf("./pkg/")
|
|
59
|
+
FileUtils.rm_f(Dir.glob("*.gem"))
|
|
60
|
+
puts "Cleaned build artifacts"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
desc "Show the current version"
|
|
64
|
+
task :version do
|
|
65
|
+
puts "number_station version: #{NumberStation::VERSION}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
desc "Validate the gemspec"
|
|
69
|
+
task :validate do
|
|
70
|
+
require 'rubygems/specification'
|
|
71
|
+
|
|
72
|
+
begin
|
|
73
|
+
spec = Gem::Specification.load('number_station.gemspec')
|
|
74
|
+
puts "✓ Gemspec is valid"
|
|
75
|
+
puts " Name: #{spec.name}"
|
|
76
|
+
puts " Version: #{spec.version}"
|
|
77
|
+
puts " Dependencies: #{spec.dependencies.map(&:name).join(', ')}"
|
|
78
|
+
rescue => e
|
|
79
|
+
puts "✗ Gemspec validation failed: #{e.message}"
|
|
80
|
+
exit 1
|
|
81
|
+
end
|
|
39
82
|
end
|
|
40
83
|
|
|
84
|
+
desc "Start an interactive console"
|
|
85
|
+
task :console do
|
|
86
|
+
require 'irb'
|
|
87
|
+
require 'number_station'
|
|
88
|
+
ARGV.clear
|
|
89
|
+
IRB.start
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Clean before building
|
|
93
|
+
task :build => :clean
|
|
94
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Ruby Number Station
|
|
3
|
+
Author: David Kirwan https://gitub.com/davidkirwan
|
|
4
|
+
Licence: GPL 3.0
|
|
5
|
+
NumberStation is a collection of utilities to aid in the running of a number station
|
|
6
|
+
Copyright (C) 2018 David Kirwan
|
|
7
|
+
|
|
8
|
+
This program is free software: you can redistribute it and/or modify
|
|
9
|
+
it under the terms of the GNU General Public License as published by
|
|
10
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
11
|
+
(at your option) any later version.
|
|
12
|
+
|
|
13
|
+
This program is distributed in the hope that it will be useful,
|
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
GNU General Public License for more details.
|
|
17
|
+
|
|
18
|
+
You should have received a copy of the GNU General Public License
|
|
19
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
20
|
+
=end
|
|
21
|
+
|
|
22
|
+
module NumberStation
|
|
23
|
+
def self.generate_glados_espeak(input_file_path)
|
|
24
|
+
# Read message from file
|
|
25
|
+
message = File.read(input_file_path)
|
|
26
|
+
|
|
27
|
+
# Generate output filename: remove .txt extension and append .xml
|
|
28
|
+
input_basename = File.basename(input_file_path, File.extname(input_file_path))
|
|
29
|
+
output_filename = "#{input_basename}.xml"
|
|
30
|
+
output_path = File.join(File.dirname(input_file_path), output_filename)
|
|
31
|
+
|
|
32
|
+
# Process message into GLaDOS-style XML
|
|
33
|
+
# Split by whitespace but preserve the structure - handle spaces and newlines
|
|
34
|
+
# Split on whitespace boundaries but keep track of what was between words
|
|
35
|
+
sentence = "<speak version=\"1.0\" xmlns=\"\" xmlns:xsi=\"\" xsi:schemaLocation=\"\" xml:lang=\"\"><voice gender=\"female\">"
|
|
36
|
+
sentenceend = "</voice></speak>"
|
|
37
|
+
|
|
38
|
+
# Split message into words, preserving spacing structure
|
|
39
|
+
# Use a regex that captures words and the whitespace after them
|
|
40
|
+
parts = message.split(/(\s+)/)
|
|
41
|
+
|
|
42
|
+
parts.each do |part|
|
|
43
|
+
if part.match?(/^\s+$/)
|
|
44
|
+
# This is whitespace - preserve it (spaces or newlines)
|
|
45
|
+
sentence += part
|
|
46
|
+
elsif !part.empty?
|
|
47
|
+
# This is a word - wrap it in prosody tags
|
|
48
|
+
sentence += template(part)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
final = sentence + sentenceend
|
|
53
|
+
|
|
54
|
+
# Write XML file
|
|
55
|
+
File.write(output_path, final)
|
|
56
|
+
if NumberStation.respond_to?(:log) && NumberStation.log
|
|
57
|
+
NumberStation.log.info "Generated GLaDOS espeak XML: #{output_path}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
output_path
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def self.template(word)
|
|
66
|
+
sign = randomsign() || ""
|
|
67
|
+
"<prosody pitch=\"#{sign + rand(0..80).to_s}\">#{word}</prosody>"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self.randomsign()
|
|
71
|
+
rnum = rand(0..1)
|
|
72
|
+
|
|
73
|
+
if rnum == 0
|
|
74
|
+
return "-"
|
|
75
|
+
else
|
|
76
|
+
return "+"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|