Index: /trunk/pymigemo/README.ja_JP.UTF-8
===================================================================
--- /trunk/pymigemo/README.ja_JP.UTF-8	(revision 30)
+++ /trunk/pymigemo/README.ja_JP.UTF-8	(revision 30)
@@ -0,0 +1,140 @@
+$Id$
+
+= ããã¯äœïŒ =
+C/Migemo ã Python ããäœ¿ãããã® wrapper ã§ãïŒ
+
+
+= å¿
+èŠãªãã® =
+C/Migemo ã©ã€ãã©ãªãã€ã³ã¹ããŒã«ãããŠããããšãåæãšãªã£ãŠããŸãïŒ
+ã©ã€ãã©ãªæ€çŽ¢ãã¹ã« migemo.so ãïŒãããæ€çŽ¢ãã¹ã« migemo.h ãå­åšããããšããç¢ºèªäžããïŒ
+
+
+= ã€ã³ã¹ããŒã«æ¹æ³ =
+åæ¢±ã® setup.py ããå©çšäžããïŒ
+
+{{{
+$ ./setup.py build
+# ./setup.py install
+}}}
+
+
+= ã©ã€ã»ã³ã¹ =
+äºæ¡é 
+ BSD ã©ã€ã»ã³ã¹ã«æºæ ããŸãïŒ
+è©³çŽ°ã¯åæ¢±ã® LICENSE ãã¡ã€ã«ããèŠ§äžããïŒ
+
+
+= äœ¿ãæ¹ =
+{{{
+>>> import migemo
+>>> m = migemo.Migemo("/usr/share/migemo/migemo-dict")
+>>> print m.query("hoge")
+(hoge|ïœïœïœïœ
+|ã»ã|æé¯š|åžæ¡|è£å
+|ãã²)
+}}}
+
+
+== ãªãã¡ã¬ã³ã¹ ==
+=== ã¢ãžã¥ãŒã«ã³ã³ãã³ã ===
+ * VERSION
+   * MIGEMO_VERSION
+     * C/Migemo ã®ããŒãžã§ã³
+   * PYMIGEMO_VERSION
+     * PyMigemo ã®ããŒãžã§ã³
+
+ * DICTID
+   * DICTID_MIGEMO
+     * migemo-dict èŸæž
+   * DICTID_ROMA2HIRA
+     * ã­ãŒãå­âå¹³ä»®åå€æè¡š
+   * DICTID_HIRA2KATA
+     * å¹³ä»®åâã«ã¿ã«ãå€æè¡š
+   * DICTID_HAN2ZEN
+     * åè§âå
+šè§å€æè¡š
+   * DICTID_ZEN2HAN
+     * å
+šè§âåè§å€æè¡š
+   * DICTID_INVALID
+     * load ã¡ãœããã§èŸæžã®èª­ã¿èŸŒã¿ã«å€±æããå Žåã«è¿ã
+
+ * OPINDEX
+   * OPINDEX_OR
+     * è«çå
+     * Migemo.get_operator() ã«æž¡ããéã®ããã©ã«ãã¯ "|"
+   * OPINDEX_NEST_IN
+     * ã°ã«ãŒãã³ã°æã®éãæ¬åŒ§
+     * Migemo.get_operator() ã«æž¡ããéã®ããã©ã«ãã¯ "("
+   * OPINDEX_NEST_OUT
+     * ã°ã«ãŒãã³ã°æã®éãæ¬åŒ§
+     * Migemo.get_operator() ã«æž¡ããéã®ããã©ã«ãã¯ ")"
+   * OPINDEX_SELECT_IN
+     * éžæã®éå§ãè¡šãéãéæ¬åŒ§
+     * Migemo.get_operator() ã«æž¡ããéã®ããã©ã«ãã¯ "["
+   * OPINDEX_SELECT_OUT
+     * éžæã®çµäºãè¡šãéãéæ¬åŒ§
+     * Migemo.get_operator() ã«æž¡ããéã®ããã©ã«ãã¯ "]"
+   * OPINDEX_NEWLINE
+     * åæå­ã®éã«æ¿å
+¥ãããã0 åä»¥äžã®ç©ºçœãããã¯æ¹è¡ã«ãããããããã¿ãŒã³
+     * Migemo.get_operator() ã«æž¡ããéã®ããã©ã«ãã¯ "" (ç©ºæå­å)
+
+ * Migemo ã¯ã©ã¹
+   * __init__(dictionary)
+     * Migemo ã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿
+     * åŒæ°
+       * dictionary: migemo-dict èŸæžãã¡ã€ã«ã®ãã¹ (str)
+   * get_encoding()
+     * migemo-dict èŸæžã®ãšã³ã³ãŒãã£ã³ã°ã str ã§è¿ãïŒ
+       äŸãã° EUC-JP ã§æžãããèŸæžã§ããã° "euc_jp" ãè¿ãïŒ
+       cp932ïŒeuc_jpïŒutf8 ã®ãããããè¿ããïŒ
+       èŸæžã®ãšã³ã³ãŒãã£ã³ã°ããããã«è©²åœããªãã£ãå Žåã¯ "ascii" ãè¿ã
+     * åŒæ°
+       * ãªã
+     * è¿ãå€
+       * ãšã³ã³ãŒãã£ã³ã°æå­å (str)
+   * get_operator(index)
+     * index ã§æå®ãããïŒæ­£èŠè¡šçŸã«äœ¿çšããã¡ã¿æå­ãè¿ã (str)
+     * åŒæ°
+       * index: åè¿°ã® OPINDEX ã®ãããã
+     * è¿ãå€
+       * ã¡ã¿æå­å (str)
+   * is_enable()
+     * Migemo å
+éšã«ïŒæ­£åžžã«èŸæžãèª­ã¿èŸŒããŠãããã©ããããã§ãã¯ãã
+     * åŒæ°
+       * ãªã
+     * è¿ãå€
+       * çåœå€ (int) : æ­£åžžã«èª­ã¿èŸŒããŠããå Žåã«ç
+   * load(dict_id, dict_file)
+     * Migemo ãªããžã§ã¯ãã«èŸæžãè¿œå ã§èª­ã¿èŸŒã
+     * åŒæ°
+       * dict_id: åè¿°ã® DICTID ã®ãããã
+       * dict_file: èŸæžãã¡ã€ã«ã®ãã¹
+     * è¿ãå€
+       * èª­ã¿èŸŒãã èŸæžã® DICTIDïŒ
+         èª­ã¿èŸŒã¿ã«å€±æããå Žå DICTID_INVALID ãè¿ã
+   * query(query)
+     * query ã§äžããããæå­åããæ¥æ¬èªæ€çŽ¢ã®ããã®æ­£èŠè¡šçŸãè¿ã
+     * åŒæ°
+       * query: åãåãããæå­å (Unicode or str)ïŒ
+         str ã§ ascii ä»¥å€ã®æå­åãæž¡ãå ŽåïŒ
+         èŸæžãšåããšã³ã³ãŒãã£ã³ã°ã®æå­åã§ãªããšãšã©ãŒã«ãªãå¯èœæ§ããã
+     * è¿ãå€
+       * æ­£èŠè¡šçŸæå­å (Unicode)
+   * set_operator(index, op)
+     * index ã§æå®ãããïŒæ­£èŠè¡šçŸã«äœ¿çšããã¡ã¿æå­ã op ã«å€æŽãã
+     * åŒæ°
+       * index: åè¿°ã® OPINDEX ã®ãããã
+       * op: ã¡ã¿æå­å (str)
+     * è¿ãå€
+       * çåœå€ (int) : æåæã«ç
+
+
+= ãã®ä» =
+æ¬ãœãããŠã§ã¢ã«å¯Ÿããã³ã¡ã³ãïŒãã°å ±åïŒããããªã©ã¯å€§ãã«æ­è¿ããŸãïŒ
+äžèšã¡ãŒã«ã¢ãã¬ã¹ãŸã§ãæ°è»œã«ãå¯ãäžããïŒ
+
+Atzm WATANABE <atzm@atzm.org>
Index: /trunk/pymigemo/LICENSE
===================================================================
--- /trunk/pymigemo/LICENSE	(revision 30)
+++ /trunk/pymigemo/LICENSE	(revision 30)
@@ -0,0 +1,23 @@
+Copyright (c) 2005-2009, Atzm WATANABE <atzm@atzm.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
Index: /trunk/pymigemo/pymigemo.c
===================================================================
--- /trunk/pymigemo/pymigemo.c	(revision 30)
+++ /trunk/pymigemo/pymigemo.c	(revision 30)
@@ -0,0 +1,386 @@
+/*
+ * pymigemo.c - C/Migemo wrapper for Python
+ * Copyright(C) 2005-2009, Atzm WATANABE <atzm@atzm.org>
+ *
+ * $Id$
+ */
+
+#include <Python.h>
+#include <structmember.h>
+#include <migemo.h>
+#include <string.h>
+
+#define PYMIGEMO_VERSION "0.2"
+
+/* for dereference migemo object members */
+struct _migemo {
+    int   enable;
+    void *mtree;
+    int   charset;
+    void *roma2hira;
+    void *hira2kata;
+    void *han2zen;
+    void *zen2han;
+    void *rx;
+    void *addword;
+    void *char2int;
+};
+
+typedef struct {
+    PyObject_HEAD
+    migemo *migemo_obj;
+} Migemo;
+
+static void
+Migemo_dealloc(Migemo *self)
+{
+    if (self->migemo_obj) {
+        migemo_close(self->migemo_obj);
+    }
+
+    self->ob_type->tp_free((PyObject *)self);
+}
+
+static PyObject *
+Migemo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    Migemo *self;
+
+    self = (Migemo *)type->tp_alloc(type, 0);
+
+    if (self != NULL) {
+        self->migemo_obj = NULL;
+    }
+
+    return (PyObject *)self;
+}
+
+static int
+Migemo_init(Migemo *self, PyObject *args, PyObject *kwds)
+{
+    migemo *migemo_obj;
+    char   *dictionary;
+
+    static char *kwlist[] = {"dictionary", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &dictionary)) {
+        return -1;
+    }
+
+    if (dictionary) {
+        if (self->migemo_obj) {
+            migemo_close(self->migemo_obj);
+        }
+
+        migemo_obj = migemo_open(dictionary);
+
+        if (migemo_obj) {
+            self->migemo_obj = migemo_obj;
+        }
+        else {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int
+get_encoding(char *encoding, size_t size, int charset)
+{
+    char *enc;
+
+    switch(charset) {
+    case 1:
+        enc = "cp932";
+        break;
+    case 2:
+        enc = "euc_jp";
+        break;
+    case 3:
+        enc = "utf_8";
+        break;
+    default:
+        enc = "ascii";
+    }
+
+    if (strlen(enc) < size) {
+        strcpy(encoding, enc);
+        return 1;
+    }
+
+    return 0;
+}
+
+static PyObject *
+Migemo_get_encoding(Migemo *self)
+{
+    char encoding[7];
+
+    if (!get_encoding(encoding, sizeof(encoding), self->migemo_obj->charset)) {
+        return NULL;
+    }
+
+    return PyString_FromString(encoding);
+}
+
+static PyObject *
+Migemo_query(Migemo *self, PyObject *args, PyObject *kwds)
+{
+    PyObject      *result, *query_obj, *query_str = NULL, *regex_strobj = NULL;
+    char          *query, encoding[7];
+    unsigned char *regex;
+
+    static char *kwlist[] = {"query", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &query_obj)) {
+        return NULL;
+    }
+
+    if (!get_encoding(encoding, sizeof(encoding), self->migemo_obj->charset)) {
+        return NULL;
+    }
+
+    if (PyUnicode_Check(query_obj)) {
+        query_str = PyUnicode_AsEncodedString(query_obj, encoding, "strict");
+        query     = PyString_AS_STRING(query_str);
+    }
+    else if (PyString_Check(query_obj)) {
+        query = PyString_AS_STRING(query_obj);
+    }
+    else {
+        return NULL;
+    }
+
+    if (query) {
+        regex = migemo_query(self->migemo_obj, query);
+
+        if (regex) {
+            regex_strobj = PyString_FromString(regex);
+
+            if (regex_strobj) {
+                result = PyUnicode_FromEncodedObject(regex_strobj, encoding, "strict");
+            }
+
+            migemo_release(self->migemo_obj, regex);
+        }
+    }
+
+    Py_XDECREF(regex_strobj);
+    Py_XDECREF(query_str);
+
+    if (!result) {
+        return NULL;
+    }
+
+    return result;
+}
+
+static PyObject *
+Migemo_set_operator(Migemo *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *result;
+    char     *op;
+    int       index;
+  
+    static char *kwlist[] = {"index", "op", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &index, &op)) {
+        return NULL;
+    }
+
+    if (op) {
+        result = PyInt_FromLong((long)migemo_set_operator(self->migemo_obj, index, op));
+    }
+
+    if (!result) {
+        return NULL;
+    }
+
+    return result;
+}
+
+static PyObject *
+Migemo_get_operator(Migemo *self, PyObject *args, PyObject *kwds)
+{
+    PyObject      *result;
+    unsigned char *op;
+    int            index;
+  
+    static char *kwlist[] = {"index", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &index)) {
+        return NULL;
+    }
+
+    if (op = migemo_get_operator(self->migemo_obj, index)) {
+        result = PyString_FromString(op);
+    }
+
+    if (!result) {
+        return NULL;
+    }
+
+    return result;
+}
+
+static PyObject *
+Migemo_load(Migemo *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *result;
+    char     *dict_file;
+    int       dict_id;
+  
+    static char *kwlist[] = {"dict_id", "dict_file", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &dict_id, &dict_file)) {
+        return NULL;
+    }
+
+    if (dict_file) {
+        result = PyInt_FromLong((long)migemo_load(self->migemo_obj, dict_id, dict_file));
+    }
+
+    if (!result) {
+        return NULL;
+    }
+
+    return result;
+}
+
+static PyObject *
+Migemo_is_enable(Migemo *self)
+{
+    return PyInt_FromLong((long)migemo_is_enable(self->migemo_obj));
+}
+
+static PyMethodDef Migemo_methods[] = {
+    {"query", (PyCFunction)Migemo_query, METH_KEYWORDS,
+     "return regex from romaji string\n\
+\n\
+def query(query)\n\
+  query: romaji string (str or unicode)\n\
+\n\
+  returns: regex string as Unicode object"},
+    {"set_operator", (PyCFunction)Migemo_set_operator, METH_KEYWORDS,
+     "set operator string as the meta character of regex\n\
+\n\
+def set_operator(index, op):\n\
+  index: (OPINDEX_NEST_IN|OPINDEX_NEST_OUT|OPINDEX_NEWLINE|\n\
+          OPINDEX_OR|OPINDEX_SELECT_IN|OPINDEX_SELECT_OUT)\n\
+  op: operator string (str)\n\
+\n\
+  returns: boolean value"},
+    {"get_operator", (PyCFunction)Migemo_get_operator, METH_KEYWORDS,
+     "get operator string as the meta character of regex\n\
+\n\
+def get_operator(index)\n\
+  index: (OPINDEX_NEST_IN|OPINDEX_NEST_OUT|OPINDEX_NEWLINE|\n\
+          OPINDEX_OR|OPINDEX_SELECT_IN|OPINDEX_SELECT_OUT)\n\
+\n\
+  returns: operator string (str)"},
+    {"load", (PyCFunction)Migemo_load, METH_KEYWORDS,
+     "add dictionary to Migemo object\n\
+\n\
+def load(dict_id, dict_file)\n\
+  dict_id: (DICTID_HAN2ZEN|DICTID_HIRA2KATA|DICTID_MIGEMO|\n\
+            DICTID_ROMA2HIRA|DICTID_ZEN2HAN)\n\
+  dict_file: path to dictionary file (str)\n\
+\n\
+  returns: boolean value"},
+    {"is_enable", (PyCFunction)Migemo_is_enable, METH_NOARGS,
+     "check internal migemo_dict\n\
+\n\
+def is_enable()\n\
+  returns: boolean value"},
+    {"get_encoding", (PyCFunction)Migemo_get_encoding, METH_NOARGS,
+     "get dictionary encoding\n\
+\n\
+def get_encoding()\n\
+  returns: encoding string (str)"},
+    {NULL} /* Sentinel */
+};
+
+static PyMemberDef Migemo_members[] = {
+    {NULL} /* Sentinel */
+};
+
+static PyTypeObject MigemoType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                          /*ob_size*/
+    "migemo.Migemo",            /*tp_name*/
+    sizeof(Migemo),             /*tp_basicsize*/
+    0,                          /*tp_itemsize*/
+    (destructor)Migemo_dealloc, /*tp_dealloc*/
+    0,                          /*tp_print*/
+    0,                          /*tp_getattr*/
+    0,                          /*tp_setattr*/
+    0,                          /*tp_compare*/
+    0,                          /*tp_repr*/
+    0,                          /*tp_as_number*/
+    0,                          /*tp_as_sequence*/
+    0,                          /*tp_as_mapping*/
+    0,                          /*tp_hash */
+    0,                          /*tp_call*/
+    0,                          /*tp_str*/
+    0,                          /*tp_getattro*/
+    0,                          /*tp_setattro*/
+    0,                          /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+    "Migemo wrapper object",    /* tp_doc */
+    0,                          /* tp_traverse */
+    0,                          /* tp_clear */
+    0,                          /* tp_richcompare */
+    0,                          /* tp_weaklistoffset */
+    0,                          /* tp_iter */
+    0,                          /* tp_iternext */
+    Migemo_methods,             /* tp_methods */
+    Migemo_members,             /* tp_members */
+    0,                          /* tp_getset */
+    0,                          /* tp_base */
+    0,                          /* tp_dict */
+    0,                          /* tp_descr_get */
+    0,                          /* tp_descr_set */
+    0,                          /* tp_dictoffset */
+    (initproc)Migemo_init,      /* tp_init */
+    0,                          /* tp_alloc */
+    Migemo_new,                 /* tp_new */
+};
+
+static PyMethodDef module_methods[] = {
+    {NULL} /* Sentinel */
+};
+
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+initmigemo(void) 
+{
+    PyObject* m;
+
+    if (PyType_Ready(&MigemoType) < 0)
+        return;
+
+    m = Py_InitModule3("migemo", module_methods, "C/Migemo wrapper");
+
+    Py_INCREF(&MigemoType);
+    PyModule_AddObject(m, "Migemo", (PyObject *)&MigemoType);
+    PyModule_AddObject(m, "PYMIGEMO_VERSION", Py_BuildValue("s", PYMIGEMO_VERSION));
+
+    PyModule_AddObject(m, "MIGEMO_VERSION", Py_BuildValue("s", MIGEMO_VERSION));
+
+    PyModule_AddObject(m, "DICTID_INVALID", Py_BuildValue("i", MIGEMO_DICTID_INVALID));
+    PyModule_AddObject(m, "DICTID_MIGEMO", Py_BuildValue("i", MIGEMO_DICTID_MIGEMO));
+    PyModule_AddObject(m, "DICTID_ROMA2HIRA", Py_BuildValue("i", MIGEMO_DICTID_ROMA2HIRA));
+    PyModule_AddObject(m, "DICTID_HIRA2KATA", Py_BuildValue("i", MIGEMO_DICTID_HIRA2KATA));
+    PyModule_AddObject(m, "DICTID_HAN2ZEN", Py_BuildValue("i", MIGEMO_DICTID_HAN2ZEN));
+    PyModule_AddObject(m, "DICTID_ZEN2HAN", Py_BuildValue("i", MIGEMO_DICTID_ZEN2HAN));
+
+    PyModule_AddObject(m, "OPINDEX_OR", Py_BuildValue("i", MIGEMO_OPINDEX_OR));
+    PyModule_AddObject(m, "OPINDEX_NEST_IN", Py_BuildValue("i", MIGEMO_OPINDEX_NEST_IN));
+    PyModule_AddObject(m, "OPINDEX_NEST_OUT", Py_BuildValue("i", MIGEMO_OPINDEX_NEST_OUT));
+    PyModule_AddObject(m, "OPINDEX_SELECT_IN", Py_BuildValue("i", MIGEMO_OPINDEX_SELECT_IN));
+    PyModule_AddObject(m, "OPINDEX_SELECT_OUT", Py_BuildValue("i", MIGEMO_OPINDEX_SELECT_OUT));
+    PyModule_AddObject(m, "OPINDEX_NEWLINE", Py_BuildValue("i", MIGEMO_OPINDEX_NEWLINE));
+}
Index: /trunk/pymigemo/setup.py
===================================================================
--- /trunk/pymigemo/setup.py	(revision 28)
+++ /trunk/pymigemo/setup.py	(revision 28)
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+
+from distutils.core import setup, Extension
+setup(name="migemo",
+      version="1.0",
+      description="C/Migemo wrapper for Python",
+      author="Atzm WATANABE",
+      author_email="atzm@atzm.org",
+      ext_modules=[Extension("migemo", ["pymigemo.c"], libraries=["migemo"])])
Index: /trunk/amazonbot/amazonbot.py
===================================================================
--- /trunk/amazonbot/amazonbot.py	(revision 20)
+++ /trunk/amazonbot/amazonbot.py	(revision 28)
@@ -3,10 +3,11 @@
 
 __version__ = '$Revision$'
