draftcode-termtter 1.0.8

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.
Files changed (118) hide show
  1. data/History.txt +4 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +55 -0
  4. data/bin/kill_termtter +22 -0
  5. data/bin/termtter +6 -0
  6. data/lib/plugins/addspace.rb +27 -0
  7. data/lib/plugins/april_fool.rb +15 -0
  8. data/lib/plugins/bomb.rb +39 -0
  9. data/lib/plugins/clear.rb +14 -0
  10. data/lib/plugins/command_plus.rb +47 -0
  11. data/lib/plugins/confirm.rb +33 -0
  12. data/lib/plugins/cool.rb +10 -0
  13. data/lib/plugins/countter.rb +23 -0
  14. data/lib/plugins/devel.rb +18 -0
  15. data/lib/plugins/direct_messages.rb +36 -0
  16. data/lib/plugins/en2ja.rb +11 -0
  17. data/lib/plugins/english.rb +25 -0
  18. data/lib/plugins/erb.rb +17 -0
  19. data/lib/plugins/exec.rb +17 -0
  20. data/lib/plugins/exec_and_update.rb +14 -0
  21. data/lib/plugins/expand-tinyurl.rb +34 -0
  22. data/lib/plugins/fib.rb +28 -0
  23. data/lib/plugins/fib_filter.rb +14 -0
  24. data/lib/plugins/filter.rb +69 -0
  25. data/lib/plugins/graduatter.rb +8 -0
  26. data/lib/plugins/grass.rb +27 -0
  27. data/lib/plugins/group.rb +64 -0
  28. data/lib/plugins/growl.rb +52 -0
  29. data/lib/plugins/growl2.rb +143 -0
  30. data/lib/plugins/hatebu.rb +59 -0
  31. data/lib/plugins/hatebu_and_update.rb +58 -0
  32. data/lib/plugins/history.rb +93 -0
  33. data/lib/plugins/ignore.rb +19 -0
  34. data/lib/plugins/keyword.rb +18 -0
  35. data/lib/plugins/l2.rb +25 -0
  36. data/lib/plugins/log.rb +73 -0
  37. data/lib/plugins/me.rb +10 -0
  38. data/lib/plugins/modify_arg_hook_sample.rb +7 -0
  39. data/lib/plugins/msagent.rb +38 -0
  40. data/lib/plugins/multi_reply.rb +27 -0
  41. data/lib/plugins/notify-send.rb +22 -0
  42. data/lib/plugins/notify-send2.rb +52 -0
  43. data/lib/plugins/notify-send3.rb +45 -0
  44. data/lib/plugins/open_url.rb +59 -0
  45. data/lib/plugins/otsune.rb +21 -0
  46. data/lib/plugins/outputz.rb +33 -0
  47. data/lib/plugins/pause.rb +3 -0
  48. data/lib/plugins/post_exec_hook_sample.rb +9 -0
  49. data/lib/plugins/pre_exec_hook_sample.rb +9 -0
  50. data/lib/plugins/primes.rb +30 -0
  51. data/lib/plugins/quicklook.rb +41 -0
  52. data/lib/plugins/random.rb +23 -0
  53. data/lib/plugins/reblog.rb +40 -0
  54. data/lib/plugins/reload.rb +3 -0
  55. data/lib/plugins/reply.rb +8 -0
  56. data/lib/plugins/retweet.rb +46 -0
  57. data/lib/plugins/reverse.rb +13 -0
  58. data/lib/plugins/say.rb +26 -0
  59. data/lib/plugins/scrape.rb +41 -0
  60. data/lib/plugins/screen-notify.rb +20 -0
  61. data/lib/plugins/screen.rb +24 -0
  62. data/lib/plugins/shell.rb +14 -0
  63. data/lib/plugins/sl.rb +48 -0
  64. data/lib/plugins/spam.rb +16 -0
  65. data/lib/plugins/standard_plugins.rb +525 -0
  66. data/lib/plugins/stdout.rb +220 -0
  67. data/lib/plugins/storage.rb +55 -0
  68. data/lib/plugins/storage/DB.rb +37 -0
  69. data/lib/plugins/storage/status.rb +83 -0
  70. data/lib/plugins/storage/status_mook.rb +30 -0
  71. data/lib/plugins/switch_user.rb +22 -0
  72. data/lib/plugins/system_status.rb +33 -0
  73. data/lib/plugins/timer.rb +18 -0
  74. data/lib/plugins/tinyurl.rb +20 -0
  75. data/lib/plugins/translation.rb +38 -0
  76. data/lib/plugins/typable_id.rb +94 -0
  77. data/lib/plugins/update_editor.rb +53 -0
  78. data/lib/plugins/uri-open.rb +66 -0
  79. data/lib/plugins/wassr_post.rb +22 -0
  80. data/lib/plugins/yhara.rb +148 -0
  81. data/lib/plugins/yhara_filter.rb +8 -0
  82. data/lib/plugins/yonda.rb +21 -0
  83. data/lib/termtter.rb +38 -0
  84. data/lib/termtter/api.rb +57 -0
  85. data/lib/termtter/client.rb +324 -0
  86. data/lib/termtter/command.rb +80 -0
  87. data/lib/termtter/config.rb +68 -0
  88. data/lib/termtter/config_setup.rb +38 -0
  89. data/lib/termtter/connection.rb +41 -0
  90. data/lib/termtter/hook.rb +31 -0
  91. data/lib/termtter/optparse.rb +14 -0
  92. data/lib/termtter/system_extensions.rb +115 -0
  93. data/lib/termtter/task.rb +17 -0
  94. data/lib/termtter/task_manager.rb +116 -0
  95. data/lib/termtter/version.rb +4 -0
  96. data/spec/plugins/cool_spec.rb +10 -0
  97. data/spec/plugins/english_spec.rb +19 -0
  98. data/spec/plugins/fib_spec.rb +15 -0
  99. data/spec/plugins/filter_spec.rb +18 -0
  100. data/spec/plugins/pause_spec.rb +8 -0
  101. data/spec/plugins/primes_spec.rb +15 -0
  102. data/spec/plugins/shell_spec.rb +10 -0
  103. data/spec/plugins/sl_spec.rb +8 -0
  104. data/spec/plugins/spam_spec.rb +4 -0
  105. data/spec/plugins/standard_plugins_spec.rb +23 -0
  106. data/spec/plugins/storage/DB_spec.rb +12 -0
  107. data/spec/plugins/storage/status_spec.rb +24 -0
  108. data/spec/spec_helper.rb +7 -0
  109. data/spec/termtter/client_spec.rb +255 -0
  110. data/spec/termtter/command_spec.rb +107 -0
  111. data/spec/termtter/config_spec.rb +111 -0
  112. data/spec/termtter/hook_spec.rb +78 -0
  113. data/spec/termtter/task_manager_spec.rb +78 -0
  114. data/spec/termtter/task_spec.rb +22 -0
  115. data/spec/termtter_spec.rb +29 -0
  116. data/test/friends_timeline.json +5 -0
  117. data/test/search.json +8 -0
  118. metadata +211 -0
