kogno 1.0.1
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 +7 -0
- data/bin/kogno +92 -0
- data/lib/boot.rb +9 -0
- data/lib/core/bin_helpers/messenger_ctl.rb +48 -0
- data/lib/core/bin_helpers/scaffolding.rb +203 -0
- data/lib/core/bin_helpers/scheduled_messages_ctl.rb +95 -0
- data/lib/core/bin_helpers/sequences_ctl.rb +95 -0
- data/lib/core/bin_helpers/server_ctl.rb +127 -0
- data/lib/core/bin_helpers/telegram_ctl.rb +48 -0
- data/lib/core/bin_helpers/webhook_ctl.rb +96 -0
- data/lib/core/db.rb +8 -0
- data/lib/core/extensions/array.rb +28 -0
- data/lib/core/extensions/hash.rb +12 -0
- data/lib/core/extensions/logger.rb +70 -0
- data/lib/core/extensions/string.rb +6 -0
- data/lib/core/extensions/wit.rb +60 -0
- data/lib/core/global_methods.rb +67 -0
- data/lib/core/helpers/string.rb +105 -0
- data/lib/core/lib/base_config.rb +17 -0
- data/lib/core/lib/block_params.rb +4 -0
- data/lib/core/lib/context.rb +1573 -0
- data/lib/core/lib/error_handler.rb +36 -0
- data/lib/core/lib/message.rb +182 -0
- data/lib/core/lib/messenger/api.rb +281 -0
- data/lib/core/lib/messenger/facebook_graph.rb +32 -0
- data/lib/core/lib/messenger/message.rb +202 -0
- data/lib/core/lib/messenger/notification.rb +351 -0
- data/lib/core/lib/messenger/post_comment.rb +104 -0
- data/lib/core/lib/messenger/recurring_notification.rb +81 -0
- data/lib/core/lib/nlp.rb +191 -0
- data/lib/core/lib/notification.rb +371 -0
- data/lib/core/lib/spelling.rb +13 -0
- data/lib/core/lib/telegram/api.rb +197 -0
- data/lib/core/lib/telegram/chat_activity.rb +111 -0
- data/lib/core/lib/telegram/inline_query.rb +112 -0
- data/lib/core/lib/telegram/message.rb +327 -0
- data/lib/core/lib/telegram/notification.rb +507 -0
- data/lib/core/lib/whatsapp/api.rb +153 -0
- data/lib/core/lib/whatsapp/message.rb +132 -0
- data/lib/core/lib/whatsapp/notification.rb +206 -0
- data/lib/core/lib/whatsapp/status_message.rb +58 -0
- data/lib/core/loaders/config_files.rb +15 -0
- data/lib/core/models/chat_log.rb +4 -0
- data/lib/core/models/long_payload.rb +25 -0
- data/lib/core/models/matched_message.rb +5 -0
- data/lib/core/models/messenger_recurring_notification.rb +16 -0
- data/lib/core/models/scheduled_message.rb +40 -0
- data/lib/core/models/sequence.rb +29 -0
- data/lib/core/models/telegram_chat_group.rb +26 -0
- data/lib/core/models/user.rb +285 -0
- data/lib/core/web/webhook.rb +198 -0
- data/lib/kogno.rb +130 -0
- data/scaffolding/new_project/Gemfile +3 -0
- data/scaffolding/new_project/application.rb +5 -0
- data/scaffolding/new_project/bot/contexts/main_context.rb +10 -0
- data/scaffolding/new_project/bot/conversation.rb +14 -0
- data/scaffolding/new_project/bot/models/user.rb +3 -0
- data/scaffolding/new_project/config/application.rb +28 -0
- data/scaffolding/new_project/config/database.yml +8 -0
- data/scaffolding/new_project/config/locales/en.yml +4 -0
- data/scaffolding/new_project/config/locales/es.yml +3 -0
- data/scaffolding/new_project/config/nlp.rb +23 -0
- data/scaffolding/new_project/config/platforms/messenger.rb +74 -0
- data/scaffolding/new_project/config/platforms/telegram.rb +45 -0
- data/scaffolding/new_project/config/platforms/whatsapp.rb +13 -0
- data/scaffolding/new_project/web/routes.rb +10 -0
- metadata +220 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Kogno
|
|
2
|
+
class TelegramCtl
|
|
3
|
+
class << self
|
|
4
|
+
|
|
5
|
+
def options(a)
|
|
6
|
+
error = false
|
|
7
|
+
case (a[1].to_sym rescue nil)
|
|
8
|
+
when :webhook
|
|
9
|
+
if a[2] == 'start'
|
|
10
|
+
Kogno::Telegram::Api.set_webhook("#{Kogno::Application.config.telegram.webhook_https_server}#{Kogno::Application.config.telegram.webhook_route}", Kogno::Application.config.telegram.webhook_drop_pending_updates)
|
|
11
|
+
elsif a[2] == 'stop'
|
|
12
|
+
Kogno::Telegram::Api.delete_webhook(Kogno::Application.config.telegram.webhook_drop_pending_updates)
|
|
13
|
+
else
|
|
14
|
+
error = true
|
|
15
|
+
end
|
|
16
|
+
when :set_commands
|
|
17
|
+
puts a[2]
|
|
18
|
+
scope = a[2]
|
|
19
|
+
if scope == "all"
|
|
20
|
+
puts "Aca222"
|
|
21
|
+
Kogno::Telegram::Api.set_all_commands
|
|
22
|
+
elsif Kogno::Telegram::Api.command_valid_scopes.include?(scope.to_sym)
|
|
23
|
+
Kogno::Telegram::Api.set_scope_commands(scope.to_sym)
|
|
24
|
+
else
|
|
25
|
+
error = true
|
|
26
|
+
end
|
|
27
|
+
when :delete_commands
|
|
28
|
+
scope = a[2]
|
|
29
|
+
if Kogno::Telegram::Api.command_valid_scopes.include?(scope.to_sym)
|
|
30
|
+
Kogno::Telegram::Api.delete_commands(scope)
|
|
31
|
+
else
|
|
32
|
+
error = true
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
error = true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
puts %{Usage:
|
|
39
|
+
kogno telegram
|
|
40
|
+
webhook start|stop
|
|
41
|
+
set_commands #{Kogno::Telegram::Api.command_valid_scopes.join("|")}|all
|
|
42
|
+
delete_commands #{Kogno::Telegram::Api.command_valid_scopes.join("|")}
|
|
43
|
+
} if error
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Kogno
|
|
2
|
+
class WebhookCtl
|
|
3
|
+
class << self
|
|
4
|
+
|
|
5
|
+
def pid_file
|
|
6
|
+
Application.file_path(File.join(Application.project_path,"tmp","webhook.pid"))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def log_environment_info
|
|
10
|
+
logger.write "Kogno #{Gem.loaded_specs["kogno"].version.version} http server starting in #{Kogno::Application.config.environment}", :bright
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def server_file
|
|
14
|
+
File.join(Application.core_path,"lib/core/web/webhook.rb")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def save_pid(pid)
|
|
18
|
+
File.write(self.pid_file, pid)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def delete_pid
|
|
22
|
+
save_pid("")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_pid
|
|
26
|
+
File.read(File.join(self.pid_file)).to_i
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def kill_process(pid)
|
|
30
|
+
return false if pid.to_i == 0
|
|
31
|
+
Process.kill("KILL",pid) rescue nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def alive?
|
|
35
|
+
pid = get_pid
|
|
36
|
+
return false if pid == 0
|
|
37
|
+
Process.getpgid(pid) rescue false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def start
|
|
41
|
+
log_environment_info()
|
|
42
|
+
if get_pid > 0 && alive?
|
|
43
|
+
logger.write "Error: It has already started..", :red
|
|
44
|
+
else
|
|
45
|
+
system(%{
|
|
46
|
+
RACK_ENV=#{Kogno::Application.config.environment} ruby #{self.server_file} daemon > /dev/null&
|
|
47
|
+
echo $! > "#{self.pid_file}"
|
|
48
|
+
})
|
|
49
|
+
logger.write "START", :green
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def fg
|
|
54
|
+
log_environment_info()
|
|
55
|
+
if get_pid > 0 && alive?
|
|
56
|
+
logger.write "Error: It has already started..", :red
|
|
57
|
+
else
|
|
58
|
+
system("RACK_ENV=#{Kogno::Application.config.environment} ruby #{self.server_file}")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def stop
|
|
63
|
+
pid = self.get_pid
|
|
64
|
+
self.kill_process(pid)
|
|
65
|
+
self.delete_pid
|
|
66
|
+
logger.write "STOP", :red
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def status
|
|
70
|
+
if alive?
|
|
71
|
+
logger.write "Running | Pid: #{self.get_pid}..", :green
|
|
72
|
+
else
|
|
73
|
+
logger.write "Stopped", :red
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def options(option)
|
|
78
|
+
case option.to_s.to_sym
|
|
79
|
+
when :start
|
|
80
|
+
self.start
|
|
81
|
+
when :stop
|
|
82
|
+
self.stop
|
|
83
|
+
when :restart
|
|
84
|
+
self.stop
|
|
85
|
+
self.start
|
|
86
|
+
when :status
|
|
87
|
+
self.status
|
|
88
|
+
when :fg
|
|
89
|
+
self.fg
|
|
90
|
+
else
|
|
91
|
+
puts "usage: http stop|start|restart|status|fg"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
data/lib/core/db.rb
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
db_configuration_file = File.join(Kogno::Application.project_path,'config', 'database.yml')
|
|
2
|
+
db_configuration = YAML.load(File.read(db_configuration_file))
|
|
3
|
+
|
|
4
|
+
def db_connect(db_configuration)
|
|
5
|
+
ActiveRecord::Base.establish_connection(db_configuration)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
db_connect(db_configuration)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
class Array
|
|
3
|
+
|
|
4
|
+
def replace_keys(defaults)
|
|
5
|
+
new_a = []
|
|
6
|
+
self.each do |v|
|
|
7
|
+
if v.class == Array
|
|
8
|
+
new_a << v.replace_keys(defaults)
|
|
9
|
+
elsif v.class == Hash
|
|
10
|
+
new_h = v
|
|
11
|
+
defaults.each do |find,replace|
|
|
12
|
+
# logger.debug "#{find} => #{replace}"
|
|
13
|
+
# logger.debug "v:#{v}"
|
|
14
|
+
new_h = new_h.transform_keys{|k| k == find ? replace : k}
|
|
15
|
+
end
|
|
16
|
+
new_a << new_h
|
|
17
|
+
else
|
|
18
|
+
new_a << v
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
return(new_a)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def deep_symbolize_keys!
|
|
25
|
+
self.map{|h| h.deep_symbolize_keys!}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
class Logger
|
|
2
|
+
|
|
3
|
+
def write(str, color=nil)
|
|
4
|
+
if color.nil?
|
|
5
|
+
self.info(str)
|
|
6
|
+
else
|
|
7
|
+
self.info(Logger::colorize(str, color.to_sym))
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def write_json(json,color=nil)
|
|
12
|
+
write(JSON.pretty_generate(json),color)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def debug(str,color=nil)
|
|
16
|
+
write(str,color) if Kogno::Application.config.environment == :development
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def debug_json(json,color=nil)
|
|
20
|
+
write(JSON.pretty_generate(json),color) if Kogno::Application.config.environment == :development
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
|
|
26
|
+
def set(daemon)
|
|
27
|
+
case daemon
|
|
28
|
+
when :webhook
|
|
29
|
+
$logger = Logger.new(File.join(Kogno::Application.project_path,'logs','http.log'))
|
|
30
|
+
when :sequences
|
|
31
|
+
$logger = Logger.new(File.join(Kogno::Application.project_path,'logs','sequences.log'))
|
|
32
|
+
when :scheduled_messages
|
|
33
|
+
$logger = Logger.new(File.join(Kogno::Application.project_path,'logs','scheduled_messages.log'))
|
|
34
|
+
else
|
|
35
|
+
$logger = Logger.new(STDOUT)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# logger.datetime_format = ""
|
|
39
|
+
$logger.formatter = proc do |severity, datetime, progname, msg|
|
|
40
|
+
"#{msg}\n"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
ActiveRecord::Base.logger = $logger
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def colors
|
|
48
|
+
@colors ||= {
|
|
49
|
+
bright: 1,
|
|
50
|
+
blue: 34,
|
|
51
|
+
green: 32,
|
|
52
|
+
light_blue: 36,
|
|
53
|
+
pink: 35,
|
|
54
|
+
red: 31,
|
|
55
|
+
white: 256,
|
|
56
|
+
yellow: 33
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def colorize(str, color_code)
|
|
61
|
+
"\e[#{colors[color_code]}m#{str}\e[0m"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def logger
|
|
69
|
+
$logger
|
|
70
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'wit'
|
|
2
|
+
class Wit
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def initialize(opts = {})
|
|
6
|
+
@access_token = opts[:access_token]
|
|
7
|
+
@api_version = opts[:api_version] || "20210928"
|
|
8
|
+
|
|
9
|
+
if opts[:logger]
|
|
10
|
+
@logger = opts[:logger]
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def message_with_context(msg, context=nil)
|
|
15
|
+
params = {}
|
|
16
|
+
params[:q] = msg unless msg.nil?
|
|
17
|
+
params[:context] = context.to_json unless context.nil?
|
|
18
|
+
res = req(logger, @access_token, Net::HTTP::Get, '/message', params)
|
|
19
|
+
return res
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def entity_create(params) # extras = {roles: [], keywords: [], lookups: []}
|
|
23
|
+
res = req(logger, @access_token, Net::HTTP::Post, "/entities", {}, params)
|
|
24
|
+
return res
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def entity_keyword_add(name, role, keyword, synonyms)
|
|
28
|
+
res = req(logger, @access_token, Net::HTTP::Post, "/entities/#{name}/keywords", {}, {keyword: keyword, synonyms: synonyms})
|
|
29
|
+
return res
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def entity_keyword_remove(name, keyword)
|
|
33
|
+
res = req(logger, @access_token, Net::HTTP::Delete, "/entities/#{name}/keywords/#{keyword}")
|
|
34
|
+
return res
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def req(logger, access_token, meth_class, path, params={}, payload={})
|
|
38
|
+
uri = URI(WIT_API_HOST + path)
|
|
39
|
+
uri.query = URI.encode_www_form(params)
|
|
40
|
+
# logger.debug uri, :green
|
|
41
|
+
request = meth_class.new(uri)
|
|
42
|
+
request['authorization'] = 'Bearer ' + access_token
|
|
43
|
+
request['accept'] = 'application/vnd.wit.' + @api_version + '+json'
|
|
44
|
+
request.add_field 'Content-Type', 'application/json'
|
|
45
|
+
request.body = payload.to_json
|
|
46
|
+
# logger.debug request, :yellow
|
|
47
|
+
Net::HTTP.start(uri.host, uri.port, {:use_ssl => uri.scheme == 'https'}) do |http|
|
|
48
|
+
rsp = http.request(request)
|
|
49
|
+
json = JSON.parse(rsp.body)
|
|
50
|
+
if rsp.code.to_i != 200
|
|
51
|
+
error_msg = (json.is_a?(Hash) and json.has_key?('error')) ? json['error'] : json
|
|
52
|
+
logger.write "Wit.ai responded with an error: #{error_msg}", :red
|
|
53
|
+
raise Error.new("Wit.ai responded with an error: #{error_msg}")
|
|
54
|
+
end
|
|
55
|
+
# logger.debug("#{meth_class} #{uri} #{json}")
|
|
56
|
+
json
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
def t(key, **interpolation)
|
|
2
|
+
translation = I18n.t(key, **interpolation)
|
|
3
|
+
if translation.class == Array
|
|
4
|
+
return translation[rand(translation.count)]
|
|
5
|
+
else
|
|
6
|
+
return translation
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def l(value, **format)
|
|
11
|
+
I18n.l(value, **format)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def set_payload(payload,params=nil)
|
|
15
|
+
unless params.nil?
|
|
16
|
+
output_payload = "#{payload}:#{params.to_json}"
|
|
17
|
+
else
|
|
18
|
+
output_payload = payload
|
|
19
|
+
end
|
|
20
|
+
return output_payload
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def reload!(print = true)
|
|
24
|
+
puts 'Reloading ...' if print
|
|
25
|
+
Kogno::Application.load_locales
|
|
26
|
+
Kogno::Application.load_app
|
|
27
|
+
return true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def sql_query(query)
|
|
31
|
+
# logger.debug "sql_query = > #{query}", :green
|
|
32
|
+
results = ActiveRecord::Base.connection.select_all(query)
|
|
33
|
+
{
|
|
34
|
+
columns: results.columns,
|
|
35
|
+
rows: results.rows
|
|
36
|
+
}
|
|
37
|
+
results
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def html_template(route, params={})
|
|
41
|
+
|
|
42
|
+
route_array = route.to_s.split("/")
|
|
43
|
+
if route_array.count == 2
|
|
44
|
+
action_group = route_array[0]
|
|
45
|
+
action = route_array[1]
|
|
46
|
+
elsif route_array.count == 1
|
|
47
|
+
if self.type == :context
|
|
48
|
+
action_group = self.name
|
|
49
|
+
action = route_array[0]
|
|
50
|
+
else
|
|
51
|
+
raise "Can't determine the context for template #{route}"
|
|
52
|
+
return false
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
raise "Wrong format on route. Expected:'context_name/template_name'"
|
|
56
|
+
return false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
template = $context_html_templates[action_group.to_sym][action.to_sym]
|
|
60
|
+
if template.nil?
|
|
61
|
+
logger.write "Template bot/templates/#{action_group}/#{action}.rhtml not found.", :red
|
|
62
|
+
return ""
|
|
63
|
+
else
|
|
64
|
+
return template.render(self, params)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
def tabulate(text, divider, max_chars, orientation = "left")
|
|
2
|
+
amount = text.count(divider)
|
|
3
|
+
amount = amount + 1
|
|
4
|
+
spacing = max_chars / amount
|
|
5
|
+
text = text.split(divider)
|
|
6
|
+
text.each do |str|
|
|
7
|
+
str = str.strip
|
|
8
|
+
index = text.find_index(str)
|
|
9
|
+
if str[0] == " "
|
|
10
|
+
text[index] = str[1..-1]
|
|
11
|
+
elsif str[str.length - 1] == " "
|
|
12
|
+
text[index] = str.chop
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
new_text = []
|
|
16
|
+
#even_space = 0
|
|
17
|
+
|
|
18
|
+
case orientation
|
|
19
|
+
when "left"
|
|
20
|
+
new_text = tabulateLeft(text, spacing)
|
|
21
|
+
when "right"
|
|
22
|
+
new_text = tabulateRight(text, spacing)
|
|
23
|
+
when "middle"
|
|
24
|
+
new_text = tabulateMiddle(text, spacing)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
return new_text.join(divider)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def tabulateLeft(text, spacing)
|
|
31
|
+
new_text = []
|
|
32
|
+
text.each do |str|
|
|
33
|
+
tab_str = str
|
|
34
|
+
spaces = spacing - str.length
|
|
35
|
+
|
|
36
|
+
if text.find_index(tab_str).even?
|
|
37
|
+
if spacing > tab_str.length && text.find_index(tab_str) != 0
|
|
38
|
+
tab_str.prepend(" ")
|
|
39
|
+
spaces -= 1
|
|
40
|
+
end
|
|
41
|
+
while spaces > 0 do
|
|
42
|
+
tab_str.concat(" ")
|
|
43
|
+
spaces -= 1
|
|
44
|
+
end
|
|
45
|
+
else
|
|
46
|
+
if spacing > tab_str.length
|
|
47
|
+
tab_str.prepend(" ")
|
|
48
|
+
spaces -= 1
|
|
49
|
+
end
|
|
50
|
+
while spaces > 0 do
|
|
51
|
+
tab_str.concat(" ")
|
|
52
|
+
spaces -= 1
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
new_text << tab_str
|
|
56
|
+
end
|
|
57
|
+
return new_text
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def tabulateRight(text, spacing)
|
|
61
|
+
new_text = []
|
|
62
|
+
text.each do |str|
|
|
63
|
+
tab_str = str
|
|
64
|
+
spaces = spacing - str.length
|
|
65
|
+
|
|
66
|
+
if text.find_index(tab_str).even?
|
|
67
|
+
if spacing > tab_str.length
|
|
68
|
+
tab_str.concat(" ")
|
|
69
|
+
spaces -= 1
|
|
70
|
+
end
|
|
71
|
+
while spaces > 0 do
|
|
72
|
+
tab_str.prepend(" ")
|
|
73
|
+
spaces -= 1
|
|
74
|
+
end
|
|
75
|
+
else
|
|
76
|
+
while spaces > 0 do
|
|
77
|
+
tab_str.prepend(" ")
|
|
78
|
+
spaces -= 1
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
new_text << tab_str
|
|
82
|
+
end
|
|
83
|
+
return new_text
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def tabulateMiddle(text, spacing)
|
|
87
|
+
new_text = []
|
|
88
|
+
text.each do |str|
|
|
89
|
+
tab_str = str
|
|
90
|
+
spaces = spacing - str.length
|
|
91
|
+
divided = spaces / 2
|
|
92
|
+
concat = false
|
|
93
|
+
|
|
94
|
+
while spaces > divided do
|
|
95
|
+
tab_str.prepend(" ")
|
|
96
|
+
spaces -= 1
|
|
97
|
+
end
|
|
98
|
+
while spaces > 0 do
|
|
99
|
+
tab_str.concat(" ")
|
|
100
|
+
spaces -= 1
|
|
101
|
+
end
|
|
102
|
+
new_text << tab_str
|
|
103
|
+
end
|
|
104
|
+
return new_text
|
|
105
|
+
end
|