-__author__ = 'Atzm WATANABE <sitosito@p.chan.ne.jp>'
+__author__ = 'Atzm WATANABE <atzm@atzm.org>'
 __date__ = '$Date$'
-__copyright__ = 'Copyright(C) 2006 Atzm WATANABE, all rights reserved.'
+__copyright__ = 'Copyright(C) 2006-2007 Atzm WATANABE, all rights reserved.'
 __license__ = 'Python'
 
 import re
+import string
 import sys
 import time
@@ -147,4 +148,6 @@
             return method(c, e, to, words[1:]) # words[0] == command name
 
+        self.message_action(msg, c, e, to)
+
         # silence
         self.silence(msg, c, e, to)
@@ -217,4 +220,63 @@
     def get_prev_time(self):
         return self._prev_time
+
+    def message_action(self, msg, c, e, to):
+        for i in xrange(100):
+            action = 'action%d' % i
+            if not config.has_section(action):
+                break
+
+            c_stime = config.get(action, 'start_time')
+            c_etime = config.get(action, 'end_time')
+
+            try:
+                if c_stime and c_etime:
+                    now = time.time()
+                    [now_y, now_m, now_d] = time.localtime(now)[:3]
+
+                    stime = '%04d/%02d/%02d %s' % (now_y, now_m, now_d, c_stime)
+                    etime = '%04d/%02d/%02d %s' % (now_y, now_m, now_d, c_etime)
+                    stime = time.mktime(time.strptime(stime, '%Y/%m/%d %H:%M'))
+                    etime = time.mktime(time.strptime(etime, '%Y/%m/%d %H:%M'))
+
+                    if not ((stime <= now) and (now <= etime)):
+                        _debug('Out of time: %s - %s' % (c_stime, c_etime))
+                        continue
+            except:
+                _debug('Invalid time: %s - %s' % (str(c_stime), str(c_etime)))
+                continue
+
+            pattern = unicoding(config.get(action, 'input_pattern'))
+            match   = None
+            try:
+                match = re.search(pattern, msg)
+            except:
+                _debug('Invalid regexp: %s', pattern)
+                continue
+
+            if not match:
+                continue
+
+            act = config.get(action, 'action')
+            fmt = config.get(action, 'message')
+            try:
+                _from   = nm_to_n(e.source())
+                message = ununicoding(fmt % _from)
+
+                if not message:
+                    _debug('No message specified')
+                    continue
+
+                if not act:
+                    c.notice(to, message)
+                    continue
+
+                method = getattr(self, 'onact_%s' % act, lambda *arg: False)
+                method(message, c, e, to)
+
+            except:
+                _debug('Action failed: %s (%s)' % (str(act), str(fmt)))
+
+        return True
 
 class AmazonBot(AmazonBotBase):
