colloquy 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +160 -0
- data/TODO.md +256 -0
- data/bin/colloquy +14 -0
- data/examples/config/flows.yaml +22 -0
- data/examples/config/logger.yaml +2 -0
- data/examples/config/messages.yaml +3 -0
- data/examples/config/mysql.yaml +18 -0
- data/examples/config/redis.yaml +9 -0
- data/examples/config/scribe.yaml +2 -0
- data/examples/config/settings.yaml +2 -0
- data/examples/config/test.yaml +8 -0
- data/examples/config/urls.yaml +18 -0
- data/examples/flows/active_record_flow.rb +42 -0
- data/examples/flows/art_of_war_flow.rb +27 -0
- data/examples/flows/calculator_flow.rb +71 -0
- data/examples/flows/crossover_flow.rb +17 -0
- data/examples/flows/database_flow.rb +33 -0
- data/examples/flows/hangman_flow.rb +82 -0
- data/examples/flows/metadata_flow.rb +11 -0
- data/examples/flows/pagination_flow.rb +23 -0
- data/examples/flows/pass_flow.rb +29 -0
- data/examples/flows/prefix_menu_flow.rb +24 -0
- data/examples/flows/scribe_flow.rb +26 -0
- data/examples/flows/settings_flow.rb +23 -0
- data/examples/flows/special/special_redis_flow.rb +28 -0
- data/examples/flows/url_flow.rb +27 -0
- data/examples/log/renderer.log +198381 -0
- data/examples/log/urls.log +3269 -0
- data/examples/messages/active_record.yaml +2 -0
- data/examples/messages/art_of_war.yaml +1 -0
- data/examples/messages/calculator.yaml +2 -0
- data/examples/messages/database.yaml +1 -0
- data/examples/messages/hangman.yaml +0 -0
- data/examples/messages/prefix_menu.yaml +3 -0
- data/examples/models/activations.rb +5 -0
- data/lib/colloquy.rb +39 -0
- data/lib/colloquy/exceptions.rb +64 -0
- data/lib/colloquy/flow_parser.rb +315 -0
- data/lib/colloquy/flow_pool.rb +21 -0
- data/lib/colloquy/helpers.rb +15 -0
- data/lib/colloquy/helpers/mysql.rb +110 -0
- data/lib/colloquy/helpers/redis.rb +103 -0
- data/lib/colloquy/helpers/scribe.rb +103 -0
- data/lib/colloquy/helpers/settings.rb +111 -0
- data/lib/colloquy/helpers/url.rb +10 -0
- data/lib/colloquy/input.rb +14 -0
- data/lib/colloquy/logger.rb +11 -0
- data/lib/colloquy/menu.rb +128 -0
- data/lib/colloquy/message_builder.rb +54 -0
- data/lib/colloquy/node.rb +67 -0
- data/lib/colloquy/paginator.rb +59 -0
- data/lib/colloquy/paginator/menu.rb +79 -0
- data/lib/colloquy/paginator/prompt.rb +32 -0
- data/lib/colloquy/prompt.rb +35 -0
- data/lib/colloquy/renderer.rb +423 -0
- data/lib/colloquy/response.rb +4 -0
- data/lib/colloquy/runner.rb +93 -0
- data/lib/colloquy/server.rb +157 -0
- data/lib/colloquy/session_store.rb +46 -0
- data/lib/colloquy/session_store/memory.rb +14 -0
- data/lib/colloquy/session_store/redis.rb +24 -0
- data/lib/colloquy/simulator.rb +114 -0
- data/lib/colloquy/spec_helpers.rb +21 -0
- metadata +459 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
testing:
|
2
|
+
host: 'localhost'
|
3
|
+
username: 'root'
|
4
|
+
password: ''
|
5
|
+
reconnect: true
|
6
|
+
database: 'activations'
|
7
|
+
encoding: 'utf8'
|
8
|
+
adapter: 'em_mysql2'
|
9
|
+
|
10
|
+
customer:
|
11
|
+
host: 'localhost'
|
12
|
+
username: 'root'
|
13
|
+
password: ''
|
14
|
+
reconnect: true
|
15
|
+
database: 'activations'
|
16
|
+
encoding: 'utf8'
|
17
|
+
adapter: 'em_mysql2'
|
18
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
log_cancellations:
|
2
|
+
active: http://google.com/?q=hello
|
3
|
+
backup: http://www.google.com/search?q=%%msisdn%%
|
4
|
+
|
5
|
+
pinger:
|
6
|
+
log_cancellations:
|
7
|
+
verb: get
|
8
|
+
params:
|
9
|
+
msisdn: 9745044399
|
10
|
+
tick: 5
|
11
|
+
|
12
|
+
timeouts:
|
13
|
+
connection: 2
|
14
|
+
inactivity: 5
|
15
|
+
|
16
|
+
logger:
|
17
|
+
log_level: debug
|
18
|
+
path: log/urls.log
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
require_relative '../models/activations'
|
5
|
+
|
6
|
+
class ActiveRecordFlow
|
7
|
+
include Colloquy::FlowParser
|
8
|
+
|
9
|
+
index {
|
10
|
+
request {
|
11
|
+
menu << :activate << :cancel
|
12
|
+
}
|
13
|
+
|
14
|
+
process { |input|
|
15
|
+
case menu.key(input)
|
16
|
+
when :activate
|
17
|
+
privileged_user = true
|
18
|
+
if privileged_user
|
19
|
+
if count = activate(headers[:msisdn])
|
20
|
+
notify [:activation_success, :count => count]
|
21
|
+
else
|
22
|
+
notify :activation_failure
|
23
|
+
end
|
24
|
+
else
|
25
|
+
notify :priveleges_required
|
26
|
+
end
|
27
|
+
when :cancel
|
28
|
+
url.call(:log_cancellations, { :msisdn => headers[:msisdn] })
|
29
|
+
notify :canceled
|
30
|
+
end
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
def setup
|
35
|
+
::Activation.establish_connection(mysql.configuration[:customer])
|
36
|
+
end
|
37
|
+
|
38
|
+
def activate(msisdn)
|
39
|
+
logger.info "Activating #{msisdn}!"
|
40
|
+
count = Activation.count
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
class ArtOfWarFlow
|
3
|
+
include Colloquy::FlowParser
|
4
|
+
|
5
|
+
index {
|
6
|
+
request {
|
7
|
+
session[:hello] = "yellow!"
|
8
|
+
menu.push(
|
9
|
+
:calculator, # to test a swtich
|
10
|
+
:special_redis,
|
11
|
+
:estimates, :waging_war, :offensive_strategy, :dispositions, :energy,
|
12
|
+
:weaknesses_and_strengths, :manoeuvre, :nine_variables, :marches,
|
13
|
+
:terrain, :the_nine_varieties_of_ground, :attack_by_fire,
|
14
|
+
:employment_of_secret_agents
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
18
|
+
process { |input|
|
19
|
+
session[:hello] = "world"
|
20
|
+
switch :index, :flow => :calculator if menu.key(input) == :calculator
|
21
|
+
switch :index, :flow => :special_redis if menu.key(input) == :special_redis
|
22
|
+
switch :index, :flow => :unknown if menu.key(input) == :offensive_strategy
|
23
|
+
|
24
|
+
notify "#{menu.key(input)}_notification".to_sym
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
class CalculatorFlow
|
3
|
+
|
4
|
+
include Colloquy::FlowParser
|
5
|
+
|
6
|
+
index {
|
7
|
+
request {
|
8
|
+
menu << "Add" << "Subtract" << "Back"
|
9
|
+
}
|
10
|
+
|
11
|
+
process { |input|
|
12
|
+
session[:operation] = case menu.key(input)
|
13
|
+
when "Add"
|
14
|
+
:add
|
15
|
+
when "Subtract"
|
16
|
+
:subtract
|
17
|
+
when "Back"
|
18
|
+
switch :back
|
19
|
+
else
|
20
|
+
notify :operation_invalid
|
21
|
+
end
|
22
|
+
|
23
|
+
switch :number_first
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
number_first {
|
28
|
+
request {
|
29
|
+
prompt "Enter the first number:"
|
30
|
+
}
|
31
|
+
|
32
|
+
process { |input|
|
33
|
+
if valid_input? input
|
34
|
+
session[:first_number] = input.to_i
|
35
|
+
switch :number_second
|
36
|
+
else
|
37
|
+
notify :number_invalid
|
38
|
+
end
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
number_second {
|
43
|
+
request {
|
44
|
+
prompt "Enter the second number:"
|
45
|
+
}
|
46
|
+
|
47
|
+
process { |number|
|
48
|
+
if valid_input? number
|
49
|
+
value = calculate(session[:operation], session[:first_number], number.to_i)
|
50
|
+
notify "The result is: #{value}"
|
51
|
+
end
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
def calculate(operation, first_number, second_number)
|
56
|
+
case operation
|
57
|
+
when :add
|
58
|
+
first_number + second_number
|
59
|
+
when :subtract
|
60
|
+
first_number - second_number
|
61
|
+
else
|
62
|
+
logger.error "Got an unexpected operation."
|
63
|
+
notify :error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def valid_input?(number)
|
68
|
+
"#{number.to_i}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
class CrossoverFlow
|
3
|
+
|
4
|
+
include Colloquy::FlowParser
|
5
|
+
|
6
|
+
index {
|
7
|
+
request { |input|
|
8
|
+
session[:calculator_type] = (input == "1") ? :scientific : :normal
|
9
|
+
pass
|
10
|
+
}
|
11
|
+
|
12
|
+
process { |input|
|
13
|
+
switch :index, :flow => :calculator
|
14
|
+
}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
class DatabaseFlow
|
3
|
+
include Colloquy::FlowParser
|
4
|
+
|
5
|
+
index {
|
6
|
+
request {
|
7
|
+
menu << :activate << :cancel
|
8
|
+
}
|
9
|
+
|
10
|
+
process { |input|
|
11
|
+
case menu.key(input)
|
12
|
+
when :activate
|
13
|
+
privileged_user = mysql[:customer].query("select sleep(0.25);")
|
14
|
+
if privileged_user
|
15
|
+
if activate(headers[:msisdn])
|
16
|
+
notify :activation_success
|
17
|
+
else
|
18
|
+
notify :activation_failure
|
19
|
+
end
|
20
|
+
else
|
21
|
+
notify :priveleges_required
|
22
|
+
end
|
23
|
+
when :cancel
|
24
|
+
url.call(:log_cancellations, { :msisdn => headers[:msisdn] })
|
25
|
+
notify :canceled
|
26
|
+
end
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
def activate(msisdn)
|
31
|
+
logger.info "Activating #{msisdn}!"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'random_word_generator'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
class HangmanFlow
|
5
|
+
|
6
|
+
include Colloquy::FlowParser
|
7
|
+
NUMBER_CRYPTEX = "22233344455566677778889999"
|
8
|
+
|
9
|
+
index {
|
10
|
+
request {
|
11
|
+
prompt "Hangman..Ready to die? No escape now!\n" +
|
12
|
+
"Enter any key to start."
|
13
|
+
}
|
14
|
+
|
15
|
+
process { |input|
|
16
|
+
session[:secret] = RandomWordGenerator.word
|
17
|
+
session[:lives] = 9
|
18
|
+
session[:used_letters] = "0"
|
19
|
+
session[:message] = ""
|
20
|
+
|
21
|
+
switch :game_logic
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
game_logic {
|
26
|
+
request {
|
27
|
+
notify "#{session[:secret]}\n You WIN!" if session[:secret] == word_with_user_input
|
28
|
+
notify "You LOSE. The word was #{session[:secret]}" if session[:lives] == 0
|
29
|
+
|
30
|
+
prompt "#{session[:message]}\n #{word_with_user_input} \n" +
|
31
|
+
"You have #{session[:lives]} #{pluralize(session[:lives], 'life')} left.\n" +
|
32
|
+
"Enter letter (A=>2,B=>22,C=>222,D=>3). Enter 0 to quit."
|
33
|
+
}
|
34
|
+
|
35
|
+
process { |input|
|
36
|
+
notify "Exiting application.." if input == "0"
|
37
|
+
|
38
|
+
if valid_input? input
|
39
|
+
letter_entered = translate_letter_code(input)
|
40
|
+
if session[:used_letters].include? letter_entered
|
41
|
+
session[:message] = "You already entered this letter."
|
42
|
+
else
|
43
|
+
session[:used_letters] << letter_entered
|
44
|
+
if session[:secret].include? letter_entered
|
45
|
+
session[:message] = "You entered #{letter_entered}. Aha! Good guess."
|
46
|
+
else
|
47
|
+
session[:lives] -= 1
|
48
|
+
session[:message] = "You entered #{letter_entered}. Bad luck!"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
else
|
52
|
+
session[:message] = "Invalid letter code."
|
53
|
+
end
|
54
|
+
switch :game_logic
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
|
59
|
+
def valid_input?(number)
|
60
|
+
if number.length <= 4 && ["7","9"].include?(number.squeeze)
|
61
|
+
return true
|
62
|
+
elsif number.length <= 3 && ["2","3","4","5","6","8"].include?(number.squeeze)
|
63
|
+
return true
|
64
|
+
else
|
65
|
+
return false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def translate_letter_code(letter_code)
|
70
|
+
("a".."z").to_a[NUMBER_CRYPTEX.index(letter_code) + letter_code.length - 1]
|
71
|
+
end
|
72
|
+
|
73
|
+
def word_with_user_input
|
74
|
+
regex = Regexp.new("[^#{session[:used_letters]}]")
|
75
|
+
session[:secret].gsub(regex,'-')
|
76
|
+
end
|
77
|
+
|
78
|
+
def pluralize(number, text)
|
79
|
+
return text.pluralize if number != 1
|
80
|
+
text
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
class PaginationFlow
|
3
|
+
|
4
|
+
include Colloquy::FlowParser
|
5
|
+
|
6
|
+
index {
|
7
|
+
request {
|
8
|
+
menu.prefix {
|
9
|
+
if headers[:page] == 1
|
10
|
+
"Welcome to Some new application. Please choose from one of the packs below to get latest news from Some new application"
|
11
|
+
end
|
12
|
+
}
|
13
|
+
1.upto(10).each do |item|
|
14
|
+
menu << "Pack #{item}"
|
15
|
+
end
|
16
|
+
}
|
17
|
+
|
18
|
+
process { |input|
|
19
|
+
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
class PassFlow
|
3
|
+
include Colloquy::FlowParser
|
4
|
+
|
5
|
+
index {
|
6
|
+
request { |input|
|
7
|
+
pass unless input.blank?
|
8
|
+
menu << :activate << :cancel
|
9
|
+
}
|
10
|
+
|
11
|
+
process { |input|
|
12
|
+
notify :direct if input.direct?
|
13
|
+
|
14
|
+
case menu.key(input)
|
15
|
+
when :activate
|
16
|
+
notify :activation_success
|
17
|
+
when :cancel
|
18
|
+
cancelation = url[:log_cancellations].call(:msisdn => headers[:msisdn])
|
19
|
+
notify cancelation.response
|
20
|
+
else
|
21
|
+
notif "Hello World!" #Deliberate error!
|
22
|
+
end
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
def activate
|
27
|
+
logger.info "Activating!"
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
class PrefixMenuFlow
|
3
|
+
include Colloquy::FlowParser
|
4
|
+
|
5
|
+
index {
|
6
|
+
request { |input|
|
7
|
+
menu.push(headers[:msisdn])
|
8
|
+
menu.push(*('a'..'z').to_a)
|
9
|
+
menu.prefix { "Hello #{headers[:session_id]}" }
|
10
|
+
menu.suffix do
|
11
|
+
logger.info "Headers: #{headers.inspect}"
|
12
|
+
"Your world is my oyster! And there's nothing better than beer! Or a touch of lemonade." if headers[:page] == 1
|
13
|
+
end
|
14
|
+
|
15
|
+
menu.before_page do
|
16
|
+
session[:wonker] = "Page: #{headers[:page]}"
|
17
|
+
end
|
18
|
+
}
|
19
|
+
|
20
|
+
process { |input|
|
21
|
+
notify menu.key(input)
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|