Module: Dialog

Extended by:
Dry::Configurable
Defined in:
lib/require.rb,
lib/version.rb,
lib/tdlib/auth.rb,
lib/tdlib/func.rb,
lib/tdlib/init.rb,
lib/dialog_ruby.rb,
lib/tooling/log.rb,
lib/tooling/lang.rb,
lib/configuration.rb,
lib/metamess/_run.rb,
lib/metamess/func.rb,
lib/triggers/init.rb,
lib/triggers/false.rb,
lib/metamess/naming.rb,
lib/telegram/botapi.rb,
lib/metamess/event_c.rb,
lib/telegram/wrappers.rb,
lib/triggers/start/bot.rb,
lib/dialect/codegen/run.rb,
lib/telegram/infra_info.rb,
lib/triggers/_meta/full.rb,
lib/triggers/start/_main.rb,
lib/triggers/start/tdlib.rb,
lib/dialect/canvas/canvas.rb,
lib/triggers/deploy/deploy.rb,
lib/dialect/codegen/codegen.rb,
lib/metamess/event/notify_o.rb,
lib/triggers/start/_pre_bot.rb,
lib/storage/redis/redisPubSub.rb,
lib/storage/redis/rediscached.rb,
lib/metamess/content/content_o.rb,
lib/metamess/service/service_o.rb,
lib/dialect/canvas/mod/send/func.rb,
lib/metamess/event/notify_o-create_f.rb,
lib/metamess/event/notify_o-pinned_f.rb,
lib/metamess/event/notify_o-migrate_f.rb,
lib/dialect/canvas/element/data/search.rb,
lib/dialect/canvas/mod/send/_keyboards.rb,
lib/metamess/content/content_o-media_f.rb,
lib/metamess/content/content_o-simple_f.rb,
lib/metamess/event/notify_o-chattitle_f.rb,
lib/metamess/service/service_o-inline_f.rb,
lib/dialect/canvas/element/send/restrict.rb,
lib/dialect/canvas/mod/send/general/chat.rb,
lib/dialect/canvas/mod/send/general/user.rb,
lib/metamess/content/content_o-command_f.rb,
lib/metamess/event/notify_o-chatmember_f.rb,
lib/dialect/canvas/element/send/keyboards.rb,
lib/dialect/canvas/element/send/recognize.rb,
lib/metamess/service/service_o-callback_f.rb,
lib/dialect/canvas/element/send/tdlib_chat.rb,
lib/dialect/canvas/mod/send/general/_heads.rb,
lib/dialect/canvas/mod/send/general/common.rb,
lib/dialect/canvas/element/send/bot_message.rb,
lib/dialect/canvas/mod/send/general/message.rb,
lib/dialect/canvas/element/send/tdlib_message.rb,
lib/dialect/canvas/element/convert/SearchBaloo.rb,
lib/dialect/canvas/mod/send/_Inline_query_result.rb,
lib/dialect/canvas/element/send/Inline_query_result.rb,
lib/dialect/codegen/repack/functional/1.Expect2Events.rb,
lib/dialect/codegen/repack/functional/7.ElementChains.rb,
lib/dialect/canvas/mod/send/inline_query_result/common.rb,
lib/dialect/codegen/repack/constructor/Element2ModSend.rb,
lib/dialect/codegen/repack/constructor/ElementsInElements.rb,
lib/dialect/codegen/repack/functional/5.2.Element2ModSend.rb,
lib/dialect/codegen/repack/functional/2.2.1.Events2ModReceive.rb,
lib/dialect/codegen/repack/functional/5.1.Element2ModElements.rb,
lib/dialect/codegen/repack/functional/2.2.2.ModReceive2AppEvent.rb,
lib/dialect/codegen/repack/constructor/DockedGroupings2AppFunctions.rb

Overview

####### ######## ####### ######## ########

 / / / /    License    \ \ \ \ 
Copyleft culture, Copyright (C) is prohibited here
This work is licensed under a CC BY-SA 4.0
Creative Commons Attribution-ShareAlike 4.0 License
Refer to the http://creativecommons.org/licenses/by-sa/4.0/
#######    ########    #######    ########    ########
/ / / /    Code Climate    \ \ \ \ 
Language = ruby
Indent = space;    2 chars;
#######    ########    #######    ########    ########

Defined Under Namespace

Modules: BotApi, Canvas, Dialect, ElementData, ElementSend, Lang, Metamess, ModSend, Naming, RedisCached, RedisPubSub, TDLib, Wrappers Classes: Log

Constant Summary collapse

VERSION =
'0.1.9'.freeze

Class Method Summary collapse

Class Method Details

._requireObject



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/require.rb', line 33