@@ -244,4 +306,28 @@
         return 'AmazonBot by %s, based on python-irclib' % __author__
 
+    def onmsg_reload(self, c, e, to, args):
+        """Syntax: !reload
+        """
+        _debug('in reload command: %s', str(args))
+        config.read()
+        c.notice(to, 'reloaded config')
+        return True
+
+    def onmsg_lt(self, c, e, to, args): return self.onmsg_localtime(c, e, to, args)
+    def onmsg_localtime(self, c, e, to, args):
+        """Syntax: !localtime <unix time>
+        """
+        _debug('in localtime command: %s', str(args))
+
+        _from = nm_to_n(e.source())
+        try:
+            sec = float(args[0])
+            c.notice(_from, time.strftime('%b %d %T', time.localtime(sec)))
+        except ValueError, e:
+            c.notice(_from, 'Invalid argument: %s' % args[0])
+            return False
+
+        return True
+
     def onmsg_s(self, c, e, to, args): return self.onmsg_status(c, e, to, args)
     def onmsg_status(self, c, e, to, args):
@@ -385,4 +471,48 @@
         return [product_name, url]
 
+    def onact_oper(self, msg, c, e, to):
+        nick = nm_to_n(e.source())
+        _debug('in oper action: %s to %s in %s' % (msg, nick, to))
+        c.notice(to, msg)
+        c.mode(to, '+o %s' % nick)
+        return True
+
+    def onact_nooper(self, msg, c, e, to):
+        nick = nm_to_n(e.source())
+        _debug('in nooper action: %s to %s in %s' % (msg, nick, to))
+        c.notice(to, msg)
+        c.mode(to, '-o %s' % nick)
+        return True
+
+    def onact_kick(self, msg, c, e, to):
+        nick = nm_to_n(e.source())
+        _debug('in kick action: %s to %s in %s' % (msg, nick, to))
+        c.kick(to, nick, msg)
+        return True
+
+    def onact_kick_and_invite(self, msg, c, e, to):
+        nick = nm_to_n(e.source())
+        _debug('in kick_and_invite action: %s to %s in %s' % (msg, nick, to))
+        c.kick(to, nick, msg)
+        c.invite(nick, to)
+        return True
+
+    NICK_TRANS_TABLE = string.maketrans('-_i1z2o0s5bdnmft', '_-1i2z0o5sdbmntf')
+    def onact_nick(self, msg, c, e, to):
+        nick   = nm_to_n(e.source())
+        nickto = nick[0] + nick[1:].translate(self.NICK_TRANS_TABLE)
+        if nick == nickto:
+            nickto = nick + '_'
+        _debug('in nick action: %s to %s in %s (%s)' % (msg, nick, to, nickto))
+        c.notice(to, msg)
+        c.nick(nickto)
+        return True
+
+    def onact_topic(self, msg, c, e, to):
+        nick = nm_to_n(e.source())
+        _debug('in topic action: %s to %s in %s' % (msg, nick, to))
+        c.topic(to, msg)
+        return True
+
 if __name__ == '__main__':
     bot = AmazonBot()
