omnibot 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,83 +1,72 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module OmniBot
4
+ # entry point
5
+ class Launcher
6
+ def get_config_path(args)
7
+ return args[0] if args[0] && File.file?(args[0])
8
+ path = ENV['HOME'] + '/.local/share/omnibot/omnibot.yaml'
9
+ return path if File.file?(path)
10
+ raise 'No config file found, checked command line and ~/.local/share/omnibot/omnibot.yaml'
11
+ end
4
12
 
5
- # entry point
6
- class Launcher
7
- def get_config_path args
8
- return args[0] if args[0] && File.file?(args[0])
9
- path = File.join(ENV['HOME'],'.omnibot.yaml')
10
- return path if ENV['HOME'] && File.file?(path)
11
- raise 'No config file found, checked command line and ~/.omnibot.yaml'
12
- end
13
+ def ensure_omnidir
14
+ path = ENV['HOME'] + '/.local/share/omnibot'
15
+ FileUtils.mkdir path unless File.directory? path
16
+ path
17
+ end
13
18
 
14
- def ensure_omnidir
15
- path = ENV['HOME']+'/.omnibot'
16
- FileUtils.mkdir path unless File.directory? path unless File.directory? path
17
- path
18
- end
19
+ def log_path(config)
20
+ return config['logpath'] unless (config['logpath'] || '').empty?
21
+ ensure_omnidir + '/omnibot.log'
22
+ end
19
23
 
20
- def get_log_path config
21
- return config['logpath'] unless (config['logpath'] or '').empty?
22
- ensure_omnidir + '/omnibot.log'
23
- end
24
+ def create_db
25
+ db = SQLite3::Database.new(ensure_omnidir + '/omnibot.sqlite3')
26
+ if db.execute("select * from sqlite_master where type='table' and name='received_messages'").empty?
27
+ db.execute <<-SQL
28
+ create table received_messages (
29
+ account TEXT,
30
+ message TEXT,
31
+ date TEXT
32
+ );
33
+ SQL
34
+ end
35
+ db
36
+ end
24
37
 
25
- def get_db
26
- db = SQLite3::Database.new(ensure_omnidir + '/omnibot.sqlite3')
27
- if db.execute("select * from sqlite_master where type='table' and name='received_messages'").empty?
28
- db.execute <<-SQL
29
- create table received_messages (
30
- account TEXT,
31
- message TEXT,
32
- date TEXT
33
- );
34
- SQL
35
- end
36
- db
37
- end
38
+ def provide_handlers(config, db)
39
+ periodic_commands = [config['periodiccommands']].flatten.compact
38
40
 
39
- def provide_handlers config, db
40
- periodic_commands = [config['periodiccommands']].flatten.compact
41
-
42
- mails = [config['mails']].flatten.compact
43
- mail_triggers = [config['mailtriggers']].flatten.compact
44
- mail_triggers.each do |mt|
45
- raise 'No mail found for a trigger' unless mails.find { |m| m['user'] == mt['for'] }
46
- raise 'Not supported action' unless mt['action'] == 'unpack'
47
- end
48
- used_mails = mails.select { |m| mail_triggers.find { |mt| m['user'] == mt['for'] } }
49
- raise 'Sorry but multiple mail addresses is not supported yet' if used_mails.size > 1
41
+ mails = [config['mails']].flatten.compact
42
+ mail_triggers = [config['mailtriggers']].flatten.compact
43
+ mail_triggers.each do |mt|
44
+ raise 'No mail found for a trigger' unless mails.find { |m| m['user'] == mt['for'] }
45
+ raise 'Not supported action' unless mt['action'] == 'unpack'
46
+ end
47
+ used_mails = mails.select { |m| mail_triggers.find { |mt| m['user'] == mt['for'] } }
48
+ raise 'Sorry but multiple mail addresses is not supported yet' if used_mails.size > 1
50
49
 
