pidgin2adium 3.1.1 → 3.2.0

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.
data/Rakefile CHANGED
@@ -1,19 +1,21 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
+ require './lib/version.rb'
3
4
 
4
5
  begin
5
6
  require 'jeweler'
6
7
  Jeweler::Tasks.new do |gem|
7
8
  gem.name = "pidgin2adium"
9
+ gem.version = Pidgin2Adium::VERSION
8
10
  gem.summary = %Q{Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the Adium format}
9
11
  gem.description = %Q{Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the Adium format.}
10
12
  gem.email = "gbw@brandeis.edu"
11
13
  gem.homepage = "http://github.com/gabebw/pidgin2adium"
12
14
  gem.authors = ["Gabe Berke-Williams"]
13
15
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
- gem.add_development_dependency(%q<bundler>, [">= 0.9.26"])
16
+ gem.add_development_dependency(%q<bundler>, [">= 1.0.0"])
15
17
  gem.add_development_dependency(%q<jeweler>, [">= 0"])
16
- gem.add_development_dependency(%q<rspec>, [">= 1.2.9"])
18
+ gem.add_development_dependency(%q<rspec>, [">= 1.3.0"])
17
19
  end
18
20
  Jeweler::GemcutterTasks.new
19
21
  rescue LoadError
@@ -22,22 +24,22 @@ end
22
24
 
23
25
  begin
24
26
  # RSpec 2
25
- gem "rspec", ">= 2.0.0.beta.18"
27
+ gem "rspec", ">= 2.0.0"
26
28
  require 'rspec/core/rake_task'
27
29
 
28
30
  RSpec::Core::RakeTask.new(:spec) do |spec|
29
- spec.spec_opts << %w{-Ilib -Ispec}
31
+ spec.rspec_opts = %w{-Ilib -Ispec}
30
32
  spec.pattern = 'spec/**/*_spec.rb'
31
33
  end
32
34
 
33
35
  RSpec::Core::RakeTask.new(:rcov) do |spec|
34
- spec.spec_opts << %w{-Ilib -Ispec}
36
+ spec.rspec_opts = %w{-Ilib -Ispec}
35
37
  spec.pattern = 'spec/**/*_spec.rb'
36
38
  spec.rcov = true
37
39
  end
38
40
  rescue Gem::LoadError
39
41
  # RSpec 1
40
- gem "rspec"
42
+ gem "rspec", "~> 1.3.0"
41
43
  require 'spec/rake/spectask'
42
44
 
43
45
  Spec::Rake::SpecTask.new(:spec) do |spec|
@@ -50,6 +52,9 @@ rescue Gem::LoadError
50
52
  spec.pattern = 'spec/**/*_spec.rb'
51
53
  spec.rcov = true
52
54
  end
55
+ rescue Gem::LoadError => bang
56
+ puts "!! Please install RSpec: `gem install rspec`"
57
+ raise bang
53
58
  end
54
59
 
55
60
  task :spec => :check_dependencies
@@ -59,7 +64,7 @@ task :default => :spec
59
64
 
60
65
  require 'rake/rdoctask'
61
66
  Rake::RDocTask.new do |rdoc|
62
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
67
+ version = Pidgin2Adium::VERSION
63
68
 
64
69
  rdoc.rdoc_dir = 'rdoc'
65
70
  rdoc.title = "pidgin2adium #{version}"
data/lib/pidgin2adium.rb CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  require 'fileutils'
7
7
  require 'time'
8
+ require 'version'
8
9
  require 'pidgin2adium/parsers/all'
9
10
 
10
11
  module Pidgin2Adium
@@ -13,124 +14,121 @@ module Pidgin2Adium
13
14
  ADIUM_LOG_DIR = File.expand_path('~/Library/Application Support/Adium 2.0/Users/Default/Logs/') << '/'
14
15
  # These files/directories show up in Dir.entries()
15
16
  BAD_DIRS = %w{. .. .DS_Store Thumbs.db .system}
16
- VERSION = "3.1.0"
17
- # "-0500" (3d rather than 2d to allow for "+")
18
- DEFAULT_TZ_OFFSET = sprintf('%+03d00', Time.zone_offset(Time.now.zone) / 3600)
19
17
  # For displaying after we finish converting
20
18
  @@oops_messages = []
21
19
  @@error_messages = []
22
20
 
23
- def log_msg(str) #:nodoc:
24
- puts str.to_s
25
- end
26
-
27
- def oops(str) #:nodoc:
28
- @@oops_messages << str
29
- warn("Oops: #{str}")
30
- end
21
+ def log_msg(str) #:nodoc:
22
+ puts str.to_s
23
+ end
31
24
 
