ruby-rescuetime 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +16 -0
  3. data/Rakefile +37 -0
  4. data/bin/ruby-rescuetime +6 -0
  5. data/lib/rescuetime.rb +16 -0
  6. data/lib/rescuetime/application.rb +152 -0
  7. data/lib/rescuetime/commands.rb +50 -0
  8. data/lib/rescuetime/config.rb +83 -0
  9. data/lib/rescuetime/debug.rb +18 -0
  10. data/lib/rescuetime/extension.rb +29 -0
  11. data/lib/rescuetime/extensions/chromium.rb +32 -0
  12. data/lib/rescuetime/extensions/gedit.rb +13 -0
  13. data/lib/rescuetime/loop.rb +97 -0
  14. data/lib/rescuetime/uploader.rb +79 -0
  15. data/lib/rescuetime/version.rb +3 -0
  16. data/lib/tasks/ruby-rescuetime_tasks.rake +4 -0
  17. data/test/application_test.rb +12 -0
  18. data/test/dummy/Rakefile +7 -0
  19. data/test/dummy/app/assets/javascripts/application.js +9 -0
  20. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  21. data/test/dummy/app/controllers/application_controller.rb +3 -0
  22. data/test/dummy/app/helpers/application_helper.rb +2 -0
  23. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  24. data/test/dummy/config.ru +4 -0
  25. data/test/dummy/config/application.rb +45 -0
  26. data/test/dummy/config/boot.rb +10 -0
  27. data/test/dummy/config/database.yml +25 -0
  28. data/test/dummy/config/environment.rb +5 -0
  29. data/test/dummy/config/environments/development.rb +30 -0
  30. data/test/dummy/config/environments/production.rb +60 -0
  31. data/test/dummy/config/environments/test.rb +39 -0
  32. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/test/dummy/config/initializers/inflections.rb +10 -0
  34. data/test/dummy/config/initializers/mime_types.rb +5 -0
  35. data/test/dummy/config/initializers/secret_token.rb +7 -0
  36. data/test/dummy/config/initializers/session_store.rb +8 -0
  37. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  38. data/test/dummy/config/locales/en.yml +5 -0
  39. data/test/dummy/config/routes.rb +58 -0
  40. data/test/dummy/db/test.sqlite3 +0 -0
  41. data/test/dummy/log/development.log +0 -0
  42. data/test/dummy/log/test.log +0 -0
  43. data/test/dummy/public/404.html +26 -0
  44. data/test/dummy/public/422.html +26 -0
  45. data/test/dummy/public/500.html +26 -0
  46. data/test/dummy/public/favicon.ico +0 -0
  47. data/test/dummy/script/rails +6 -0
  48. data/test/loop_test.rb +16 -0
  49. data/test/rescuetime_test.rb +8 -0
  50. data/test/test_helper.rb +10 -0
  51. metadata +180 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,16 @@
