#!/usr/local/bin/ruby
# $Id: tmladmin,v 1.13 2004/01/14 11:14:29 tommy Exp $
#
# Copyright (C) 2003 TOMITA Masahiro
# tommy@tmtm.org
#

require "getopts"

$script_dir = File::dirname $0
require $script_dir+"/tml.rb"

conf = $script_dir+"/tml.conf"
load conf if File::exist? conf

$cmds = {
  :list		=> [0, nil],
  :create	=> [2, nil],
  :drop		=> [1, nil],
  :add		=> [2..9999, ["send-mail"]],
  :bye		=> [2..9999, ["send-mail"]],
  :addml	=> [2..9999, nil],
  :byeml	=> [2..9999, nil],
  :members	=> [1, nil],
  :allmembers	=> [1, nil],
  :children	=> [1, nil],
  :parents	=> [1, nil],
  :admins	=> [1, nil],
  :addadmin	=> [2, nil],
  :byeadmin	=> [2, nil],
  :setattr	=> [2..9999, nil],
  :getattr	=> [1..9999, nil],
  :setcounter	=> [2, nil],
  :getcounter	=> [1, nil],
  :command	=> [2..9999, nil],
}

def usage()
  $stderr.puts <<EOS
Usage: tmladmin [option] cmd
option:
  -f configfile
  --domain domainname

cmd:
  list
  create mlname admin
  drop mlname
  add mlname addr ...
  bye mlname addr ...
  addml mlname child ...
  byeml mlname child ...
  members mlname
  allmembers mlname
  children mlname
  parents mlname
  admins mlname
  addadmin mlname addr
  byeadmin mlname addr
  setattr mlname attr=value ...
  getattr mlname [attr ...]
  setcounter mlname number
  getcounter mlname

attr:
  sender:            envelope sender address
  overview:          overview of ML
  not_member:        true or false
  subject_mlname:    true or false
  counter_width:     n (>= 0)
  remote_command:    true or false
  remote_admin:      true or false
  spool:             true or false
  web_interface:     0:nobody, 1:admin only, 2:member only, 3:everybody
  allowed_command:   comma separeted list of remote command
  anonymous_command: comma separated list of remote command
  admin_command:     comma separated list of remote command
EOS
  exit 1
end

unless getopts("f:", "domain:") then
  $stderr.puts "#{ARGV[0]}: invalid option"
  usage
end

load $OPT_f if $OPT_f
$domain = $OPT_domain if $OPT_domain

$OPT_f = nil
$OPT_domain = nil

if not $domain then
  $stderr.puts "$domain parameter required"
  exit 1
end

def list()
  puts TML::list.join("\n") unless TML::list.empty?
end

def create(mlname, admin)
  ml = TML::create(mlname, admin)
end

def drop(mlname)
  TML::drop mlname
end

def add(mlname, *members)
  ml = TML::new mlname
  ml.add(*members)
  if $OPT_send_mail then
    members.each do |m|
      ml.send_msg ml.get_attr(:sender), m, "welcome"
    end
  end
end

def bye(mlname, *members)
  ml = TML::new mlname
  ml.bye(*members)
  if $OPT_send_mail then
    members.each do |m|
      ml.send_msg ml.get_attr(:sender), m, "unsubscribe"
    end
  end
end

def addml(mlname, *children)
  ml = TML::new mlname
  children.each do |child|
    ml.addml child
  end
end

def byeml(mlname, *children)
  ml = TML::new mlname
  children.each do |child|
    ml.byeml child
  end
end

def members(mlname)
  ml = TML::new mlname
  puts ml.members.join("\n")
end

def allmembers(mlname)
  ml = TML::new mlname
  puts ml.all_members.join("\n")
end

def children(mlname)
  ml = TML::new mlname
  puts ml.children.map{|c| c.name}.join("\n")
end

def parents(mlname)
  ml = TML::new mlname
  puts ml.parents.map{|c| c.name}.join("\n")
end

def admins(mlname)
  ml = TML::new mlname
  puts ml.admins.join("\n")
end

def addadmin(mlname, addr)
  ml = TML::new mlname
  ml.add_admin addr
end

def byeadmin(mlname, addr)
  ml = TML::new mlname
  ml.bye_admin addr
end

def setattr(mlname, *args)
  ml = TML::new mlname
  args.each do |av|
    attr, value = av.split(/=/, 2)
    ml.set_attr attr, value
  end
end

def getattr(mlname, *args)
  ml = TML::new mlname
  if args.empty? then
    hash = ml.get_attr
    puts hash.keys.sort{|a,b|a.to_s<=>b.to_s}.map{|a| "#{a}=#{hash[a]}"}.join("\n")
  else
    puts args.map{|a| ml.get_attr a}.join("\n")
  end
end

def setcounter(mlname, cnt)
  ml = TML::new mlname
  ml.counter = cnt
end

def getcounter(mlname)
  ml = TML::new mlname
  puts ml.counter
end

def command(mlname, *args)
  ml = TML::new mlname
  system(*args)
end

if ARGV.empty? then
  usage
end
cmd = ARGV.shift.intern
unless $cmds.key? cmd then
  $stderr.puts "#{cmd}: invalid command"
  usage
end
unless getopts(*([nil]+$cmds[cmd][1].to_a)) then
  $stderr.puts "#{ARGV[0]}: invalid option"
  usage 
end
args = ARGV
if $cmds[cmd][0].kind_of? Integer and args.length != $cmds[cmd][0] then
  $stderr.puts "invalid argument number"
  usage
elsif $cmds[cmd][0].kind_of? Range and not $cmds[cmd][0].include? args.length then
  $stderr.puts "invalid argument number"
  usage
end

begin
  method(cmd).call(*args)
rescue TML::Error
  $stderr.puts $!.to_s
  exit 1
end