def _require
  ### SYSTEM
  require 'uri'
  require 'erb'
  require 'shellwords'

  ### GEMS
  require 'dialect_lookup'
  require 'telegram/bot'
  require 'i18n'
  require 'redis'
  require 'concurrent'
  require 'oj'
  require 'sidekiq-cron'
  require 'sidekiq-rate-limiter'
  #lazy_object

  ### DRY
  # require 'dry-monads'
  # require 'dry-matcher'
  # require 'dry-transaction'
  # require 'dry/inflector'
  # require 'dry-validation'
  # require 'dry-struct'
  # require 'dry-types'

  #dry-events - pub/sub

  ### CODE
  Dir.glob(File.join("#{File.dirname(__FILE__)}/**", "*.rb")).each{|f| require f}
end

._require_minObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/require.rb', line 16

def _require_min
  ### SYSTEM
  require 'pp'
  require 'timeout'
  require 'logger'
  require 'socket'
  require 'fileutils'
  require 'open3'

  ### DRY
  require 'dry-configurable'
  require_relative './version.rb'
  require_relative './configuration.rb'
  Dir.glob(File.join("#{File.dirname(__FILE__)}/triggers/**", "*.rb")).each{|f| require f}      
end

.bot(args) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/triggers/start/bot.rb', line 17

def bot(args)
  args[:globals] = {}
  
  ### LANG
  i18n = Dialog::Lang.initial
        
  begin    
    Dialog::redis.call(['info', 'clients'])
  rescue
    Dialog.logger.error "No Redis connection!"
    sleep(2) 
    retry
  end
  Telegram::Bot::Client.run Dialog.config.secure.token do |bot|
    args[:bot]= bot; args[:bot].freeze
    
    #bot getMe
    Dialog.logger.info 'BotAPI getMe-request started'        
    me = bot.api.send(:getMe)
    Dialog.logger.info 'BotAPI getMe-request completed'     
    
    #bot globals
    args[:globals][:botUsername] = me["result"]["username"]
    args[:globals][:botFirstName] = me["result"]["first_name"]
    args[:globals][:botFirstNameArray] = me["result"]["first_name"].split("\s")
    args[:globals].freeze
    
    #common queue
    args[:queue] = {}
    args[:queue][:threadCommon] = Concurrent::CachedThreadPool.new
    
    #Success
    Dialog.logger.info "Started: Bot named \"#{args[:globals][:botUsername]}\", botInstance=\"#{Dialog.config.naming.instance}\" of botInterface=\"#{Dialog.config.naming.interface}\", ID=\"#{Dialog.config.naming.id}\", loglevel=\"#{Dialog.config.log.base}\""

    begin        
      bot.listen do |rmsg|
        args[:rmsg] = rmsg
        Dialog.clear(args) 
        Dialog.clearApi(args)
        args[:perf] = {init: Time.now}
          if args[:rmsg].respond_to?(:from)
            fromId = args[:rmsg][:from][:id]
            args[:queue][fromId] ||= {}
            args[:queue][fromId][:thread] = Concurrent::ImmediateExecutor.new unless args[:queue][fromId][:thread]
            args[:queue][fromId][:thread].post do
              runMessage(args)
            end
          else
            Concurrent::Future.execute(executor: args[:queue][:threadCommon]) do
              runMessage(args)
            end                
          end

      end
      rescue
#         rescue Exception => @e
      retry
#           Dialog.logger.error "ERROR - #{@e.inspect}\n\n Backtrace:\n #{@e.backtrace.join("\n\t")}\n \
#           MMSG:\n#{args[:mmsg]}\n" if @e             
    end        
  end
end

.checkEnv(env, val, err = []) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/configuration.rb', line 20

def self.checkEnv(env, val, err=[])
  if ENV[env].nil?
    case val
      when true;  res = true  
      when false; res = false && err << "There is no #{env} in envs"
      else        res = val 
    end
  else res = ENV[env]; end
    puts err
  return res
end

.clear(args) ⇒ Object



21
22
23
24
# File 'lib/triggers/start/_pre_bot.rb', line 21

def clear(args)
  args[:x] = {metamess: {}, redis: {}, data: {}, labels: {}, send: {}, exec: {}}
  args[:smsg] = {}
end

.clearApi(args) ⇒ Object



30
31
32
# File 'lib/triggers/start/_pre_bot.rb', line 30

def clearApi(args)
  args[:api] = {}
end

.clearRedis(args) ⇒ Object



26
27
28
# File 'lib/triggers/start/_pre_bot.rb', line 26

def clearRedis(args)
  args[:x][:redis] = {}
end

.createObject



16
17
18
19
20
21
22
23
24
25
# File 'lib/dialog_ruby.rb', line 16

def create
  version = RUBY_VERSION.split('.').map { |x| x.to_i }
  if (version <=> [2, 5, 0]) >= 1
    require_relative './require.rb'
    _require_min
    send("trigger_#{Dialog.config.run.scope}".to_sym)
  else
    puts "Minimum required Ruby version - 2.5.0"
  end