32
- def error(str) #:nodoc:
33
- @@error_messages << str
34
- warn("Error: #{str}")
35
- end
25
+ def oops(str) #:nodoc:
26
+ @@oops_messages << str
27
+ warn("Oops: #{str}")
28
+ end
36
29
 
37
- #######################
38
- #So that we can use log_msg when calling delete_search_indexes() by itself
39
- module_function :log_msg, :oops, :error
40
- #######################
30
+ def error(str) #:nodoc:
31
+ @@error_messages << str
32
+ warn("Error: #{str}")
33
+ end
41
34
 
42
- # Parses the provided log.
43
- # Returns a LogFile instance or false if an error occurred.
44
- def parse(logfile_path, my_aliases)
45
- logfile_path = File.expand_path(logfile_path)
46
- ext = File.extname(logfile_path).sub('.', '').downcase
35
+ #######################
36
+ #So that we can use log_msg when calling delete_search_indexes() by itself
37
+ module_function :log_msg, :oops, :error
38
+ #######################
47
39
 
48
- if(ext == "html" || ext == "htm")
49
- parser = HtmlLogParser.new(logfile_path, my_aliases)
50
- elsif(ext == "txt")
51
- parser = TextLogParser.new(logfile_path, my_aliases)
52
- else
53
- error("Doing nothing, logfile is not a text or html file. Path: #{logfile_path}.")
54
- return false
55
- end
40
+ # Parses the provided log.
41
+ # Returns a LogFile instance or false if an error occurred.
42
+ def parse(logfile_path, my_aliases)
43
+ logfile_path = File.expand_path(logfile_path)
44
+ ext = File.extname(logfile_path).sub('.', '').downcase
56
45
 
57
- return parser.parse()
46
+ if(ext == "html" || ext == "htm")
47
+ parser = HtmlLogParser.new(logfile_path, my_aliases)
48
+ elsif(ext == "txt")
49
+ parser = TextLogParser.new(logfile_path, my_aliases)
50
+ else
51
+ error("Doing nothing, logfile is not a text or html file. Path: #{logfile_path}.")
52
+ return false
58
53
  end
59
54
 
60
- # Parses the provided log and writes out the log in Adium format.
61
- # Returns:
62
- # * true if it successfully converted and wrote out the log,
63
- # * false if an error occurred, or
64
- # * Pidgin2Adium::FILE_EXISTS if file already exists AND
65
- # opts[:overwrite] = false.
66
- #
67
- # You can add options using the _opts_ hash, which can have the following
68
- # keys, all of which are optional:
69
- # * *overwrite*: If true, then overwrite even if log is found.
70
- # Defaults to false.
71
- # * *output_dir*: The top-level dir to put the logs in.
72
- # Logs under output_dir are still each in their own folders, etc.
73
- # Defaults to Pidgin2Adium::ADIUM_LOG_DIR
74
- def parse_and_generate(logfile_path, my_aliases, opts = {})
75
- opts = {} unless opts.is_a?(Hash)
76
- overwrite = !!opts[:overwrite]
77
- if opts.key?(:output_dir)
78
- output_dir = opts[:output_dir]
79
- else
80
- output_dir = ADIUM_LOG_DIR
81
- end
55
+ return parser.parse()
56
+ end
82
57
 
83
- unless File.directory?(output_dir)
84
- puts "Output log directory (#{output_dir}) does not exist or is not a directory."
85
- begin
86
- FileUtils.mkdir_p(output_dir)
87
- rescue Errno::EACCES
88
- puts "Permission denied, could not create output directory (#{output_dir})"
89
- return false
90
- end
91
- end
58
+ # Parses the provided log and writes out the log in Adium format.
59
+ # Returns:
60
+ # * true if it successfully converted and wrote out the log,
61
+ # * false if an error occurred, or
62
+ # * Pidgin2Adium::FILE_EXISTS if file already exists AND
63
+ # opts[:overwrite] = false.
64
+ #
65
+ # You can add options using the _opts_ hash, which can have the following
66
+ # keys, all of which are optional:
67
+ # * *overwrite*: If true, then overwrite even if log is found.
68
+ # Defaults to false.
69
+ # * *output_dir*: The top-level dir to put the logs in.
70
+ # Logs under output_dir are still each in their own folders, etc.
71
+ # Defaults to Pidgin2Adium::ADIUM_LOG_DIR
72
+ def parse_and_generate(logfile_path, my_aliases, opts = {})
73
+ opts = {} unless opts.is_a?(Hash)
74
+ overwrite = !!opts[:overwrite]
75
+ if opts.key?(:output_dir)
76
+ output_dir = opts[:output_dir]
77
+ else
78
+ output_dir = ADIUM_LOG_DIR
79
+ end
92
80
 
