Module: Pidgin2Adium

Included in:
LogConverter, LogFile
Defined in:
lib/pidgin2adium.rb,
lib/pidgin2adium/log_file.rb,
lib/pidgin2adium/balance_tags.rb,
lib/pidgin2adium/log_converter.rb

Defined Under Namespace

Classes: LogConverter, LogFile

Constant Summary collapse

FILE_EXISTS =

Returned by LogFile.write_out if the output logfile already exists.

42
ADIUM_LOG_DIR =
File.expand_path('~/Library/Application Support/Adium 2.0/Users/Default/Logs/') << '/'
BAD_DIRS =

These files/directories show up in Dir.entries()

%w{. .. .DS_Store Thumbs.db .system}
VERSION =
"2.0.0"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.delete_search_indexesObject

Newly-converted logs are viewable in the Adium Chat Transcript Viewer, but are not indexed, so a search of the logs doesn’t give results from the converted logs. To fix this, we delete the cached log indexes, which forces Adium to re-index.

Note: This function is run by LogConverter after converting all of its files. LogFile.write_out intentionally does not run it in order to allow for batch-processing of files. Thus, you will probably want to run Pidgin2Adium.delete_search_indexes after running LogFile.write_out in your own scripts.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/pidgin2adium.rb', line 102

def delete_search_indexes()
  log_msg "Deleting log search indexes in order to force re-indexing of imported logs..."
  dirty_file = File.expand_path("~/Library/Caches/Adium/Default/DirtyLogs.plist")
  log_index_file = File.expand_path("~/Library/Caches/Adium/Default/Logs.index")
  [dirty_file, log_index_file].each do |f|
 if File.exist?(f)
    if File.writable?(f)
  File.delete(f)
    else
  error("#{f} exists but is not writable. Please delete it yourself.")
    end
 end
  end
  log_msg "...done."
  log_msg "When you next start the Adium Chat Transcript Viewer, it will re-index the logs, which may take a while."
end

.parse(logfile_path, my_aliases) ⇒ Object

Returns a LogFile instance or false if an error occurred.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/pidgin2adium.rb', line 36

def parse(logfile_path, my_aliases)
  logfile_path = File.expand_path(logfile_path)
  ext = File.extname(logfile_path).sub('.', '').downcase

  if(ext == "html" || ext == "htm")
 parser = HtmlLogParser.new(logfile_path, my_aliases) 
  elsif(ext == "txt")
 parser = TextLogParser.new(logfile_path, my_aliases) 
  else
 error("logfile (#{logfile_path}) is not a text or html file. Doing nothing.")
 return false
  end

  return parser.parse()
end

.parse_and_generate(logfile_path, my_aliases, opts = {}) ⇒ Object

Returns the path to the converted log, false if an error occurred, or Pidgin2Adium::FILE_EXISTS if file already exists AND opts = false.

You can add options using the opts hash, which can have the following keys, all of which are optional:

  • overwrite: If true, then overwrite even if log is found.

Defaults to false.

  • output_dir: The top-level dir to put the logs in. Logs under output_dir are still each in their own folders, etc. Defaults to Pidgin2Adium::ADIUM_LOG_DIR



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/pidgin2adium.rb', line 63

def parse_and_generate(logfile_path, my_aliases, opts = {})
  opts = {} unless opts.is_a?(Hash)
  overwrite = !!opts[:overwrite]
  if opts.key?(:output_dir)
 output_dir = opts[:output_dir]
  else
 output_dir = ADIUM_LOG_DIR
  end
  
  unless File.directory?(output_dir)
 puts "Output log directory (#{output_dir}) does not exist or is not a directory."
 raise Errno::ENOENT
  end

  logfile_obj = parse(logfile_path, my_aliases)
  return false if logfile_obj == false
  dest_file_path = logfile_obj.write_out(overwrite, output_dir)
  if dest_file_path == false
 error("Converting #{logfile_path} failed.") 
 return false
  elsif dest_file_path == FILE_EXISTS
 log_msg("File already exists.")
 return FILE_EXISTS
  else
 log_msg("Output to: #{dest_file_path}")
 return true
  end
