changeset 613:ea6ebcf42b47

TJ: Initial commit of the TJ2.0 refactoring effort. Instead of using Eggdrop XTRA user flags for storing data, we now employ a SQLite3 database. The database schema is probably not yet "final", so maybe beware of deploying this script yet. Also add example configuration file and script for creating the empty database tables.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 10 Feb 2021 11:12:13 +0200
parents c340683d6c13
children 8c61b4032648
files config.tj.example create_tj_db.tcl tj.tcl
diffstat 3 files changed, 551 insertions(+), 149 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.tj.example	Wed Feb 10 11:12:13 2021 +0200
@@ -0,0 +1,100 @@
+##########################################################################
+#
+# TJ script configuration
+#
+##########################################################################
+
+###
+### Bind commands
+###
+bind pub - !tj tj_cmd_pub
+bind msg - !tj tj_cmd_msg
+proc tj_cmd_pub {unick uhost uhand uchan utext} { tj_cmd $unick $uhost $uhand $uchan $utext 1 }
+proc tj_cmd_msg {unick uhost uhand utext}       { tj_cmd $unick $uhost $uhand "" $utext 0 }
+
+
+# Name of the command used for help texts
+set tj_cmd_name "!tj"
+
+
+# Sub-command name regexp patterns
+array set tj_commands {
+  "help" {^(\?|help|apua)$}
+  "set" {^(set|aseta)$}
+  "remind" {^(remind|muist)}
+  "list" {^(list|listaa?)$}
+  "delete" {^(del|delete|poista)$}
+  "show" {^(show|näytä|nayta)$}
+}
+
+
+###
+### Settings
+###
+# SQLite3 database
+set tj_db_file "tj.sqlite"
+
+
+# Default time (hh:mm) when not specified
+set tj_default_time "12:00"
+
+
+# Default ID for TJ
+set tj_default_id "SA-INT"
+set tj_default_desc "armeijapalveluksen päättyminen"
+
+
+# Channels where TJ functionality is enabled
+# set weather_channels "#foobar;#baz"
+# You can use * to match substrings or everything
+set tj_channels "*"
+
+
+# 1 = Enable logging of various script actions into bot's log
+# 0 = Don't.
+set tj_log_enable 1
+
+
+# What IRC "command" should we use to send messages:
+# (Valid alternatives are "PRIVMSG" and "NOTICE")
+set tj_preferredmsg "PRIVMSG"
+
+
+###
+### Message texts (informal, errors, etc.)
+###
+
+array set tj_messages {
+  "datefmt" "%d.%m.%Y %H:%M"
+
+  "help_full" {"help" "help_set" "help_list"}
+  "help" "@cmd@ \[#id\] \[nimi\]"
+  "help_set" "@cmd@ set \[#id\] <\[-\]päivät \[+/-<tunnit>\] | dd.mm.yyyy \[hh:mm\]> [<kuvaus>]"
+  "help_list" "@cmd@ list"
+
+  "err_invalid_user" "Pyh, mene pois."
+  "err_unknown_user" "en tunne @1@"
+
+  "help_remind_add" "@cmd@ muistuta <id>"
+  "help_remind_delete" "@cmd@ poista <id>"
+
+  "tj_set" "@3@:n @2@-TJ asetettu @5@ (@6@): @4@"
+  "tj_updated" "@3@:n @2@-TJ päivitetty @5@ (@6@): @4@"
+
+  "tj_str_year" "vuosi"
+  "tj_str_years" "@1@ vuotta"
+  "tj_str_day" "aamu"
+  "tj_str_days" "@1@ aamua"
+  "tj_str_hour" "tunnin"
+  "tj_str_hours" "@1@ tuntia"
+  "tj_str_minute" "minuutin"
+  "tj_str_minutes" "@1@ minuuttia"
+
+  "tj_str_sep" ", "
+  "tj_str_sep_last" " ja "
+
+  "tj_remaining" "@1@:llä on @3@ jäljellä @2@ (@4@)."
+  "tj_past" "@1@ on ollut @2@-reservissä @3@ (@4@)."
+
+  "tj_not_set" "@1@:n @2@-TJ:tä ei ole asetettu."
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/create_tj_db.tcl	Wed Feb 10 11:12:13 2021 +0200
@@ -0,0 +1,48 @@
+#!/usr/bin/tclsh
+# TCL script for creating (empty) TJ 2 SQLite3 database
+#
+# Written by Matti 'ccr' Hamalainen <ccr@tnsp.org>
+# (C) Copyright 2021 Tecnic Software productions (TNSP)
+#
+package require sqlite3
+source [file dirname [info script]]/utillib.tcl
+
+set db_create_desc "Creates tables for tj.tcl in target SQLite3 file"
+set db_table_list {tj}
+
+
+proc db_create_table { dbh utable } {
+  set sch {}
+  lappend sch "id INTEGER PRIMARY KEY AUTOINCREMENT"
+
+  # username this item belongs to
+  lappend sch "uuser VARCHAR(32)"
+
+  # created timestamp
+  lappend sch "ucreated INT"
+
+  # description
+  lappend sch "udesc VARCHAR(1024)"
+
+  # 0 = TJ, 1 = one-time reminder, 2 = repeat reminder
+  lappend sch "utype INT"
+
+  # unique identifier for type 0
+  lappend sch "uid VARCHAR(32)"
+
+  # target date/time
+  lappend sch "utarget DATETIME"
+
+  utl_create_table dbh "$utable" [join $sch ","]
+}
+
+proc db_drop_table { dbh utable } {
+  utl_drop_table dbh "$utable"
+}
+
+proc db_get_table_list { utable } {
+  return [list $utable]
+}
+
+
+source [file dirname [info script]]/utilcreate.tcl
--- a/tj.tcl	Wed Feb 10 11:08:26 2021 +0200
+++ b/tj.tcl	Wed Feb 10 11:12:13 2021 +0200
@@ -1,200 +1,454 @@
 ##########################################################################
 #
-# TJ (Army Mornings Left-counter) v0.70 by ccr/TNSP <ccr@tnsp.org>
-# (C) Copyright 2000,2009,2011,2021 Tecnic Software productions (TNSP)
+# TJ v2.0 by ccr/TNSP <ccr@tnsp.org>
+# (C) Copyright 2021 Tecnic Software productions (TNSP)
 #
 # This script is freely distributable under GNU GPL (version 2) license.
 #
-# Laskee aamuja tiettyyn paivamaaraan. TJ-paivamaara annettava
-# tietenkin etta toimii, oletuksena skripti asettaa (uudelle kayttajalle)
-# sen hetkisen ajan + 180 aamua. Esimerkkeja kaytosta:
-# !tj [nick]
-# /msg TheBot tj [nick]
-#
-# Ja TJ:n asetus toimii nain:
-# !tjaamut <[-]aamujen lkm tasta hetkesta laskien> [+/- tunnit]
-# !tjset dd.mm.yyyy hh:mm
-#
 ##########################################################################
 
-# Default starting TJ
-set tj_defstarttj 180
+### The configuration should be in config.tj in same directory
+### as this script. Or change the line below to point where ever
+### you wish. See "config.tj.example" for an example config file.
+source [file dirname [info script]]/config.tj
 
+### Required utillib.tcl
+source [file dirname [info script]]/utillib.tcl
 
 
 ##########################################################################
 # No need to look below this line
 ##########################################################################
-set tj_message "TJ (SA-INT model) v0.70 by ccr/TNSP"
-set tj_dateident "tjdate"
-set tj_preferredmsg "PRIVMSG"
+package require sqlite3
+package require textutil::split
 
-putlog "$tj_message"
-bind pub - !tj tj_pubmsg
-bind pub - !tjaamut tj_pubaamut
-bind pub - !tjset tj_pubset
+set tj_name "TJ"
+set tj_message "$tj_name v2.0 (C) 2021 ccr/TNSP"
+
 
 # ------------------------------------------------------------------------
-proc tj_correctnickcase { jnick } {
+### Utility functions
+proc tj_log {umsg} {
+  global tj_log_enable tj_name
+  if {$tj_log_enable != 0} {
+    putlog "${tj_name}: $umsg"
+  }
+}
+
+
+proc tj_qm {uid} {
+  global tj_messages
+
+  if {[info exists tj_messages($uid)]} {
+    return $tj_messages($uid)
+  } else {
+    return $uid
+  }
+}
 
-  if {![validuser $jnick]} { return "" }
-  set nicklwr [string tolower $jnick]
-  foreach juser [userlist] {
-    if {[string tolower $juser] == $nicklwr} {
-      unset nicklwr
-      return "$juser"
+
+proc tj_smsg {apublic anick achan amsg {aargs {}}} {
+  global tj_preferredmsg tj_cmd_name
+  set amsg [string map [list "@cmd@" $tj_cmd_name] $amsg]
+  utl_msg_args $tj_preferredmsg $apublic $anick $achan $amsg $aargs
+}
+
+
+proc tj_msg {apublic anick achan aid {aargs {}}} {
+  tj_smsg $apublic $anick $achan [tj_qm $aid] $aargs
+}
+
+
+proc tj_correct_handle {uhand} {
+  set ulower [string tolower $uhand]
+  foreach uuser [userlist] {
+    if {[string tolower $uuser] == $ulower} {
+      return $uuser
     }
   }
-
   return ""
 }
 
 
-# ------------------------------------------------------------------------
-proc tj_smsg {udest umsg} {
-  global tj_preferredmsg
+proc tj_cmd_match {uid ustr} {
+  global tj_commands
+  return [utl_cmd_match tj_commands $uid $ustr]
+}
+
+
+proc tj_arg_rest {rarglist rindex rstr} {
+  upvar $rstr dstr
+
+  if {$rindex < [llength $rarglist]} {
+    set dstr [join [lrange $rarglist $rindex end] " "]
+    return 1
+  } else {
+    return 0
+  }
+}
+
 
-  putserv "$tj_preferredmsg $udest :$umsg"
+proc tj_get_id {rstr rindex rid} {
+  global tj_default_id
+  upvar $rindex uindex
+  upvar $rid uid
+
+  if {[string index $rstr 0] == "#"} {
+    set uid [string tolower [string range $rstr 1 end]]
+    incr uindex
+    return 1
+  } else {
+    set uid $tj_default_id
+    return 0
+  }
+}
+
+
+proc tj_ctime {ustamp} {
+  return [clock format $ustamp -format [tj_qm "datefmt"]]
 }
 
 
 # ------------------------------------------------------------------------
-proc tj_pubmsg {nick uhost hand chan args} {
-  set args [string trim [join $args ""]]
-  if {$args == ""} { set args $hand }
-
-  tj_smsg $chan [tj_gettj $args $chan]
-  return 1
-}
-
-
-# ------------------------------------------------------------------------
-proc tj_ctime { utime } {
-  return [clock format $utime -format "%d.%m.%Y %H:%M"]
+proc tj_str_append { qlist qvalue qsingular qplural } {
+  upvar $qlist ulist
+  if {$qvalue > 0} {
+    if {$qvalue > 1} {
+      set qfmt $qplural
+    } else {
+      set qfmt $qsingular
+    }
+    lappend ulist [utl_str_map_values [tj_qm "tj_str_${qfmt}"] [list $qvalue]]
+  }
 }
 
 
-# ------------------------------------------------------------------------
-proc tj_pubaamut {unick uhost uhand uchan uargs} {
-  set foo [split $uargs " "]
-  set tjdays [lindex $foo 0]
-  set tjhours [lindex $foo 1]
+proc tj_get_tj_str {udelta} {
 
-  if {$tjdays == ""} {
-    tj_smsg $uchan "Hälärm."
-    return 1
+  if {$udelta < 0} {
+    set utmp [expr -$udelta]
+  } else {
+    set utmp $udelta
   }
 
-  if {$tjhours == ""} { set tjhours 0 }
+  set uyears [expr ($utmp / (365*24*60*60))]
+  set urem [expr ($utmp % (365*24*60*60))]
+  set udays [expr ($urem / (24*60*60))]
+  set urem [expr ($urem % (24*60*60))]
+  set uhours [expr ($urem / (60*60))]
+  set urem [expr ($urem % (60*60))]
+  set uminutes [expr ($urem / 60)]
 
-  set udate [expr [unixtime] + ($tjdays * 86400) + ($tjhours * 3600)]
-  tj_smsg $uchan [tj_settj $uhand $unick $udate]
-  return 1
+  set ulist {}
+  tj_str_append ulist $uyears "year" "years"
+  tj_str_append ulist $udays "day" "days"
+  tj_str_append ulist $uhours "hour" "hours"
+  tj_str_append ulist $uminutes "minute" "minutes"
+
+  set ustr [join [lrange $ulist 0 end-1] [tj_qm "tj_str_sep"]]
+  if {[llength $ulist] > 1} {
+    append ustr [tj_qm "tj_str_sep_last"]
+  }
+  append ustr [lindex $ulist end]
+
+  return $ustr
 }
 
 
-# ------------------------------------------------------------------------
-proc tj_pubset {unick uhost uhand uchan uargs} {
+proc tj_get_tj_str_delta { ustamp } {
+  set udelta [expr $ustamp - [clock seconds]]
+
+  if {$udelta < 0} {
+    set ufmt "tj_past"
+  } else {
+    set ufmt "tj_remaining"
+  }
+
+#  return [utl_str_map_values [tj_qm $ufmt] [list ]]
+  return [tj_get_tj_str $udelta]
+}
+
 
-  set udate [clock scan $uargs -format "%d.%N.%Y %H:%M"]
-  tj_smsg $uchan [tj_settj $uhand $unick $udate]
-  return 1
+proc tj_display_tjs {upublic unick uchan uname uid} {
+  set uclock [clock seconds]
+  set nresults 0
+  set usql "SELECT * FROM tj WHERE uuser='[utl_escape $uname]' AND utype=0 AND uid='[utl_escape $uid]'"
+  tj_dbh eval $usql {
+    incr nresults
+    set ustamp [utl_sql_datetime_to_stamp $utarget]
+    set udelta [expr $ustamp - $uclock]
+
+    if {$udelta < 0} {
+      set ufmt "tj_past"
+    } else {
+      set ufmt "tj_remaining"
+    }
+
+    tj_msg $upublic $unick $uchan $ufmt [list $uname $uid [tj_get_tj_str $udelta] [tj_ctime $ustamp]]
+  }
+
+  if {!$nresults} {
+    tj_msg $upublic $unick $uchan "tj_not_set" [list $uname $uid]
+  }
 }
 
 
 # ------------------------------------------------------------------------
-proc tj_settj { uuser unick udate } {
-  global tj_dateident
+proc tj_cmd {unick $uhost uhand uchan uargs upublic} {
+  global tj_messages tj_default_id tj_default_time tj_default_desc
 
-  if {![validuser $uuser]} {
-    return "Tuntematon käyttäjä ${uuser}."
+  # Check if we have a valid user
+  if {![utl_valid_user $uhand]} {
+    tj_msg $upublic $unick $uchan "err_invalid_user" [list $uhand]
+    return 1
   }
 
-  setuser $uuser XTRA $tj_dateident $udate
-  return "$unick:n ($uuser) TJ asetettu. ([tj_ctime $udate])"
+  set uhand [tj_correct_handle $uhand]
+
+  # Check and handle arguments
+  set rarglist [::textutil::split::splitx $uargs {\s+}]
+  set rcmd [lindex $rarglist 0]
+
+  if {[tj_cmd_match "help" $rcmd]} {
+    # Show help
+    foreach ukey $tj_messages(help_full) {
+      tj_msg $upublic $unick $uchan $ukey
+    }
+    return 1
+  } elseif {[tj_cmd_match "set" $rcmd]} {
+    # !tj set [#id] <[-/+]days [[+/-]<hours>] | dd.mm.yyyy [hh:mm]> [<desc>]
+    set rindex 1
+    if {![utl_arg_get $rarglist rindex rarg 0]} {
+      tj_msg $upublic $unick $uchan "help_set"
+      return 1
+    }
+
+    # Check for #id prefix
+    if {[tj_get_id $rarg rindex uid]} {
+      set rdesc ""
+    } else {
+      set rdesc $tj_default_desc
+    }
+
+    if {![utl_arg_get $rarglist rindex rarg 1]} {
+      tj_msg $upublic $unick $uchan "help_set"
+      return 1
+    }
+
+    # Is it a time stamp?
+    if {[regexp {\d+\.\d+\.\d\d\d\d} $rarg rdate]} {
+      # Seems so .. check for hours
+      set rtime $tj_default_time
+      if {[utl_arg_get $rarglist rindex rarg 0]} {
+        if {[regexp {\d+:\d+} $rarg rtime]} {
+          incr rindex
+        } else {
+          set rtime $tj_default_time
+        }
+      }
+
+      tj_arg_rest $rarglist $rindex rdesc
+
+      # Check the timestamp validity
+      if {[catch {set rstamp [clock scan "${rdate} ${rtime}" -format "%d.%m.%Y %H:%M"]} uerrmsg]} {
+        tj_msg $upublic $unick $uchan "err_timestamp" [list $uerrmsg $rdate $rtime]
+        return 1
+      }
+
+    } elseif {[regexp {(\+|\-)?(\d+)} $rarg -> dsign rdays]} {
+      # Check for days
+      if {$dsign == "-"} { set rdays [expr -$rdays] }
+
+      set rhours 0
+      if {[utl_arg_get $rarglist rindex rarg 0]} {
+        if {[regexp {(\+|\-)?(\d+)} $rarg -> hsign rhours]} {
+          if {$hsign == "-"} { set rhours [expr -$rhours] }
+          incr rindex
+        }
+
+        tj_arg_rest $rarglist $rindex rdesc
+
+        if {$rhours < -24 || $rhours > 24} {
+          tj_msg $upublic $unick $uchan "err_invalid_hours" [list $rhours]
+          return 1
+        }
+      }
+
+      # Compute target timestamp
+      set rstamp [expr [clock seconds] + ($rdays * 24 * 60 * 60) + ($rhours * 60 * 60)]
+    } else {
+      # Only description, if any
+      if {![tj_arg_rest $rarglist 1 rdesc]} {
+        tj_msg $upublic $unick $uchan "err_invalid_format" [list]
+        return 1
+      }
+      set rstamp "invalid"
+    }
+
+    # Check if ID exists
+    set umode 1
+    set nres 0
+    set usql "SELECT * FROM tj WHERE uid='[utl_escape $uid]'"
+    tj_dbh eval $usql {
+      set umode 0
+      set cid $id
+      set ctarget $utarget
+      incr nres
+    }
+
+    # Check for DB sanity
+    if {$nres > 1} {
+      tj_msg $upublic $unick $uchan "err_db_corrupt" [list $nres]
+      tj_log "too many $nres fatal error piip"
+      return 1
+    }
+
+    # Check if we are trying to add a new entry without valid timestamp
+    if {$rstamp == "invalid"} {
+      if {$umode} {
+        tj_msg $upublic $unick $uchan "err_missing_timestamp"
+        return 1
+      }
+
+      set rdate $ctarget
+      set ustamp [utl_sql_datetime_to_stamp $ctarget]
+    } else {
+      set rdate [utl_sql_stamp_to_datetime $rstamp]
+      set ustamp $rstamp
+    }
+
+    set utjstr [tj_get_tj_str_delta $rstamp]
+    set udate [tj_ctime $ustamp]
+
+    # Max reminders ..
+    set usql "SELECT COUNT(*) FROM tj WHERE uuser='[utl_escape $uhand]'"
+    if {[catch {set nreminders [tj_dbh onecolumn $usql]} uerrmsg]} {
+      tj_msg $upublic $unick $uchan "err_sql" [list $uerrmsg]
+      tj_log "$uerrmsg on SQL:\n$usql"
+      return 1
+    }
+
+    # Check for maximum reminders
+    if {$nreminders > 5} {
+      tj_msg $upublic $unick $uchan "err_too_many" [list $nreminders]
+      return 1
+    }
+
+    if {$umode} {
+      # Insert new entry
+      set usql "INSERT INTO tj (uid,uuser,ucreated,udesc,utype,utarget) VALUES ('[utl_escape $uid]', '[utl_escape $uhand]', [unixtime], '[utl_escape $rdesc]', 0, '$rdate')"
+      if {[catch {tj_dbh eval $usql} uerrmsg]} {
+        tj_msg $upublic $unick $uchan "err_sql" [list $uerrmsg]
+        tj_log "$uerrmsg on SQL:\n$usql"
+        return 1
+      }
+
+      set cid [tj_dbh last_insert_rowid]
+      tj_msg $upublic $unick $uchan "tj_set" [list $cid $uid $uhand $rdesc $udate $utjstr]
+      tj_log "tj_set $cid:$uid:$uhand:$rdesc:$rdate:$udate"
+    } else {
+      # Update existing entry
+      set usqlargs {}
+      if {[string length $rdesc] > 0} {
+        lappend usqlargs "udesc='[utl_escape $rdesc]'"
+      }
+      if {$rstamp != "invalid"} {
+        lappend usqlargs "utarget='$rdate'"
+      }
+
+      if {[llength $usqlargs] > 0} {
+        set usql "UPDATE tj SET [join $usqlargs ,] WHERE uid='[utl_escape $uid]'"
+        if {[catch {tj_dbh eval $usql} uerrmsg]} {
+          tj_msg $upublic $unick $uchan "err_sql" [list $uerrmsg]
+          tj_log "$uerrmsg on SQL:\n$usql"
+          return 1
+        }
+      }
+
+      tj_msg $upublic $unick $uchan "tj_updated" [list $cid $uid $uhand $rdesc $udate $utjstr]
+      tj_log "tj_updated $cid:$uid:$uhand:$rdesc:$rdate:$udate"
+    }
+
+  } elseif {[tj_cmd_match "remind" $rcmd]} {
+    # !tj remind <#id> <<dd.mm.yyyy [hh:mm]>|<message>>
+    # !tj remind <#id> <<dd.mm [hh:mm]>|<message>>
+    if {[llength $rarglist] < 3} {
+      tj_msg $upublic $unick $uchan "help_add"
+      return 1
+    }
+
+  } elseif {[tj_cmd_match "list" $rcmd]} {
+    # !tj list
+    # List reminders
+    set uclock [clock seconds]
+    set nresults 0
+    set usql "SELECT * FROM tj WHERE uuser='[utl_escape $uhand]' ORDER BY ucreated"
+    tj_dbh eval $usql {
+      incr nresults
+      tj_msg $upublic $unick $uchan "#${nresults}: $utype : $utarget : $uid : $udesc"
+    }
+
+    if {!$nresults} {
+      tj_msg $upublic $unick $uchan "no_results" [list $uname]
+    }
+
+  } elseif {[tj_cmd_match "delete" $rcmd]} {
+    # !tj delete <id>
+    tj_msg $upublic $unick $uchan "help_delete"
+  } elseif {[tj_cmd_match "show" $rcmd]} {
+    # !tj show [#id] <name>
+    # Check for #id prefix
+    set rindex 1
+    if {[utl_arg_get $rarglist rindex rarg 0]} {
+      tj_get_id $rarg rindex uid
+    }
+
+    if {![utl_arg_get $rarglist rindex rarg 0]} {
+      tj_msg $upublic $unick $uchan "help_show"
+      return 1
+    }
+
+    set uname [tj_correct_handle $rarg]
+    if {$uname == ""} {
+      tj_msg $upublic $unick $uchan "err_unknown_user" [list $rcmd]
+      return 1
+    }
+
+    tj_display_tjs $upublic $unick $uchan $uname $uid
+  } else {
+    # !tj [#id] [name]
+    set uname $uhand
+    set rindex 0
+    if {[utl_arg_get $rarglist rindex rarg 0]} {
+      # Check for #id prefix
+      tj_get_id $rarg rindex uid
+
+      if {[utl_arg_get $rarglist rindex rarg 0]} {
+        set uname [tj_correct_handle $rarg]
+        if {$uname == ""} {
+          tj_msg $upublic $unick $uchan "err_unknown_user" [list $rcmd]
+          return 1
+        }
+      }
+    } else {
+      set uid $tj_default_id
+    }
+
+    tj_display_tjs $upublic $unick $uchan $uname $uid
+  }
+
+  return 1
 }
 
 
-# ------------------------------------------------------------------------
-proc tj_append { qlause qaika qstr qadd } {
-  upvar $qlause lause
-  if {$qaika > 0} {
-    if {$lause != ""} { append lause $qadd }
-    append lause $qstr
-  }
+#-------------------------------------------------------------------------
+# Script initialization
+#-------------------------------------------------------------------------
+putlog "$tj_message"
+
+if {[catch {sqlite3 tj_dbh $tj_db_file} uerrmsg]} {
+  putlog "Could not open SQLite3 database '${tj_db_file}': ${uerrmsg}"
+  exit 2
 }
 
-# ------------------------------------------------------------------------
-proc tj_gettj {ihandle ichan} {
-  global tj_defstarttj
-  global tj_dateident
-
-  # Tarkistetaan onko kayttaja OK
-  if {![validuser $ihandle]} {
-    if {$ichan == ""} {
-      return "${ihandle}, Mene pois."
-    } else {
-      if {$ihandle == "*"} {
-        return "En tiedä kuka olet, mene pois."
-      } else {
-        return "En tiedä kuka ${ihandle} on."
-      }
-    }
-  }
-
-  set chandle [tj_correctnickcase $ihandle]
-
-  # Haetaan TJ aloitus paivamaara
-  set tjpaiva [getuser $chandle XTRA $tj_dateident]
-
-  if {$tjpaiva == ""} {
-    return "$chandle ei ole asettanut itselleen TJ päivämäärää."
-  }
-
-  # Lasketaan tamanhetkinen TJ aika
-  set deltatj [expr $tjpaiva - [unixtime]]
-
-  if {$deltatj < 0} {
-    set tmp [expr [unixtime] - $tjpaiva]
-  } else {
-    set tmp $deltatj
-  }
-
-  # Lasketaan TJ aamut, tunnit jne
-  set vuodet [expr ($tmp / (365*24*60*60))]
-  set rem [expr ($tmp % (365*24*60*60))]
-  set aamut [expr ($rem / (24*60*60))]
-  set rem [expr ($rem % (24*60*60))]
-  set tunnit [expr ($rem / (60*60))]
-
-  # Maaritetaan sanalause
-  if {$ichan != ""} {
-    set tjmt "${chandle}:lla on"
-    set tjmi "${chandle} on"
-  } else {
-    set tjmt "Sinulla on"
-    set tjmi "Sinä olet"
-  }
-
-  set lause ""
-  tj_append lause $vuodet "${vuodet} vuotta" ""
-  tj_append lause $aamut "${aamut} aamua" ", "
-  tj_append lause $tunnit "${tunnit} tuntia" " ja "
-
-  if {$aamut == 0 && $deltatj > 0} {
-    if {$tunnit == 0} {
-      return "$tjmt TOSI WÄINÖ! TJ 0!!"
-    } else {
-      return "$tjmt AIKA WÄBÄ -- TJ ${tunnit} tuntia!"
-    }
-  } else {
-    if {$deltatj > 0} {
-      return "${tjmt} ${lause} jäljellä... ([tj_ctime $tjpaiva])"
-    } else {
-      return "${tjmi} ollut reservissä jo ${lause}! ([tj_ctime $tjpaiva])"
-    }
-  }
-
-}
-
-# ------------------------------------------------------------------------
+# end of script