1
+ = RubyRescuetime
2
+
3
+ == Ruby port of: https://launchpad.net/rescuetime-linux-uploader
4
+ So, it's basically a inofficial uploader for:
5
+ https://www.rescuetime.com/
6
+
7
+ _It's probably running only on Ubuntu machines. (Feel free to test)_
8
+
9
+ == Installation:
10
+ gem install ruby-rescuetime
11
+
12
+ == Usage:
13
+ ruby-rescuetime --help
14
+
15
+ This project rocks and uses MIT-LICENSE.
16
+
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'RubyRescuetime'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task :default => :test
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # TODO: description
4
+
5
+ require 'rescuetime/commands'
6
+
data/lib/rescuetime.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Rescuetime
2
+ require 'rescuetime/debug'
3
+ require 'rescuetime/extension'
4
+
5
+ require 'rescuetime/application'
6
+ require 'rescuetime/config'
7
+ require 'rescuetime/loop'
8
+ require 'rescuetime/uploader'
9
+
10
+ # Load Extensions
11
+ Dir["#{File.dirname(__FILE__)}/rescuetime/extensions/**/*.rb"].each { |f| require f }
12
+
13
+ # Load Extensions defined in users home directory
14
+ Dir["#{Dir.home}/.ruby-rescuetime/extensions/**/*.rb"].each { |f| require f }
15
+ end
16
+
@@ -0,0 +1,152 @@
1
+ module Rescuetime
2
+ class Application
3
+ include Rescuetime::Debug
4
+
5
+ def self.current_application_name
6
+ cmd = <<-CMD
7
+ xprop -id `xprop -root |
8
+ awk '/_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |
9
+ awk -F = '/WM_CLASS/ {print $2; exit;}'|
10
+ awk '{print $2}' |
11
+ sed 's/^"//g' |
12
+ sed 's/"$//g'
13
+ CMD
14
+ `#{cmd}`.strip
15
+ end
16
+
17
+ def self.current_window_title
18
+ cmd = <<-CMD
19
+ xprop -id `xprop -root |
20
+ awk '/_NET_ACTIVE_WINDOW/ {print $5; exit;}'` |
21
+ awk -F = '/^WM_NAME/ {print $2; exit;}' |
22
+ sed -e's/^ *"//g' |
23
+ sed -e's/\\"$//g'
24
+ CMD
25
+ `#{cmd}`.strip
26
+ end
27
+
28
+ attr_reader :name, :title, :created_at, :finished_at
29
+ #protected_class_method :new
30
+
31
+ # TODO
32
+ def self.create(options = {})
33
+ name = options[:name] || self.current_application_name
34
+ klass = Rescuetime::Extension.get(name) || self
35
+ klass.new(options)
36
+ end
37
+
38
+
39
+
40
+ # Constructor: Call with {:debug => true} to get debug messages
41
+ def initialize(options = {})
42
+ @debug = options[:debug]
43
+ @name = options[:name] || current_application_name
44
+ @title = options[:title] || current_window_title
45
+
46
+ @created_at = Time.now
47
+ @finished_at = nil
48
+ @active = true
49
+ end
50
+
51
+ def name
52
+ @name.gsub("\000", "").gsub("'", "`")
53
+ end
54
+
55
+ def title
56
+ @title.gsub("\000", "").gsub("'", "`")
57
+ end
58
+
59
+ # Returns: Time of where app where detected to not be active anymore, or
60
+ # Time now if not finished yet
61
+ def finished_at
62
+ (@finished_at || Time.now).to_s[0..-7] # HACK: to remove offset (e.g. + 01:00)
63
+ end
64
+
65
+ def created_at
66
+ (@created_at || Time.now).to_s[0..-7] # HACK: to remove offset (e.g. + 01:00)
67
+ end
68
+
69
+ # Returns: boolean, if application is still active window
70
+ def active?
71
+ return @active unless @active
72
+
73
+ @active = @name == current_application_name &&
74
+ @title == current_window_title
75
+ finish! unless @active
76
+
77
+ return @active
78
+ end
79
+
80
+ def finished?
81
+ !active?
82
+ end
83
+
84
+ # Returns difference between StartTime and now if still active, or
85
+ # StartTime and FinishedTime if not ative anymore
86
+ def active_time
87
+ (active?) ? (Time.now - @created_at) : (@finished_at - @created_at)
88
+ end
89
+
90
+ def to_s
91
+ "#{name}:#{title}:#{extended_info}"
92
+ end
93
+
94
+ def extended_info
95
+ (@extended_info || "").gsub("\000", "").gsub("'", "`")
96
+ end
97
+
98
+ def os_username
99
+ @os_username ||= `uname -n`.strip + "\\" + `id -un`.strip
100
+ end
101
+
102
+ # TODO
103
+ def to_upload_data
104
+ return "" if name.empty?
105
+
106
+ out = "- os_username: '#{os_username}'\n"
107
+ out += " app_name: '#{name}'\n"
108
+ out += " window_title: '#{title}'\n"
109
+ out += " extended_info: '#{extended_info}'\n"
110
+ out += " start_time: #{created_at}\n"
111
+ out += " end_time: #{finished_at}\n"
112
+
113
+ return out
114
+ end
115
+
116
+
117
+
118
+ private
119
+ def finish!
120
+ @active = false
121
+ @finished_at = Time.now
122
+ end
123
+
124
+ def current_application_name
125
+ application_name(self.class.current_application_name)
126
+ end
127
+
128
+ def current_window_title
129
+ window_title(self.class.current_window_title)
130
+ end
131
+
132
+ # To be overwritten
133
+ def application_name(name)
134
+ name
135
+ end
136
+
137
+ # To be overwritten
138
+ def window_title(title)
139
+ title
140
+ end
141
+ end
142
+ end
143
+
144
+
145
+
146
+ #- os_username: 'werbeboten-HP-Pavilion-g6-Notebook-PC\werbeboten'
147
+ # app_name: 'werbeboten@werbeboten-HP-Pavilion-g6-Notebook-PC: ~/Dev/Rails3/BuecherdeParser'
148
+ # window_title: 'werbeboten@werbeboten-HP-Pavilion-g6-Notebook-PC: ~/Dev/Rails3/BuecherdeParser'
149
+ # extended_info: ''
150
+ # start_time: 2012-02-10 11:56:52
151
+ # end_time: 2012-02-10 11:56:57
152
+
@@ -0,0 +1,50 @@
1
+ require 'rescuetime'
2
+ require 'optparse'
3
+
4
+ # This hash will hold all of the options
5
+ # parsed from the command-line by OptionParser.
6
+ options = {}
7
+
8
+ optparse = OptionParser.new do|opts|
9
+ # Set a banner, displayed at the top of the help screen.
10
+ opts.banner = "Usage: ruby-rescuetime [options]"
11
+
12
+ # Define the options, and what they do
13
+ opts.on( '-d', '--debug', 'View debug messages' ) do
14
+ options[:debug] = true
15
+ end
16
+
17
+ opts.on( '-u', '--email EMAIL', 'Your email login used.' ) do |email|
18
+ options[:email] = email
19
+ end
20
+
21
+ opts.on( '-p', '--password PASSWORD', 'Your password used.' ) do |password|
22
+ options[:password] = password
23
+ end
24
+
25
+ options[:config] = File.join(Dir.home, ".ruby-rescuetime", "config.yml")
26
+ opts.on( '-c', '--config FILE', 'Path to your config-file. (Default: ~/.ruby-rescuetime/config.yml)' ) do |config|
27
+ options[:config] = config
28
+ end
29
+
30
+ options[:path] = File.join(Dir.home, ".ruby-rescuetime")
31
+ opts.on('--path PATH', 'Path to your config directory. (Default: ~/.ruby-rescuetime/)' ) do |path|
32
+ options[:path] = path
33
+ end
34
+
35
+ # This displays the help screen, all programs are assumed to have this option.
36
+ opts.on( '-h', '--help', 'Display this screen' ) do
37
+ puts opts
38
+ exit
39
+ end
40
+ end
41
+
42
+ # Parse the command-line. Remember there are two forms
43
+ # of the parse method. The 'parse' method simply parses
44
+ # ARGV, while the 'parse!' method parses ARGV and removes
45
+ # any options found there, as well as any parameters for
46
+ # the options. What's left is the list of files to resize.
47
+ optparse.parse!
48
+
49
+ Rescuetime::Loop.new(options)
50
+
@@ -0,0 +1,83 @@
1
+ module Rescuetime
2
+ class Config
3
+ include Rescuetime::Debug
4
+ require 'fileutils'
5
+ require 'yaml'
6
+
7
+ DEFAULT_PATH = File.join(Dir.home, ".ruby-rescuetime")
8
+ DEFAULT_FILE = "config.yml"
9
+
10
+ DEFAULT_CONFIG = {
11
+ :email => "foo@example.com",
12
+ :password => ""
13
+ }
14
+
15
+ # Constructor
16
+ def initialize(options = {})
17
+ options = {
18
+ :debug => false,
19
+ :email => nil,
20
+ :password => nil,
21
+ :config => File.join(DEFAULT_PATH, DEFAULT_FILE),
22
+ :path => nil
23
+ }.merge(options)
24
+
25
+ @debug = options[:debug]
26
+ @config_path = options[:config] || File.join(options[:path] || DEFAULT_PATH, DEFAULT_FILE)
27
+ config = read_config(@config_path)
28
+
29
+ @config = {
30
+ :email => options[:email] || config[:email],
31
+ :password => options[:password] || config[:password],
32
+ :path => DEFAULT_PATH || config[:path]
33
+ }
34
+ update if @config != config
35
+ end
36
+
37
+ def email
38
+ @config[:email]
39
+ end
40
+
41
+ def password
42
+ @config[:password]
43
+ end
44
+
45
+ # Path where to store data
46
+ def path
47
+ @config[:path]
48
+ end
49
+
50
+ def location
51
+ @config_path
52
+ end
53
+
54
+ # Write current config to disc
55
+ def update
56
+ update_config(@config, @config_path)
57
+ end
58
+
59
+
60
+
61
+ private
62
+ def read_config(path)
63
+ create_config_file(path) unless File.exist?(path)
64
+ YAML::load(File.open(path))
65
+ end
66
+
67
+ def create_config_file(path)
68
+ write_config_file(DEFAULT_CONFIG, path)
69
+ end
70
+
71
+ def update_config(config, path)
72
+ write_config_file(config, path)
73
+ end
74
+
75
+ def write_config_file(config, path)
76
+ FileUtils.mkdir_p(File.dirname(path))
77
+ File.open(path, 'w') do |f|
78
+ f.write(YAML::dump(config))
79
+ end
80
+ end
81
+ end
82
+ end
83
+
@@ -0,0 +1,18 @@
1
+ module Rescuetime
2
+ module Debug
3
+ # Debug-mode turned on?
4
+ def debug?
5
+ @debug == true
6
+ end
7
+
8
+ private
9
+ # Debug-Wrapper
10
+ def debug(msg = nil, &block)
11
+ return unless debug?
12
+
13
+ puts msg if msg
14
+ yield if block_given?
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,29 @@
1
+ module Rescuetime
2
+ module Extension
3
+ @extensions = {}
4
+
5
+ def self.included(klass)
6
+ # TODO: raise "No APPLICATION constant defined."
7
+
8
+ app = klass::APPLICATION.to_s
9
+ if @extensions[app]
10
+ warn <<-WARN
11
+ Extension for given APPLICATION (#{app}) allready exists.
12
+ Class: #{klass}
13
+ Trace: #{caller.first.inspect}
14
+ WARN
15
+ end
16
+
17
+ @extensions[app] = klass
18
+ end
19
+
20
+ def self.extensions
21
+ @extensions
22
+ end
23
+
24
+ def self.get(key)
25
+ @extensions[key.to_s]
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,32 @@
1
+ class Rescuetime::Chromium < Rescuetime::Application
2
+ APPLICATION = "Chromium-browser"
3
+ include Rescuetime::Extension
4
+ include Rescuetime::Debug
5
+
6
+ def window_title(given_title)
7
+ title = given_title.gsub(/- Chromium$/, '').strip
8
+ t = title.downcase
9
+ if t["google mail"]
10
+ return "http://www.mail.google.com"
11
+ elsif t["twitter"]
12
+ return "http://www.twitter.com"
13
+ elsif t["facebook"]
14
+ return "http://www.facebook.com"
15
+ else
16
+ return t
17
+ end
18
+ end
19
+
20
+ alias :old_name :name
21
+ def name
22
+ ["google mail", "twitter", "facebook"].each do |e|
23
+ return "#{e} - chromium" if title[e]
24
+ end
25
+ "#{title} - chromium"
26
+ end
27
+
28
+ # def extended_info
29
+ # title
30
+ # end
31
+ end
32
+