end

Instance Method Details

#balance_tags(text) ⇒ Object

From Wordpress’s formatting.php; rewritten in Ruby by Gabe Berke-Williams, 2009.

Author

Leonard Lin <[email protected]>

License

GPL v2.0

Copyright

November 4, 2001



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/pidgin2adium/balance_tags.rb', line 11

def balance_tags( text )
  tagstack = []
  stacksize = 0
  tagqueue = ''
  newtext = ''
  single_tags = %w{br hr img input meta} # Known single-entity/self-closing tags
  #nestable_tags = %w{blockquote div span} # Tags that can be immediately nested within themselves
  nestable_tags = %w{blockquote div span font} # Tags that can be immediately nested within themselves
  # 1: tagname, with possible leading "/"
  # 2: attributes
  tag_regex = /<(\/?\w*)\s*([^>]*)>/

  # WP bug fix for comments - in case you REALLY meant to type '< !--'
  text.gsub!('< !--', '<    !--')

  # WP bug fix for LOVE <3 (and other situations with '<' before a number)
  text.gsub!(/<([0-9]{1})/, '&lt;\1')

  while ( pos = (text =~ tag_regex) )
 newtext << tagqueue
 tag = $1.downcase
 attributes = $2
 matchlen = $~[0].size

 # clear the shifter
 tagqueue = ''
 # Pop or Push
 if (tag[0,1] == "/") # End Tag
    tag.slice!(0,1)
    # if too many closing tags
    if(stacksize <= 0)
  tag = ''
  #or close to be safe: tag = '/' << tag
    elsif (tagstack[stacksize - 1] == tag) # found closing tag
  # if stacktop value == tag close value then pop
  tag = '</' << tag << '>' # Close Tag
  # Pop
  tagstack.pop
  stacksize -= 1
    else # closing tag not at top, search for it
  (stacksize-1).downto(0) do |j|
      if (tagstack[j] == tag)
   # add tag to tagqueue
   ss = stacksize - 1
   ss.downto(j) do |k|
tagqueue << '</' << tagstack.pop << '>'
stacksize -= 1
   end
   break
      end
  end
  tag = ''
    end
 else
    # Begin Tag

    # Tag Cleaning
    if( (attributes[-1,1] == '/') || (tag == '') )
  # If: self-closing or '', don't do anything.
    elsif ( single_tags.include?(tag) )
  # ElseIf: it's a known single-entity tag but it doesn't close itself, do so
  attributes << '/'
    else
  # Push the tag onto the stack
  # If the top of the stack is the same as the tag we want to push, close previous tag
  if ((stacksize > 0) &&
      ! nestable_tags.include?(tag) &&
      (tagstack[stacksize - 1] == tag))
      tagqueue = '</' << tagstack.pop << '>'
      stacksize -= 1
  end
  tagstack.push(tag)
  stacksize += 1
    end

    # Attributes
    if(attributes != '')
  attributes = ' ' << attributes
    end
    tag = '<' << tag << attributes << '>'
    #If already queuing a close tag, then put this tag on, too
    if (tagqueue)
  tagqueue << tag
  tag = ''
    end
 end
 newtext << text[0,pos] << tag
 text = text[pos+matchlen, text.length - (pos+matchlen)]
  end

  # Clear Tag Queue
  newtext << tagqueue

  # Add Remaining text
  newtext << text

  # Empty Stack
  tagstack.reverse_each do |t|
 newtext << '</' << t << '>' # Add remaining tags to close
  end

  # WP fix for the bug with HTML comments
  newtext.gsub!("< !--", "<!--")
  newtext.gsub!("<    !--", "< !--")

  return newtext
end