cogibara 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,153 @@
1
+ module Cogibara
2
+ class MessageHandler
3
+
4
+ def handle(message)
5
+ if(message.is_a? String)
6
+ message = Message.new(message, "local")
7
+ end
8
+
9
+ Responder.new.send_reply("@think",message.clientID)
10
+
11
+ if Cogibara::config.soft_parse
12
+ message.structure = derive_structure(message)
13
+ end
14
+
15
+
16
+ msg = message.text
17
+ @verbose = Cogibara::config.verbose
18
+ @name = Cogibara::config.name
19
+
20
+ if msg
21
+ puts "core" if @verbose
22
+ reply = process_core(msg, message)
23
+ unless reply
24
+ reply = process_confirm_deny(msg, message)
25
+ unless reply
26
+ splitmsg = msg
27
+ splitmsg = splitmsg.split
28
+ puts "instruction #{splitmsg[0]}" if @verbose
29
+ if splitmsg[0]==@name
30
+ slicemessage = splitmsg
31
+ slicemessage.shift
32
+ slicemessage = slicemessage.join(' ')
33
+ # slicemessage.slice!(@name)
34
+ slicemessage = slicemessage.strip
35
+ puts "instructed #{slicemessage}" if @verbose
36
+ # if @soft_parse
37
+
38
+ reply = process_instruction(slicemessage, message)
39
+ unless reply
40
+ puts "defaults" if @verbose
41
+ reply = process_default(msg, message)
42
+ end
43
+ elsif Cogibara::config.active_mode
44
+ puts "active module #{Cogibara::config.active_mode} processing #{msg}" if @verbose
45
+ reply = process_instruction(Cogibara::config.active_mode + " " + msg, message)
46
+ unless reply
47
+ puts "defaultx" if @verbose
48
+ reply = process_default(msg, message)
49
+ end
50
+ elsif message.structure[:category]
51
+ reply = process_intent(msg, message)
52
+ unless reply
53
+ puts "defaulty" if @verbose
54
+ reply = process_default(msg, message)
55
+ end
56
+ else
57
+ puts "defaultz" if @verbose
58
+ reply = process_default(msg, message)
59
+ end
60
+ end
61
+ end
62
+
63
+ puts reply if @verbose
64
+ Responder.new.send_reply("@listen",message.clientID)
65
+ Cogibara::say Message.new("#{@name}: " + reply.to_s, message.clientID)
66
+
67
+ reply
68
+ end
69
+ end
70
+
71
+ def process_core(message, obj)
72
+ @yourname = "person"
73
+ if message == "hey #{@name}"
74
+ "what's up #{@yourname}?"
75
+ elsif message == "reset mode"
76
+ Cogibara::config.active_mode = nil
77
+ Cogibara::config.active_file_mode = nil
78
+ "Disabling any active modules"
79
+ elsif /your name is now/ =~ message
80
+ message.slice!("your name is now ")
81
+ @name = message.chomp
82
+ "OK, you can call me #{@name}"
83
+ elsif /my name is/ =~ message
84
+ message.slice!("my name is ")
85
+ @yourname = message.chomp
86
+ "OK, I'll call you #{@yourname}"
87
+ elsif message == "what time is it"
88
+ "it is #{Time.now.hour} o'clock and #{Time.now.min} minutes"
89
+ else
90
+ nil
91
+ end
92
+ end
93
+
94
+ def process_default(msg, obj)
95
+ chatmsg = Message.new(msg, obj.clientID, obj.structure)
96
+ puts chatmsg.inspect if @verbose
97
+ Cogibara::dispatcher.call("chat", chatmsg)
98
+ end
99
+
100
+ def process_instruction(message, obj)
101
+
102
+ puts "instruction: #{message.split[0]} (#{Cogibara::dispatcher.registered?(message.split[0])})" if @verbose
103
+ if message =~ /\Aset mode/
104
+ message.slice!("set mode")
105
+ Cogibara::config.active_mode = message.chomp.strip
106
+ "Going into #{Cogibara::config.active_mode} mode"
107
+ elsif message =~ /\Aset file mode/
108
+ message.slice!("set file mode")
109
+ Cogibara::config.active_file_mode = message.chomp.strip
110
+ "Handling files with #{Cogibara::config.active_file_mode}"
111
+ elsif Cogibara::dispatcher.registered?(message.split[0])
112
+ splitmsg = message.split
113
+ Responder.new.send_reply("@search",obj.clientID)
114
+ puts "recognized instruction #{message.split[0]} (#{splitmsg})" if @verbose
115
+ mod = splitmsg[0]
116
+ splitmsg.shift
117
+ Cogibara::dispatcher.call(mod, Message.new(splitmsg.join(' '), obj.clientID, obj.structure))
118
+ else
119
+ puts "didn't understand instruction #{message.split[0]}" if @verbose
120
+ nil
121
+ end
122
+ end
123
+
124
+ def process_intent(message, obj)
125
+ if (obj.structure[:action] && Cogibara::dispatcher.registered?(obj.structure[:action].to_s))
126
+ puts "recognized instruction #{obj.structure[:action]}" if @verbose
127
+ Cogibara::dispatcher.call(obj.structure[:category].to_s,obj)
128
+ elsif (obj.structure[:category] && Cogibara::dispatcher.registered?(obj.structure[:category].to_s))
129
+ puts "recognized instruction #{obj.structure[:category]}" if @verbose
130
+ Cogibara::dispatcher.call(obj.structure[:category].to_s,obj)
131
+ else
132
+ puts "didn't understand instruction #{message.split[0]}" if @verbose
133
+ nil
134
+ end
135
+ end
136
+
137
+ def derive_structure(message)
138
+ response = Cogibara::dispatcher.call("maluuba",message)
139
+ end
140
+
141
+
142
+ def process_confirm_deny(message, obj)
143
+ if message == "yes"
144
+ if Cogibara::confirmer.waiting?
145
+ Cogibara::confirmer.confirm_action
146
+ "Confirmed!"
147
+ end
148
+ else
149
+ nil
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,39 @@
1
+ module Cogibara
2
+ class OperatorBase
3
+
4
+ attr :clientID
5
+ attr :message_text
6
+ attr :message_structure
7
+ attr :operator_config
8
+
9
+ def initialize(config={})
10
+ @operator_config = config
11
+ initialize_operator if self.respond_to?(:initialize_operator)
12
+ end
13
+
14
+ def receive_message(message)
15
+ @clientID = message.clientID
16
+ @message_text = message.text
17
+ @message_structure = message.structure
18
+ process(message)
19
+ end
20
+
21
+ def process(message)
22
+ "!!!text processing not implemented for this operator!!!"
23
+ end
24
+
25
+ def process_file(file)
26
+ "!!!file processing not implemented for this operator!!!"
27
+ end
28
+
29
+ def say(message)
30
+ Cogibara::say Message.new("#{Cogibara::config.name}: " + message, @clientID)
31
+ end
32
+
33
+ def confirm(message, success=nil, failure=nil)
34
+ puts "new confirm"
35
+ Cogibara::confirmer.add_action(message, success)
36
+ message
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ require 'google_calendar'
2
+
3
+ class Calendar < Cogibara::OperatorBase
4
+
5
+ def initialize_operator
6
+ @calendar = Google::Calendar.new(username: self.operator_config["username"], password: self.operator_config["password"], app_name: 'cogibara-calendar-operator')
7
+ end
8
+
9
+ def process(message)
10
+ info = message.structure
11
+ puts info
12
+ case info[:action]
13
+ when :CALENDAR_CREATE_EVENT
14
+ # puts info
15
+ title = info[:entities][:title]? info[:entities][:title][0] : "Untitled event"
16
+ if info[:entities][:daterange]
17
+ start_t = Time.parse(info[:entities][:daterange][0][:start] + " " + info[:entities][:timerange][0][:start])
18
+ end_t = Time.parse(info[:entities][:daterange][0][:start] + " " + info[:entities][:timerange][0][:end]) # use same day because broken?
19
+ else
20
+ start_t = Time.parse(info[:entities][:timerange][0][:start])
21
+ end_t = Time.parse(info[:entities][:timerange][0][:end]) # use same day because broken?
22
+ end
23
+
24
+
25
+ create_event = lambda do
26
+ say "adding #{title} to your calendar"
27
+ @calendar.create_event do |e|
28
+ e.title = title
29
+ e.start_time = start_t
30
+ e.end_time = end_t
31
+ end
32
+ end
33
+ # {code: :confirm, message: "create calendar event #{title} from #{start_t} to #{end_t}?", success: create_event}
34
+ puts "confirming event"
35
+ confirm("create calendar event #{title} from #{start_t} to #{end_t}?", create_event)
36
+ else
37
+ puts "unsupported calendar operation #{info[:action]}, returning nil"
38
+ nil
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ require 'cleverbot'
2
+ require 'curb'
3
+
4
+ class Chat < Cogibara::OperatorBase
5
+ def initialize_operator
6
+ @cleverbot_client = Cleverbot::Client.new
7
+ pf_ID = self.operator_config["Bot_ID"].to_i
8
+ if pf_ID > 0
9
+ @pf_ID = pf_ID
10
+ end
11
+ end
12
+
13
+ def process(message)
14
+ if @pf_ID
15
+ reply = Curl.post("http://www.personalityforge.com/directchat.php?BotID=#{@pf_ID}&MID=8", {Message: message.text, action: "Send Message", UserID: @pf_ID})
16
+ reply.body_str.slice(/<\!-- Bot's reply -->.*?<\!-- end section -->/m).slice(/<span class="bigfont">.*<\/span>/m).gsub(/<.*>/,'').gsub("\n\t",'')
17
+ else
18
+ @cleverbot_client.write message.text
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # require_relative 'wolfram_alpha.rb'
2
+
3
+ class Help < Cogibara::OperatorBase
4
+
5
+ def process(message)
6
+ operators = Cogibara::dispatcher.operators.keys
7
+
8
+ soft_operators = operators.reject{ |o| o.upcase != o}
9
+ hard_operators = operators
10
+
11
+ "I understand the following categories of natural speech: #{soft_operators}, and keyword queries of the form <my name>: #{hard_operators}. Most natural speech categories implement a more natural response, so, for example, 'what is 18 dollars in rupees' activates the knowledge module, and returns 'rupee 968.31(Indian rupees)', while the 'ask' keyword sends the query to the knowledge engine and prints raw output, so 'cucumber ask what is 18 dollars in rupees' = 'Input Interpretation: convert $18 (US dollars) to Indian rupees, Result: rupee968.31 (Indian rupees), 1-year minimum | rupee931.42 (October 4, 2012 | 7 months ago) 1-year maximum | rupee1030.38 (June 24, 2012 | 10 months ago)"
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ # require_relative 'wolfram_alpha.rb'
2
+ require 'cleverbot'
3
+ require 'wolfram'
4
+
5
+ class Knowledge < Cogibara::OperatorBase
6
+
7
+ def initialize_operator
8
+ Wolfram.appid = self.operator_config["WOLFRAM_KEY"]
9
+ # @wolfram = WolframAlpha.new
10
+ @cleverbot = Cleverbot::Client.new
11
+ end
12
+
13
+ def is_question_word?(word)
14
+ qwords = %w{who what why where when how are can if}
15
+ qwords.include? word.downcase
16
+ end
17
+
18
+ def process(query)
19
+ word = query.text.split[0]
20
+
21
+ if is_question_word?(word)
22
+ result = Wolfram::HashPresenter.new(Wolfram.fetch(query.text)).to_hash
23
+ if result[:pods]["Result"] || result[:pods]["Exact result"] || result[:pods]["Basic information"]
24
+ valid_result = true
25
+ if result[:pods]["Result"]
26
+ msg = result[:pods]["Result"][0]
27
+ elsif result[:pods]["Exact result"]
28
+ msg = result[:pods]["Exact result"][0]
29
+ elsif result[:pods]["Basic information"]
30
+ msg = result[:pods]["Basic information"][0]
31
+ end
32
+ else
33
+ valid_result == false
34
+ end
35
+ # valid_result = !(!result[:pods]["Result"] || result[:pods]["Result"][0] == "(data not available)")
36
+ else
37
+ valid_result = false
38
+ end
39
+
40
+ if valid_result
41
+ if msg == "(data not available)"
42
+ # msg = @cleverbot.write(query.text) + " (dk)"
43
+ # # puts msg
44
+ # msg
45
+ nil
46
+ else
47
+ msg
48
+ end
49
+ else
50
+ # @cleverbot.write(query.text)
51
+ nil
52
+ end
53
+ # valid_result ? result[:pods]["Result"][0] : @cleverbot.write(query.text)
54
+ end
55
+ end
@@ -0,0 +1,8 @@
1
+ # require 'twilio-ruby'
2
+
3
+ class ReminderSetter < Cogibara::OperatorBase
4
+ def process(message)
5
+
6
+ "reminder setter heard #{message.inspect}, set reminder for (nothing right now)"
7
+ end
8
+ end
@@ -0,0 +1,48 @@
1
+ require 'maluuba_napi'
2
+
3
+ class SoftParser < Cogibara::OperatorBase
4
+ def initialize_operator
5
+ @api_key = self.operator_config["API_KEY"]
6
+ @client = MaluubaNapi::Client.new(@api_key)
7
+ end
8
+
9
+ def normalize(message, type)
10
+ @client.normalize phrase: message, type: type, timezone:"CST"
11
+ end
12
+
13
+ def normalize_response!(msg, response)
14
+ if response[:entities]
15
+ if response[:entities][:daterange]
16
+ n = normalize(msg, "daterange")[:entities][:daterange]
17
+ response[:entities][:daterange] = n if n
18
+ end
19
+ if response[:entities][:timerange]
20
+ n = normalize(msg, "timerange")[:entities][:timerange]
21
+ response[:entities][:timerange] = n if n
22
+ end
23
+ if response[:entities][:time]
24
+ n = normalize(msg, "time")[:entities][:time]
25
+ response[:entities][:time] = n if n
26
+ end
27
+ end
28
+ end
29
+
30
+ def process(message)
31
+ response = @client.interpret phrase: message.text
32
+ normalize_response!(message.text, response)
33
+ ## Should normalize times and do something with them
34
+ # time_categories = [:REMINDER, :ALARM, :TIMER]
35
+ # timerange_categories = [:TIMER]
36
+ # date_categories = [:CALENDAR]
37
+ #
38
+ # if time_categories.includes? response[:category]
39
+ # normalized = @client.normalize phrase: message, type: 'time', timezone: 'CST'
40
+ # elsif timerange_categories.includes? response[:category]
41
+ # normalized = @client.normalize phrase: message, type: 'timerange', timezone: 'CST'
42
+ # elsif date_categories.includes? response[:category]
43
+ # normalized = @client.normalize phrase: message, type: 'daterange', timezone: 'CST'
44
+ # end
45
+ #
46
+ response
47
+ end
48
+ end
@@ -0,0 +1,33 @@
1
+ require 'bing_translator'
2
+
3
+ class Translate < Cogibara::OperatorBase
4
+
5
+ LANGUAGES = {'english' => 'en-US', 'English' => 'en-US', 'Japanese' => 'ja', 'japanese' => 'ja', 'en-US' => 'en-US', 'dutch' => 'nl-NL', 'Dutch' => 'nl-NL', 'German' => 'de-DE','german' => 'de-DE', 'Spanish' => 'es-US', 'spanish' => 'es-US'}
6
+
7
+ def initialize_operator
8
+ @bing = BingTranslator.new('wstrinz', 'aMAR9BHp6NxCml97/OjCaZDB/WRpCDCdmXNHXbCz83s=')
9
+ end
10
+
11
+ def translate(message)
12
+ in_language = @bing.detect message
13
+ @bing.translate message, :from => in_language, :to => "en"
14
+ end
15
+
16
+ def process(input)
17
+ message = input.text
18
+ if LANGUAGES.has_key? message
19
+ @language = LANGUAGES[message]
20
+ "Translating from #{message} (#{@language})"
21
+ elsif message =~ /\Aset language/
22
+ @language = LANGUAGES[message.split[2]]
23
+ "Translating from #{message.split[2]} (#{@language})"
24
+ else
25
+ "you said: " + translate(message)
26
+ end
27
+ end
28
+
29
+ def process_file(file)
30
+ message = Cogibara::Transcriber.new.transcribe_lang(file, @language)
31
+ "you said: " + translate(message)
32
+ end
33
+ end
@@ -0,0 +1,89 @@
1
+ require 'forecast_io'
2
+ require 'geocoder'
3
+ require 'date'
4
+
5
+ class Weather < Cogibara::OperatorBase
6
+ def initialize_operator
7
+ Forecast::IO.api_key = self.operator_config["API_KEY"]
8
+ end
9
+
10
+ # def translate(message)
11
+ # in_language = @bing.detect message
12
+ # @bing.translate message, :from => in_language, :to => "en"
13
+ # end
14
+
15
+ def location_to_coordinates(location)
16
+ Geocoder.coordinates(location)
17
+ end
18
+
19
+ def get_location(message)
20
+ info = message.structure
21
+ if info[:entities][:location]
22
+ location_to_coordinates(info[:entities][:location][0])
23
+ else
24
+ [43.092, -89.369]
25
+ end
26
+ end
27
+
28
+ def get_forecast_period(message)
29
+ info = message.structure[:entities]
30
+
31
+ if info[:daterange]
32
+ start_d = Date.parse(info[:daterange][0][:start])
33
+ end_d = Date.parse(info[:daterange][0][:end])
34
+ start_d..end_d
35
+ elsif info[:time]
36
+ info[:time]=="tomorrow" ? Date.today + 1 : Date.today
37
+ else
38
+ nil
39
+ end
40
+ end
41
+
42
+ def current_conditions
43
+ # if @forecast.minutely
44
+ # say "now: #{@forecast.minutely.summary}"
45
+ # end
46
+ curr_summary = " Currently " + @forecast.currently.summary + ", "
47
+ curr_cond = "#{@forecast.currently.temperature.round} degrees, cloud cover #{(@forecast.currently.cloudCover * 100).round}% "
48
+ next_cond = @forecast.minutely ? @forecast.minutely.summary : ""
49
+ # next_cond = @forecast.minutely ? "Then " + @forecast.minutely.summary : ""
50
+ curr_summary + curr_cond + "then, " + next_cond
51
+ end
52
+
53
+ def todays_forecast
54
+ temps = @forecast.hourly.data[0..18].map{|hr| hr.temperature}
55
+ max_t = temps.each_with_index.max
56
+ min_t = temps.each_with_index.min
57
+ @forecast.hourly.summary + " The high temperature will be #{max_t[0].round} degrees, in #{max_t[1]} hours, and the low will be #{min_t[0].round} degrees, in #{min_t[1]} hours"
58
+ end
59
+
60
+ def week_forecast
61
+ say @forecast.daily.summary
62
+ end
63
+
64
+ def process(message)
65
+ return nil if message.text.split.include?("cool")
66
+
67
+ @loc = get_location(message)
68
+ @date = get_forecast_period(message)
69
+ @forecast = Forecast::IO.forecast(@loc[0],@loc[1])
70
+
71
+ unless @date
72
+ current_conditions
73
+ else
74
+ if @date.is_a? Range
75
+ if @date.first == Date.today || @date.first == Date.today+1
76
+ todays_forecast
77
+ else
78
+ week_forecast
79
+ end
80
+ else
81
+ if @date == Date.today || @date == Date.today + 1
82
+ todays_forecast
83
+ else
84
+ week_forecast
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,47 @@
1
+ require 'wikipedia'
2
+ require 'wikicloth'
3
+ require 'json'
4
+ require 'sanitize'
5
+
6
+ class WikiGetter
7
+
8
+ def checkRedirect(article)
9
+ if(/\Aredirect/ =~ article.strip)
10
+ return article.strip.gsub(/\Aredirect/,'')
11
+ elsif(/\AREDIRECT/ =~ article.strip)
12
+ return article.strip.gsub(/\AREDIRECT/,'').strip
13
+ end
14
+ end
15
+
16
+ def getArticle(title)
17
+ article = JSON.parse(Wikipedia.find(title).json)["query"]["pages"].to_a[0][1]["revisions"]
18
+ unless article
19
+ "Could not find article, sorry"
20
+ else
21
+ raw = article[0]["*"]
22
+ # parsed = Wikitext::Parser.new.parse(raw)
23
+ parsed = WikiCloth::Parser.new({:data => raw})
24
+ sanitized = Sanitize.clean(parsed.to_html)
25
+ redirect = checkRedirect(sanitized)
26
+ if redirect
27
+ puts "redirecting to #{redirect}"
28
+ getArticle(redirect)
29
+ else
30
+ ref_links = sanitized.gsub(/\[\d+\]/,'').gsub(/\[edit\]/,'')
31
+ http_links = ref_links.gsub(/\[http+\s?\]/m,'')
32
+
33
+
34
+ # leftover = sanitized.gsub(/\[\[.*\]\]/, '').gsub(/\{\{.*\}\}/, '')
35
+ # leftover = leftover.gsub(/\[\[.*?\]\]/m, '').gsub(/\{\{.*?\}\}/m, '').gsub(/&lt;.*?&gt;/m,'')
36
+ # leftover = leftover.gsub(/\'\'/,'').gsub(/\[http.*?\]/m,'').gsub(/\{\|.*?\|\}/m,'').gsub(/\}\}/,'')
37
+ # removeUgly = leftover.gsub(/\|/,' ').gsub(/\_/,'')
38
+ end
39
+ end
40
+
41
+ # leftover
42
+ # leftover
43
+ end
44
+ end
45
+
46
+ # puts WikiGetter.new.getArticle("Cattle")
47
+ # puts WikiGetter.new.getArticle("Cat").length
@@ -0,0 +1,22 @@
1
+ require_relative 'wiki/wiki_getter.rb'
2
+
3
+ class Wiki < Cogibara::OperatorBase
4
+
5
+ def initialize_operator
6
+ @handler = WikiGetter.new
7
+ end
8
+
9
+ def process(message)
10
+ search = message.text
11
+ article = WikiGetter.new.getArticle(search)
12
+ # splits = article.split
13
+ # (splits.count / 100).times do |n|
14
+ # if (n+1)*100 > splits.count
15
+ # chunk = splits[n*100..splits.count] * ' '
16
+ # else
17
+ # chunk = splits[n*100..((n+1)*100 - 1)] * ' '
18
+ # end
19
+ # yield chunk
20
+ # end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # require_relative 'wolfram_alpha/'
2
+ require 'wolfram'
3
+ class WolframAlpha < Cogibara::OperatorBase
4
+
5
+ def initialize_operator
6
+ Wolfram.appid = self.operator_config["API_KEY"]
7
+ end
8
+
9
+ def resultToString(result)
10
+ rhash = Wolfram::HashPresenter.new(result).to_hash
11
+ rarr = []
12
+ rhash[:pods].keys.each do |key|
13
+ value = rhash[:pods][key][0]
14
+ rarr << (key + ":\n\t" + value + "\n")
15
+ end
16
+ rarr.join
17
+ end
18
+
19
+ def process(message)
20
+ # puts "asking wolfram #{query}"
21
+ query = message.text
22
+ result = resultToString(Wolfram.fetch(query))
23
+ # puts result == "Result:\n"
24
+ # result == "Result:\n" ? nil : result
25
+
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ require 'redis'
2
+
3
+ module Cogibara
4
+ class Responder
5
+ def redis
6
+ @redis ||= Redis.new
7
+ end
8
+
9
+ def send_reply(message, client, options={type: "text"})
10
+ if(Cogibara::config.use_redis)
11
+ redis.multi do
12
+ redis.incr "sendMsgNum"
13
+ @msgid = redis.get "sendMsgNum"
14
+ end
15
+
16
+ redis.hmset("sendMsg:#{@msgid.value}",options[:type],message,"client",client)
17
+ redis.publish("fromCapy","sendMsg:#{@msgid.value}")
18
+ end
19
+ if(Cogibara::config.local)
20
+ puts message unless message[0] == "@"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ module Cogibara
2
+ class Speaker
3
+ def speak_to_local(message, voice="rab_diphone", engine=:festival)
4
+ if engine == :pico
5
+ `pico2wave -w out.wav "#{self}"`
6
+ `aplay out.wav`
7
+ `rm ./out.wav`
8
+ else
9
+ `echo "#{self}" | text2wave -eval "(voice_#{voice})" | aplay`
10
+ end
11
+ end
12
+
13
+ def speak_to_file(message)
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+
20
+
21
+
@@ -0,0 +1,8 @@
1
+ module Cogibara
2
+ class TextParser
3
+ def parse(message)
4
+ Message.new(message.text, {msg: message.text + " structured"})
5
+ end
6
+ end
7
+
8
+ end