end

.deploy_binariesObject



59
60
61
62
63
# File 'lib/triggers/deploy/deploy.rb', line 59

def deploy_binaries
    Dialog.logger.info "openSUSE: zypper ar -cf https://download.opensuse.org/repositories/home:/in4ops:/4wrap/openSUSE_Leap_15.0/home:in4ops:4wrap.repo"
    #will be 'home:in4ops:Innosense:libs'
    Dialog.logger.info "openSUSE: zypper --no-gpg-checks --non-interactive in zbar tdlib"      
end

.deploy_botObject



46
47
48
49
50
51
52
# File 'lib/triggers/deploy/deploy.rb', line 46

def deploy_bot
  erb('systemd/[email protected]', "#{Dir.home}/.config/systemd/user/[email protected]", 'check')
  systemd("dialog_bot@#{Dialog.config.naming.full}")
  
  erb('systemd/[email protected]', "#{Dir.home}/.config/systemd/user/[email protected]", Dialog.config.run.mode)
  systemd("dialog_bot@#{Dialog.config.naming.full}")      
end

.deploy_devenvObject



65
66
# File 'lib/triggers/deploy/deploy.rb', line 65

def deploy_devenv
end

.deploy_gitsyncObject



68
69
# File 'lib/triggers/deploy/deploy.rb', line 68

def deploy_gitsync
end

.deploy_redisObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/triggers/deploy/deploy.rb', line 30

def deploy_redis
  if File.file?('/usr/sbin/redis-server')
    redisDir = "#{Dialog.config.path.dialogData}/redis"
    FileUtils.mkdir_p redisDir
    erb('systemd/dialog_redis.service', "#{Dir.home}/.config/systemd/user/dialog_redis.service")
    erb('conf/redis_local.conf', "#{redisDir}/redis_local.conf")
    erb('conf/redis_global.conf', "#{redisDir}/redis_global.conf")
    systemd('dialog_redis')
  else
    Dialog.logger.error "Please install Redis binary"
    Dialog.logger.info "openSUSE: zypper --no-gpg-checks --non-interactive in redis"
    exit(false)
  end
end

.deploy_tdlibObject



54
55
56
57
# File 'lib/triggers/deploy/deploy.rb', line 54

def deploy_tdlib
  erb('systemd/[email protected]', "#{Dir.home}/.config/systemd/user/[email protected]", Dialog.config.run.mode)
  systemd("dialog_tdlib@#{Dialog.config.naming.full}")      
end

.dialectDriven(args) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/triggers/start/_main.rb', line 44

def dialectDriven(args)
  require 'dialect_lookup'
  state = {
    dialectFolder:  Dialog.config.dialect.folder, 
    myAppName:      Dialog.config.naming.app, 
    sqlite:         Dialog.config.dialect.sqlite, 
    jsonFolder:  "#{Dialog.config.path.dialogRender}/json/"
  }
  ::Dialect::Lookup.new.run(state)
#       File.delete(Dialog.config.dialect.sqlite)
end

.erb(erbFile, dst, mode = '') ⇒ Object



23
24
25
26
27
28
# File 'lib/triggers/deploy/deploy.rb', line 23

def erb(erbFile, dst, mode='')
  if not File.file?(dst)
    tmpl = ERB.new(File.read("#{Dialog.config.path.dialog_ruby}/exec/#{erbFile}")).result(binding)
    File.open(dst, 'w') do |f| f.write tmpl; end         
  end
end

.getDialog_rubyPathObject



18
# File 'lib/configuration.rb', line 18

def self.getDialog_rubyPath; return File.dirname(__FILE__);  end

.getDialogPathObject



17
# File 'lib/configuration.rb', line 17

def self.getDialogPath; return @dialogPath;  end

.jsonDriven(args, type) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/triggers/start/_main.rb', line 57

def jsonDriven(args, type)
  FileUtils.rm_rf(Dir.glob("#{Dialog.config.path.dialogRender}/code_#{type}/*.rb"))     
  args[:dialect] = {}      
  
  json = "#{Dialog.config.path.dialogRender}/json/#{Dialog.config.dialect.folder}_#{Dialog.config.naming.app}.json"
  jsonLoad = Oj.load(File.read(json), symbol_keys: true)
  args[:dialect] = jsonLoad[:stages][Dialog.config.dialect.folder.to_sym]
  Dialog::Dialect.run(args, type)
  
  args[:dialect] ={} 
  args[:tmp] = {}      
  Dir.glob(File.join("#{Dialog.config.path.dialogRender}/code_#{type}/**", "*.rb")).sort.each{|f| require f}
  Dialog.logger.info "Rendered bot code is ok"      
end

.loggerObject



15
16
17
# File 'lib/tooling/log.rb', line 15

