source: protocols/python/src/bpython.c @ 76ca5cb

Last change on this file since 76ca5cb was 76ca5cb, checked in by Nick Murdoch <nick@…>, at 2013-03-27T20:31:46Z

bpython.register_protocl() actually takes meaningful args and does something.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * bpython.c - Python plugin for bitlbee
3 *
4 * Copyright (c) 2013 Nick Murdoch
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <Python.h>
26#include "bytesobject.h"
27#include "structmember.h"
28
29#include <bitlbee.h>
30
31/* Python module classes: */
32
33typedef struct {
34    PyObject_HEAD
35    PyObject * name; /* protocol name */
36} Protocol;
37
38static void Protocol_dealloc(Protocol * self) {
39    Py_XDECREF(self->name);
40    self->ob_type->tp_free((PyObject*)self);
41}
42
43static PyObject * Protocol_new(PyTypeObject * type, PyObject * args, PyObject * kwds) {
44    Protocol * self;
45
46    self = (Protocol *)type->tp_alloc(type, 0);
47    if (self != NULL) {
48        self->name = PyString_FromString("unnamed");
49        if (self->name == NULL) {
50            Py_DECREF(self);
51            return NULL;
52        }
53    }
54
55    return (PyObject *)self;
56}
57
58static int Protocol_init(Protocol *self, PyObject *args, PyObject *kwds)
59{
60    PyObject * name;
61    PyObject * tmp;
62
63    static char *kwlist[] = {"name", NULL};
64
65    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, 
66                                      &name))
67        return -1; 
68
69    if (name) {
70        tmp = self->name;
71        Py_INCREF(name);
72        self->name = name;
73        Py_XDECREF(tmp);
74    }
75
76    return 0;
77}
78
79static PyMemberDef Protocol_members[] = {
80    {"name", T_OBJECT_EX, offsetof(Protocol, name), 0,
81     "protocol name (used in 'account add')"},
82    {NULL}  /* Sentinel */
83};
84
85
86static PyMethodDef Protocol_methods[] = {
87    //{"name", (PyCFunction)Noddy_name, METH_NOARGS,
88    // "Return the name, combining the first and last name"
89    //},
90    {NULL}  /* Sentinel */
91};
92
93
94static PyTypeObject ProtocolType = {
95    PyObject_HEAD_INIT(NULL)
96    0,                         /*ob_size*/
97    "bpython.Protocol",  /*tp_name*/
98    sizeof(Protocol), /*tp_basicsize*/
99    0,                         /*tp_itemsize*/
100    (destructor)Protocol_dealloc, /*tp_dealloc*/
101    0,                         /*tp_print*/
102    0,                         /*tp_getattr*/
103    0,                         /*tp_setattr*/
104    0,                         /*tp_compare*/
105    0,                         /*tp_repr*/
106    0,                         /*tp_as_number*/
107    0,                         /*tp_as_sequence*/
108    0,                         /*tp_as_mapping*/
109    0,                         /*tp_hash */
110    0,                         /*tp_call*/
111    0,                         /*tp_str*/
112    0,                         /*tp_getattro*/
113    0,                         /*tp_setattro*/
114    0,                         /*tp_as_buffer*/
115    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /*tp_flags*/
116    "Protocol plugin objects",           /* tp_doc */
117    0,                         /* tp_traverse */
118    0,                         /* tp_clear */
119    0,                         /* tp_richcompare */
120    0,                         /* tp_weaklistoffset */
121    0,                         /* tp_iter */
122    0,                         /* tp_iternext */
123    Protocol_methods,             /* tp_methods */
124    Protocol_members,             /* tp_members */
125    0,                         /* tp_getset */
126    0,                         /* tp_base */
127    0,                         /* tp_dict */
128    0,                         /* tp_descr_get */
129    0,                         /* tp_descr_set */
130    0,                         /* tp_dictoffset */
131    (initproc)Protocol_init,      /* tp_init */
132    0,                         /* tp_alloc */
133    Protocol_new,                 /* tp_new */
134};
135
136/* Python module functions: */
137
138static PyObject * bpython_register_protocol(PyObject *self, PyObject *args)
139{
140    PyObject *protocol;
141    char * name;
142    struct prpl * ret;
143
144    if (!PyArg_ParseTuple(args, "sO", &name, &protocol))
145        return NULL;
146   
147    /* Increase the reference count to stop garbage collection */
148    Py_INCREF(protocol);
149
150    ret = g_new0(struct prpl, 1);
151    ret->name = name;
152    ret->data = ret;
153
154    register_protocol(ret);
155
156    Py_RETURN_NONE;
157}
158
159static PyMethodDef bpython_methods[] = {
160    {"register_protocol",  bpython_register_protocol, METH_VARARGS,
161     "Register a protocol."},
162    {NULL, NULL, 0, NULL}        /* Sentinel */
163};
164
165PyMODINIT_FUNC initbpython(void)
166{
167    PyObject * m;
168
169    ProtocolType.tp_new = PyType_GenericNew;
170    if (PyType_Ready(&ProtocolType) < 0) {
171        return;
172    }
173
174    m = Py_InitModule3("bpython", bpython_methods, "Bitlbee Plugin module");
175
176    Py_INCREF(&ProtocolType);
177    PyModule_AddObject(m, "Protocol", (PyObject *)&ProtocolType);
178}
179
180
181/* Bitlbee plugin functions: */
182
183void init_plugin() {
184    GDir *dir;
185    GError *error = NULL;
186
187    printf("Initialising Python... ");
188    Py_Initialize();
189    PyRun_SimpleString("print 'Python initialised!'\n");
190   
191    /* Add our static module */
192    initbpython();
193
194    /* Get a reference to the main module. */
195    PyObject* main_module = PyImport_AddModule("__main__");
196
197    /* Get the main module's dictionary */
198    PyObject* main_dict = PyModule_GetDict(main_module);
199
200    dir = g_dir_open(global.conf->plugindir, 0, &error);
201    if (dir) {
202        const gchar *entry;
203        char * path;
204        while ((entry = g_dir_read_name(dir))) {
205            path = g_build_filename(global.conf->plugindir, entry, NULL);
206            if (!path) {
207                log_message(LOGLVL_WARNING, "Can't build path for %s\n", entry);
208                continue;
209            }
210           
211            if (g_str_has_suffix(path, ".py")) {
212                FILE * pyfile;
213                PyObject * result;
214                printf("Loading python file %s\n", path);
215                pyfile = fopen(path, "r");
216               
217                /* Copy main dict to make sure that separate plugins
218                   run in separate environments */
219                PyObject * main_dict_copy = PyDict_Copy(main_dict);
220
221                /* Run the python file */
222                result = PyRun_File(pyfile, path, Py_file_input, main_dict_copy, main_dict_copy);
223                if (result == NULL) {
224                    printf("Error loading module %s\n", path);
225                    PyErr_PrintEx(0);
226                }
227            }
228
229            g_free(path);
230        }
231    }
232
233    // Py_Finalize(); // TODO - there's no plugin_unload for us to do this in.
234}
235
236int main(int argc, char ** argv) {
237    printf("This is a bitlbee plugin, you should place it in bitlbee's plugins directory.");
238    return 0;
239}
Note: See TracBrowser for help on using the repository browser.