@@ -0,0 +1,80 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+
5
+ class Command
6
+
7
+ attr_accessor :name, :aliases, :exec_proc, :completion_proc, :help
8
+
9
+ # args
10
+ # name: Symbol as command name
11
+ # aliases: Array of command alias (ex. ['u', 'up'])
12
+ # exec_proc: Proc for procedure of the command. If need the proc must return object for hook.
13
+ # completion_proc: Proc for input completion. The proc must return Array of candidates (Optional)
14
+ # help: help text for the command (Optional)
15
+ def initialize(args)
16
+ raise ArgumentError, ":name is not given." unless args.has_key?(:name)
17
+ args[:exec_proc] ||= args[:exec]
18
+ args[:completion_proc] ||= args[:completion]
19
+ args[:aliases] ||= [args[:alias]].compact
20
+
21
+ cfg = {
22
+ :aliases => [],
23
+ :exec_proc => lambda {|arg| },
24
+ :comletion_proc => lambda {|command, arg| [] }
25
+ }.merge(args)
26
+
27
+ set cfg
28
+ end
29
+
30
+ def set(cfg)
31
+ @name = cfg[:name].to_sym
32
+ @aliases = cfg[:aliases].map {|e| e.to_sym }
33
+ @exec_proc = cfg[:exec_proc]
34
+ @completion_proc = cfg[:completion_proc]
35
+ @help = cfg[:help]
36
+ end
37
+
38
+ def complement(input)
39
+ if match?(input) && input =~ /^[^\s]+\s/
40
+ if completion_proc
41
+ command_str, command_arg = Command.split_command_line(input)
42
+ [completion_proc.call(command_str, command_arg || '')].flatten.compact
43
+ else
44
+ []
45
+ end
46
+ else
47
+ [name.to_s, aliases.to_s].grep(/^#{Regexp.quote(input)}/)
48
+ end
49
+ end
50
+
51
+ def call(cmd = nil, arg = nil, original_text = nil)
52
+ arg = case arg
53
+ when nil
54
+ ''
55
+ when String
56
+ arg
57
+ else
58
+ raise ArgumentError, 'arg should be String or nil'
59
+ end
60
+ exec_proc.call(arg)
61
+ end
62
+
63
+ def match?(input)
64
+ (pattern =~ input) != nil
65
+ end
66
+
67
+ def pattern
68
+ commands_regex = commands.map {|name| Regexp.quote(name.to_s) }.join('|')
69
+ /^((#{commands_regex})|(#{commands_regex})\s+(.*?))\s*$/
70
+ end
71
+
72
+ def commands
73
+ [name] + aliases
74
+ end
75
+
76
+ def self.split_command_line(line)
77
+ line.strip.split(/\s+/, 2)
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,68 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ module Termtter
4
+ class Config
5
+ def initialize
6
+ @store = Hash.new(:undefined)
7
+ end
8
+
9
+ def inspect
10
+ @store.inspect
11
+ end
12
+
13
+ # set_default :: (Symbol | String) -> a -> IO ()
14
+ def set_default(name, value)
15
+ match_p, init, last = *name.to_s.match(/^(.+)\.([^\.]+)$/)
16
+ if match_p
17
+ tmp = eval(init)
18
+ if tmp.__refer__(last.to_sym).empty?
19
+ tmp.__assign__(last.to_sym, value)
20
+ end
21
+ else
22
+ __assign__(name.to_sym, value) if __refer__(name.to_sym).empty?
23
+ end
24
+ end
25
+
26
+ # empty? :: Boolean
27
+ def empty?
28
+ @store.empty?
29
+ end
30
+
31
+ def method_missing(name, *args)
32
+ case name.to_s
33
+ when /(.*)=$/
34
+ __assign__($1.to_sym, args.first)
35
+ else
36
+ __refer__(name.to_sym)
37
+ end
38
+ end
39
+
40
+ # __assign__ :: Symbol -> a -> IO ()
41
+ def __assign__(name, value)
42
+ @store[name] = value
43
+ end
44
+
45
+ # __refer__ :: Symbol -> IO a
46
+ def __refer__(name)
47
+ @store[name] == :undefined ? @store[name] = Termtter::Config.new : @store[name]
48
+ end
49
+
50
+ def __values__
51
+ @store.dup
52
+ end
53
+
54
+ __instance = self.new
55
+ (class << self; self end).
56
+ __send__(:define_method, :instance) { __instance }
57
+ end
58
+ end
59
+
60
+ def config
61
+ Termtter::Config.instance
62
+ end
63
+
64
+ def configatron
65
+ # remove this method until Termtter-1.2.0
66
+ warn "configatron method will be removed. Use config instead. (#{caller.first})"
67
+ Termtter::Config.instance
68
+ end
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ module ConfigSetup
5
+ module_function
6
+ def run
7
+ ui = create_highline
8
+ username = ui.ask('your twitter username: ')
9
+ password = ui.ask('your twitter password: ') { |q| q.echo = false }
10
+
11
+ Dir.mkdir(Termtter::CONF_DIR) unless File.exists?(Termtter::CONF_DIR)
12
+ File.open(Termtter::CONF_FILE, 'w') {|io|
13
+ io.puts '# -*- coding: utf-8 -*-'
14
+
15
+ io.puts
16
+ io.puts "config.user_name = '#{username}'"
17
+ io.puts "config.password = '#{password}'"
18
+ io.puts "#config.update_interval = 120"
19
+ io.puts "#config.proxy.host = 'proxy host'"
20
+ io.puts "#config.proxy.port = '8080'"
21
+ io.puts "#config.proxy.user_name = 'proxy user'"
22
+ io.puts "#config.proxy.password = 'proxy password'"
23
+ io.puts
24
+ plugins = Dir.glob(File.expand_path(File.dirname(__FILE__) + "/../plugins/*.rb")).map {|f|
25
+ f.match(%r|lib/plugins/(.*?).rb$|)[1]
26
+ }
27
+ plugins -= %w[stdout standard_plugins]
28
+ plugins.each do |p|
29
+ io.puts "#plugin '#{p}'"
30
+ end
31
+ io.puts
32
+ io.puts "# vim: set filetype=ruby"
33
+ }
34
+ puts "generated: ~/.termtter/config"
35
+ puts "enjoy!"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,41 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ class Connection
5
+ attr_reader :protocol, :port, :proxy_uri
6
+
7
+ def initialize
8
+ unless config.proxy.empty?
9
+ @proxy_host = config.proxy.host
10
+ @proxy_port = config.proxy.port
11
+ @proxy_user = config.proxy.user_name
12
+ @proxy_password = config.proxy.password
13
+ @proxy_uri = nil
14
+ @enable_ssl = config.enable_ssl
15
+ end
16
+ @protocol = "http"
17
+ @port = 80
18
+
19
+ if @proxy_host
20
+ @http_class = Net::HTTP::Proxy(@proxy_host, @proxy_port,
21
+ @proxy_user, @proxy_password)
22
+ @proxy_uri = "http://" + @proxy_host + ":" + @proxy_port + "/"
23
+ else
24
+ @http_class = Net::HTTP
25
+ end
26
+
27
+ if @enable_ssl
28
+ @protocol = "https"
29
+ @port = 443
30
+ end
31
+ end
32
+
33
+ def start(host, port, &block)
34
+ http = @http_class.new(host, port)
35
+ http.use_ssl = @enable_ssl
36
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl?
37
+ http.start(&block)
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ class Hook
5
+ attr_accessor :name, :points, :exec_proc
6
+
7
+ def initialize(args)
8
+ raise ArgumentError, ":name is not given." unless args.has_key?(:name)
9
+ @name = args[:name].to_sym
10
+ @points = args[:points] || [args[:point]].compact
11
+ @exec_proc = args[:exec_proc] || args[:exec] || lambda {}
12
+ end
13
+
14
+ def match?(point)
15
+ !points.select{|pt|
16
+ case pt
17
+ when String, Symbol
18
+ pt.to_s == point.to_s
19
+ when Regexp
20
+ (pt =~ point.to_s) ? true : false
21
+ else
22
+ false
23
+ end
24
+ }.empty?
25
+ end
26
+
27
+ def call(*args)
28
+ self.exec_proc.call(*args)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ OptionParser.new { |opt|
2
+ opt.on('-f', '--file config_file', 'Set path to configfile') do |val|
3
+ config.system.__assign__(:conf_file, val)
4
+ end
5
+ opt.on('-t', '--termtter-directory directory', 'Set termtter directory') do |val|
6
+ config.system.__assign__(:conf_dir, val)
7
+ end
8
+ opt.on('-d', '--devel', 'Start in developer mode') do |flg|
9
+ config.system.__assign__(:devel, true) if flg
10
+ end
11
+
12
+ Version = Termtter::VERSION
13
+ opt.parse!(ARGV)
14
+ }
@@ -0,0 +1,115 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ def plugin(name, init = {})
4
+ unless init.empty?
5
+ init.each do |key, value|
6
+ config.plugins.__refer__(name.to_sym).__assign__(key.to_sym, value)
7
+ end
8
+ end
9
+ load "plugins/#{name}.rb"
10
+ rescue Exception => e
11
+ Termtter::Client.handle_error(e)
12
+ end
13
+
14
+ def filter(name, init = {})
15
+ warn "filter method will be removed. Use plugin instead."
16
+ plugin(name, init)
17
+ end
18
+
19
+ def win?
20
+ RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
21
+ end
22
+
23
+ if win?
24
+ require 'iconv'
25
+ require 'Win32API'
26
+ $wGetACP = Win32API.new('kernel32','GetACP','','I')
27
+
28
+ $wSetConsoleTextAttribute = Win32API.new('kernel32','SetConsoleTextAttribute','II','I')
29
+ $wGetConsoleScreenBufferInfo = Win32API.new("kernel32", "GetConsoleScreenBufferInfo", ['l', 'p'], 'i')
30
+ $wGetStdHandle = Win32API.new('kernel32','GetStdHandle','I','I')
31
+ $wGetACP = Win32API.new('kernel32','GetACP','','I')
32
+
33
+ $hStdOut = $wGetStdHandle.call(0xFFFFFFF5)
34
+ lpBuffer = ' ' * 22
35
+ $wGetConsoleScreenBufferInfo.call($hStdOut, lpBuffer)
36
+ $oldColor = lpBuffer.unpack('SSSSSssssSS')[4]
37
+
38
+ $colorMap = {
39
+ 0 => 0x07|0x00|0x00|0x00, # black/white
40
+ 37 => 0x08|0x00|0x00|0x00, # white/intensity
41
+ 31 => 0x04|0x08|0x00|0x00, # red/red
42
+ 32 => 0x02|0x08|0x00|0x00, # green/green
43
+ 33 => 0x06|0x08|0x00|0x00, # yellow/yellow
44
+ 34 => 0x01|0x08|0x00|0x00, # blue/blue
45
+ 35 => 0x05|0x08|0x00|0x00, # magenta/purple
46
+ 36 => 0x03|0x08|0x00|0x00, # cyan/aqua
47
+ 39 => 0x07, # default
48
+ 40 => 0x00|0x00|0xf0|0x00, # background:white
49
+ 41 => 0x07|0x00|0x40|0x00, # background:red
50
+ 42 => 0x07|0x00|0x20|0x00, # background:green
51
+ 43 => 0x07|0x00|0x60|0x00, # background:yellow
52
+ 44 => 0x07|0x00|0x10|0x00, # background:blue
53
+ 45 => 0x07|0x00|0x50|0x80, # background:magenta
54
+ 46 => 0x07|0x00|0x30|0x80, # background:cyan
55
+ 47 => 0x07|0x00|0x70|0x80, # background:gray
56
+ 49 => 0x70, # default
57
+ 90 => 0x07|0x00|0x00|0x00, # erase/white
58
+ }
59
+ $iconv_u8_to_sj = Iconv.new("CP#{$wGetACP.call()}", 'UTF-8')
60
+ def print(str)
61
+ str.to_s.gsub("\xef\xbd\x9e", "\xe3\x80\x9c").split(/(\e\[\d*[a-zA-Z])/).each do |token|
62
+ case token
63
+ when /\e\[(\d+)m/
64
+ $wSetConsoleTextAttribute.call $hStdOut, $colorMap[$1.to_i].to_i
65
+ when /\e\[\d*[a-zA-Z]/
66
+ # do nothing
67
+ else
68
+ loop do
69
+ begin
70
+ STDOUT.print $iconv_u8_to_sj.iconv(token)
71
+ break
72
+ rescue Iconv::Failure
73
+ STDOUT.print "#{$!.success}?"
74
+ token = $!.failed[1..-1]
75
+ end
76
+ end
77
+ end
78
+ end
79
+ $wSetConsoleTextAttribute.call $hStdOut, $oldColor
80
+ $iconv_u8_to_sj.iconv(nil)
81
+ end
82
+ def puts(str)
83
+ print str
84
+ STDOUT.puts
85
+ end
86
+ end
87
+
88
+ unless Array.instance_methods.include?('take')
89
+ class Array
90
+ def take(n) self[0...n] end
91
+ end
92
+ end
93
+
94
+ unless Symbol.instance_methods.include?('to_proc')
95
+ class Symbol
96
+ def to_proc
97
+ Proc.new { |*args| args.shift.__send__(self, *args) }
98
+ end
99
+ end
100
+ end
101
+
102
+ require 'highline'
103
+ def create_highline
104
+ HighLine.track_eof = false
105
+ if $stdin.respond_to?(:getbyte) # for ruby1.9
106
+ require 'delegate'
107
+ stdin_for_highline = SimpleDelegator.new($stdin)
108
+ def stdin_for_highline.getc
109
+ getbyte
110
+ end
111
+ else
112
+ stdin_for_highline = $stdin
113
+ end
114
+ HighLine.new(stdin_for_highline)
115
+ end
@@ -0,0 +1,17 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ class Task
5
+ attr_accessor :name, :exec_at, :exec_proc, :interval, :work
6
+ def initialize(args = {}, &block)
7
+ @name = args[:name]
8
+ @exec_at = Time.now + (args[:after] || 0)
9
+ @interval = args[:interval]
10
+ @exec_proc = block || lambda {}
11
+ @work = true
12
+ end
13
+ def execute
14
+ exec_proc.call(self) if work
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,116 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Termtter
4
+ class TaskManager
5
+
6
+ INTERVAL = 1
7
+
8
+ def initialize()
9
+ @tasks = {}
10
+ @work = true
11
+ @mutex = Mutex.new
12
+ @pause = false
13
+ end
14
+
15
+ def pause
16
+ @pause = true
17
+ end
18
+
19
+ def resume
20
+ @pause = false
21
+ end
22
+
23
+ def kill
24
+ @work = false
25
+ end
26
+
27
+ def run
28
+ Thread.new do
29
+ while @work
30
+ step unless @pause
31
+ sleep INTERVAL
32
+ end
33
+ end
34
+ end
35
+
36
+ def step
37
+ pull_due_tasks.each do |task|
38
+ invoke_and_wait do
39
+ task.execute
40
+ end
41
+ end
42
+ end
43
+
44
+ def invoke_later
45
+ Thread.new do
46
+ invoke_and_wait do
47
+ yield
48
+ end
49
+ end
50
+ end
51
+
52
+ def invoke_and_wait(&block)
53
+ synchronize do
54
+ begin
55
+ yield
56
+ rescue Exception => e
57
+ Termtter::Client.handle_error(e)
58
+ end
59
+ end
60
+ end
61
+
62
+ def add_task(args = {}, &block)
63
+ synchronize do
64
+ task = Task.new(args, &block)
65
+ @tasks[task.name || task.object_id] = task
66
+ end
67
+ end
68
+
69
+ def get_task(key)
70
+ synchronize do
71
+ @tasks[key]
72
+ end
73
+ end
74
+
75
+ def delete_task(key)
76
+ synchronize do
77
+ @tasks.delete(key)
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def synchronize
84
+ unless Thread.current == @thread_in_sync
85
+ @mutex.synchronize do
86
+ @thread_in_sync = Thread.current
87
+ yield
88
+ end
89
+ else
90
+ yield
91
+ end
92
+ end
93
+
94
+ def pull_due_tasks()
95
+ synchronize do
96
+ time_now = Time.now
97
+ due_tasks = []
98
+ @tasks.delete_if do |key, task|
99
+ if task.work && task.exec_at <= time_now
100
+ due_tasks << task
101
+ if task.interval
102
+ task.exec_at = time_now + task.interval
103
+ false
104
+ else
105
+ true
106
+ end
107
+ else
108
+ false
109
+ end
110
+ end
111
+ return due_tasks
112
+ end
113
+ end
114
+
115
+ end
116
+ end