colloquy 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +160 -0
  3. data/TODO.md +256 -0
  4. data/bin/colloquy +14 -0
  5. data/examples/config/flows.yaml +22 -0
  6. data/examples/config/logger.yaml +2 -0
  7. data/examples/config/messages.yaml +3 -0
  8. data/examples/config/mysql.yaml +18 -0
  9. data/examples/config/redis.yaml +9 -0
  10. data/examples/config/scribe.yaml +2 -0
  11. data/examples/config/settings.yaml +2 -0
  12. data/examples/config/test.yaml +8 -0
  13. data/examples/config/urls.yaml +18 -0
  14. data/examples/flows/active_record_flow.rb +42 -0
  15. data/examples/flows/art_of_war_flow.rb +27 -0
  16. data/examples/flows/calculator_flow.rb +71 -0
  17. data/examples/flows/crossover_flow.rb +17 -0
  18. data/examples/flows/database_flow.rb +33 -0
  19. data/examples/flows/hangman_flow.rb +82 -0
  20. data/examples/flows/metadata_flow.rb +11 -0
  21. data/examples/flows/pagination_flow.rb +23 -0
  22. data/examples/flows/pass_flow.rb +29 -0
  23. data/examples/flows/prefix_menu_flow.rb +24 -0
  24. data/examples/flows/scribe_flow.rb +26 -0
  25. data/examples/flows/settings_flow.rb +23 -0
  26. data/examples/flows/special/special_redis_flow.rb +28 -0
  27. data/examples/flows/url_flow.rb +27 -0
  28. data/examples/log/renderer.log +198381 -0
  29. data/examples/log/urls.log +3269 -0
  30. data/examples/messages/active_record.yaml +2 -0
  31. data/examples/messages/art_of_war.yaml +1 -0
  32. data/examples/messages/calculator.yaml +2 -0
  33. data/examples/messages/database.yaml +1 -0
  34. data/examples/messages/hangman.yaml +0 -0
  35. data/examples/messages/prefix_menu.yaml +3 -0
  36. data/examples/models/activations.rb +5 -0
  37. data/lib/colloquy.rb +39 -0
  38. data/lib/colloquy/exceptions.rb +64 -0
  39. data/lib/colloquy/flow_parser.rb +315 -0
  40. data/lib/colloquy/flow_pool.rb +21 -0
  41. data/lib/colloquy/helpers.rb +15 -0
  42. data/lib/colloquy/helpers/mysql.rb +110 -0
  43. data/lib/colloquy/helpers/redis.rb +103 -0
  44. data/lib/colloquy/helpers/scribe.rb +103 -0
  45. data/lib/colloquy/helpers/settings.rb +111 -0
  46. data/lib/colloquy/helpers/url.rb +10 -0
  47. data/lib/colloquy/input.rb +14 -0
  48. data/lib/colloquy/logger.rb +11 -0
  49. data/lib/colloquy/menu.rb +128 -0
  50. data/lib/colloquy/message_builder.rb +54 -0
  51. data/lib/colloquy/node.rb +67 -0
  52. data/lib/colloquy/paginator.rb +59 -0
  53. data/lib/colloquy/paginator/menu.rb +79 -0
  54. data/lib/colloquy/paginator/prompt.rb +32 -0
  55. data/lib/colloquy/prompt.rb +35 -0
  56. data/lib/colloquy/renderer.rb +423 -0
  57. data/lib/colloquy/response.rb +4 -0
  58. data/lib/colloquy/runner.rb +93 -0
  59. data/lib/colloquy/server.rb +157 -0
  60. data/lib/colloquy/session_store.rb +46 -0
  61. data/lib/colloquy/session_store/memory.rb +14 -0
  62. data/lib/colloquy/session_store/redis.rb +24 -0
  63. data/lib/colloquy/simulator.rb +114 -0
  64. data/lib/colloquy/spec_helpers.rb +21 -0
  65. metadata +459 -0
@@ -0,0 +1,2 @@
1
+ log_level: debug
2
+ path: log/renderer.log
@@ -0,0 +1,3 @@
1
+ more: "More"
2
+ previous: "Previous"
3
+ error_unexpected: "We're facing technical difficulties at this time. Please try again later!"
@@ -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,9 @@
1
+ testing:
2
+ host: localhost
3
+
4
+ sessions:
5
+ host: localhost
6
+
7
+ state:
8
+ host: localhost
9
+
@@ -0,0 +1,2 @@
1
+ testing:
2
+ schema_uri: "http://s1.mobme.in/itw/schema.yml"
@@ -0,0 +1,2 @@
1
+ testing: "/home/mobme/infrastructure/ussd-renderer-redux/examples/config/test.yaml"
2
+ testing_rel: "config/test.yaml"
@@ -0,0 +1,8 @@
1
+ testing:
2
+ host: 'localhost'
3
+ username: 'root'
4
+ password: ''
5
+ reconnect: true
6
+ database: 'activations'
7
+ encoding: 'utf8'
8
+ adapter: 'em_mysql2'
@@ -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,11 @@
1
+
2
+ class MetadataFlow
3
+ include Colloquy::FlowParser
4
+
5
+ index {
6
+ request { |input|
7
+ logger.info "Metadata: #{headers[:metadata].inspect}"
8
+ notify "I love #{headers[:metadata][:love]}"
9
+ }
10
+ }
11
+ 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