93
- logfile_obj = parse(logfile_path, my_aliases)
94
- return false if logfile_obj == false
95
- dest_file_path = logfile_obj.write_out(overwrite, output_dir)
96
- if dest_file_path == false
97
- error("Successfully parsed file, but failed to write it out. Path: #{logfile_path}.")
81
+ unless File.directory?(output_dir)
82
+ puts "Output log directory (#{output_dir}) does not exist or is not a directory."
83
+ begin
84
+ FileUtils.mkdir_p(output_dir)
85
+ rescue Errno::EACCES
86
+ puts "Permission denied, could not create output directory (#{output_dir})"
98
87
  return false
99
- elsif dest_file_path == FILE_EXISTS
100
- log_msg("File already exists.")
101
- return FILE_EXISTS
102
- else
103
- log_msg("Output to: #{dest_file_path}")
104
- return true
105
88
  end
106
89
  end
107
90
 
108
- # Newly-converted logs are viewable in the Adium Chat Transcript
109
- # Viewer, but are not indexed, so a search of the logs doesn't give
110
- # results from the converted logs. To fix this, we delete the cached log
111
- # indexes, which forces Adium to re-index.
112
- #
113
- # Note: This function is run by LogConverter after converting all of its
114
- # files. LogFile.write_out intentionally does _not_ run it in order to
115
- # allow for batch-processing of files. Thus, you will probably want to run
116
- # Pidgin2Adium.delete_search_indexes after running LogFile.write_out in
117
- # your own scripts.
118
- def delete_search_indexes()
119
- log_msg "Deleting log search indexes in order to force re-indexing of imported logs..."
120
- dirty_file = File.expand_path("~/Library/Caches/Adium/Default/DirtyLogs.plist")
121
- log_index_file = File.expand_path("~/Library/Caches/Adium/Default/Logs.index")
122
- [dirty_file, log_index_file].each do |f|
123
- if File.exist?(f)
124
- if File.writable?(f)
125
- File.delete(f)
126
- else
127
- error("File exists but is not writable. Please delete it yourself: #{f}")
128
- end
91
+ logfile_obj = parse(logfile_path, my_aliases)
92
+ return false if logfile_obj == false
93
+ dest_file_path = logfile_obj.write_out(overwrite, output_dir)
94
+ if dest_file_path == false
95
+ error("Successfully parsed file, but failed to write it out. Path: #{logfile_path}.")
96
+ return false
97
+ elsif dest_file_path == FILE_EXISTS
98
+ log_msg("File already exists.")
99
+ return FILE_EXISTS
100
+ else
101
+ log_msg("Output to: #{dest_file_path}")
102
+ return true
103
+ end
104
+ end
105
+
106
+ # Newly-converted logs are viewable in the Adium Chat Transcript
107
+ # Viewer, but are not indexed, so a search of the logs doesn't give
108
+ # results from the converted logs. To fix this, we delete the cached log
109
+ # indexes, which forces Adium to re-index.
110
+ #
111
+ # Note: This function is run by LogConverter after converting all of its
112
+ # files. LogFile.write_out intentionally does _not_ run it in order to
113
+ # allow for batch-processing of files. Thus, you will probably want to run
114
+ # Pidgin2Adium.delete_search_indexes after running LogFile.write_out in
115
+ # your own scripts.
116
+ def delete_search_indexes()
117
+ log_msg "Deleting log search indexes in order to force re-indexing of imported logs..."
118
+ dirty_file = File.expand_path("~/Library/Caches/Adium/Default/DirtyLogs.plist")
119
+ log_index_file = File.expand_path("~/Library/Caches/Adium/Default/Logs.index")
120
+ [dirty_file, log_index_file].each do |f|
121
+ if File.exist?(f)
122
+ if File.writable?(f)
123
+ File.delete(f)
124
+ else
125
+ error("File exists but is not writable. Please delete it yourself: #{f}")
129
126
  end
130
127
  end
131
- log_msg "...done."
132
- log_msg "When you next start the Adium Chat Transcript Viewer, it will re-index the logs, which may take a while."
133
128
  end
129
+ log_msg "...done."
130
+ log_msg "When you next start the Adium Chat Transcript Viewer, it will re-index the logs, which may take a while."
131
+ end
134
132
 
135
- module_function :parse, :parse_and_generate, :delete_search_indexes
133
+ module_function :parse, :parse_and_generate, :delete_search_indexes
136
134
  end
@@ -41,11 +41,8 @@ module Pidgin2Adium
41
41
 
42
42
  # Returns contents of log file
43
43
  def to_s
44
- if @chat_str.nil?
45
- # Faster than inject() or each()
46
- @chat_str = @chat_lines.map{|l| l.to_s }.join
47
- end
48
- return @chat_str
44
+ # Faster than inject() or each()
45
+ @chat_str ||= @chat_lines.map{|l| l.to_s }.join
49
46
  end
50
47
 