51
- [] +
52
- periodic_commands.map do |command|
53
- PeriodicCommand.new command
54
- end +
55
- mail_triggers.map do |trigger|
56
- mail = mails.find { |m| m['user'] == trigger['for'] }
57
- MailChecker.new mail, trigger, db
58
- end
59
- end
50
+ [] +
51
+ periodic_commands.map { |command| PeriodicCommand.new command } +
52
+ mail_triggers.map { |trigger| MailChecker.new(mails.find { |m| m['user'] == trigger['for'] }, trigger, db) }
53
+ end
60
54
 
61
- def start args
62
- config_path = get_config_path args
63
- puts "Using config at #{config_path}"
64
- config = YAML.load_file(config_path)["config"]
55
+ def start(args)
56
+ config_path = get_config_path args
57
+ puts "Using config at #{config_path}"
58
+ config = YAML.load_file(config_path)['config']
65
59
 
66
- log_path = get_log_path config
67
- puts "Using log at #{log_path}"
68
- OmniLog::log = Logger.new(log_path)
69
- OmniLog::log.level = Logger::DEBUG
60
+ OmniLog::log = Logger.new(log_path(config))
61
+ OmniLog::log.level = Logger::DEBUG
70
62
 
71
- db = get_db
72
- consumer = AMQPConsumer.new config
73
- consumer.db = db
74
- consumer.handlers = provide_handlers(config, db)
75
- consumer.start
63
+ db = create_db
64
+ consumer = AMQPConsumer.new config
65
+ consumer.db = db
66
+ consumer.handlers = provide_handlers(config, db)
67
+ consumer.start
76
68
 
77
- OmniLog::log.close
78
- end
79
- end
69
+ OmniLog::log.close
70
+ end
71
+ end
80
72
  end
81
-
82
-
83
-
@@ -1,20 +1,19 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module OmniBot
4
- module LoggedCommand
4
+ module LoggedCommand
5
+ def jabber_logged_command(banner, command)
6
+ body = `#{command}`
7
+ if $? != 0
8
+ @jabber_messenger.call "#{banner} command #{command} failed with an error #{$?}:\n" + body
9
+ end
10
+ if body.strip != ''
11
+ @jabber_messenger.call "#{banner} command #{command} succeeded with:\n" + body
12
+ end
13
+ end
5
14
 
6
- def jabber_logged_command banner, command
7
- body = `#{command}`
8
- if $? != 0
9
- @jabber_messenger.call "#{banner} command #{command} failed with an error #{$?}:\n" + body
10
- end
11
- if body.strip != ''
12
- @jabber_messenger.call "#{banner} command #{command} succeeded with:\n" + body
13
- end
14
- end
15
-
16
- def set_jabber_messenger &block
17
- @jabber_messenger = block
18
- end
19
- end
15
+ def jabber_messenger(&block)
16
+ @jabber_messenger = block
17
+ end
18
+ end
20
19
  end