def self.logger
  @logger ||= Log.new(Dialog.config.log.base)
end

.perf(perf) ⇒ Object



35
36
37
38
39
40
# File 'lib/triggers/start/_pre_bot.rb', line 35

def perf(perf)
a = []
a << "mmsg: #{perf[:metamess] - perf[:init]}s" if perf.has_key?(:metamess)
a << "preApiAction: #{perf[:preApiAction] - perf[:init]}s" if perf.has_key?(:preApiAction)
a << "full: #{perf[:fullend] - perf[:init]}s"  
end

.redisObject



17
18
19
# File 'lib/triggers/start/_pre_bot.rb', line 17

def redis
  @redis ||= Redis.new(path: Dialog.config.db.redis_url)
end

.runMessage(args) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/triggers/start/bot.rb', line 81

def runMessage(args)      
    begin
#           Dialog.logger.debug "######### - REDIS STAT:\n #{Dialog::redis.call(['client', 'list'])}\n\n"
      Dialog::Metamess.firstpoint(args)
      args[:perf][:fullend] = Time.now                     
      Dialog.logger.info("## PERF: #{perf(args[:perf]).join(", ")}")  
      
    rescue Exception => @e
      Dialog.logger.error "ERROR - #{@e.inspect}\n\n Backtrace:\n #{@e.backtrace.join("\n\t")}\n \
      MMSG:\n#{args[:mmsg]}\n" if @e
      args[:bot].api.send("sendMessage".to_sym, {chat_id: Dialog.config.monitoring.channel, disable_notification: true, text: @e}) unless Dialog.config.monitoring.channel.nil?
      raise
    end
end

.start_tdlib(args) ⇒ Object



16
17
18
19
20
21
22
23
24
25
# File 'lib/triggers/start/tdlib.rb', line 16

def start_tdlib(args)
  require 'tdlib-ruby'
  args[:globals] = {}
  Dir.glob(File.join("#{Dialog.config.path.dialog_rubyLib}/tdlib/**", "*.rb")).each{|f| require f}      
  tdlibInit(args)
  args[:tdlib][:cli].on_ready do |client|
    a = client.fetch('@type' => 'getMe')
    args[:globals][:cliId] = a['id'].to_i
  end        
end

.systemd(service) ⇒ Object



71
72
73
74
75
# File 'lib/triggers/deploy/deploy.rb', line 71

def systemd(service)
  Open3.popen3('/usr/bin/systemctl', '--user', 'daemon-reload')
#       Open3.popen3('/usr/bin/systemctl', '--user', 'restart', service)
  #enable
end

.tdlibAuthObject



20
21
22
23
# File 'lib/triggers/init.rb', line 20

def tdlibAuth
  sess = Dialog::TDLib.tdlibInit(Dialog.config.run.mode)
  Dialog::TDLib.tdlibAuth(Dialog.config.run.mode, sess)
end

.tdlibInit(args) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/triggers/start/tdlib.rb', line 28

def tdlibInit(args)
  inits = ['cli']
  args[:tdlib] = {}
  inits.each do |init|
    unless File.exists?("#{Dialog.config.path.dialogData}/tdlib/#{init}/td.binlog")
      Dialog.logger.error "ERROR: please make init of the '#{init}' using 'ruby dialog.rb init #{init}"
      exit(false)
    end
    args[:tdlib][init.to_sym] = Dialog::TDLib.tdlibInit(init)        
  end
  args[:tdlib].freeze
end

.trigger_deployObject



16
17
18
19
20
21
# File 'lib/triggers/deploy/deploy.rb', line 16

def trigger_deploy
  require 'erb'
  deploy_redis
  deploy_bot
  deploy_binaries
end

.trigger_falseObject



16
17
18
# File 'lib/triggers/false.rb', line 16

def trigger_false
  Dialog.logger.error "Something wrong in runtime scenario"
end

.trigger_fullObject



16
17
18
# File 'lib/triggers/_meta/full.rb', line 16

def trigger_full
  
end

.trigger_initObject



16
17
18
# File 'lib/triggers/init.rb', line 16

def trigger_init
  Dialog.tdlibAuth
end

.trigger_startObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/triggers/start/_main.rb', line 16

def trigger_start
  args = {}
  case Dialog.config.common.mode
  when 'check'
    _require
    jsonDriven(args, :check)
  when 'bot'
    _require
    jsonDriven(args, :prod)
    bot(args)
  when 'dev'
    _require
    dialectDriven(args)
    jsonDriven(args, :prod)
    bot(args)
  when 'dev_offline'
    _require
    dialectDriven(args)
    jsonDriven(args, :check) 
  when 'tdlib'
    start_tdlib(args) 
  else
     Dialog.logger.error "ERROR: no such mode - '#{Dialog.config.common.mode}'"
  end      
end