51
48
  def each(&blk)
@@ -8,15 +8,32 @@ module Pidgin2Adium
8
8
  # appropriate for putting in an Adium log file.
9
9
  # Subclasses: XMLMessage, AutoReplyMessage, StatusMessage, Event.
10
10
  class Message
11
+ include Comparable
11
12
  def initialize(sender, time, buddy_alias)
12
13
  # The sender's screen name
13
14
  @sender = sender
14
15
  # The time the message was sent, in Adium format (e.g.
15
16
  # "2008-10-05T22:26:20-0800")
16
17
  @time = time
18
+ @time_object = Time.parse(@time)
17
19
  # The receiver's alias (NOT screen name)
18
20
  @buddy_alias = buddy_alias
19
21
  end
20
22
  attr_accessor :sender, :time, :buddy_alias
23
+
24
+ # Compare this Message to +other_message+, based on their timestamps.
25
+ # Returns a number < 0 if this message was sent before +other_message+,
26
+ # 0 if they were sent at the same time, and a number > 0 if this message
27
+ # was sent after +other_message+.
28
+ def <=>(other_message)
29
+ return @time_object - other_message.time_object
30
+ end
31
+
32
+ protected
33
+ # Protected because Time.parse doesn't have exactly the right time
34
+ # zone. It works fine for <=>, though.
35
+ def time_object
36
+ return @time_object
37
+ end
21
38
  end
22
39
  end
@@ -34,8 +34,6 @@ module Pidgin2Adium
34
34
  # us an alias.
35
35
  @user_alias = user_aliases.split(',')[0]
36
36
 
37
- @tz_offset = get_time_zone_offset()
38
-
39
37
  @log_file_is_valid = true
40
38
  begin
41
39
  file = File.new(@src_path, 'r')
@@ -48,28 +46,20 @@ module Pidgin2Adium
48
46
  return nil
49
47
  end
50
48
 
51
- # Time regexes must be set before pre_parse().
52
- # "4/18/2007 11:02:00 AM" => %w{4, 18, 2007, 11, 02, 00, AM}
49
+ # Time regexes must be set before pre_parse!().
50
+ # "4/18/2007 11:02:00 AM" => %w{4, 18, 2007}
53
51
  # ONLY used (if at all) in first line of chat ("Conversation with...at...")
54
- @time_regex_first_line = %r{^(\d{1,2})/(\d{1,2})/(\d{4}) (\d{1,2}):(\d{2}):(\d{2}) ([AP]M)$}
55
- # "2007-04-17 12:33:13" => %w{2007, 04, 17, 12, 33, 13}
56
- @time_regex = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/
52
+ @time_regex_first_line = %r{^(\d{1,2})/(\d{1,2})/(\d{4}) \d{1,2}:\d{2}:\d{2} [AP]M$}
53
+ # "2007-04-17 12:33:13" => %w{2007, 04, 17}
54
+ @time_regex = /^(\d{4})-(\d{2})-(\d{2}) \d{2}:\d{2}:\d{2}$/
57
55
 
58
56
  begin
59
- @service,
60
- @user_SN,
61
- @partner_SN,
62
- # @basic_time_info is for files that only have the full
63
- # timestamp at the top; we can use it to fill in the minimal
64
- # per-line timestamps. It is a hash with 3 keys:
65
- # * :year
66
- # * :mon
67
- # * :mday (day of month)
68
- # You should be able to fill everything else in. If you can't,
69
- # something's wrong.
70
- @basic_time_info,
71
- # When the chat started, in Adium's format
72
- @adium_chat_time_start = pre_parse()
57
+ successfully_set_variables = pre_parse!
58
+ if not successfully_set_variables
59
+ error("Failed to set some key variables: #{@src_path}")
60
+ @log_file_is_valid = false
61
+ return
62
+ end
73
63
  rescue InvalidFirstLineError
74
64
  # The first line isn't parseable
75
65
  @log_file_is_valid = false
@@ -173,119 +163,76 @@ module Pidgin2Adium
173
163
  return LogFile.new(@file_content, @service, @user_SN, @partner_SN, @adium_chat_time_start)
174
164
  end
175
165
 
176
- def get_time_zone_offset()
177
- # We must have a tz_offset or else the Adium Chat Log viewer
178
- # doesn't read the date correctly and then:
179
- # 1) the log has an empty start date column in the viewer
180
- # 2) The timestamps are all the same for the whole log
181
- tz_match = /([-\+]\d+)[A-Z]{3}\.(?:txt|htm|html)/.match(@src_path)
182
- if tz_match and tz_match[1]
183
- tz_offset = tz_match[1]
184
- else
185
- tz_offset = Pidgin2Adium::DEFAULT_TZ_OFFSET
186
- end
187
- return tz_offset
166
+ # Returns a Time object, or nil if the format string doesn't match the
167
+ # time string.
168
+ def strptime(time, format)
169
+ date_hash = Date._strptime(time, format)
170
+ return nil if date_hash.nil?
171
+ # Fill in any blanks using @basic_time_info
172
+ date_hash = @basic_time_info.merge(date_hash)
173
+ time = Time.local(date_hash[:year], date_hash[:mon], date_hash[:mday],
174
+ date_hash[:hour], date_hash[:min], date_hash[:sec],
175
+ date_hash[:sec_fraction], date_hash[:zone])
176
+ time
188
177
  end