Index: /trunk/amazonbot/my_amazon.py
===================================================================
--- /trunk/amazonbot/my_amazon.py	(revision 8)
+++ /trunk/amazonbot/my_amazon.py	(revision 24)
@@ -291,5 +291,11 @@
     u = urllib.FancyURLopener(proxies)
     usock = u.open(url)
-    xmldoc = minidom.parse(usock)
+    xmldoc = None
+    try:
+        xmldoc = minidom.parse(usock)
+    except:
+        raise AmazonError, 'XML Parsing Error'
+    if xmldoc is None:
+        raise AmazonError, 'XML Parsing Error (Result is None)'
 
 #     from xml.dom.ext import PrettyPrint
Index: /trunk/amazonbot/amazonbot.ini.sample
===================================================================
--- /trunk/amazonbot/amazonbot.ini.sample	(revision 18)
+++ /trunk/amazonbot/amazonbot.ini.sample	(revision 22)
@@ -1,19 +1,31 @@
 [amazon]
-locale = jp
+locale     = jp
 access_key = your access key
 
 [irc]
-server = irc.freenode.net
-port = 6667
+server  = irc.freenode.net
+port    = 6667
 channel = #amazonbot
 
 [bot]
-nick = amazonbot
-content = ãããªã¢ãã¿ã«ããããªã¹ã¹ã¡
-thanks = ããããšã
-sorry = æ­£çŽããŸããã£ã
-bye = ããããªããŸãäŒãæ¥ãŸã§
-active_pattern = ããã|ãŽã¡ã³|ããŸã|ã¹ãã³|ãããŸãã
-silent_pattern = éªé­|ãããŸ|ãžã£ã|ãã(ãã|ããŒ)|ã ãŸã
+nick           = amazonbot
+content        = ãããªã¢ãã¿ã«ããããªã¹ã¹ã¡
+thanks         = ããããšã
+sorry          = æ­£çŽããŸããã£ã
+bye            = ããããªããŸãäŒãæ¥ãŸã§
+no_products    = èŠã€ãããŸããã§ãã
+active_pattern = ((ããã|ãŽã¡ã³)(ãªãã)?|(ããŸã|ã¹ãã³)|(ã(ã|ã¿)ãŸãã))[ãªãã­ãŒã»âŠ.ããïŒ!]*$
+silent_pattern = (éªé­|ãããŸ|ãžã£ã|ãã(ãã|ããŒ)|ã ãŸã)[ã ããªãŒ-ïŒ!]*$
+
+[action0]
+input_pattern = ã(æ©|ã¯ã)ãããããŸã
+message       = ãã¯ããããããŸã %s ãã
+action        = oper
+start_time    = 06:00
+end_time      = 12:00
+
+[action1]
+input_pattern = ããã²ãšãããã.*ãã¯ãŒãã¡ããªã«
+message       = ããã§ããšãïŒ
 
 [freq]
Index: /trunk/amazonbot/config.py
===================================================================
--- /trunk/amazonbot/config.py	(revision 8)
+++ /trunk/amazonbot/config.py	(revision 28)
@@ -2,10 +2,10 @@
 
 __version__ = '$Revision$'
-__author__ = 'Atzm WATANABE <sitosito@p.chan.ne.jp>'
+__author__ = 'Atzm WATANABE <atzm@atzm.org>'
 
 import os, ConfigParser
 
 _userconfig = 'amazonbot.ini'
-_parser = ConfigParser.SafeConfigParser()
+_parser = ConfigParser.RawConfigParser()
 
 def set(sect, key, val):
@@ -30,4 +30,7 @@
 			return ''
 
+def has_section(sect):
+    return _parser.has_section(sect)
+
 def write(filename=''):
 	if not filename:
