1009
|
1 /* |
|
2 * This is a sample plugin in native C API. |
|
3 * |
|
4 * Note: we recommend that C plugins should be used as last resort because any |
|
5 * error will crash the whole daemon. It is also less convenient to share and |
|
6 * update. |
|
7 * |
|
8 * You can use CMake to build and install it to appropriate place using the |
|
9 * following code: |
|
10 * |
|
11 * find_package(irccd REQUIRED) |
|
12 * irccd_define_c_plugin( |
|
13 * MAME myplugin |
|
14 * SOURCES muplugin.c |
|
15 * ) |
|
16 * |
|
17 * You can also compile by hand using the pkg-config irccd file. |
|
18 * |
|
19 * cc myplugin.c -o myplugin.so $(pkg-config --libs --cflags irccd) |
|
20 * |
|
21 * All symbols exported from the file must start with the plugin file basename |
|
22 * without its extension and with every non allowed character translated to |
|
23 * `_'. For example if the plugin is name `example-stuff' symbol must start |
|
24 * with `example_stuff_'. In this example we consider `example_`. |
|
25 */ |
|
26 |
|
27 /* |
|
28 * Include convention is using irccd/ prefix. |
|
29 * |
|
30 * The compat.h header contains additional BSD/POSIX extensions that may be |
|
31 * missing on your system. It is optional unless you explicitly use them. |
|
32 */ |
|
33 |
|
34 #include <string.h> |
|
35 |
|
36 #include <irccd/compat.h> |
|
37 #include <irccd/event.h> |
|
38 #include <irccd/server.h> |
|
39 |
|
40 /* |
|
41 * This is the plugin identifier, every variable are optional. |
|
42 */ |
|
43 const char *example_description = "Example of C plugin" |
|
44 const char *example_version = "0.1.0"; |
|
45 const char *example_license = "ISC"; |
|
46 const char *example_author = "Name and optional email"; |
|
47 |
|
48 /* |
|
49 * get_options | get_templates | get_paths |
|
50 * ---------------------------------------------------------------------- |
|
51 * |
|
52 * The following optional functions indicate to the daemon which keys are |
|
53 * supported as options, templates and paths respectively. |
|
54 * |
|
55 * Note: even if get_paths is not present or return NULL, irccd allows `cache', |
|
56 * `data' and `config' as standard keys. |
|
57 * |
|
58 * All three functions should return an array of strings which should be |
|
59 * terminated with a NULL value. They should not be dynamically allocated |
|
60 * because irccd does not assume they are. |
|
61 */ |
|
62 |
|
63 const char ** |
|
64 example_get_options(void) |
|
65 { |
|
66 /* Indicate to irccd we support options `level' and `language' */ |
|
67 static const char *keys[] = { |
|
68 "level", |
|
69 "language", |
|
70 NULL |
|
71 }; |
|
72 |
|
73 return keys; |
|
74 } |
|
75 |
|
76 const char ** |
|
77 example_get_templates(void) |
|
78 { |
|
79 /* Indicate to irccd we support templates `start' and `finish' */ |
|
80 static const char *keys[] = { |
|
81 "start", |
|
82 "finish", |
|
83 NULL |
|
84 }; |
|
85 |
|
86 return keys; |
|
87 } |
|
88 |
|
89 /* |
|
90 * get_option | get_template | get_path |
|
91 * ---------------------------------------------------------------------- |
|
92 * |
|
93 * Those optional functions are analogous to their respective plural form |
|
94 * except they take a key as parameter. |
|
95 * |
|
96 * The plugin can receive an unknown key from the user, NULL can be returned if |
|
97 * they are not supported. |
|
98 * |
|
99 * The returned string isn't free'd by irccd so don't allocate any value |
|
100 * without storing it somewhere if really needed. |
|
101 */ |
|
102 |
|
103 const char * |
|
104 example_get_option(const char *key) |
|
105 { |
|
106 if (strcmp(key, "level") == 0) |
|
107 return "hard"; |
|
108 else if (strcmp(key, "language") == 0) |
|
109 return "french"; |
|
110 |
|
111 return NULL; |
|
112 } |
|
113 |
|
114 const char * |
|
115 example_get_template(const char *key) |
|
116 { |
|
117 if (strcmp(key, "start") == 0) |
|
118 return "#{nickname}, the game has started"; |
|
119 else if (strcmp(key, "finish") == 0) |
|
120 return "#{nickname}, the game has finished"; |
|
121 |
|
122 return NULL; |
|
123 } |
|
124 |
|
125 /* |
|
126 * set_option | set_template | set_path |
|
127 * ---------------------------------------------------------------------- |
|
128 * |
|
129 * Finally the three functions are used to set a new value as options, |
|
130 * templates and paths respectively. Like their `get_*' counterpart, the plugin |
|
131 * may receive a unknown key from the user in that case it should be simply |
|
132 * ignored. |
|
133 * |
|
134 * Tip: the easiest to manage those is to use global fixed size strings. |
|
135 */ |
|
136 |
|
137 void |
|
138 example_set_option(const char *key, const char *value) |
|
139 { |
|
140 /* Assuming my_option_* variable exist. */ |
|
141 if (strcmp(key, "level") == 0) |
|
142 strlcpy(my_option_level, value, sizeof (my_option_level)); |
|
143 else if (strcmp(key, "language") == 0) |
|
144 strlcpy(my_option_language, value, sizeof (my_option_language)); |
|
145 } |
|
146 |
|
147 void |
|
148 example_set_template(const char *key) |
|
149 { |
|
150 /* Assuming my_template_* variable exist. */ |
|
151 if (strcmp(key, "level") == 0) |
|
152 strlcpy(my_template_level, value, sizeof (my_template_level)); |
|
153 else if (strcmp(key, "language") == 0) |
|
154 strlcpy(my_template_language, value, sizeof (my_template_language)); |
|
155 } |
|
156 |
|
157 /* |
|
158 * event |
|
159 * ---------------------------------------------------------------------- |
|
160 * |
|
161 * This function is called when an event has been received. The parameter ev |
|
162 * contains a union with every possible supported event, the plugin must not |
|
163 * modify it. |
|
164 * |
|
165 * Use the ev->type enumeration to read the appropriate union member. |
|
166 */ |
|
167 |
|
168 void |
|
169 example_event(const struct irc_event *ev) |
|
170 { |
|
171 /* Simply echo back in case of message. */ |
|
172 if (ev->type == IRC_EVENT_MESSAGE) |
|
173 irc_server_message(ev->server, ev->message.channel, ev->message.message); |
|
174 } |