189
178
 
190
- def try_to_parse_first_line_time(first_line_time)
191
- formats = [
192
- "%m/%d/%Y %I:%M:%S %P", # 01/22/2008 03:01:45 PM
193
- "%Y-%m-%d %H:%M:%S" # 2008-01-22 23:08:24
194
- ]
179
+ # Tries to parse _time_ (a string) according to the formats in _formats_, which
180
+ # should be an array of strings. For more on acceptable format strings,
181
+ # see the official documentation for Time.strptime. Returns a Time
182
+ # object or nil (if no formats matched).
183
+ def try_to_parse_time_with_formats(time, formats)
195
184
  parsed = nil
196
185
  formats.each do |format|
197
- begin
198
- parsed = Time.strptime(first_line_time, format)
199
- break
200
- rescue ArgumentError
201
- end
186
+ parsed = strptime(time, format)
187
+ break unless parsed.nil?
202
188
  end
203
189
  parsed
204
190
  end
205
191
 
206
192
  def try_to_parse_time(time)
207
193
  formats = [
194
+ "%m/%d/%Y %I:%M:%S %P", # 01/22/2008 03:01:45 PM
195
+ "%Y-%m-%d %H:%M:%S", # 2008-01-22 23:08:24
208
196
  "%Y/%m/%d %H:%M:%S", # 2008/01/22 04:01:45
209
- "%Y-%m-%d %H:%M:%S" # 2008-01-22 04:01:45
197
+ "%Y-%m-%d %H:%M:%S", # 2008-01-22 04:01:45
198
+ '%a %d %b %Y %H:%M:%S %p %Z' # "Sat 18 Apr 2009 10:43:35 AM PDT"
210
199
  ]
211
- parsed = nil
212
- formats.each do |format|
213
- begin
214
- parsed = Time.strptime(time, format)
215
- break
216
- rescue ArgumentError
217
- end
218
- end
219
- parsed
200
+ try_to_parse_time_with_formats(time, formats)
220
201
  end
221
202
 
222
203
  def try_to_parse_minimal_time(minimal_time)
223
- # 04:01:45 AM
224
- minimal_format_with_ampm = "%I:%M:%S %P"
225
- # 23:01:45
226
- minimal_format_without_ampm = "%H:%M:%S"
227
-
228
- time_hash = nil
204
+ formats = [
205
+ "%I:%M:%S %P", # 04:01:45 AM
206
+ "%H:%M:%S" # 23:01:45
207
+ ]
229
208
 
230
- # Use Date._strptime to allow filling in the blanks on minimal
231
- # timestamps
232
- if minimal_time =~ /[AP]M$/
233
- time_hash = Date._strptime(minimal_time, minimal_format_with_ampm)
234
- else
235
- time_hash = Date._strptime(minimal_time, minimal_format_without_ampm)
236
- end
237
- if time_hash.nil?
238
- # Date._strptime returns nil on failure
239
- return nil
240
- end
241
- # Fill in the blanks
242
- time_hash[:year] = @basic_time_info[:year]
243
- time_hash[:mon] = @basic_time_info[:mon]
244
- time_hash[:mday] = @basic_time_info[:mday]
245
- new_time = Time.local(time_hash[:year],
246
- time_hash[:mon],
247
- time_hash[:mday],
248
- time_hash[:hour],
249
- time_hash[:min],
250
- time_hash[:sec])
251
- new_time
209
+ try_to_parse_time_with_formats(minimal_time, formats)
252
210
  end
253
211
 
254
-
255
- #--
256
- # Adium time format: YYYY-MM-DD\THH:MM:SS[+-]TZ_HRS like:
257
- # 2008-10-05T22:26:20-0800
258
- # HOWEVER:
259
- # If it's the first line, then return it like this (note periods):
260
- # 2008-10-05T22.26.20-0800
261
- # because it will be used in the filename.
262
- #++
263
212
  # Converts a pidgin datestamp to an Adium one.
264
213
  # Returns a string representation of _time_ or
265
214
  # nil if it couldn't parse the provided _time_.
266
- def create_adium_time(time, is_first_line = false)
215
+ def create_adium_time(time)
267
216
  return nil if time.nil?