@@ -1,118 +1,110 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module OmniBot
4
-
5
- class MailChecker
6
-
7
- include LoggedCommand
8
-
9
- def on_first_timer
10
- on_periodic_timer
11
- @timer_provider.add_periodic_timer(3600) { on_periodic_timer }
12
- end
13
-
14
- def match_condition m, condition_name, mail_name = condition_name
15
- values = m.send(mail_name)
16
- [values].flatten.any? do |value|
17
- @conditions[condition_name] && Regexp.new(@conditions[condition_name]).match(value.to_s)
18
- end
19
- end
20
-
21
- def match_conditions m
22
- @conditions.empty? || %w{ subject from to cc date}.any? { |condition| match_condition m, condition }
23
- end
24
-
25
- def on_periodic_timer
26
- begin
27
- OmniLog::info "Checking mail #{@address}"
28
- is_new_mail = false
29
- Mail.all.each do |m|
30
- rows = @db.execute "select message from received_messages where account=? and message=?", @address, m.message_id
31
-
32
- if rows.empty?
33
- is_new_mail = true
34
- OmniLog::info "New message from #{m.from} about #{m.subject}; id #{m.message_id}"
35
- if match_conditions m
36
- handle_message(m)
37
- end
38
- @db.execute "insert into received_messages values(?, ?, ?)", @address, m.message_id, m.date.to_s
39
- end
40
- end
41
- OmniLog::info "No new mail" unless is_new_mail
42
- rescue => e
43
- OmniLog::error "MailChecker error: #{e.message}\ntrace:\n#{Helpers::backtrace e}"
44
- end
45
- end
46
-
47
- def handle_message m
48
- OmniLog::info "Matched " + m.inspect.to_s
49
- attached = m.attachments.find { |a| a.mime_type =~ /application\/(zip|x-zip|rar|x-rar).*/ }
50
- if attached
51
- Dir.mktmpdir('omniatt') do |tmpdir|
52
- filename = tmpdir + '/' + attached.filename
53
- OmniLog::info "Writing attachment to #{filename}"
54
- File.open(filename,'w') { |f| f.write attached.read }
55
- Dir.chdir(@unpack_to) do
56
- if filename =~ /\.zip$/
57
- system("unzip -oq '#{filename}'")
58
- elsif filename =~ /\.rar$/
59
- system("unrar x -y '#{filename}'")
60
- else
61
- raise "Wrong filetype"
62
- end
63
- raise "Error extracting file #{filename} to #{@unpack_to}" if $? != 0
64
- end
65
-
66
- message_body = "Received an email '#{m.subject}' from '#{m.from.join(',')}' with "+
67
- "an attachment #{attached.filename}. Successfully extracted an attachment to #{@unpack_to}."
68
- @jabber_messenger.call message_body
69
-
70
- jabber_logged_command 'Mail post-receive ', "#{@command_post} #{filename} #{@unpack_to}"
71
- end
72
- else
73
- OmniLog::info "No attachment found"
74
- end
75
- end
76
-
77
- def yaml_to_mailhash yaml_config
78
- { :address => yaml_config['host'],
79
- :port => yaml_config['port'],
80
- :user_name => yaml_config['user'],
81
- :password => yaml_config['password'],
82
- :enable_ssl => yaml_config['ssl']
83
- }
84
- end
85
-
86
- public
87
- attr_writer :timer_provider
88
- attr_writer :startup_pause
89
-
90
- def initialize mail_config, trigger_config, db
91
- @startup_pause = 0
92
- @mail_config = mail_config
93
- @db = db
94
- @conditions = (trigger_config['if'] or {})
95
- @unpack_to = trigger_config['unpack_to']
96
- @command_post = trigger_config['command_post']
97
- @address = trigger_config['for']
98
-
99
- mailhash = yaml_to_mailhash(mail_config)
100
- Mail.defaults do
101
- retriever_method :pop3, mailhash
102
- end
103
-
104
- raise 'Wrong command' if (@command_post or '') == ''
105
- raise 'No dir to extract to' unless File.directory? @unpack_to
106
- end
107
-
108
- def to_s
109
- "Mail checker for #{@address}"
110
- end
111
-
112
- def start
113
- @timer_provider.add_timer(@startup_pause) { on_first_timer }
114
- end
115
- end
116
-
4
+ class MailChecker
5
+ include LoggedCommand
6
+
7
+ def on_first_timer
8
+ on_periodic_timer
9
+ @timer_provider.add_periodic_timer(3600) { on_periodic_timer }
10
+ end
11
+
12
+ def match_condition(m, condition_name, mail_name = condition_name)
13
+ values = m.send(mail_name)
14
+ [values].flatten.any? do |value|
15
+ @conditions[condition_name] && Regexp.new(@conditions[condition_name]).match(value.to_s)
16
+ end
17
+ end
18
+
19
+ def match_conditions(m)
20
+ @conditions.empty? || %w( subject from to cc date).any? { |condition| match_condition m, condition }
21
+ end
22
+
23
+ def on_periodic_timer
24
+ OmniLog::info "Checking mail #{@address}"
25
+ is_new_mail = false
26
+ Mail.all.each do |m|
27
+ rows = @db.execute 'select message from received_messages where account=? and message=?', @address, m.message_id
28
+
29
+ next unless rows.empty?
30
+ is_new_mail = true
31
+ OmniLog::info "New message from #{m.from} about #{m.subject}; id #{m.message_id}"
32
+ handle_message(m) if match_conditions(m)
33
+ @db.execute 'insert into received_messages values(?, ?, ?)', @address, m.message_id, m.date.to_s
34
+ end
35
+ OmniLog::info 'No new mail' unless is_new_mail
36
+ rescue => e
37
+ OmniLog::error "MailChecker error: #{e.message}\ntrace:\n#{Helpers::backtrace e}"
38
+ end
39
+
40
+ def handle_message(m)
41
+ OmniLog::info 'Matched ' + m.inspect.to_s
42
+ attached = m.attachments.find { |a| a.mime_type =~ %r{application/(zip|x-zip|rar|x-rar).*} }
43
+ if attached
44
+ Dir.mktmpdir('omniatt') do |tmpdir|
45
+ filename = tmpdir + '/' + attached.filename
46
+ OmniLog::info "Writing attachment to #{filename}"
47
+ File.open(filename, 'w') { |f| f.write attached.read }
48
+ Dir.chdir(@unpack_to) do
49
+ if filename =~ /\.zip$/
50
+ system("unzip -oq '#{filename}'")
51
+ elsif filename =~ /\.rar$/
52
+ system("unrar x -y '#{filename}'")
53
+ else
54
+ raise 'Wrong filetype'
55
+ end
56
+ raise "Error extracting file #{filename} to #{@unpack_to}" if $? != 0
57
+ end
58
+
59
+ message_body = "Received an email '#{m.subject}' from '#{m.from.join(',')}' with "\
60
+ "an attachment #{attached.filename}. Successfully extracted an attachment to #{@unpack_to}."
61
+ @jabber_messenger.call message_body
62
+
63
+ jabber_logged_command 'Mail post-receive ', "#{@command_post} #{filename} #{@unpack_to}"
64
+ end
65
+ else
66
+ OmniLog::info 'No attachment found'
67
+ end
68
+ end
69
+
70
+ def yaml_to_mailhash(yaml_config)
71
+ { address: yaml_config['host'],
72
+ port: yaml_config['port'],
73
+ user_name: yaml_config['user'],
74
+ password: yaml_config['password'],
75
+ enable_ssl: yaml_config['ssl']
76
+ }
77
+ end
78
+
79
+ public
80
+
81
+ attr_writer :timer_provider
82
+ attr_writer :startup_pause
83
+
84
+ def initialize(mail_config, trigger_config, db)
85
+ @startup_pause = 0
86
+ @mail_config = mail_config
87
+ @db = db
88
+ @conditions = (trigger_config['if'] || {})
89
+ @unpack_to = trigger_config['unpack_to']
90
+ @command_post = trigger_config['command_post']
91
+ @address = trigger_config['for']
92
+
93
+ mailhash = yaml_to_mailhash(mail_config)
94
+ Mail.defaults do
95
+ retriever_method :pop3, mailhash
96
+ end
97
+
98
+ raise 'Wrong command' if (@command_post || '') == ''
99
+ raise 'No dir to extract to' unless File.directory? @unpack_to
100
+ end
101
+
102
+ def to_s
103
+ "Mail checker for #{@address}"
104
+ end
105
+
106
+ def start
107
+ @timer_provider.add_timer(@startup_pause) { on_first_timer }
108
+ end
109
+ end
117
110
  end
