livejournal 0.0.1
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/LICENSE +17 -0
- data/README +50 -0
- data/Rakefile +60 -0
- data/lib/livejournal/basic.rb +59 -0
- data/lib/livejournal/comment.rb +82 -0
- data/lib/livejournal/comments-xml.rb +158 -0
- data/lib/livejournal/database.rb +292 -0
- data/lib/livejournal/entry.rb +280 -0
- data/lib/livejournal/friends.rb +102 -0
- data/lib/livejournal/login.rb +43 -0
- data/lib/livejournal/logjam.rb +76 -0
- data/lib/livejournal/request.rb +126 -0
- data/lib/livejournal/sync.rb +185 -0
- data/sample/export +154 -0
- data/sample/lj +23 -0
- data/setup.rb +1585 -0
- data/test/checkfriends.rb +29 -0
- data/test/comments-xml.rb +108 -0
- data/test/database.rb +54 -0
- data/test/time.rb +49 -0
- metadata +60 -0
@@ -0,0 +1,280 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'livejournal/request'
|
26
|
+
|
27
|
+
module LiveJournal
|
28
|
+
# LiveJournal times have no time zone, as they are for display only:
|
29
|
+
# "I wrote this post at midnight". However, it's convenient to represent
|
30
|
+
# times with a Ruby time object. But when time zones get involved,
|
31
|
+
# everything gets confused; we'd like to store a Unix time in the database
|
32
|
+
# and those only make sense as GMT. To reduce confusion, then, we imagine
|
33
|
+
# all LiveJournal times are in GMT.
|
34
|
+
# This function takes a time in any time zone and just switches the
|
35
|
+
# timezone to GMT. That is, coerce_gmt of 11:12pm PST is 11:12 pm GMT.
|
36
|
+
# The entry time-setting functions require this GMT part to verify you're
|
37
|
+
# thinking carefully about time when you use Entry#time. If I want an
|
38
|
+
# entry that has a time that corresponds to what I feel is "now", I'd use
|
39
|
+
# LiveJournal::coerce_gmt Time.now
|
40
|
+
def self.coerce_gmt time
|
41
|
+
expanded = time.to_a
|
42
|
+
expanded[8] = false # dst flag
|
43
|
+
expanded[9] = 'GMT'
|
44
|
+
return Time.gm(*expanded)
|
45
|
+
end
|
46
|
+
|
47
|
+
class Entry
|
48
|
+
attr_accessor :itemid, :anum, :subject, :event, :moodid, :mood
|
49
|
+
attr_accessor :music, :taglist, :pickeyword, :preformatted, :backdated
|
50
|
+
attr_accessor :comments # values: {:normal, :none, :noemail}
|
51
|
+
attr_reader :time # a Ruby Time object
|
52
|
+
attr_accessor :security # values: {:public, :private, :friends, :custom}
|
53
|
+
attr_accessor :allowmask
|
54
|
+
attr_accessor :screening # values {:default, :all, :anonymous, :nonfriends, :none}
|
55
|
+
attr_accessor :props
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@subject = nil
|
59
|
+
@event = nil
|
60
|
+
@moodid = nil
|
61
|
+
@mood = nil
|
62
|
+
@music = nil
|
63
|
+
@taglist = []
|
64
|
+
@pickeyword = nil
|
65
|
+
@preformatted = false
|
66
|
+
@backdated = false
|
67
|
+
@comments = :normal
|
68
|
+
@time = nil
|
69
|
+
@security = :public
|
70
|
+
@allowmask = nil
|
71
|
+
@screening = :default
|
72
|
+
@props = {}
|
73
|
+
end
|
74
|
+
|
75
|
+
def ==(other)
|
76
|
+
[:subject, :event, :moodid, :mood, :music, :taglist, :pickeyword,
|
77
|
+
:preformatted, :backdated, :comments, :time, :security, :allowmask,
|
78
|
+
:screening, :props].each do |attr|
|
79
|
+
return false if send(attr) != other.send(attr)
|
80
|
+
end
|
81
|
+
return true
|
82
|
+
end
|
83
|
+
|
84
|
+
def time=(time)
|
85
|
+
raise RuntimeError, "Must use GMT times everywhere to reduce confusion. See LiveJournal::coerce_gmt for details." unless time.gmt?
|
86
|
+
@time = time
|
87
|
+
end
|
88
|
+
|
89
|
+
def from_request(req)
|
90
|
+
@itemid, @anum = req['itemid'].to_i, req['anum'].to_i
|
91
|
+
@subject, @event = req['subject'], CGI.unescape(req['event'])
|
92
|
+
|
93
|
+
case req['security']
|
94
|
+
when 'public'
|
95
|
+
@security = :public
|
96
|
+
when 'private'
|
97
|
+
@security = :private
|
98
|
+
when 'usemask'
|
99
|
+
if req['allowmask'] == '1'
|
100
|
+
@security = :friends
|
101
|
+
else
|
102
|
+
@security = :custom
|
103
|
+
@allowmask = req['allowmask'].to_i
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
@time = LiveJournal::Request::ljtime_to_time req['eventtime']
|
108
|
+
|
109
|
+
# further metadata is loaded via #load_prop
|
110
|
+
|
111
|
+
self
|
112
|
+
end
|
113
|
+
def load_prop(name, value) #:nodoc:#
|
114
|
+
case name
|
115
|
+
when 'current_mood'
|
116
|
+
@mood = value.to_i
|
117
|
+
when 'current_moodid'
|
118
|
+
@moodid = value.to_i
|
119
|
+
when 'current_music'
|
120
|
+
@music = value
|
121
|
+
when 'taglist'
|
122
|
+
@taglist = value.split(/, /).sort
|
123
|
+
when 'picture_keyword'
|
124
|
+
@pickeyword = value
|
125
|
+
when 'opt_preformatted'
|
126
|
+
@preformatted = value == '1'
|
127
|
+
when 'opt_nocomments'
|
128
|
+
@comments = :none
|
129
|
+
when 'opt_noemail'
|
130
|
+
@comments = :noemail
|
131
|
+
when 'opt_backdated'
|
132
|
+
@backdated = value == '1'
|
133
|
+
when 'opt_screening'
|
134
|
+
case value
|
135
|
+
when 'A'; @screening = :all
|
136
|
+
when 'R'; @screening = :anonymous
|
137
|
+
when 'F'; @screening = :nonfriends
|
138
|
+
when 'N'; @screening = :none
|
139
|
+
else
|
140
|
+
raise LiveJournalException,
|
141
|
+
"unknown opt_screening value #{value.inspect}"
|
142
|
+
end
|
143
|
+
when 'hasscreened'
|
144
|
+
@screened = value == '1'
|
145
|
+
# and then some props we just store by name
|
146
|
+
when 'revnum'; @props[name] = value
|
147
|
+
when 'revtime'; @props[name] = value
|
148
|
+
when 'commentalter'; @props[name] = value
|
149
|
+
when 'unknown8bit'; @props[name] = value
|
150
|
+
else
|
151
|
+
@props[name] = value
|
152
|
+
raise Request::ProtocolException, "unknown prop (#{name}, #{value})"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Get the numeric id used in URLs (it's a function of the itemid and the
|
157
|
+
# anum).
|
158
|
+
def display_itemid
|
159
|
+
(@itemid << 8) + @anum
|
160
|
+
end
|
161
|
+
|
162
|
+
# Render LJ markup to an HTML simulation.
|
163
|
+
# (The server to use is for rendering links to other LJ users.)
|
164
|
+
def event_as_html server=LiveJournal::DEFAULT_SERVER
|
165
|
+
# I'd like to use REXML but the content isn't XML, so REs it is!
|
166
|
+
html = @event.dup
|
167
|
+
html.gsub!(/\n/, "<br/>\n") unless @preformatted
|
168
|
+
html.gsub!(%r{< \s* lj \s+ user \s* = \s*
|
169
|
+
['"]? ([^\s'"]+) ['"]?
|
170
|
+
\s* /? \s* >}ix) do
|
171
|
+
user = $1
|
172
|
+
url = "#{server.url}/~#{user}/"
|
173
|
+
"<a href='#{url}'><b>#{user}</b></a>"
|
174
|
+
end
|
175
|
+
html
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
module Request
|
180
|
+
class GetEvents < Req
|
181
|
+
# We support three different types of GetEvents:
|
182
|
+
# * <tt>GetEvents.new(user, :itemid => itemid)</tt> (fetch a single item)
|
183
|
+
# * <tt>GetEvents.new(user, :recent => n)</tt> (fetch most recent n itemds)
|
184
|
+
# * <tt>GetEvents.new(user, :lastsync => lastsync)</tt> (for syncing)
|
185
|
+
def initialize(user, opts)
|
186
|
+
super(user, 'getevents')
|
187
|
+
self['lineendings'] = 'unix'
|
188
|
+
|
189
|
+
if opts.has_key? :itemid
|
190
|
+
self['selecttype'] = 'one'
|
191
|
+
self['itemid'] = opts[:itemid]
|
192
|
+
elsif opts.has_key? :recent
|
193
|
+
self['selecttype'] = 'lastn'
|
194
|
+
self['howmany'] = opts[:recent]
|
195
|
+
elsif opts.has_key? :lastsync
|
196
|
+
self['selecttype'] = 'syncitems'
|
197
|
+
self['lastsync'] = opts[:lastsync] if opts[:lastsync]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns either a single #Entry or an array of #Entry, depending on
|
202
|
+
# the mode this was constructed with.
|
203
|
+
def run
|
204
|
+
super
|
205
|
+
|
206
|
+
entries = {}
|
207
|
+
each_in_array('events') do |req|
|
208
|
+
entry = Entry.new.from_request(req)
|
209
|
+
entries[entry.itemid] = entry
|
210
|
+
end
|
211
|
+
|
212
|
+
each_in_array('prop') do |prop|
|
213
|
+
itemid = prop['itemid'].to_i
|
214
|
+
entries[itemid].load_prop(prop['name'], prop['value'])
|
215
|
+
end
|
216
|
+
|
217
|
+
if @reqparams.has_key? 'itemid'
|
218
|
+
return entries[@reqparams['itemid']]
|
219
|
+
else
|
220
|
+
return entries
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
class EditEvent < Req
|
225
|
+
def initialize(user, entry, opts={})
|
226
|
+
super(user, 'editevent')
|
227
|
+
self['itemid'] = entry.itemid
|
228
|
+
if entry.event
|
229
|
+
self['event'] = entry.event
|
230
|
+
elsif entry.entry.nil? and opts.has_key? :delete
|
231
|
+
self['event'] = ''
|
232
|
+
else
|
233
|
+
raise AccidentalDeleteError
|
234
|
+
end
|
235
|
+
self['lineendings'] = 'unix'
|
236
|
+
self['subject'] = entry.subject
|
237
|
+
|
238
|
+
case entry.security
|
239
|
+
when :public
|
240
|
+
self['security'] = 'public'
|
241
|
+
when :friends
|
242
|
+
self['security'] = 'usemask'
|
243
|
+
self['allowmask'] = 1
|
244
|
+
when :private
|
245
|
+
self['security'] = 'private'
|
246
|
+
when :custom
|
247
|
+
self['security'] = 'usemask'
|
248
|
+
self['allowmask'] = entry.allowmask
|
249
|
+
end
|
250
|
+
|
251
|
+
self['year'], self['mon'], self['day'] =
|
252
|
+
entry.time.year, entry.time.mon, entry.time.day
|
253
|
+
self['hour'], self['min'] = entry.time.hour, entry.time.min
|
254
|
+
|
255
|
+
{ 'current_mood' => entry.mood,
|
256
|
+
'current_moodid' => entry.moodid,
|
257
|
+
'current_music' => entry.music,
|
258
|
+
'picture_keyword' => entry.pickeyword,
|
259
|
+
'taglist' => entry.taglist.join(', '),
|
260
|
+
'opt_preformatted' => entry.preformatted ? 1 : 0,
|
261
|
+
'opt_nocomments' => entry.comments == :none ? 1 : 0,
|
262
|
+
'opt_noemail' => entry.comments == :noemail ? 1 : 0,
|
263
|
+
'opt_backdated' => entry.backdated ? 1 : 0,
|
264
|
+
'opt_screening' =>
|
265
|
+
case entry.screening
|
266
|
+
when :all; 'A'
|
267
|
+
when :anonymous; 'R'
|
268
|
+
when :nonfriends; 'F'
|
269
|
+
when :none; 'N'
|
270
|
+
when :default; ''
|
271
|
+
end
|
272
|
+
}.each do |name, value|
|
273
|
+
self["prop_#{name}"] = value
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
# vim: ts=2 sw=2 et :
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'livejournal/request'
|
26
|
+
|
27
|
+
module LiveJournal
|
28
|
+
# Represents a LiveJournal friend relationship.
|
29
|
+
# See LiveJournal::Request::Friends to get an array of these.
|
30
|
+
class Friend
|
31
|
+
attr_accessor :username, :fullname
|
32
|
+
attr_accessor :background, :foreground, :groupmask, :type
|
33
|
+
def initialize
|
34
|
+
@username = nil
|
35
|
+
@fullname = nil
|
36
|
+
@background = nil
|
37
|
+
@foreground = nil
|
38
|
+
@groupmask = nil
|
39
|
+
@type = nil
|
40
|
+
end
|
41
|
+
def from_request(req)
|
42
|
+
@username = req['user']
|
43
|
+
@fullname = req['name']
|
44
|
+
@foreground = req['fg']
|
45
|
+
@background = req['bg']
|
46
|
+
@groupmask = req['groupmask']
|
47
|
+
@type = req['type']
|
48
|
+
self
|
49
|
+
end
|
50
|
+
def to_s
|
51
|
+
"#{@username}: #{@fullname}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module Request
|
56
|
+
class Friends < Req
|
57
|
+
attr_reader :friends
|
58
|
+
def initialize(user)
|
59
|
+
super(user, 'getfriends')
|
60
|
+
@friends = nil
|
61
|
+
end
|
62
|
+
# Returns an array of LiveJournal::Friend.
|
63
|
+
def run
|
64
|
+
super
|
65
|
+
@friends = build_array('friend') { |r| Friend.new.from_request(r) }
|
66
|
+
@friends
|
67
|
+
end
|
68
|
+
end
|
69
|
+
class FriendOfs < Req
|
70
|
+
attr_reader :friendofs
|
71
|
+
def initialize(user)
|
72
|
+
super(user, 'friendof')
|
73
|
+
@friendofs = nil
|
74
|
+
end
|
75
|
+
# Returns an array of LiveJournal::Friend.
|
76
|
+
def run
|
77
|
+
super
|
78
|
+
@friends = build_array('friendof') { |r| Friend.new.from_request(r) }
|
79
|
+
@friends
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class CheckFriends < Req
|
84
|
+
attr_reader :interval
|
85
|
+
def initialize(user, lastupdate=nil)
|
86
|
+
super(user, 'checkfriends')
|
87
|
+
@lastupdate = lastupdate
|
88
|
+
@interval = 90 # reasonable default?
|
89
|
+
end
|
90
|
+
# Returns true if there are new posts available.
|
91
|
+
def run
|
92
|
+
self['lastupdate'] = @lastupdate if @lastupdate
|
93
|
+
super
|
94
|
+
@lastupdate = self['lastupdate']
|
95
|
+
@interval = self['interval']
|
96
|
+
self['new'] == '1'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# vim: ts=2 sw=2 et :
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'livejournal/request'
|
26
|
+
|
27
|
+
module LiveJournal
|
28
|
+
module Request
|
29
|
+
class Login < Req
|
30
|
+
def initialize(user)
|
31
|
+
super(user, 'login')
|
32
|
+
end
|
33
|
+
def run
|
34
|
+
super
|
35
|
+
u = @user # should we clone here?
|
36
|
+
u.fullname = @result['name']
|
37
|
+
u
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# vim: ts=2 sw=2 et :
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#--
|
3
|
+
# ljrb -- LiveJournal Ruby module
|
4
|
+
# Copyright (c) 2005 Evan Martin <martine@danga.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#++
|
24
|
+
#
|
25
|
+
# This module extends the LiveJournal module to work with LogJam's data.
|
26
|
+
|
27
|
+
require 'rexml/document' # parsing logjam conf
|
28
|
+
|
29
|
+
module LiveJournal
|
30
|
+
module LogJam
|
31
|
+
# Path to LogJam data.
|
32
|
+
def self.logjam_path
|
33
|
+
File.expand_path '~/.logjam'
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.xml_fetch(file, path) #:nodoc:
|
37
|
+
doc = REXML::Document.new(File.open(file))
|
38
|
+
doc.elements.each(path) { |element| return element.text }
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Name of LogJam's current server.
|
43
|
+
def self.current_server
|
44
|
+
xml_fetch(logjam_path + '/conf.xml', '/configuration/currentserver')
|
45
|
+
end
|
46
|
+
|
47
|
+
# Path to LogJam's data for a given server.
|
48
|
+
def self.server_path servername
|
49
|
+
logjam_path + '/servers/' + servername # is escaping needed here?
|
50
|
+
end
|
51
|
+
|
52
|
+
# Username for a given server's current user.
|
53
|
+
def self.current_user servername
|
54
|
+
xml_fetch(server_path(servername) + '/conf.xml',
|
55
|
+
'/server/currentuser')
|
56
|
+
end
|
57
|
+
|
58
|
+
# Path to a given user's data.
|
59
|
+
def self.user_path servername, username
|
60
|
+
server_path(servername) + "/users/#{username}"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return [current_server, current_user].
|
64
|
+
def self.current_server_user
|
65
|
+
server = current_server
|
66
|
+
user = current_user server
|
67
|
+
[server, user]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.database_from_server_user servername, username
|
71
|
+
Database.new(LogJam::user_path(servername, username) + "/journal.db")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# vim: ts=2 sw=2 et :
|