mirror of
https://github.com/EnergyMech/energymech.git
synced 2025-12-29 16:14:43 +00:00
Initial Import
This commit is contained in:
973
src/python.c
Normal file
973
src/python.c
Normal file
@@ -0,0 +1,973 @@
|
||||
/*
|
||||
|
||||
EnergyMech, IRC bot software
|
||||
Copyright (c) 2009 Nemesis128 <stnsls@gmail.com>
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/* Python scripting backend for Energymech
|
||||
|
||||
by Nemesis128 <stnsls@gmail.com>
|
||||
|
||||
*/
|
||||
|
||||
#define PYTHON_C
|
||||
#include "config.h"
|
||||
|
||||
#ifdef PYTHON
|
||||
|
||||
#include "defines.h"
|
||||
#include "structs.h"
|
||||
#include "global.h"
|
||||
#include "h.h"
|
||||
#include "text.h"
|
||||
#include "mcmd.h"
|
||||
|
||||
#define PYVAR_guid 0
|
||||
#define PYVAR_currentnick 1
|
||||
#define PYVAR_botnick 2
|
||||
#define PYVAR_wantnick 3
|
||||
#define PYVAR_userhost 4
|
||||
#define PYVAR_server 5
|
||||
#define PYVAR_nextserver 6
|
||||
#define PYVAR_currentchan 7
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
||||
char *python_unicode2char(PyUnicodeObject *obj)
|
||||
{ /* try to get a valid char* from PyUnicode object.
|
||||
returned str must be free'd afterwards. */
|
||||
int sz = PyUnicode_GET_SIZE(obj);
|
||||
wchar_t *wcs = (wchar_t*) malloc(sizeof(wchar_t) * sz);
|
||||
PyUnicode_AsWideChar(obj, wcs, sz);
|
||||
char *cs = (char*) malloc(sizeof(char) * (sz + 1));
|
||||
wcstombs(cs, wcs, sz);
|
||||
cs[sz] = '\0';
|
||||
free(wcs);
|
||||
return cs;
|
||||
}
|
||||
|
||||
#endif /* Py3k */
|
||||
|
||||
static PyObject *python_error; /* emech exception object */
|
||||
|
||||
static PyObject *python_getvar(PyObject *self, PyObject *args)
|
||||
{ /* get some global var */
|
||||
#ifdef DEBUG
|
||||
if (!current)
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_getvar) No current bot?!");
|
||||
return NULL;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
int vartype;
|
||||
if (!PyArg_ParseTuple(args, "i", &vartype))
|
||||
return NULL;
|
||||
switch (vartype)
|
||||
{
|
||||
case PYVAR_guid:
|
||||
return Py_BuildValue("i", current ? current->guid : -1);
|
||||
case PYVAR_currentnick:
|
||||
return Py_BuildValue("s", CurrentNick);
|
||||
case PYVAR_botnick:
|
||||
return Py_BuildValue("s", current && current->nick ? current->nick : "");
|
||||
case PYVAR_wantnick:
|
||||
return Py_BuildValue("s", current && current->wantnick ? current->wantnick : "");
|
||||
case PYVAR_userhost:
|
||||
return Py_BuildValue("s", current && current->userhost ? current->userhost : "");
|
||||
case PYVAR_server:
|
||||
return Py_BuildValue("i", current && current->server ? current->server : -1);
|
||||
case PYVAR_nextserver:
|
||||
return Py_BuildValue("i", current && current->nextserver ? current->nextserver : -1);
|
||||
case PYVAR_currentchan:
|
||||
return Py_BuildValue("s", current && current->activechan ? current->activechan->name : "");
|
||||
default:
|
||||
PyErr_SetString(python_error, "(python_getvar) invalid var");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* From channel.c */
|
||||
|
||||
static PyObject *python_is_chanuser(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Return True if $nick is on $chan, else False */
|
||||
{
|
||||
char *chan, *nick;
|
||||
static char *kwlist[] = {"chan", "nick", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &chan, &nick))
|
||||
return NULL;
|
||||
Chan *ch = (Chan*) find_channel(chan, CHAN_ANY);
|
||||
if (!ch) Py_RETURN_FALSE;
|
||||
ChanUser *cu = find_chanuser(ch, nick);
|
||||
if (!cu) Py_RETURN_FALSE;
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static PyObject *python_do_join(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Join a channel */
|
||||
{
|
||||
char *from, *to="", *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|i", kwlist,
|
||||
&from, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_join(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_part(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Part a channel */
|
||||
{
|
||||
char *from, *to, *rest="";
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &from, &to))
|
||||
return NULL;
|
||||
do_part(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_cycle(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Cycle a channel */
|
||||
{
|
||||
char *from, *to, *rest="";
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &from, &to))
|
||||
return NULL;
|
||||
do_cycle(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_wall(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Wall */
|
||||
{
|
||||
char *from, *to, *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
|
||||
&from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_wall(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_mode(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Mode */
|
||||
{
|
||||
char *from, *to, *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
|
||||
&from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_mode(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_invite(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Invite */
|
||||
{
|
||||
char *from, *to, *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
|
||||
&from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_invite(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_sayme(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Say /me */
|
||||
{
|
||||
char *from, *to, *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
|
||||
&from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_sayme(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_topic(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Set topic */
|
||||
{
|
||||
char *from, *to, *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
|
||||
&from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_topic(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_idle(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Check idle time */
|
||||
{
|
||||
char *from, *to, *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
|
||||
&from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_idle(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
static PyObject *python_find_nuh(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Find nuh */
|
||||
{
|
||||
char *nick, *nuh;
|
||||
static char *kwlist[] = {"nick", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s", kwlist, &nick))
|
||||
return NULL;
|
||||
nuh = find_nuh(nick);
|
||||
if (nuh == NULL) Py_RETURN_NONE;
|
||||
else return Py_BuildValue("s", nuh);
|
||||
}
|
||||
|
||||
/* From core.c */
|
||||
|
||||
#if 0
|
||||
|
||||
static PyObject *python_do_die(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
char *from="", *to="", *rest="";
|
||||
int cmdaccess=0;
|
||||
static char *kwlist[] = {"from", "rest", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|s", kwlist, &from, &rest))
|
||||
return NULL;
|
||||
do_die(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_shutdown(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
char *from="", *to="", *rest="";
|
||||
int cmdaccess=0;
|
||||
static char *kwlist[] = {"from", "rest", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|s", kwlist, &from, &rest))
|
||||
return NULL;
|
||||
do_shutdown(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *python_do_server(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
/* Connect server */
|
||||
{
|
||||
char *from, *to, *rest;
|
||||
int cmdaccess = 100;
|
||||
static char *kwlist[] = {"from", "to", "rest", "cmdaccess", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sss|i", kwlist,
|
||||
&from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
do_server(from, to, rest, cmdaccess);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
PyObject *python_hook(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
Hook *hook;
|
||||
HookTimer hooktimer;
|
||||
PyObject *cb, *funcname;
|
||||
char *type, *command, *cbname;
|
||||
int guid = 0, mode, sz1, sz2;
|
||||
|
||||
static char *kwlist[] = {"type", "command", "callback", "guid", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ssO|i", kwlist,
|
||||
&type, &command, &cb, &guid))
|
||||
return NULL;
|
||||
|
||||
/* check callback function */
|
||||
if (!PyFunction_Check(cb))
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_hook) callback is not a function");
|
||||
return NULL;
|
||||
}
|
||||
funcname = PyObject_GetAttrString(cb, "__name__"); /* new ref */
|
||||
if (!funcname)
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_hook) cant get function name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
cbname = python_unicode2char((PyUnicodeObject*) funcname);
|
||||
#else
|
||||
cbname = PyString_AsString(funcname); /* not a copy! */
|
||||
#endif /* Py3k */
|
||||
|
||||
mode = strlen(type);
|
||||
sz1 = strlen(command);
|
||||
sz2 = strlen(cbname);
|
||||
if (!mode || !sz1 || !sz2)
|
||||
{
|
||||
Py_DECREF(funcname);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
free(cbname);
|
||||
#endif /* Py3k */
|
||||
PyErr_SetString(python_error, "(python_hook) invalid params");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!Strcasecmp(type, "command"))
|
||||
mode = HOOK_COMMAND;
|
||||
else
|
||||
if (!Strcasecmp(type, "dcc_complete"))
|
||||
mode = HOOK_DCC_COMPLETE;
|
||||
else
|
||||
if (!Strcasecmp(type, "parse"))
|
||||
mode = HOOK_PARSE;
|
||||
else
|
||||
if (!Strcasecmp(type, "timer"))
|
||||
{
|
||||
if (compile_timer(&hooktimer, command) < 0)
|
||||
{
|
||||
Py_DECREF(funcname);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
free(cbname);
|
||||
#endif /* Py3k */
|
||||
PyErr_SetString(python_error, "(python_hook) cant compile timer");
|
||||
return NULL;
|
||||
}
|
||||
mode = HOOK_TIMER;
|
||||
sz1 = sizeof(HookTimer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_DECREF(funcname);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
free(cbname);
|
||||
#endif /* Py3k */
|
||||
PyErr_SetString(python_error, "(python_hook) invalid hook type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
set_mallocdoer(python_hook);
|
||||
hook = (Hook*) Calloc(sizeof(Hook) + sz1 + sz2);
|
||||
hook->guid = guid;
|
||||
hook->flags = mode;
|
||||
hook->next = hooklist;
|
||||
hooklist = hook;
|
||||
|
||||
hook->type.any = (void*) (Strcpy(hook->self, cbname) + 1);
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case HOOK_COMMAND:
|
||||
case HOOK_PARSE:
|
||||
Strcpy(hook->type.command, command);
|
||||
hook->func = python_parse_jump;
|
||||
break;
|
||||
default:
|
||||
/* case HOOK_TIMER: */
|
||||
memcpy(hook->type.timer, &hooktimer, sizeof(HookTimer));
|
||||
hook->func = python_timer_jump;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("(python_hook) hooked %s `%s' --> %s\n",
|
||||
nullstr(type), nullstr(command), nullstr(cbname));
|
||||
#endif /* DEBUG */
|
||||
|
||||
Py_DECREF(funcname);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
free(cbname);
|
||||
#endif /* Py3k */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject *python_unhook(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
return Py_BuildValue("i", 1);
|
||||
}
|
||||
|
||||
int python_parse_jump(char *from, char *rest, Hook *hook)
|
||||
{
|
||||
int i;
|
||||
PyObject *mainmod, *cb, *res;
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("(python_parse_jump) %s %s %s\n",
|
||||
nullstr(hook->self), nullstr(from), nullstr(rest));
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (from)
|
||||
nickcpy(CurrentNick, from);
|
||||
else
|
||||
*CurrentNick = 0;
|
||||
|
||||
/* get callback object */
|
||||
mainmod = PyImport_AddModule("__main__");
|
||||
if (!mainmod)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_parse_jump) cant get main module\n");
|
||||
#endif /* DEBUG */
|
||||
return 0; /* python exception has been set */
|
||||
}
|
||||
cb = PyDict_GetItemString(PyModule_GetDict(mainmod), hook->self);
|
||||
if (!PyFunction_Check(cb))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_parse_jump) invalid callback function\n");
|
||||
#endif /* DEBUG */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call our function */
|
||||
res = PyObject_CallFunction(cb, "ss", from, rest); /* new ref */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
i = PyLong_AsLong(res);
|
||||
#else
|
||||
i = PyInt_AS_LONG(res);
|
||||
#endif /* Py3k */
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("(python_parse_jump) result = %d\n", i);
|
||||
#endif
|
||||
Py_DECREF(res);
|
||||
return i;
|
||||
}
|
||||
|
||||
int python_timer_jump(Hook *hook)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DCC_FILE
|
||||
|
||||
void python_dcc_complete(Client *client, int cps)
|
||||
{
|
||||
PyObject *mainmod = NULL, *cb, *res;
|
||||
Hook *hook;
|
||||
|
||||
for (hook = hooklist; hook; hook = hook->next)
|
||||
{
|
||||
if (hook->flags == HOOK_DCC_COMPLETE &&
|
||||
hook->guid && current && hook->guid == current->guid)
|
||||
{
|
||||
/* get callback object */
|
||||
if (!mainmod)
|
||||
mainmod = PyImport_AddModule("__main__");
|
||||
if (!mainmod)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_dcc_complete) cant get main module\n");
|
||||
#endif /* DEBUG */
|
||||
return; /* python exception has been set */
|
||||
}
|
||||
cb = PyDict_GetItemString(PyModule_GetDict(mainmod), hook->self);
|
||||
if (!PyFunction_Check(cb))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_dcc_complete) invalid callback function\n");
|
||||
#endif /* DEBUG */
|
||||
return;
|
||||
}
|
||||
|
||||
/* call our function */
|
||||
res = PyObject_CallFunction(cb, "ssi",
|
||||
client->whom, client->filename, cps); /* new ref */
|
||||
#ifdef DEBUG
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
debug("(python_dcc_complete) result = %d\n", PyLong_AsLong(res));
|
||||
#else
|
||||
debug("(python_dcc_complete) result = %d\n", PyInt_AS_LONG(res));
|
||||
#endif /* Py3k */
|
||||
#endif /* DEBUG */
|
||||
Py_DECREF(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DCC_FILE */
|
||||
|
||||
PyObject *python_userlevel(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!current)
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_userlevel) No current bot?!");
|
||||
return NULL;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
char *nuh, *chan;
|
||||
int n;
|
||||
static char *kwlist[] = {"nuh", "chan", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|s", kwlist, &nuh, &chan))
|
||||
return NULL;
|
||||
n = get_useraccess(nuh, chan);
|
||||
return Py_BuildValue("i", n);
|
||||
}
|
||||
|
||||
PyObject *python_to_server(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!current)
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_to_server) No current bot?!");
|
||||
return NULL;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
Strp *sp, **pp;
|
||||
char *line;
|
||||
int sendqmax = -1, n, sz;
|
||||
static char *kwlist[] = {"line", "sendqmax", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|i", kwlist, &line, &sendqmax))
|
||||
return NULL;
|
||||
#ifdef DEBUG
|
||||
debug("(python_to_server) max = %i; line = %s\n", sendqmax, line);
|
||||
#endif /* DEBUG */
|
||||
sz = strlen(line);
|
||||
if (sendqmax >= 0)
|
||||
{
|
||||
n = 0;
|
||||
pp = ¤t->sendq;
|
||||
while (*pp)
|
||||
{
|
||||
n++;
|
||||
pp = &(*pp)->next;
|
||||
}
|
||||
if (sendqmax && n >= sendqmax) n = -n;
|
||||
else
|
||||
if (sz)
|
||||
{
|
||||
*pp = sp = (Strp*) Calloc(sizeof(Strp) + sz);
|
||||
/* Calloc sets to zero sp->next = NULL; */
|
||||
Strcpy(sp->p, line);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((n = write(current->sock, line, sz)) < 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_to_server) {%i} errno = %i\n", current->sock, errno);
|
||||
#endif /* DEBUG */
|
||||
close(current->sock);
|
||||
current->sock = -1;
|
||||
current->connect = CN_NOSOCK;
|
||||
PyErr_SetString(python_error, "Socket error");
|
||||
return NULL;
|
||||
}
|
||||
current->sendq_time += 2;
|
||||
}
|
||||
return Py_BuildValue("i", n);
|
||||
}
|
||||
|
||||
PyObject *python_to_file(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
int fd, r;
|
||||
char *txt;
|
||||
static char *kwlist[] = {"fd", "text", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "is", kwlist, &fd, &txt))
|
||||
return NULL;
|
||||
r = write(fd, txt, strlen(txt));
|
||||
return Py_BuildValue("i", r);
|
||||
}
|
||||
|
||||
#ifdef DCC_FILE
|
||||
|
||||
static PyObject *python_dcc_sendfile(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
char *filename, *target;
|
||||
int sz;
|
||||
static char *kwlist[] = {"file", "target", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &filename, &target))
|
||||
return NULL;
|
||||
if ((sz = dcc_sendfile(target, filename)) < 0)
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_dcc_sendfile) error!");
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", sz);
|
||||
}
|
||||
|
||||
#endif /* DCC_FILE */
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
PyObject *python_debug(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *o;
|
||||
if (!PyArg_ParseTuple(args, "O", &o))
|
||||
return NULL;
|
||||
o = PyObject_Repr(o);
|
||||
if (!o)
|
||||
{
|
||||
debug("(python_debug) object has no __repr__ method\n");
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
char *cs;
|
||||
cs = python_unicode2char((PyUnicodeObject*) o);
|
||||
debug("(python_debug) %s\n", cs);
|
||||
free(cs);
|
||||
#else
|
||||
debug("(python_debug) %s\n", PyString_AsString(o));
|
||||
#endif /* Py3k */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef RAWDNS
|
||||
|
||||
int python_dns_jump(char *host, char *resolved, Hook *hook)
|
||||
{
|
||||
PyObject *mainmod, *cb, *res;
|
||||
int i = 0;
|
||||
#ifdef DEBUG
|
||||
debug("(python_dns_jump) %s %s %s\n",
|
||||
nullstr(hook->self), nullstr(host), nullstr(resolved));
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* get callback object */
|
||||
mainmod = PyImport_AddModule("__main__");
|
||||
if (!mainmod)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_dns_jump) cant get main module\n");
|
||||
#endif /* DEBUG */
|
||||
return 0; /* python exception has been set */
|
||||
}
|
||||
cb = PyDict_GetItemString(PyModule_GetDict(mainmod), hook->self);
|
||||
if (!PyFunction_Check(cb))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_dns_jump) invalid callback function\n");
|
||||
#endif /* DEBUG */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call our function */
|
||||
res = PyObject_CallFunction(cb, "ss", host, resolved); /* new ref */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
i = PyLong_AsLong(res);
|
||||
#else
|
||||
i = PyInt_AS_LONG(res);
|
||||
#endif /* Py3k */
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("(python_dns_jump) result = %d\n", i);
|
||||
#endif /* DEBUG */
|
||||
Py_DECREF(res);
|
||||
return i;
|
||||
}
|
||||
|
||||
static PyObject *python_dns(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
PyObject *cb, *funcname;
|
||||
Hook *hook;
|
||||
char *host, *cbname;
|
||||
|
||||
static char *kwlist[] = {"host", "callback", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "sO", kwlist, host, cb))
|
||||
return NULL;
|
||||
|
||||
/* check callback function */
|
||||
if (!PyFunction_Check(cb))
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_dns) callback is not a function");
|
||||
return NULL;
|
||||
}
|
||||
funcname = PyObject_GetAttrString(cb, "__name__"); /* new ref */
|
||||
if (!funcname)
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_dns) cant get function name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
cbname = python_unicode2char((PyUnicodeObject*) funcname);
|
||||
#else
|
||||
cbname = PyString_AsString(funcname); /* not a copy! */
|
||||
#endif /* Py3k */
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("(python_dns) resolving: %s (callback %s)\n", host, cbname);
|
||||
#endif /* DEBUG */
|
||||
|
||||
set_mallocdoer(python_dns);
|
||||
hook = (Hook*)Calloc(sizeof(Hook) + strlen(host));
|
||||
hook->guid = (current) ? current->guid : 0;
|
||||
hook->flags = HOOK_DNS;
|
||||
hook->next = hooklist;
|
||||
hooklist = hook;
|
||||
hook->type.host = Strcpy(hook->self, cbname) + 1;
|
||||
Strcpy(hook->type.host, host);
|
||||
hook->func = python_dns_jump;
|
||||
|
||||
rawdns(host);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
free(cbname);
|
||||
#endif /* Py3k */
|
||||
Py_DECREF(funcname);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#endif /* RAWDNS */
|
||||
|
||||
static PyObject *python_execute(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *cmd, *from, *to, *rest;
|
||||
char *c_cmd, *c_from, *c_to, *c_rest;
|
||||
int cmdaccess, i;
|
||||
void (*found)(char*,char*,char*,int) = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "OOOOi", &cmd, &from, &to, &rest, &cmdaccess))
|
||||
return NULL;
|
||||
|
||||
/* check for 4 strings */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
if (!PyUnicode_CheckExact(cmd)
|
||||
|| !(PyUnicode_CheckExact(from))/* || Py_None == from)*/
|
||||
|| !PyUnicode_CheckExact(to)
|
||||
|| !PyUnicode_CheckExact(rest))
|
||||
#else
|
||||
if (!PyString_CheckExact(cmd)
|
||||
|| !(PyString_CheckExact(from))/* || Py_None == from)*/
|
||||
|| !PyString_CheckExact(to)
|
||||
|| !PyString_CheckExact(rest))
|
||||
#endif /* Py3k */
|
||||
{
|
||||
PyErr_SetString(python_error, "(python_execute) invalid arguments");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* extract vars */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
c_cmd = python_unicode2char((PyUnicodeObject*) cmd);
|
||||
if (from != Py_None) c_from = python_unicode2char((PyUnicodeObject*) from);
|
||||
c_to = python_unicode2char((PyUnicodeObject*) to);
|
||||
c_rest = python_unicode2char((PyUnicodeObject*) rest);
|
||||
#else
|
||||
c_cmd = PyString_AsString(cmd); /* not a copy */
|
||||
if (from != Py_None) c_from = PyString_AsString(from);
|
||||
c_to = PyString_AsString(to);
|
||||
c_rest = PyString_AsString(rest);
|
||||
#endif /* Py3k */
|
||||
|
||||
/*
|
||||
if (from == Py_None)
|
||||
{
|
||||
from = LocalBot..;
|
||||
}*/
|
||||
|
||||
/* check command exists */
|
||||
for (i = 0; mcmd[i].name; ++i)
|
||||
{
|
||||
if (!Strcmp(mcmd[i].name, c_cmd))
|
||||
{
|
||||
found = mcmd[i].func;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug("(python_execute) squeeze me (%s) !?!\n", c_cmd);
|
||||
#endif /* DEBUG */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
free(c_cmd); if (from != Py_None) free(c_from); free(c_to); free(c_rest);
|
||||
#endif /* Py3k */
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("(python_execute) (%s) (%s) (%s) (%s) (%d)\n", c_cmd, c_from, c_to, c_rest, cmdaccess);
|
||||
#endif /* DEBUG */
|
||||
|
||||
(*found)(c_from, c_to, c_rest, cmdaccess);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
free(c_cmd); if (from != Py_None) free(c_from); free(c_to); free(c_rest);
|
||||
#endif /* Py3k */
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static struct PyMethodDef pythonMethods[] =
|
||||
{
|
||||
{"getvar", (PyCFunction) python_getvar, METH_VARARGS, "Get variable"},
|
||||
{"userlevel", (PyCFunction) python_userlevel, METH_VARARGS|METH_KEYWORDS, "User level"},
|
||||
/* From channel.c */
|
||||
{"is_chanuser", (PyCFunction) python_is_chanuser, METH_VARARGS|METH_KEYWORDS, "Check nick is in channel"},
|
||||
#if 0
|
||||
{"join", (PyCFunction) python_do_join, METH_VARARGS|METH_KEYWORDS, "Join a channel"},
|
||||
{"part", (PyCFunction) python_do_part, METH_VARARGS|METH_KEYWORDS, "Part a channel"},
|
||||
{"cycle", (PyCFunction) python_do_cycle, METH_VARARGS|METH_KEYWORDS, "Cycle a channel"},
|
||||
{"wall", (PyCFunction) python_do_wall, METH_VARARGS|METH_KEYWORDS, "Do wall"},
|
||||
{"mode", (PyCFunction) python_do_mode, METH_VARARGS|METH_KEYWORDS, "Do mode"},
|
||||
{"invite", (PyCFunction) python_do_invite, METH_VARARGS|METH_KEYWORDS, "Do invite"},
|
||||
{"sayme", (PyCFunction) python_do_sayme, METH_VARARGS|METH_KEYWORDS, "Do sayme"},
|
||||
{"topic", (PyCFunction) python_do_topic, METH_VARARGS|METH_KEYWORDS, "Do topic"},
|
||||
{"idle", (PyCFunction) python_do_idle, METH_VARARGS|METH_KEYWORDS, "Do idle"},
|
||||
#endif /* 0 */
|
||||
{"find_nuh", (PyCFunction) python_find_nuh, METH_VARARGS|METH_KEYWORDS, "Find nuh"},
|
||||
/* From core.c */
|
||||
#if 0
|
||||
{"die", (PyCFunction) python_do_die, METH_VARARGS|METH_KEYWORDS, "Die"},
|
||||
{"shutdown", (PyCFunction) python_do_shutdown, METH_VARARGS|METH_KEYWORDS, "Shutdown"},
|
||||
{"server", (PyCFunction) python_do_server, METH_VARARGS|METH_KEYWORDS, "Connect server"},
|
||||
#endif /* 0 */
|
||||
/* Scripting stuff */
|
||||
{"hook", (PyCFunction) python_hook, METH_VARARGS|METH_KEYWORDS, "Create hook"},
|
||||
{"unhook", (PyCFunction) python_unhook, METH_VARARGS|METH_KEYWORDS, "Destroy hook"},
|
||||
#ifdef DCC_FILE
|
||||
{"dcc_sendfile", (PyCFunction) python_dcc_sendfile, METH_VARARGS|METH_KEYWORDS, "DCC send file"},
|
||||
#endif /* DCC_FILE */
|
||||
{"to_server", (PyCFunction) python_to_server, METH_VARARGS|METH_KEYWORDS, "Write line to server"},
|
||||
{"to_file", (PyCFunction) python_to_file, METH_VARARGS|METH_KEYWORDS, "Write text to file"},
|
||||
#ifdef DEBUG
|
||||
{"debug", (PyCFunction) python_debug, METH_VARARGS, "Emech debug"},
|
||||
#endif /* DEBUG */
|
||||
#ifdef RAWDNS
|
||||
{"dns", (PyCFunction) python_dns, METH_VARARGS|METH_KEYWORDS, "DNS"},
|
||||
#endif /* RAWDNS */
|
||||
{"execute", (PyCFunction) python_execute, METH_VARARGS, "Execute internal command"},
|
||||
{NULL, NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
||||
struct PyModuleDef pythonModule =
|
||||
{
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"emech", /* module name */
|
||||
"EnergyMech", /* module docstring */
|
||||
-1, /* size of per-interpreter state of the module,
|
||||
or -1 if the module keeps state in global variables. */
|
||||
pythonMethods
|
||||
};
|
||||
|
||||
#endif /* Py3k */
|
||||
|
||||
PyMODINIT_FUNC pythonInit(void)
|
||||
{
|
||||
PyObject *m;
|
||||
|
||||
#if PY_MAJOR_VERSION == 3
|
||||
if ((m = PyModule_Create(&pythonModule)) == NULL)
|
||||
return NULL;
|
||||
#else
|
||||
m = Py_InitModule4("emech", pythonMethods,
|
||||
"EnergyMech", (PyObject*) NULL, PYTHON_API_VERSION);
|
||||
#endif /* Py3k */
|
||||
|
||||
python_error = PyErr_NewException("emech.Error", NULL, NULL);
|
||||
Py_INCREF(python_error);
|
||||
PyModule_AddObject(m, "Error", python_error);
|
||||
|
||||
#ifdef DEBUG
|
||||
PyModule_AddIntConstant(m, "define_debug", 1);
|
||||
#else
|
||||
PyModule_AddIntConstant(m, "define_debug", 0);
|
||||
#endif /* DEBUG */
|
||||
|
||||
PyModule_AddStringConstant(m, "HOOK_COMMAND", "command");
|
||||
PyModule_AddStringConstant(m, "HOOK_PARSE", "parse");
|
||||
PyModule_AddStringConstant(m, "HOOK_TIMER", "timer");
|
||||
PyModule_AddStringConstant(m, "DCC_COMPLETE", "dcc_complete");
|
||||
|
||||
PyModule_AddIntConstant(m, "OK", 0);
|
||||
PyModule_AddIntConstant(m, "ERROR", 1);
|
||||
|
||||
PyModule_AddIntConstant(m, "GUID", PYVAR_guid);
|
||||
PyModule_AddIntConstant(m, "CURRENTNICK", PYVAR_currentnick);
|
||||
PyModule_AddIntConstant(m, "BOTNICK", PYVAR_botnick);
|
||||
PyModule_AddIntConstant(m, "WANTNICK", PYVAR_wantnick);
|
||||
PyModule_AddIntConstant(m, "USERHOST", PYVAR_userhost);
|
||||
PyModule_AddIntConstant(m, "SERVER", PYVAR_server);
|
||||
PyModule_AddIntConstant(m, "NEXTSERVER", PYVAR_nextserver);
|
||||
PyModule_AddIntConstant(m, "CURRENTCHAN", PYVAR_currentchan);
|
||||
|
||||
PyModule_AddStringConstant(m, "VERSION", (char *)VERSION);
|
||||
PyModule_AddStringConstant(m, "SRCDATE", (char *)SRCDATE);
|
||||
PyModule_AddStringConstant(m, "BOTCLASS", (char *)BOTCLASS);
|
||||
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_Print();
|
||||
Py_FatalError("Cant initialize module emech!");
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return m;
|
||||
#endif /* Py3k */
|
||||
}
|
||||
|
||||
void init_python(void)
|
||||
{
|
||||
if (Py_IsInitialized()) return;
|
||||
|
||||
PyImport_AppendInittab((char*) "emech", pythonInit);
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Py_SetProgramName(L"energymech");
|
||||
wchar_t *argv2[] = {L""};
|
||||
#else
|
||||
Py_SetProgramName("energymech");
|
||||
char *argv2[] = {""};
|
||||
#endif /* Py3k */
|
||||
|
||||
Py_Initialize();
|
||||
PySys_SetArgv(1, argv2);
|
||||
}
|
||||
|
||||
#ifdef PLEASE_HACK_MY_SHELL
|
||||
|
||||
void do_python(COMMAND_ARGS)
|
||||
{
|
||||
init_python();
|
||||
int res = PyRun_SimpleString(rest);
|
||||
to_user(from, "python command %s", (res == 0) ? "executed ok" : "failed");
|
||||
}
|
||||
|
||||
#endif /* PLEASE_HACK_MY_SHELL */
|
||||
|
||||
void do_pythonscript(COMMAND_ARGS)
|
||||
{
|
||||
init_python();
|
||||
FILE *f = fopen(rest, "r");
|
||||
if (f == NULL)
|
||||
{
|
||||
to_user(from, "python script %s not existing or unreadable", rest);
|
||||
return;
|
||||
}
|
||||
int res = PyRun_SimpleFileEx(f, rest, 1);
|
||||
to_user(from,"python script %s", (res == 0) ? "loaded ok" : "failed to load");
|
||||
}
|
||||
|
||||
void free_python(void)
|
||||
{
|
||||
if (Py_IsInitialized()) Py_Finalize();
|
||||
}
|
||||
|
||||
#endif /* PYTHON */
|
||||
Reference in New Issue
Block a user