|
/home/dan/dev/icqlite-history/icqlitehistorybrowser-0.5/icq.rb
1| # icq.rb - functions providing interfaces to the icq db and a
2| # nickname resolver
3|
4| require "net/http"
5| require "rexml/document"
6| include REXML
7|
8| module Icq
9| class ICQUser
10| # a basic ICQ user class
11| attr_accessor :uin, :name
12|
13| def initialize(uin, name)
14| @uin = uin
15| @name = name
16| end
17| end
18|
19| class ICQError < Exception
20| end
21|
22| class ICQPathError < Exception
23| # invalid history directory
24| end
25|
26| class Info
27| # a simple icq info retriever.
28| # loads the website and extracts contact information, a more elegant
29| # but more difficult way would be to use the ICQ protocol
30| # however, it doesn't work too well because icq.com is protected against "floods"
31|
32| attr_reader :nick
33|
34| @@server = "people.icq.com"
35| @@request = "/whitepages/about_me/1,,,00.html?Uin="
36|
37| def initialize(uin)
38| @uin = uin
39| h = Net::HTTP.new(@@server, nil)
40| resp, data = nil
41| begin
42| resp, data = h.get(@@request + uin, {"User-Agent: " => "Mozilla"})
43| rescue
44| print "Could not fetch details for " + uin + "\n"
45| raise ICQError
46| end
47| if 200 != resp.code.to_i
48| print "Could not fetch details for " + uin + " (return code " + resp.code + ")\n"
49| raise ICQError
50| end
51| @nick = data.gsub(/.*Nickname:.*? (.*?)<\/span>.*/m, '\1')
52| end
53| end
54|
55| class Parser
56| # a XML parser for ICQ Lites history files
57| attr_reader :messages
58|
59| def initialize
60| @messages = []
61| end
62|
63| def parse(string)
64| doc = Document.new(string)
65| doc.elements.each("root/event") { | item |
66| event = {"text" => "", "incoming" => true, "time" => nil}
67| item.each_element { | el |
68| if ("text" == el.name) and (nil != el.text)
69| # convert text from UTF-8 to ISO-8859-1
70| event["text"] = el.text.unpack("U*").pack("C*")
71| elsif ("incoming" == el.name) and (nil != el.text)
72| event["incoming"] = ("YES" == el.text.upcase)
73| elsif ("time" == el.name) and (nil != el.text)
74| event["time"] = el.text
75| end
76| }
77| @messages.push(event)
78| }
79| end
80| end
81|
82| class History
83| # Comfortable wrapper for the history directory
84|
85| attr_reader :users
86|
87| def initialize(historydir)
88| @dir = historydir
89| @users = Hash.new
90|
91| wd = Dir.getwd
92| begin
93| Dir.chdir(@dir)
94| rescue Errno::ENOENT
95| raise ICQPathError
96| end
97| Dir["[0-9]*"].each do | uin |
98| @users[uin] = ICQUser.new(uin, nil)
99| end
100| Dir.chdir(wd)
101| end
102|
103| def getAvailableDates(uin)
104| # returns a list of all available months(years) in the
105| # history of a given user
106|
107| wd = Dir.getwd
108| begin
109| Dir.chdir(@dir + File::SEPARATOR + uin)
110| rescue Errno::ENOENT
111| raise ICQPathError
112| end
113| dates = []
114| Dir["*.xml"].each do | filename |
115| entry = {}
116| entry["month"], entry["year"] =
117| Regexp.new("([0-9][0-9])([0-9][0-9]).xml").match(filename)[1, 2]
118| dates.push(entry)
119| end
120| Dir.chdir(wd)
121| dates
122| end
123|
124| def getHistory(uin, month, year)
125| # get the users history for a specific month
126|
127| filename = [@dir, uin, uin+"-"+month+year+".xml"].join(File::SEPARATOR)
128| history = {}
129| history["messages"] = nil
130| parser = Parser.new
131| file = File.new(filename)
132| begin
133| parser.parse(file.read)
134| history["messages"] = parser.messages
135| rescue ParseException
136| print "Error parsing the XML file.\n\n"
137| end
138| history
139| end
140| end
141|
142| end
|