omnibot 0.0.21 → 0.0.22

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.
@@ -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
-