118
-
@@ -1,27 +1,25 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module OmniBot
4
+ class OmniSend
5
+ def start(args)
6
+ if args.empty?
7
+ message = STDIN.readlines.join
8
+ else
9
+ message = args.join(' ')
10
+ end
11
+ puts "Sending message #{message}"
12
+ data = Base64.encode64(Marshal.dump(message))
4
13
 
5
- class OmniSend
14
+ Signal.trap('INT') { AMQP.stop { EM.stop } }
6
15
 
7
- def start args
8
- if args.empty?
9
- message = STDIN.readlines.join
10
- else
11
- message = args.join(' ')
12
- end
13
- puts "Sending message #{message}"
14
- data = Base64.encode64(Marshal.dump(message))
15
-
16
- Signal.trap('INT') { AMQP.stop{ EM.stop } }
17
-
18
- AMQP.start do |connection|
19
- mq = AMQP::Channel.new(connection)
20
- exchange = mq.direct(Helpers::amqp_exchange_name)
21
- exchange.publish(data, :routing_key => Helpers::amqp_routing_key)
22
- EM.add_timer(2.0) { connection.close { puts 'sent' ; EM.stop } }
23
- end
24
- end
25
- end
16
+ AMQP.start do |connection|
17
+ mq = AMQP::Channel.new(connection)
18
+ exchange = mq.direct(Helpers::amqp_exchange_name)
19
+ exchange.publish(data, routing_key: Helpers::amqp_routing_key)
20
+ EM.add_timer(2.0) { connection.close { EM.stop } }
21
+ end
22
+ puts 'Sent'
23
+ end
24
+ end
26
25
  end