268
- if is_first_line
269
- new_time = try_to_parse_first_line_time(time)
270
- else
271
- new_time = try_to_parse_time(time)
272
- if new_time.nil?
273
- new_time = try_to_parse_minimal_time(time)
274
- end
217
+ new_time = try_to_parse_time(time)
218
+ if new_time.nil?
219
+ new_time = try_to_parse_minimal_time(time)
275
220
  end
276
221
 
277
222
  return nil if new_time.nil?
278
223
 
279
- if is_first_line
280
- adium_time = new_time.strftime("%Y-%m-%dT%H.%M.%S#{@tz_offset}")
281
- else
282
- adium_time = new_time.strftime("%Y-%m-%dT%H:%M:%S#{@tz_offset}")
283
- end
284
- adium_time
224
+ new_time.xmlschema
285
225
  end
286
226
 
287
- # Extract required data from the file. Run by parse.
288
- def pre_parse
227
+ # Extract required data from the file. Run by parse. Sets these
228
+ # variables:
229
+ # * @service
230
+ # * @user_SN
231
+ # * @partner_SN
232
+ # * @basic_time_info
233
+ # * @adium_chat_time_start
234
+ # Returns true if none of these variables are false or nil.
235
+ def pre_parse!
289
236
  # Deal with first line.
290
237
 
291
238
  # the first line is special. It tells us (in order of regex groups):
@@ -297,27 +244,43 @@ module Pidgin2Adium
297
244
  if first_line_match.nil?
298
245
  raise InvalidFirstLineError
299
246
  else
300
- service = first_line_match[4]
247
+ # first_line_match is like so:
248
+ # ["Conversation with BUDDY_PERSON at 2006-12-21 22:36:06 on awesome SN (aim)",
249
+ # "BUDDY_PERSON",
250
+ # "2006-12-21 22:36:06",
251
+ # "awesome SN",
252
+ # "aim"]
253
+ @service = first_line_match[4]
301
254
  # @user_SN is normalized to avoid "AIM.name" and "AIM.na me" folders
302
- user_SN = first_line_match[3].downcase.tr(' ', '')
303
- partner_SN = first_line_match[1]
255
+ @user_SN = first_line_match[3].downcase.tr(' ', '')
256
+ @partner_SN = first_line_match[1]
304
257
  pidgin_chat_time_start = first_line_match[2]
305
- basic_time_info = case pidgin_chat_time_start
306
- when @time_regex
307
- {:year => $1.to_i,
308
- :mon => $2.to_i,
309
- :mday => $3.to_i}
310
- when @time_regex_first_line
311
- {:year => $3.to_i,
312
- :mon => $1.to_i,
313
- :mday => $2.to_i}
314
- end
315
- adium_chat_time_start = create_adium_time(pidgin_chat_time_start, true)
316
- return [service,
317
- user_SN,
318
- partner_SN,
319
- basic_time_info,
320
- adium_chat_time_start]
258
+ # @basic_time_info is for files that only have the full
259
+ # timestamp at the top; we can use it to fill in the minimal
260
+ # per-line timestamps. It is a hash with 3 keys:
261
+ # * :year
262
+ # * :mon
263
+ # * :mday (day of month)
264
+ # You should be able to fill everything else in. If you can't,
265
+ # something's wrong.
266
+ @basic_time_info = case pidgin_chat_time_start
267
+ when @time_regex
268
+ {:year => $1.to_i,
269
+ :mon => $2.to_i,
270
+ :mday => $3.to_i}
271
+ when @time_regex_first_line
272
+ {:year => $3.to_i,
273
+ :mon => $1.to_i,
274
+ :mday => $2.to_i}
275
+ end
276
+ # Need @basic_time_info set for create_adium_time
277
+ # When the chat started, in Adium's format
278
+ @adium_chat_time_start = create_adium_time(pidgin_chat_time_start)
279
+ [@service,
280
+ @user_SN,
281
+ @partner_SN,
282
+ @basic_time_info,
283
+ @adium_chat_time_start].all?
321
284
  end
322
285
  end
323
286
 
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Pidgin2Adium
2
+ VERSION = "3.2.0"
3
+ end
data/pidgin2adium.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{pidgin2adium}
8
- s.version = "3.1.1"
8
+ s.version = "3.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Gabe Berke-Williams"]
12
- s.date = %q{2010-08-13}
12
+ s.date = %q{2010-10-12}
13
13
  s.default_executable = %q{pidgin2adium}
14
14
  s.description = %q{Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the Adium format.}
15
15
  s.email = %q{gbw@brandeis.edu}
@@ -30,7 +30,6 @@ Gem::Specification.new do |s|
30
30
  "Manifest.txt",
31
31
  "README.rdoc",
32
32
  "Rakefile",
33
- "VERSION",
34
33
  "bin/pidgin2adium",
