1 /*
2  * idle.c - I'dle Mak'er plugin for Purple
3  *
4  * This file is part of Purple.
5  *
6  * Purple is the legal property of its developers, whose names are too numerous
7  * to list here.  Please refer to the COPYRIGHT file distributed with this
8  * source distribution.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
23  */
24 
25 #include "internal.h"
26 
27 #include "connection.h"
28 #include "debug.h"
29 #include "notify.h"
30 #include "plugin.h"
31 #include "request.h"
32 #include "server.h"
33 #include "status.h"
34 #include "version.h"
35 
36 /* This plugin no longer depends on gtk */
37 #define IDLE_PLUGIN_ID "core-idle"
38 
39 static GList *idled_accts = NULL;
40 
41 static gboolean
unidle_filter(PurpleAccount * acct)42 unidle_filter(PurpleAccount *acct)
43 {
44 	if (g_list_find(idled_accts, acct))
45 		return TRUE;
46 
47 	return FALSE;
48 }
49 
50 static gboolean
idleable_filter(PurpleAccount * account)51 idleable_filter(PurpleAccount *account)
52 {
53 	PurplePlugin *prpl;
54 
55 	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
56 	g_return_val_if_fail(prpl != NULL, FALSE);
57 
58 	return (PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->set_idle != NULL);
59 }
60 
61 static void
set_idle_time(PurpleAccount * acct,int mins_idle)62 set_idle_time(PurpleAccount *acct, int mins_idle)
63 {
64 	time_t t;
65 	PurpleConnection *gc = purple_account_get_connection(acct);
66 	PurplePresence *presence = purple_account_get_presence(acct);
67 
68 	if (!gc)
69 		return;
70 
71 	purple_debug_info("idle",
72 			"setting idle time for %s to %d\n",
73 			purple_account_get_username(acct), mins_idle);
74 
75 	if (mins_idle)
76 		t = time(NULL) - (60 * mins_idle); /* subtract seconds idle from current time */
77 	else
78 		t = 0; /* time idle is irrelevant */
79 
80 	purple_presence_set_idle(presence, mins_idle ? TRUE : FALSE, t);
81 }
82 
83 static void
idle_action_ok(void * ignored,PurpleRequestFields * fields)84 idle_action_ok(void *ignored, PurpleRequestFields *fields)
85 {
86 	int tm = purple_request_fields_get_integer(fields, "mins");
87 	PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
88 
89 	/* only add the account to the GList if it's not already been idled */
90 	if (!unidle_filter(acct))
91 	{
92 		purple_debug_misc("idle",
93 				"%s hasn't been idled yet; adding to list.\n",
94 				purple_account_get_username(acct));
95 		idled_accts = g_list_append(idled_accts, acct);
96 	}
97 
98 	set_idle_time(acct, tm);
99 }
100 
101 static void
idle_all_action_ok(void * ignored,PurpleRequestFields * fields)102 idle_all_action_ok(void *ignored, PurpleRequestFields *fields)
103 {
104 	PurpleAccount *acct = NULL;
105 	GList *list, *iter;
106 	int tm = purple_request_fields_get_integer(fields, "mins");
107 
108 	list = purple_accounts_get_all_active();
109 	for(iter = list; iter; iter = iter->next) {
110 		acct = (PurpleAccount *)(iter->data);
111 
112 		if(acct && idleable_filter(acct)) {
113 			purple_debug_misc("idle", "Idling %s.\n",
114 					purple_account_get_username(acct));
115 
116 			set_idle_time(acct, tm);
117 
118 			if(!g_list_find(idled_accts, acct))
119 				idled_accts = g_list_append(idled_accts, acct);
120 		}
121 	}
122 
123 	g_list_free(list);
124 }
125 
126 static void
unidle_action_ok(void * ignored,PurpleRequestFields * fields)127 unidle_action_ok(void *ignored, PurpleRequestFields *fields)
128 {
129 	PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
130 
131 	set_idle_time(acct, 0); /* unidle the account */
132 
133 	/* once the account has been unidled it shouldn't be in the list */
134 	idled_accts = g_list_remove(idled_accts, acct);
135 }
136 
137 
138 static void
idle_action(PurplePluginAction * action)139 idle_action(PurplePluginAction *action)
140 {
141 	/* Use the super fancy request API */
142 
143 	PurpleRequestFields *request;
144 	PurpleRequestFieldGroup *group;
145 	PurpleRequestField *field;
146 
147 	group = purple_request_field_group_new(NULL);
148 
149 	field = purple_request_field_account_new("acct", _("Account"), NULL);
150 	purple_request_field_account_set_filter(field, idleable_filter);
151 	purple_request_field_account_set_show_all(field, FALSE);
152 	purple_request_field_group_add_field(group, field);
153 
154 	field = purple_request_field_int_new("mins", _("Minutes"), 10);
155 	purple_request_field_group_add_field(group, field);
156 
157 	request = purple_request_fields_new();
158 	purple_request_fields_add_group(request, group);
159 
160 	purple_request_fields(action->plugin,
161 			N_("I'dle Mak'er"),
162 			_("Set Account Idle Time"),
163 			NULL,
164 			request,
165 			_("_Set"), G_CALLBACK(idle_action_ok),
166 			_("_Cancel"), NULL,
167 			NULL, NULL, NULL,
168 			NULL);
169 }
170 
171 static void
unidle_action(PurplePluginAction * action)172 unidle_action(PurplePluginAction *action)
173 {
174 	PurpleRequestFields *request;
175 	PurpleRequestFieldGroup *group;
176 	PurpleRequestField *field;
177 
178 	if (idled_accts == NULL)
179 	{
180 		purple_notify_info(NULL, NULL, _("None of your accounts are idle."), NULL);
181 		return;
182 	}
183 
184 	group = purple_request_field_group_new(NULL);
185 
186 	field = purple_request_field_account_new("acct", _("Account"), NULL);
187 	purple_request_field_account_set_filter(field, unidle_filter);
188 	purple_request_field_account_set_show_all(field, FALSE);
189 	purple_request_field_group_add_field(group, field);
190 
191 	request = purple_request_fields_new();
192 	purple_request_fields_add_group(request, group);
193 
194 	purple_request_fields(action->plugin,
195 			N_("I'dle Mak'er"),
196 			_("Unset Account Idle Time"),
197 			NULL,
198 			request,
199 			_("_Unset"), G_CALLBACK(unidle_action_ok),
200 			_("_Cancel"), NULL,
201 			NULL, NULL, NULL,
202 			NULL);
203 }
204 
205 static void
idle_all_action(PurplePluginAction * action)206 idle_all_action(PurplePluginAction *action)
207 {
208 	PurpleRequestFields *request;
209 	PurpleRequestFieldGroup *group;
210 	PurpleRequestField *field;
211 
212 	group = purple_request_field_group_new(NULL);
213 
214 	field = purple_request_field_int_new("mins", _("Minutes"), 10);
215 	purple_request_field_group_add_field(group, field);
216 
217 	request = purple_request_fields_new();
218 	purple_request_fields_add_group(request, group);
219 
220 	purple_request_fields(action->plugin,
221 			N_("I'dle Mak'er"),
222 			_("Set Idle Time for All Accounts"),
223 			NULL,
224 			request,
225 			_("_Set"), G_CALLBACK(idle_all_action_ok),
226 			_("_Cancel"), NULL,
227 			NULL, NULL, NULL,
228 			NULL);
229 }
230 
231 static void
unidle_all_action(PurplePluginAction * action)232 unidle_all_action(PurplePluginAction *action)
233 {
234 	GList *l;
235 
236 	/* freeing the list here will cause segfaults if the user idles an account
237 	 * after the list is freed */
238 	for (l = idled_accts; l; l = l->next)
239 	{
240 		PurpleAccount *account = l->data;
241 		set_idle_time(account, 0);
242 	}
243 
244 	g_list_free(idled_accts);
245 	idled_accts = NULL;
246 }
247 
248 static GList *
actions(PurplePlugin * plugin,gpointer context)249 actions(PurplePlugin *plugin, gpointer context)
250 {
251 	GList *l = NULL;
252 	PurplePluginAction *act = NULL;
253 
254 	act = purple_plugin_action_new(_("Set Account Idle Time"),
255 			idle_action);
256 	l = g_list_append(l, act);
257 
258 	act = purple_plugin_action_new(_("Unset Account Idle Time"),
259 			unidle_action);
260 	l = g_list_append(l, act);
261 
262 	act = purple_plugin_action_new(_("Set Idle Time for All Accounts"),
263 			idle_all_action);
264 	l = g_list_append(l, act);
265 
266 	act = purple_plugin_action_new(
267 			_("Unset Idle Time for All Idled Accounts"), unidle_all_action);
268 	l = g_list_append(l, act);
269 
270 	return l;
271 }
272 
273 static void
signing_off_cb(PurpleConnection * gc,void * data)274 signing_off_cb(PurpleConnection *gc, void *data)
275 {
276 	PurpleAccount *account;
277 
278 	account = purple_connection_get_account(gc);
279 	idled_accts = g_list_remove(idled_accts, account);
280 }
281 
282 static gboolean
plugin_load(PurplePlugin * plugin)283 plugin_load(PurplePlugin *plugin)
284 {
285 	purple_signal_connect(purple_connections_get_handle(), "signing-off",
286 						plugin,
287 						PURPLE_CALLBACK(signing_off_cb), NULL);
288 
289 	return TRUE;
290 }
291 
292 static gboolean
plugin_unload(PurplePlugin * plugin)293 plugin_unload(PurplePlugin *plugin)
294 {
295 	unidle_all_action(NULL);
296 
297 	return TRUE;
298 }
299 
300 static PurplePluginInfo info =
301 {
302 	PURPLE_PLUGIN_MAGIC,
303 	PURPLE_MAJOR_VERSION,
304 	PURPLE_MINOR_VERSION,
305 	PURPLE_PLUGIN_STANDARD,
306 	NULL,
307 	0,
308 	NULL,
309 	PURPLE_PRIORITY_DEFAULT,
310 	IDLE_PLUGIN_ID,
311 
312 	/* This is a cultural reference.  Dy'er Mak'er is a song by Led Zeppelin.
313 	   If that doesn't translate well into your language, drop the 's before translating. */
314 	N_("I'dle Mak'er"),
315 	DISPLAY_VERSION,
316 	N_("Allows you to hand-configure how long you've been idle"),
317 	N_("Allows you to hand-configure how long you've been idle"),
318 	"Eric Warmenhoven <eric@warmenhoven.org>",
319 	PURPLE_WEBSITE,
320 	plugin_load,
321 	plugin_unload,
322 	NULL,
323 	NULL,
324 	NULL,
325 	NULL,
326 	actions,
327 
328 	/* padding */
329 	NULL,
330 	NULL,
331 	NULL,
332 	NULL
333 };
334 
335 static void
init_plugin(PurplePlugin * plugin)336 init_plugin(PurplePlugin *plugin)
337 {
338 }
339 
340 
341 PURPLE_INIT_PLUGIN(idle, init_plugin, info)
342 
343