27
-
@@ -1,49 +1,44 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module OmniBot
4
-
5
- # Send to jabber user result of a daily command
6
- class PeriodicCommand
7
-
8
- include OmniBot::LoggedCommand
9
-
10
- def on_first_timer
11
- on_periodic_timer
12
- @timer_provider.add_periodic_timer(24*3600) { on_periodic_timer }
13
- end
14
-
15
- def on_periodic_timer
16
- begin
17
- OmniLog::info "Reporting command #{@command}"
18
- jabber_logged_command 'Periodic command', @command
19
- rescue => e
20
- OmniLog::error "PeriodicCommand error: #{e.message}\ntrace:\n#{Helpers::backtrace e}"
21
- end
22
- end
23
-
24
- public
25
- attr_writer :timer_provider
26
- attr_writer :startup_pause
27
-
28
- def initialize command
29
- @command = command
30
- @startup_pause = 0
31
-
32
- raise 'Wrong command' if (@command or '') == ''
33
- end
34
-
35
- def to_s
36
- "Periodic command '#{@command}'"
37
- end
38
-
39
- def start
40
- now = Time.now
41
- tomorrow = DateTime.now+1
42
- next_report_time = Time.local(tomorrow.year, tomorrow.month, tomorrow.day, 1, 0, 0)
43
- next_report_time = next_report_time + @startup_pause
44
- @timer_provider.add_timer(next_report_time - now) { on_first_timer }
45
- end
46
- end
47
-
4
+ # Send to jabber user result of a daily command
5
+ class PeriodicCommand
6
+ include OmniBot::LoggedCommand
7
+
8
+ def on_first_timer
9
+ on_periodic_timer
10
+ @timer_provider.add_periodic_timer(24 * 3600) { on_periodic_timer }
11
+ end
12
+
13
+ def on_periodic_timer
14
+ OmniLog::info "Reporting command #{@command}"
15
+ jabber_logged_command 'Periodic command', @command
16
+ rescue => e
17
+ OmniLog::error "PeriodicCommand error: #{e.message}\ntrace:\n#{Helpers::backtrace e}"
18
+ end
19
+
20
+ public
21
+
22
+ attr_writer :timer_provider
23
+ attr_writer :startup_pause
24
+
25
+ def initialize(command)
26
+ @command = command
27
+ @startup_pause = 0
28
+
29
+ raise 'Wrong command' if (@command || '') == ''
30
+ end
31
+
32
+ def to_s
33
+ "Periodic command '#{@command}'"
34
+ end
35
+
36
+ def start
37
+ now = Time.now
38
+ tomorrow = DateTime.now + 1
39
+ next_report_time = Time.local(tomorrow.year, tomorrow.month, tomorrow.day, 1, 0, 0)
40
+ next_report_time += @startup_pause
41
+ @timer_provider.add_timer(next_report_time - now) { on_first_timer }
42
+ end
43
+ end
48
44
  end
49
-