35
34
  "config/website.yml",
36
35
  "ext/balance_tags_c/balance_tags_c.c",
@@ -50,6 +49,7 @@ Gem::Specification.new do |s|
50
49
  "lib/pidgin2adium/parsers/basic_parser.rb",
51
50
  "lib/pidgin2adium/parsers/html_log_parser.rb",
52
51
  "lib/pidgin2adium/parsers/text_log_parser.rb",
52
+ "lib/version.rb",
53
53
  "pidgin2adium.gemspec",
54
54
  "spec/balance_tags_c_extn_spec.rb",
55
55
  "spec/basic_parser_spec.rb",
@@ -90,18 +90,18 @@ Gem::Specification.new do |s|
90
90
  s.specification_version = 3
91
91
 
92
92
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
93
- s.add_development_dependency(%q<bundler>, [">= 0.9.26"])
93
+ s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
94
94
  s.add_development_dependency(%q<jeweler>, [">= 0"])
95
- s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
95
+ s.add_development_dependency(%q<rspec>, [">= 1.3.0"])
96
96
  else
97
- s.add_dependency(%q<bundler>, [">= 0.9.26"])
97
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
98
98
  s.add_dependency(%q<jeweler>, [">= 0"])
99
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
99
+ s.add_dependency(%q<rspec>, [">= 1.3.0"])
100
100
  end
101
101
  else
102
- s.add_dependency(%q<bundler>, [">= 0.9.26"])
102
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
103
103
  s.add_dependency(%q<jeweler>, [">= 0"])
104
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
104
+ s.add_dependency(%q<rspec>, [">= 1.3.0"])
105
105
  end
106
106
  end
107
107
 
@@ -13,24 +13,6 @@ describe "BasicParser" do
13
13
  end
14
14
  end
15
15
 
16
- describe "#get_time_zone_offset" do
17
- context "with no timezone available" do
18
- it "should return the local time zone" do
19
- bp = Pidgin2Adium::BasicParser.new(@text_logfile_path,
20
- @aliases)
21
- bp.get_time_zone_offset.should == @current_tz_offset
22
- end
23
- end
24
-
25
- context "with a time zone available" do
26
- it "should return the logfiles's time zone" do
27
- bp = Pidgin2Adium::BasicParser.new(@html_logfile_path,
28
- @aliases)
29
- bp.get_time_zone_offset.should == "-0500"
30
- end
31
- end
32
- end
33
-
34
16
  describe "#create_adium_time" do
35
17
  before(:each) do
36
18
  @first_line_time = "4/18/2007 11:02:00 AM"
@@ -46,23 +28,23 @@ describe "BasicParser" do
46
28
  end
47
29
 
48
30
  it "should parse a first line time correctly" do
49
- time = @bp.create_adium_time(@first_line_time, true)
50
- time.should == "2007-04-18T11.02.00-0500"
31
+ time = @bp.create_adium_time(@first_line_time)
32
+ time.should =~ /2007-04-18T11:02:00-\d{2}:00/
51
33
  end
52
34
 
53
35
  it "should parse a normal time correctly" do
54
36
  time = @bp.create_adium_time(@time)
55
- time.should == "2007-08-20T12:33:13-0500"
37
+ time.should =~ /2007-08-20T12:33:13-\d{2}:00/
56
38
  end
57
39
 
58
40
  it "should parse a minimal time correctly" do
59
41
  time = @bp.create_adium_time(@minimal_time)
60
- time.should == "2008-01-15T04:22:05-0500"
42
+ time.should =~ /2008-01-15T04:22:05-\d{2}:00/
61
43
  end
62
44
 
63
45
  it "should parse a minimal time without AM/PM correctly" do
64
46
  time = @bp.create_adium_time(@minimal_time_2)
65
- time.should == "2008-01-15T04:22:05-0500"
47
+ time.should =~ /2008-01-15T04:22:05-\d{2}:00/
66
48
  end
67
49
 
68
50
  it "should return an array of nils for an invalid time" do
@@ -92,7 +74,7 @@ describe "BasicParser" do
92
74
  'othersn', # my SN
93
75
  'aolsystemmsg', # other person's SN
94
76
  {:year=>2008, :mon=>1, :mday=>15}, # basic time info
95
- '2008-01-15T07.14.45-0500' # chat start time
77
+ '2008-01-15T07:14:45-05:00' # chat start time
96
78
  ]
97
79
  end
98
80
  end
@@ -129,7 +111,7 @@ describe "BasicParser" do
129
111
  "To sign off the other location(s), reply to this message " + "with the number 1. Click " +
130
112
  "<a href='http://www.aim.com/password/routing.adp'>here</a> " +
131
113
  "for more information."
