mirror of
https://github.com/leahneukirchen/mblaze
synced 2024-11-11 13:10:32 +00:00
3663d7365b
Previously, a typo in the newsgroup name would leave an empty mailbox for a non-existent newsgroup. This can be avoided by delaying maildir initialization until after the NNTP server has 221ed the group.
141 lines
2.7 KiB
Ruby
Executable File
141 lines
2.7 KiB
Ruby
Executable File
#!/usr/bin/ruby
|
|
# msuck - suck NNTP groups into Maildirs
|
|
#
|
|
# msuck [-s NNTPSERVER[:PORT]] [-d BASEDIR] [-l LIMIT] GROUPS... to fetch GROUPS
|
|
# msuck [-s NNTPSERVER[:PORT]] -L to list all groups
|
|
|
|
require 'socket'
|
|
require 'fileutils'
|
|
require 'optparse'
|
|
|
|
$delivery = 0
|
|
HOST = Socket.gethostname
|
|
def genname(id)
|
|
$delivery += 1
|
|
t = Time.now
|
|
"%d.M%06dP%05dQ%d.%s,N=%d" % [t.tv_sec, t.tv_usec, $$, $delivery, HOST, id]
|
|
end
|
|
|
|
params = ARGV.getopts("d:fl:s:L")
|
|
dir = params["d"] || '.'
|
|
LIMIT = if params["l"]
|
|
Integer(params["l"])
|
|
else
|
|
10
|
|
end
|
|
|
|
port = 119
|
|
if params["s"] =~ /(.*):(.*)/
|
|
params["s"] = $1
|
|
port = Integer($2)
|
|
end
|
|
|
|
SERVER = params["s"] || ENV["NNTPSERVER"] || "news"
|
|
|
|
nntp = TCPSocket.new SERVER, port
|
|
|
|
msg = nntp.gets
|
|
abort msg unless msg =~ /^20[01] /
|
|
|
|
if params["L"] # list all groups
|
|
nntp.write("LIST NEWSGROUPS\r\n")
|
|
msg = nntp.gets
|
|
if msg !~ /^215 /
|
|
abort msg
|
|
end
|
|
|
|
loop {
|
|
msg = nntp.gets
|
|
break if msg == ".\r\n"
|
|
puts msg
|
|
}
|
|
|
|
exit
|
|
end
|
|
|
|
STDOUT.sync = true
|
|
|
|
ARGV.each { |group|
|
|
|
|
nntp.write("GROUP #{group}\r\n")
|
|
|
|
msg = nntp.gets
|
|
unless msg =~ /^211 /
|
|
STDERR.puts msg
|
|
$exit = 69
|
|
next
|
|
end
|
|
|
|
_, number, low, high, _ = msg.split(" ", 5)
|
|
|
|
number = number.to_i
|
|
low = low.to_i
|
|
high = high.to_i
|
|
|
|
low = high - LIMIT + 1 if number > LIMIT - 1
|
|
low = 1 if low <= 0
|
|
|
|
FileUtils.mkdir_p(File.join(dir, group, "cur"))
|
|
FileUtils.mkdir_p(File.join(dir, group, "new"))
|
|
FileUtils.mkdir_p(File.join(dir, group, "tmp"))
|
|
|
|
have = Dir.entries(File.join(dir, group, "cur")).
|
|
map { |f| $1.to_i if f =~ /N=(\d+)/ }.compact
|
|
|
|
ourhigh = have.max
|
|
if ourhigh && low < ourhigh && !params["f"]
|
|
low = ourhigh + 1
|
|
end
|
|
|
|
next if low > high
|
|
|
|
printf "%s %d-%d ", group, low, high
|
|
|
|
nntp.write("STAT #{low}\r\n")
|
|
msg = nntp.gets
|
|
_, num, mid, _ = msg.split(" ", 4)
|
|
|
|
loop {
|
|
unless have.include? num.to_i
|
|
nntp.write("ARTICLE\r\n")
|
|
msg = nntp.gets
|
|
|
|
if msg =~ /^220 /
|
|
_, num, mid, _ = msg.split(" ", 4)
|
|
|
|
text = ["X-Msuck: nntp://#{SERVER}/#{group}/#{num}\n"]
|
|
loop {
|
|
msg = nntp.gets
|
|
break if msg == ".\r\n"
|
|
msg.sub!(/\A\./, "")
|
|
msg.sub!(/\r\n\z/, "\n")
|
|
text << msg
|
|
}
|
|
text = text.join
|
|
|
|
name = genname(num)
|
|
|
|
File.write(File.join(dir, group, "tmp", name), text)
|
|
File.rename(File.join(dir, group, "tmp", name),
|
|
File.join(dir, group, "cur", name + ":2,"))
|
|
print "."
|
|
else
|
|
STDERR.puts msg
|
|
end
|
|
else
|
|
print "="
|
|
end
|
|
|
|
nntp.write("NEXT\r\n")
|
|
msg = nntp.gets
|
|
if msg !~ /^223 /
|
|
break
|
|
end
|
|
_, num, mid, _ = msg.split(" ", 4)
|
|
}
|
|
|
|
puts
|
|
}
|
|
|
|
exit $exit || 0
|
|
|