//============================================================================= // // File : kvircmodule.cpp // Creation date : Wed Nov 19 19:11:29 2008 GMT by Elvio Basello // // This file is part of the KVIrc IRC client distribution // Copyright (C) 2008 Elvio Basello (hellvis69 at netsons dot org) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #include "kvi_settings.h" #ifdef COMPILE_PYTHON_SUPPORT #include "pythonheaderwrapper.h" #define KVIRC_MODULE #include "kvircmodule.h" #include "KviApplication.h" #include "KviWindow.h" #include "KviUserInput.h" #include "KviKvsRunTimeContext.h" #include "KviKvsScript.h" #include // For compatibility with Python 3 #if PY_MAJOR_VERSION >= 3 #define KVI_PyMODINIT_RETVAL(module) module #else #define KVI_PyMODINIT_RETVAL(module) \ ; \ (void)(module) struct PyModuleDef { char m_base; const char *m_name, *m_doc; int m_size; PyMethodDef * m_methods; }; static const char PyModuleDef_HEAD_INIT = 0; static PyObject * PyModule_Create(const struct PyModuleDef * def) { return Py_InitModule3(def->m_name, def->m_methods, def->m_doc); } #endif extern KviKvsRunTimeContext * g_pCurrentKvsContext; extern bool g_bExecuteQuiet; extern KviCString g_szLastReturnValue; extern QStringList g_lWarningList; extern QString g_lError; static PyObject * PyKVIrc_echo(PyObject * /* pSelf */, PyObject * pArgs) { const char *pcText = nullptr, *pcWinId = nullptr; KviWindow * pWnd = nullptr; int iColorSet = 0; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s|is", &pcText, &iColorSet, &pcWinId)) return nullptr; if(pcText) { if(pcWinId) pWnd = g_pApp->findWindow(pcWinId); if(!pWnd) { if(g_pCurrentKvsContext) pWnd = g_pCurrentKvsContext->window(); else if(g_pActiveWindow) pWnd = g_pActiveWindow; else pWnd = (KviWindow *)g_pApp->activeConsole(); } if(pWnd) pWnd->outputNoFmt(iColorSet, QString::fromUtf8(pcText)); } return Py_BuildValue("i", 1); } static PyObject * PyKVIrc_say(PyObject * /* pSelf */, PyObject * pArgs) { const char *pcText = nullptr, *pcWinId = nullptr; KviWindow * pWnd = nullptr; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s|s", &pcText, &pcWinId)) return nullptr; if(pcText) { if(pcWinId) pWnd = g_pApp->findWindow(pcWinId); if(!pWnd) { if(g_pCurrentKvsContext) pWnd = g_pCurrentKvsContext->window(); else if(g_pActiveWindow) pWnd = g_pActiveWindow; else pWnd = (KviWindow *)g_pApp->activeConsole(); } if(pWnd) { QString szText = QString::fromUtf8(pcText); KviUserInput::parse(szText, pWnd); } } return Py_BuildValue("i", 1); } static PyObject * PyKVIrc_warning(PyObject * /* pSelf */, PyObject * pArgs) { const char * pcText = nullptr; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s", &pcText)) return nullptr; if(pcText && !g_bExecuteQuiet) { if(g_pCurrentKvsContext) g_pCurrentKvsContext->warning(pcText); } return Py_BuildValue("i", 1); } static PyObject * PyKVIrc_getLocal(PyObject * /* pSelf */, PyObject * pArgs) { const char * szVarName = nullptr; QString tmp; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s", &szVarName)) return nullptr; if(g_pCurrentKvsContext) { KviKvsVariant * pVar = g_pCurrentKvsContext->localVariables()->find(szVarName); if(pVar) { pVar->asString(tmp); return Py_BuildValue("s", tmp.toUtf8().data()); } else { return Py_BuildValue("s", ""); } } return nullptr; } static PyObject * PyKVIrc_setLocal(PyObject * /* pSelf */, PyObject * pArgs) { const char *szVarName = nullptr, *szVarValue = nullptr; QString tmp; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "ss", &szVarName, &szVarValue)) return nullptr; if(g_pCurrentKvsContext) { if(szVarValue && *szVarValue) { KviKvsVariant * pVar = g_pCurrentKvsContext->localVariables()->get(szVarName); pVar->setString(szVarValue); } else { g_pCurrentKvsContext->localVariables()->unset(szVarName); } return Py_BuildValue("i", 1); } return nullptr; } static PyObject * PyKVIrc_getGlobal(PyObject * /* pSelf */, PyObject * pArgs) { const char * szVarName = nullptr; QString tmp; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s", &szVarName)) return nullptr; if(g_pCurrentKvsContext) { KviKvsVariant * pVar = g_pCurrentKvsContext->globalVariables()->find(szVarName); if(pVar) { pVar->asString(tmp); return Py_BuildValue("s", tmp.toUtf8().data()); } else { return Py_BuildValue("s", ""); } } return nullptr; } static PyObject * PyKVIrc_setGlobal(PyObject * /* pSelf */, PyObject * pArgs) { const char *szVarName = nullptr, *szVarValue = nullptr; QString tmp; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "ss", &szVarName, &szVarValue)) return nullptr; if(g_pCurrentKvsContext) { if(szVarValue && *szVarValue) { KviKvsVariant * pVar = g_pCurrentKvsContext->globalVariables()->get(szVarName); pVar->setString(szVarValue); } else { g_pCurrentKvsContext->globalVariables()->unset(szVarName); } return Py_BuildValue("i", 1); } return nullptr; } static PyObject * PyKVIrc_eval(PyObject * /* pSelf */, PyObject * pArgs) { const char * pcCode = nullptr; KviWindow * pWnd = nullptr; char * pcRetVal = nullptr; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s", &pcCode)) return nullptr; if(pcCode) { if(g_pCurrentKvsContext) pWnd = g_pCurrentKvsContext->window(); else if(g_pActiveWindow) pWnd = g_pActiveWindow; else pWnd = (KviWindow *)g_pApp->activeConsole(); if(pWnd) { KviKvsVariant ret; QString szRet; if(KviKvsScript::run(QString::fromUtf8(pcCode), pWnd, nullptr, &ret)) { ret.asString(szRet); pcRetVal = szRet.toUtf8().data(); } } } return Py_BuildValue("s", pcRetVal); } static PyObject * PyKVIrc_internalWarning(PyObject * /* pSelf */, PyObject * pArgs) { const char * pcText = nullptr; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s", &pcText)) return nullptr; if(pcText && !g_bExecuteQuiet) g_lWarningList.append(QString(pcText)); return Py_BuildValue("i", 1); } static PyObject * PyKVIrc_error(PyObject * /* pSelf */, PyObject * pArgs) { const char * pcText = nullptr; if(QThread::currentThread() != g_pApp->thread()) { qDebug("[pythoncore][ERROR] KVIrc module functions must be called from the main KVIrc thread"); return nullptr; // Sorry, we're NOT thread safe } if(!PyArg_ParseTuple(pArgs, "s", &pcText)) return nullptr; if(pcText) g_lError.append(pcText); return Py_BuildValue("i", 1); } static PyMethodDef KVIrcMethods[] = { { "echo", PyKVIrc_echo, METH_VARARGS, "Outputs text to a KVIrc window" }, { "say", PyKVIrc_say, METH_VARARGS, "Types text in a window" }, { "warning", PyKVIrc_warning, METH_VARARGS, "Prints a warning message" }, { "getLocal", PyKVIrc_getLocal, METH_VARARGS, "Gets a local variable" }, { "setLocal", PyKVIrc_setLocal, METH_VARARGS, "Sets a local variable" }, { "getGlobal", PyKVIrc_getGlobal, METH_VARARGS, "Gets a global variable" }, { "setGlobal", PyKVIrc_setGlobal, METH_VARARGS, "Sets a global variable" }, { "eval", PyKVIrc_eval, METH_VARARGS, "Change the behaviour of a set of commands" }, { "internalWarning", PyKVIrc_internalWarning, METH_VARARGS, "" }, { "error", PyKVIrc_error, METH_VARARGS, "" }, { nullptr, nullptr, 0, nullptr } }; PyMODINIT_FUNC python_init() { static PyCFunction PyKVIrc_API[] = { PyKVIrc_echo, PyKVIrc_say, PyKVIrc_warning, PyKVIrc_getLocal, PyKVIrc_setLocal, PyKVIrc_getGlobal, PyKVIrc_setGlobal, PyKVIrc_eval, PyKVIrc_internalWarning, PyKVIrc_error, }; static struct PyModuleDef def = { PyModuleDef_HEAD_INIT, "kvirc", "KVIrc module", -1, KVIrcMethods }; PyObject * pModule = PyModule_Create(&def); if(!pModule) { KVI_ASSERT("Python: Unable to initialize KVIrc import module"); } else { // Create a CObject containing the API pointer array's address PyObject * pC_API_Object = PyCapsule_New((void *)PyKVIrc_API, "kvirc._C_API", nullptr); if(pC_API_Object) PyModule_AddObject(pModule, "_C_API", pC_API_Object); } return KVI_PyMODINIT_RETVAL(pModule); } static struct KviPythonModuleInitializer { KviPythonModuleInitializer() { PyImport_AppendInittab("kvirc", python_init); } } initializer; #endif