132
- @matches = ['2008-01-15T07.14.45-0500', # time
114
+ @matches = ['2008-01-15T07.14.45-05:00', # time
133
115
  'AOL System Msg', # alias
134
116
  nil, # not an auto-reply
135
117
  body # message body
@@ -128,7 +128,7 @@ describe "HtmlLogParser" do
128
128
  first_msg.sender.should == "aolsystemmsg"
129
129
  first_msg.buddy_alias.should == "AOL System Msg"
130
130
  # Use regex to ignore time zone
131
- first_msg.time.should =~ /^2008-01-15T07:14:45[-+]\d{2}00$/
131
+ first_msg.time.should =~ /^2008-01-15T07:14:45[-+]\d{2}:00$/
132
132
  # This fails due to balance_tags_c().
133
133
  good_body = %Q{Your screen name (otherSN) is now signed into AOL(R) Instant Messenger (TM) in 2 locations.} + " " +
134
134
  %Q{To sign off the other location(s), reply to this message with the number 1.} + " " +
@@ -137,13 +137,13 @@ describe "HtmlLogParser" do
137
137
 
138
138
  second_msg.sender.should == "othersn"
139
139
  second_msg.buddy_alias.should == "Gabe B-W"
140
- second_msg.time.should =~ /^2008-01-15T07:14:48[-+]\d{2}00$/
140
+ second_msg.time.should =~ /^2008-01-15T07:14:48[-+]\d{2}:00$/
141
141
  second_msg.body.should == "1"
142
142
 
143
143
  third_msg.sender.should == "aolsystemmsg"
144
144
  third_msg.buddy_alias.should == "AOL System Msg"
145
145
  # Use regex to ignore time zone
146
- third_msg.time.should =~ /^2008-01-15T07:14:48[-+]\d{2}00$/
146
+ third_msg.time.should =~ /^2008-01-15T07:14:48[-+]\d{2}:00$/
147
147
  third_msg.body.should == "Your other AIM sessions have been signed-off. You are now signed-on from 1 location(s)."
148
148
  end
149
149
  end
@@ -73,6 +73,18 @@ describe "LogFile" do
73
73
  end
74
74
  end
75
75
  end
76
+
77
+ describe "#max" do
78
+ it "should return the most recent message" do
79
+ @logfile.max.should == @messages.last
80
+ end
81
+ end
82
+
83
+ describe "#min" do
84
+ it "should return the oldest message" do
85
+ @logfile.min.should == @messages.first
86
+ end
87
+ end
76
88
  end
77
89
 
78
90
  describe "#write_out" do
@@ -36,7 +36,7 @@ describe "TextLogParser" do
36
36
  msg.body.should == "what are you doing tomorrow?"
37
37
  msg.buddy_alias.should == "Gabe B-W"
38
38
  # Use regex to ignore time zone
39
- msg.time.should =~ /^2006-12-21T22:36:11[-+]\d{2}00$/
39
+ msg.time.should =~ /^2006-12-21T22:36:11[-+]\d{2}:00$/
40
40
  end
41
41
  end
42
42
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 3
7
- - 1
8
- - 1
9
- version: 3.1.1
7
+ - 2
8
+ - 0
9
+ version: 3.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Gabe Berke-Williams
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-13 00:00:00 -07:00
17
+ date: 2010-10-12 00:00:00 -04:00
18
18
  default_executable: pidgin2adium
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -26,10 +26,10 @@ dependencies:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  segments:
29
+ - 1
30
+ - 0
29
31
  - 0
30
- - 9
31
- - 26
32
- version: 0.9.26
32
+ version: 1.0.0
33
33
  type: :development
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
@@ -55,9 +55,9 @@ dependencies:
55
55
  - !ruby/object:Gem::Version
56
56
  segments:
57
57
  - 1
58
- - 2
59
- - 9
60
- version: 1.2.9
58
+ - 3
59
+ - 0
60
+ version: 1.3.0
61
61
  type: :development
62
62
  version_requirements: *id003
63
63
  description: Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the Adium format.
@@ -80,7 +80,6 @@ files:
80
80
  - Manifest.txt
81
81
  - README.rdoc
82
82
  - Rakefile
83
- - VERSION
84
83
  - bin/pidgin2adium
85
84
  - config/website.yml
86
85
  - ext/balance_tags_c/balance_tags_c.c
@@ -100,6 +99,7 @@ files:
100
99
  - lib/pidgin2adium/parsers/basic_parser.rb
101
100
  - lib/pidgin2adium/parsers/html_log_parser.rb
102
101
  - lib/pidgin2adium/parsers/text_log_parser.rb
102
+ - lib/version.rb
103
103
  - pidgin2adium.gemspec
104
104
  - spec/balance_tags_c_extn_spec.rb
105
105
  - spec/basic_parser_spec.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 3.1.1