]>
jfr.im git - irc/quakenet/newserv.git/blob - lua/luacommands.c
1 /* Copyright (C) Chris Porter 2005-2006 */
2 /* ALL RIGHTS RESERVED. */
3 /* Don't put this into the SVN repo. */
7 - Write a nick printf type thing for pcalled functions.
8 - Make commands register as apposed to blinding calling.
9 - Use numerics instead of huge structures, and add lookup functions.
12 #include "../channel/channel.h"
13 #include "../control/control.h"
14 #include "../nick/nick.h"
15 #include "../localuser/localuser.h"
16 #include "../localuser/localuserchannel.h"
17 #include "../lib/irc_string.h"
31 static int lua_smsg(lua_State
*ps
);
32 static int lua_skill(lua_State
*ps
);
34 typedef struct lua_pusher
{
37 const char *structname
;
40 struct lua_pusher nickpusher
[MAX_PUSHER
];
41 struct lua_pusher chanpusher
[MAX_PUSHER
];
43 void lua_setuppusher(struct lua_pusher
*pusherlist
, lua_State
*l
, int index
, struct lua_pusher
**lp
, int max
);
45 void lua_initnickpusher(void);
46 INLINE
int lua_usepusher(lua_State
*l
, struct lua_pusher
**lp
, void *np
);
48 void lua_initchanpusher(void);
49 INLINE
int lua_usechanpusher(lua_State
*l
, struct lua_pusher
**lp
, nick
*np
);
51 #define lua_setupnickpusher(L2, I2, P2, M2) lua_setuppusher(&nickpusher[0], L2, I2, P2, M2)
52 #define lua_setupchanpusher(L2, I2, P2, M2) lua_setuppusher(&chanpusher[0], L2, I2, P2, M2)
54 int lua_lineok(const char *data
) {
55 if(strchr(data
, '\r') || strchr(data
, '\n'))
60 int lua_cmsg(char *channell
, char *message
, ...) {
65 va_start(va
, message
);
66 vsnprintf(buf
, sizeof(buf
), message
, va
);
69 cp
= findchannel(channell
);
76 lua_channelmessage(cp
, "%s", buf
);
81 static int lua_chanmsg(lua_State
*ps
) {
82 if(!lua_isstring(ps
, 1))
83 LUA_RETURN(ps
, LUA_FAIL
);
85 LUA_RETURN(ps
, lua_cmsg(LUA_PUKECHAN
, "lua: %s", lua_tostring(ps
, 1)));
88 static int lua_scripterror(lua_State
*ps
) {
89 if(!lua_isstring(ps
, 1))
90 LUA_RETURN(ps
, LUA_FAIL
);
92 LUA_RETURN(ps
, lua_cmsg(LUA_PUKECHAN
, "lua-error: %s", lua_tostring(ps
, 1)));
95 static int lua_ctcp(lua_State
*ps
) {
99 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
100 LUA_RETURN(ps
, LUA_FAIL
);
102 n
= lua_tostring(ps
, 1);
103 msg
= lua_tostring(ps
, 2);
105 np
= getnickbynick(n
);
106 if(!np
|| !lua_lineok(msg
))
107 LUA_RETURN(ps
, LUA_FAIL
);
109 lua_message(np
, "\001%s\001", msg
);
111 LUA_RETURN(ps
, lua_cmsg(LUA_PUKECHAN
, "lua-ctcp: %s (%s)", np
->nick
, msg
));
114 static int lua_noticecmd(lua_State
*ps
) {
118 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
119 LUA_RETURN(ps
, LUA_FAIL
);
121 n
= lua_tostring(ps
, 1);
122 msg
= lua_tostring(ps
, 2);
124 np
= getnickbynick(n
);
125 if(!np
|| !lua_lineok(msg
))
126 LUA_RETURN(ps
, LUA_FAIL
);
128 lua_notice(np
, "%s", msg
);
130 LUA_RETURN(ps
, LUA_OK
);
133 static int lua_kill(lua_State
*ps
) {
137 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
138 LUA_RETURN(ps
, LUA_FAIL
);
140 n
= lua_tostring(ps
, 1);
141 msg
= lua_tostring(ps
, 2);
143 np
= getnickbynick(n
);
145 LUA_RETURN(ps
, LUA_FAIL
);
147 if(IsOper(np
) || IsService(np
) || IsXOper(np
))
148 LUA_RETURN(ps
, LUA_FAIL
);
151 LUA_RETURN(ps
, LUA_FAIL
);
153 killuser(lua_nick
, np
, "%s", msg
);
155 LUA_RETURN(ps
, lua_cmsg(LUA_PUKECHAN
, "lua-KILL: %s (%s)", np
->nick
, msg
));
158 static int lua_kick(lua_State
*ps
) {
159 const char *n
, *msg
, *chan
;
164 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2) || !lua_isstring(ps
, 3))
165 LUA_RETURN(ps
, LUA_FAIL
);
167 chan
= lua_tostring(ps
, 1);
168 n
= lua_tostring(ps
, 2);
169 msg
= lua_tostring(ps
, 3);
171 if(lua_isboolean(ps
, 4) && !lua_toboolean(ps
, 4))
174 np
= getnickbynick(n
);
176 LUA_RETURN(ps
, LUA_FAIL
);
178 if(dochecks
&& (IsOper(np
) || IsXOper(np
) || IsService(np
)))
179 LUA_RETURN(ps
, LUA_FAIL
);
181 cp
= findchannel((char *)chan
);
183 LUA_RETURN(ps
, LUA_FAIL
);
186 LUA_RETURN(ps
, LUA_FAIL
);
188 localkickuser(lua_nick
, cp
, np
, msg
);
190 LUA_RETURN(ps
, LUA_OK
);
193 static int lua_invite(lua_State
*ps
) {
197 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
198 LUA_RETURN(ps
, LUA_FAIL
);
200 np
= getnickbynick((char *)lua_tostring(ps
, 1));
202 LUA_RETURN(ps
, LUA_FAIL
);
204 cp
= findchannel((char *)lua_tostring(ps
, 2));
206 LUA_RETURN(ps
, LUA_FAIL
);
208 localinvite(lua_nick
, cp
, np
);
210 LUA_RETURN(ps
, LUA_OK
);
213 static int lua_gline(lua_State
*ps
) {
217 int duration
, usercount
= 0;
220 if(!lua_isstring(ps
, 1) || !lua_isint(ps
, 2) || !lua_isstring(ps
, 3))
221 LUA_RETURN(ps
, LUA_FAIL
);
223 duration
= lua_toint(ps
, 2);
224 if((duration
< 1) || (duration
> 7 * 86400))
225 LUA_RETURN(ps
, LUA_FAIL
);
227 reason
= lua_tostring(ps
, 3);
228 if(!lua_lineok(reason
) || !reason
)
229 LUA_RETURN(ps
, LUA_FAIL
);
231 target
= getnickbynick(lua_tostring(ps
, 1));
232 if(!target
|| (IsOper(target
) || IsXOper(target
) || IsService(target
)))
233 LUA_RETURN(ps
, LUA_FAIL
);
237 LUA_RETURN(ps
, LUA_FAIL
);
239 usercount
= hp
->clonecount
;
240 if(usercount
> 10) { /* (decent) trusted host */
246 for (j
=0;j
<NICKHASHSIZE
;j
++)
247 for (np
=nicktable
[j
];np
;np
=np
->next
)
248 if (np
&& (np
->host
== hp
) && (!ircd_strcmp(np
->ident
, target
->ident
)))
252 LUA_RETURN(ps
, LUA_FAIL
);
254 snprintf(mask
, sizeof(mask
), "*%s@%s", target
->ident
, IPtostr(target
->ipaddress
));
256 snprintf(mask
, sizeof(mask
), "*@%s", IPtostr(target
->ipaddress
));
259 irc_send("%s GL * +%s %d :%s", mynumeric
->content
, mask
, duration
, reason
);
260 LUA_RETURN(ps
, lua_cmsg(LUA_PUKECHAN
, "lua-GLINE: %s (%d users, %d seconds -- %s)", mask
, usercount
, duration
, reason
));
263 static int lua_getchaninfo(lua_State
*ps
) {
266 if(!lua_isstring(ps
, 1))
269 cp
= findchannel((char *)lua_tostring(ps
, 1));
273 LUA_PUSHCHAN(ps
, cp
);
278 static int lua_opchan(lua_State
*ps
) {
282 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
283 LUA_RETURN(ps
, LUA_FAIL
);
285 cp
= findchannel((char *)lua_tostring(ps
, 1));
287 LUA_RETURN(ps
, LUA_FAIL
);
289 np
= getnickbynick((char *)lua_tostring(ps
, 2));
291 LUA_RETURN(ps
, LUA_FAIL
);
293 localsetmodes(lua_nick
, cp
, np
, MC_OP
);
294 LUA_RETURN(ps
, LUA_OK
);
297 static int lua_deopchan(lua_State
*ps
) {
301 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
302 LUA_RETURN(ps
, LUA_FAIL
);
304 cp
= findchannel((char *)lua_tostring(ps
, 1));
306 LUA_RETURN(ps
, LUA_FAIL
);
308 np
= getnickbynick((char *)lua_tostring(ps
, 2));
310 LUA_RETURN(ps
, LUA_FAIL
);
312 localsetmodes(lua_nick
, cp
, np
, MC_DEOP
);
313 LUA_RETURN(ps
, LUA_OK
);
316 static int lua_voicechan(lua_State
*ps
) {
320 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
321 LUA_RETURN(ps
, LUA_FAIL
);
323 cp
= findchannel((char *)lua_tostring(ps
, 1));
325 LUA_RETURN(ps
, LUA_FAIL
);
327 np
= getnickbynick((char *)lua_tostring(ps
, 2));
329 LUA_RETURN(ps
, LUA_FAIL
);
331 localsetmodes(lua_nick
, cp
, np
, MC_VOICE
);
332 LUA_RETURN(ps
, LUA_OK
);
335 static int lua_counthost(lua_State
*ps
) {
339 if(!lua_islong(ps
, 1))
342 numeric
= lua_tolong(ps
, 1);
344 np
= getnickbynumeric(numeric
);
348 lua_pushint(ps
, np
->host
->clonecount
);
352 static int lua_versioninfo(lua_State
*ps
) {
353 lua_pushstring(ps
, LUA_VERSION
);
354 lua_pushstring(ps
, LUA_BOTVERSION
);
355 lua_pushstring(ps
, __DATE__
);
356 lua_pushstring(ps
, __TIME__
);
359 lua_pushstring(ps
, " + " LUAJIT_VERSION
);
361 lua_pushstring(ps
, "");
367 static int lua_basepath(lua_State
*ps
) {
368 lua_pushfstring(ps
, "%s/", cpath
->content
);
374 static int lua_getuserbyauth(lua_State
*l
) {
379 if(!lua_isstring(l
, 1))
382 acc
= lua_tostring(l
, 1);
384 for(i
=0;i
<NICKHASHSIZE
;i
++) {
385 for(np
=nicktable
[i
];np
;np
=np
->next
) {
386 if(np
&& np
->authname
&& !ircd_strcmp(np
->authname
, acc
)) {
396 static int lua_getnickchans(lua_State
*l
) {
401 if(!lua_islong(l
, 1))
404 np
= getnickbynumeric(lua_tolong(l
, 1));
408 channels
= (channel
**)np
->channels
->content
;
409 for(i
=0;i
<np
->channels
->cursi
;i
++)
410 lua_pushstring(l
, channels
[i
]->index
->name
->content
);
412 return np
->channels
->cursi
;
415 static int lua_getnickchanindex(lua_State
*l
) {
419 if(!lua_islong(l
, 1) || !lua_isint(l
, 2))
422 np
= getnickbynumeric(lua_tolong(l
, 1));
426 offset
= lua_toint(l
, 2);
427 if((offset
< 0) || (offset
>= np
->channels
->cursi
))
430 lua_pushstring(l
, ((channel
**)np
->channels
->content
)[offset
]->index
->name
->content
);
438 struct lua_pusher
*nickhashpusher
[MAX_PUSHER
];
440 static int lua_getnextnick(lua_State
*l
) {
441 if(!lasthashnick
&& (hashindex
!= -1))
447 if(hashindex
>= NICKHASHSIZE
)
449 lasthashnick
= nicktable
[hashindex
];
451 lasthashnick
= lasthashnick
->next
;
453 } while(!lasthashnick
);
455 return lua_usepusher(l
, nickhashpusher
, lasthashnick
);
458 static int lua_getfirstnick(lua_State
*l
) {
462 lua_setupnickpusher(l
, 1, nickhashpusher
, MAX_PUSHER
);
464 return lua_getnextnick(l
);
468 chanindex
*lasthashchan
;
470 struct lua_pusher
*chanhashpusher
[MAX_PUSHER
];
472 static int lua_getnextchan(lua_State
*l
) {
473 if(!lasthashchan
&& (chanhashindex
!= -1))
479 if(chanhashindex
>= CHANNELHASHSIZE
)
481 lasthashchan
= chantable
[chanhashindex
];
483 lasthashchan
= lasthashchan
->next
;
485 } while(!lasthashchan
|| !lasthashchan
->channel
);
487 return lua_usepusher(l
, chanhashpusher
, lasthashchan
);
490 static int lua_getfirstchan(lua_State
*l
) {
494 lua_setupchanpusher(l
, 1, chanhashpusher
, MAX_PUSHER
);
496 return lua_getnextchan(l
);
499 static int lua_getnickchancount(lua_State
*l
) {
502 if(!lua_islong(l
, 1))
505 np
= getnickbynumeric(lua_tolong(l
, 1));
509 lua_pushint(l
, np
->channels
->cursi
);
514 static int lua_gethostusers(lua_State
*l
) {
518 if(!lua_islong(l
, 1))
521 np
= getnickbynumeric(lua_tolong(l
, 1));
522 if(!np
|| !np
->host
|| !np
->host
->nicks
)
525 np
= np
->host
->nicks
;
526 count
= np
->host
->clonecount
;
536 static int lua_getnickcountry(lua_State
*l
) {
540 ext
= findnickext("geoip");
544 if(!lua_islong(l
, 1))
547 np
= getnickbynumeric(lua_tolong(l
, 1));
551 lua_pushint(l
, (int)np
->exts
[ext
]);
555 static int lua_chanfix(lua_State
*ps
) {
559 if(!lua_isstring(ps
, 1))
560 LUA_RETURN(ps
, LUA_FAIL
);
562 cp
= findchannel((char *)lua_tostring(ps
, 1));
564 LUA_RETURN(ps
, LUA_FAIL
);
566 np
= getnickbynick(LUA_CHANFIXBOT
);
568 LUA_RETURN(ps
, LUA_FAIL
);
570 lua_message(np
, "chanfix %s", cp
->index
->name
->content
);
572 LUA_RETURN(ps
, LUA_OK
);
575 static int lua_clearmode(lua_State
*ps
) {
582 if(!lua_isstring(ps
, 1))
583 LUA_RETURN(ps
, LUA_FAIL
);
585 cp
= findchannel((char *)lua_tostring(ps
, 1));
587 LUA_RETURN(ps
, LUA_FAIL
);
589 localsetmodeinit(&changes
, cp
, lua_nick
);
591 localdosetmode_key(&changes
, NULL
, MCB_DEL
);
592 localdosetmode_simple(&changes
, 0, CHANMODE_INVITEONLY
| CHANMODE_LIMIT
);
595 localdosetmode_ban(&changes
, bantostring(cp
->bans
), MCB_DEL
);
597 for(i
=0,lp
=cp
->users
->content
;i
<cp
->users
->hashsize
;i
++,lp
++)
598 if((*lp
!= nouser
) && (*lp
& CUMODE_OP
)) {
599 np
= getnickbynumeric(*lp
);
600 if(np
&& !IsService(np
))
601 localdosetmode_nick(&changes
, np
, MC_DEOP
);
604 localsetmodeflush(&changes
, 1);
606 LUA_RETURN(ps
, LUA_OK
);
609 static int lua_ban(lua_State
*ps
) {
615 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
616 LUA_RETURN(ps
, LUA_FAIL
);
618 if(lua_isboolean(ps
, 3) && lua_toboolean(ps
, 3))
621 cp
= findchannel((char *)lua_tostring(ps
, 1));
623 LUA_RETURN(ps
, LUA_FAIL
);
625 mask
= lua_tostring(ps
, 2);
626 if(!mask
|| !mask
[0] || !lua_lineok(mask
))
627 LUA_RETURN(ps
, LUA_FAIL
);
629 localsetmodeinit(&changes
, cp
, lua_nick
);
630 localdosetmode_ban(&changes
, mask
, dir
);
631 localsetmodeflush(&changes
, 1);
633 LUA_RETURN(ps
, LUA_OK
);
636 static int lua_topic(lua_State
*ps
) {
640 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
641 LUA_RETURN(ps
, LUA_FAIL
);
643 cp
= findchannel((char *)lua_tostring(ps
, 1));
645 LUA_RETURN(ps
, LUA_FAIL
);
647 topic
= (char *)lua_tostring(ps
, 2);
648 if(!topic
|| !lua_lineok(topic
))
649 LUA_RETURN(ps
, LUA_FAIL
);
651 localsettopic(lua_nick
, cp
, topic
);
653 LUA_RETURN(ps
, LUA_OK
);
656 static int lua_getuserchanmodes(lua_State
*l
) {
661 if(!lua_islong(l
, 1) || !lua_isstring(l
, 2))
664 np
= getnickbynumeric(lua_tolong(l
, 1));
668 cp
= findchannel((char *)lua_tostring(l
, 2));
672 lp
= getnumerichandlefromchanhash(cp
->users
, np
->numeric
);
676 LUA_PUSHNICKCHANMODES(l
, lp
);
680 static int lua_getnickbynick(lua_State
*l
) {
683 if(!lua_isstring(l
, 1))
686 np
= getnickbynick(lua_tostring(l
, 1));
694 static int lua_getnickbynumeric(lua_State
*l
) {
697 if(!lua_islong(l
, 1))
700 np
= getnickbynumeric(lua_tolong(l
, 1));
708 void lua_registercommands(lua_State
*l
) {
709 lua_register(l
, "irc_smsg", lua_smsg
);
710 lua_register(l
, "irc_skill", lua_skill
);
712 lua_register(l
, "chanmsg", lua_chanmsg
);
713 lua_register(l
, "scripterror", lua_scripterror
);
714 lua_register(l
, "versioninfo", lua_versioninfo
);
715 lua_register(l
, "basepath", lua_basepath
);
717 lua_register(l
, "irc_report", lua_chanmsg
);
718 lua_register(l
, "irc_ctcp", lua_ctcp
);
719 lua_register(l
, "irc_kill", lua_kill
);
720 lua_register(l
, "irc_kick", lua_kick
);
721 lua_register(l
, "irc_invite", lua_invite
);
722 lua_register(l
, "irc_gline", lua_gline
);
723 lua_register(l
, "irc_getchaninfo", lua_getchaninfo
);
724 lua_register(l
, "irc_counthost", lua_counthost
);
725 lua_register(l
, "irc_getuserbyauth", lua_getuserbyauth
);
726 lua_register(l
, "irc_notice", lua_noticecmd
);
727 lua_register(l
, "irc_opchan", lua_opchan
);
728 lua_register(l
, "irc_voicechan", lua_voicechan
);
729 lua_register(l
, "irc_chanfix", lua_chanfix
);
730 lua_register(l
, "irc_clearmode", lua_clearmode
);
731 lua_register(l
, "irc_ban", lua_ban
);
732 lua_register(l
, "irc_deopchan", lua_deopchan
);
733 lua_register(l
, "irc_topic", lua_topic
);
735 lua_register(l
, "irc_getnickbynick", lua_getnickbynick
);
736 lua_register(l
, "irc_getnickbynumeric", lua_getnickbynumeric
);
737 lua_register(l
, "irc_getfirstnick", lua_getfirstnick
);
738 lua_register(l
, "irc_getnextnick", lua_getnextnick
);
740 lua_register(l
, "irc_getnickchans", lua_getnickchans
);
741 lua_register(l
, "irc_getnickchanindex", lua_getnickchanindex
);
742 lua_register(l
, "irc_getnickchancount", lua_getnickchancount
);
744 lua_register(l
, "irc_getuserchanmodes", lua_getuserchanmodes
);
747 lua_register(l
, "irc_gethostusers", lua_gethostusers
);
748 lua_register(l
, "irc_getnickcountry", lua_getnickcountry
);
750 lua_register(l
, "irc_getfirstchan", lua_getfirstchan
);
751 lua_register(l
, "irc_getnextchan", lua_getnextchan
);
756 static int lua_smsg(lua_State
*ps
) {
757 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
758 LUA_RETURN(ps
, LUA_FAIL
);
760 LUA_RETURN(ps
, lua_cmsg((char *)lua_tostring(ps
, 2), "%s", lua_tostring(ps
, 1)));
763 static int lua_skill(lua_State
*ps
) {
767 if(!lua_isstring(ps
, 1) || !lua_isstring(ps
, 2))
768 LUA_RETURN(ps
, LUA_FAIL
);
770 n
= lua_tostring(ps
, 1);
771 msg
= lua_tostring(ps
, 2);
773 np
= getnickbynick(n
);
775 LUA_RETURN(ps
, LUA_FAIL
);
777 if(IsOper(np
) || IsService(np
) || IsXOper(np
))
778 LUA_RETURN(ps
, LUA_FAIL
);
781 LUA_RETURN(ps
, LUA_FAIL
);
783 killuser(lua_nick
, np
, "%s", msg
);
785 LUA_RETURN(ps
, LUA_OK
);
788 #define PUSHER_STRING 1
789 #define PUSHER_REALNAME 2
791 #define PUSHER_LONG 4
792 #define PUSHER_HOSTNAME 5
793 #define PUSHER_SSTRING 6
794 #define PUSHER_TOTALUSERS 7
795 #define PUSHER_TOPIC 8
797 void lua_initnickpusher(void) {
800 #define PUSH_NICKPUSHER(F2, O2) nickpusher[i].argtype = F2; nickpusher[i].structname = #O2; nickpusher[i].offset = offsetof(nick, O2); i++;
802 PUSH_NICKPUSHER(PUSHER_STRING
, nick
);
803 PUSH_NICKPUSHER(PUSHER_STRING
, ident
);
804 PUSH_NICKPUSHER(PUSHER_HOSTNAME
, host
);
805 PUSH_NICKPUSHER(PUSHER_REALNAME
, realname
);
806 PUSH_NICKPUSHER(PUSHER_STRING
, authname
);
807 PUSH_NICKPUSHER(PUSHER_IP
, ipaddress
);
808 PUSH_NICKPUSHER(PUSHER_LONG
, numeric
);
810 nickpusher
[i
].argtype
= 0;
813 void lua_setuppusher(struct lua_pusher
*pusherlist
, lua_State
*l
, int index
, struct lua_pusher
**lp
, int max
) {
815 struct lua_pusher
*f
;
820 if(!lua_istable(l
, -1) || (max
< 2))
827 while (lua_next(l
, index
)) {
828 if(lua_isstring(l
, -1)) {
829 char *name
= (char *)lua_tostring(l
, -1);
831 for(f
=pusherlist
;f
->argtype
;f
++)
832 if(!strcmp(f
->structname
, name
))
848 INLINE
int lua_usepusher(lua_State
*l
, struct lua_pusher
**lp
, void *np
) {
852 void *offset
= (void *)np
+ (*lp
)->offset
;
854 switch((*lp
)->argtype
) {
856 lua_pushstring(l
, (char *)offset
);
858 case PUSHER_HOSTNAME
:
859 lua_pushstring(l
, (*(host
**)offset
)->name
->content
);
861 case PUSHER_REALNAME
:
862 lua_pushstring(l
, (*(realname
**)offset
)->name
->content
);
865 lua_pushstring(l
, (*((sstring
**)offset
))->content
);
868 lua_pushlong(l
, *((long *)offset
));
871 lua_pushstring(l
, IPtostr(*((long *)offset
)));
873 case PUSHER_TOTALUSERS
:
874 lua_pushint(l
, (*((channel
**)offset
))->users
->totalusers
);
877 if((*((channel
**)offset
))->topic
) {
878 lua_pushstring(l
, (*((channel
**)offset
))->topic
->content
);
892 void lua_initchanpusher(void) {
895 #define PUSH_CHANPUSHER(F2, O2, N2) chanpusher[i].argtype = F2; chanpusher[i].structname = N2; chanpusher[i].offset = offsetof(chanindex, O2); i++;
897 PUSH_CHANPUSHER(PUSHER_SSTRING
, name
, "name");
898 PUSH_CHANPUSHER(PUSHER_TOTALUSERS
, channel
, "totalusers");
899 PUSH_CHANPUSHER(PUSHER_TOPIC
, channel
, "topic");
901 chanpusher
[i
].argtype
= 0;