]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/mod-python.c
hash: add extra metadata to del user handlers
[irc/evilnet/x3.git] / src / mod-python.c
index da363ca7f8b0eef200c062890e531b5c8f51f1f6..8b69fa086c113aa627630d363f9d2121088734a4 100644 (file)
@@ -531,33 +531,13 @@ pyobj_from_exemptlist(struct exemptList* exmp) {
     return retval;
 }
 
-PyDoc_STRVAR(emb_get_channel__doc__,
-        "get_channel(channel) -> dict with channel information\n\n"
-        "Updates made to the returned dictionary does not reflect in the channel\n"
-        "information.");
-
 static PyObject*
-emb_get_channel(UNUSED_ARG(PyObject *self), PyObject *args)
-{
-    /* Returns a python dict object with all sorts of info about a channel.
-          usage: _svc.get_channel(<name>)
-    */
-    char *name;
-    struct chanNode *channel;
+pyobj_from_channode(struct chanNode* channel) {
     PyObject *pChannelMembers = NULL;
     PyObject *pChannelBans = NULL;
     PyObject *pChannelExempts = NULL;
     PyObject *retval = NULL;
 
-
-    if(!PyArg_ParseTuple(args, "s", &name))
-        return NULL;
-
-    if(!(channel = GetChannel(name))) {
-        PyErr_SetString(PyExc_Exception, "unknown channel");
-        return NULL;
-    }
-
     /* build tuple of nicks in channel */
     pChannelMembers = pyobj_from_modelist(&channel->members);
     if (pChannelMembers == NULL)
@@ -601,6 +581,31 @@ cleanup:
     return NULL;
 }
 
+PyDoc_STRVAR(emb_get_channel__doc__,
+        "get_channel(channel) -> dict with channel information\n\n"
+        "Updates made to the returned dictionary does not reflect in the channel\n"
+        "information.");
+
+static PyObject*
+emb_get_channel(UNUSED_ARG(PyObject *self), PyObject *args)
+{
+    /* Returns a python dict object with all sorts of info about a channel.
+          usage: _svc.get_channel(<name>)
+    */
+    char *name;
+    struct chanNode *channel;
+
+    if(!PyArg_ParseTuple(args, "s", &name))
+        return NULL;
+
+    if(!(channel = GetChannel(name))) {
+        PyErr_SetString(PyExc_Exception, "unknown channel");
+        return NULL;
+    }
+
+    return pyobj_from_channode(channel);
+}
+
 PyDoc_STRVAR(emb_get_account__doc__,
         "get_account(account) -> dict with account information\n\n"
         "Changes made to the returned dictionary will not be reflected in the\n"
@@ -1499,7 +1504,7 @@ python_handle_join(struct modeNode *mNode)
 }
 
 static int
-python_handle_server_link(struct server *server)
+python_handle_server_link(struct server *server, UNUSED_ARG(void *extra))
 {
     PyObject* srv = NULL;
     PyObject* funcname = NULL;
@@ -1550,7 +1555,7 @@ cleanup:
 }
 
 static int
-python_handle_new_user(struct userNode *user)
+python_handle_new_user(struct userNode *user, UNUSED_ARG(void *extra))
 {
     PyObject* name = NULL;
     PyObject* usr = NULL;
@@ -1558,6 +1563,11 @@ python_handle_new_user(struct userNode *user)
     int i = 0;
     const char* err = NULL;
 
+    if (handler_object == NULL) {
+        err = "No Python handler is allocated. Ignoring python_handle_server_link.";
+        goto cleanup;
+    }
+
     if(!user) {
         log_module(PY_LOG, LOG_WARNING, "Python code got new_user without the user");
         return 0;
@@ -1597,16 +1607,177 @@ cleanup:
 static void
 python_handle_nick_change(struct userNode *user, const char *old_nick)
 {
-    log_module(PY_LOG, LOG_INFO, "Python module handle_nick_change");
-    if(!user) {
-        log_module(PY_LOG, LOG_WARNING, "Python code got nick_change without the user!");
+    PyObject* usr = NULL;
+    PyObject* name = NULL;
+    PyObject* oldnick = NULL;
+    PyObject* retval = NULL;
+    char const* err = NULL;
+
+    if (handler_object == NULL) {
+        err = "No Python handler is allocated. Ignoring python_handle_server_link.";
+        goto cleanup;
     }
-    else {
-        char *args[] = {user->nick, (char *)old_nick};
-        python_call_handler("nick_change", args, 2, "", "", "");
+
+    if (user == NULL) {
+        err = "Python code got nick_change without the user!";
+        goto cleanup;
     }
+
+    if ((usr = pyobj_from_usernode(user)) == NULL) {
+        err = "unable to allocate Python usernode";
+        goto cleanup;
+    }
+
+    name = PyString_FromString("nick_change");
+    if (name == NULL) {
+        err = "unable to allocate memory for handler function name";
+        goto cleanup;
+    }
+
+    oldnick = PyString_FromString(old_nick);
+
+    retval = PyObject_CallMethodObjArgs(handler_object, name, usr, oldnick, NULL);
+    if (retval == NULL) {
+        err = "error calling nick_change handler";
+        goto cleanup;
+    }
+
+cleanup:
+    Py_XDECREF(usr);
+    Py_XDECREF(name);
+    Py_XDECREF(oldnick);
+    Py_XDECREF(retval);
+
+    if (err != NULL)
+        log_module(PY_LOG, LOG_WARNING, "%s", err);
 }
 
+void python_handle_del_user(struct userNode *user, struct userNode *killer, const char *why, UNUSED_ARG(void *extra)) {
+    PyObject *usr = NULL, *killr = NULL, *name = NULL;
+    PyObject *reason = NULL, *retval = NULL;
+    char const* err = NULL;
+
+    if (handler_object == NULL) {
+        err = "No Python handler is allocated. Ignoring python_handle_server_link.";
+        goto cleanup;
+    }
+
+    if (user == NULL) {
+        Py_INCREF(Py_None);
+        usr = Py_None;
+    } else {
+        usr = pyobj_from_usernode(user);
+        if (usr == NULL) {
+            err = "unable to allocate usernode for user";
+            goto cleanup;
+        }
+    }
+
+    if (killer == NULL) {
+        Py_INCREF(Py_None);
+        killr = Py_None;
+    } else {
+        killr = pyobj_from_usernode(killer);
+        if (killr == NULL) {
+            err = "unable to allocate usernode for killer";
+            goto cleanup;
+        }
+    }
+
+    if (why == NULL) {
+        Py_INCREF(Py_None);
+        reason = Py_None;
+    } else {
+        reason = PyString_FromString(why);
+        if (reason == NULL) {
+            err = "unable to allocate memory for reason";
+            goto cleanup;
+        }
+    }
+
+    name = PyString_FromString("del_user");
+    if (name == NULL) {
+        err = "unable to allocate memory for handler function name";
+        goto cleanup;
+    }
+
+    retval = PyObject_CallMethodObjArgs(handler_object, name, usr, killr, reason, NULL);
+    if (retval == NULL) {
+        err = "error calling del_user handler";
+        goto cleanup;
+    }
+
+cleanup:
+    Py_XDECREF(usr);
+    Py_XDECREF(killr);
+    Py_XDECREF(name);
+    Py_XDECREF(reason);
+    Py_XDECREF(retval);
+
+    if (err != NULL)
+        log_module(PY_LOG, LOG_WARNING, "%s", err);
+}
+
+int python_handle_topic(struct userNode *who, struct chanNode *chan, const char *old_topic) {
+    PyObject* pwho = NULL, *pchan = NULL, *oldtopic = NULL;
+    PyObject* name = NULL, *retval = NULL;
+    const char* err = NULL;
+    int i = 0;
+
+    if (who == NULL) {
+        Py_INCREF(Py_None);
+        pwho = Py_None;
+    } else {
+        if ((pwho = pyobj_from_usernode(who)) == NULL) {
+            err = "unable to allocate usernode";
+            goto cleanup;
+        }
+    }
+
+    if ((pchan = pyobj_from_channode(chan)) == NULL) {
+        err = "unable to allocate channode";
+        goto cleanup;
+    }
+
+    if (old_topic == NULL) {
+        Py_INCREF(Py_None);
+        oldtopic = Py_None;
+    } else {
+        oldtopic = PyString_FromString(old_topic);
+        if (oldtopic == NULL) {
+            err = "unable to allocate memory for old topic string";
+            goto cleanup;
+        }
+    }
+
+    name = PyString_FromString("topic");
+    if (name == NULL) {
+        err = "unable to allocate memory for topic handler function name";
+        goto cleanup;
+    }
+
+    retval = PyObject_CallMethodObjArgs(handler_object, name, pwho, pchan, oldtopic, NULL);
+    if (retval == NULL) {
+        err = "error calling topic handler";
+        goto cleanup;
+    }
+
+cleanup:
+    Py_XDECREF(pwho);
+    Py_XDECREF(pchan);
+    Py_XDECREF(oldtopic);
+    Py_XDECREF(name);
+
+    if (retval != NULL && PyInt_Check(retval))
+        i = (int)PyInt_AsLong(retval);
+
+    Py_XDECREF(retval);
+
+    if (err != NULL)
+        log_module(PY_LOG, LOG_WARNING, "%s", err);
+
+    return i;
+}
 /* ----------------------------------------------------------------------------- */
    
 
@@ -1681,9 +1852,15 @@ python_cleanup(void) {
     */
 
     log_module(PY_LOG, LOG_INFO, "python module cleanup");
+
+    Py_XDECREF(handler_object);
+    handler_object = NULL;
+
     if (PyErr_Occurred())
         PyErr_Clear();
     Py_Finalize(); /* Shut down python enterpreter */
+
+    log_module(PY_LOG, LOG_INFO, "python module cleanup done");
 }
 
 /* ---------------------------------------------------------------------------------- *
@@ -1704,59 +1881,6 @@ static MODCMD_FUNC(cmd_reload) {
     return 1;
 }
 
-static char* format_python_error(int space_nls) {
-    PyObject* extype = NULL, *exvalue = NULL, *extraceback = NULL;
-    PyObject* pextypestr = NULL, *pexvaluestr = NULL;
-    char* extypestr = NULL, *exvaluestr = NULL;
-    size_t retvallen = 0;
-    char* retval = NULL, *tmp;
-
-    PyErr_Fetch(&extype, &exvalue, &extraceback);
-    if (!extype)
-        goto cleanup;
-
-    pextypestr = PyObject_Str(extype);
-    if (!pextypestr)
-        goto cleanup;
-    extypestr = PyString_AsString(pextypestr);
-    if (!extypestr)
-        goto cleanup;
-
-    pexvaluestr = PyObject_Str(exvalue);
-    if (pexvaluestr)
-        exvaluestr = PyString_AsString(pexvaluestr);
-
-    retvallen = strlen(extypestr) + (exvaluestr ? strlen(exvaluestr) + 2 : 0) + 1;
-    retval = (char*)malloc(retvallen);
-    if (exvaluestr)
-        snprintf(retval, retvallen, "%s: %s", extypestr, exvaluestr);
-    else
-        strncpy(retval, extypestr, retvallen);
-
-    if (space_nls) {
-        tmp = retval;
-        while (*tmp) {
-            if (*tmp == '\n')
-                *tmp = ' ';
-            ++tmp;
-        }
-    }
-
-cleanup:
-    if (PyErr_Occurred())
-        PyErr_Clear(); /* ignore errors caused by formatting */
-    Py_XDECREF(extype);
-    Py_XDECREF(exvalue);
-    Py_XDECREF(extraceback);
-    Py_XDECREF(pextypestr);
-    Py_XDECREF(pexvaluestr);
-
-    if (retval)
-        return retval;
-
-    return strdup("unknown exception");
-}
-
 static MODCMD_FUNC(cmd_run) {
     /* this method allows running arbitrary python commands.
      * use with care.
@@ -1868,10 +1992,10 @@ int python_init(void) {
 
 //  Please help us by implementing any of the callbacks listed as TODO below. They already exist
 //  in x3, they just need handle_ bridges implemented. (see python_handle_join for an example)
-    reg_server_link_func(python_handle_server_link);
-    reg_new_user_func(python_handle_new_user);
+    reg_server_link_func(python_handle_server_link, NULL);
+    reg_new_user_func(python_handle_new_user, NULL);
     reg_nick_change_func(python_handle_nick_change);
-//TODO:    reg_del_user_func(python_handle_del_user);
+    reg_del_user_func(python_handle_del_user, NULL);
 //TODO:    reg_account_func(python_handle_account); /* stamping of account name to the ircd */
 //TODO:    reg_handle_rename_func(python_handle_handle_rename); /* handle used to ALSO mean account name */
 //TODO:    reg_failpw_func(python_handle_failpw);
@@ -1884,7 +2008,7 @@ int python_init(void) {
 //TODO:    reg_del_channel_func(python_handle_del_channel);
 //TODO:    reg_part_func(python_handle_part);
 //TODO:    reg_kick_func(python_handle_kick);
-//TODO:    reg_topic_func(python_handle_topic);
+    reg_topic_func(python_handle_topic);
 //TODO:    reg_channel_mode_func(python_handle_channel_mode);
 
 //TODO:    reg_privmsg_func(python_handle_privmsg);