From: Egor Date: Fri, 26 Jan 2024 13:03:33 +0000 (+0200) Subject: expose channel creation/MODE/TOPIC in lua X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=56e246e5c5c7cf060b3de1f1a5c6b68cb9d531f8;p=patchyircd.git expose channel creation/MODE/TOPIC in lua --- diff --git a/src/admin.c b/src/admin.c index eb18fe5..e3e99b1 100644 --- a/src/admin.c +++ b/src/admin.c @@ -265,6 +265,48 @@ static int fn_channel_part(lua_State *L) channel_part(cl, chan, reason, kicker); return 0; } +static int fn_channel_new(lua_State *L) +{ + const char *channel = luaL_checkstring(L, 1); + time_t creation = luaL_optinteger(L, 2, 0); + size_t chanlen = strlen(channel); + if (chanlen > 32) + return 0; // FIXME: error + char key[33]; + memcpy(key, channel, chanlen+1); + stringlower(key); + struct channel *chan = map_get(&channel_map, key); + if (!chan) { + chan = channel_new(channel, key, creation ? creation : get_time()); + if (map_set(&channel_map, key, chan, NULL) == -1) + abort(); + } + return 0; +} +static int fn_channel_mode(lua_State *L) +{ + struct channel *chan = *(struct channel **)luaL_checkudata(L, 1, "channel"); + size_t as, bs; + const char *a = luaL_checklstring(L, 2, &as); + const char *b = luaL_optlstring(L, 3, 0, &bs); + char *buf = malloc(as+bs+2); + memcpy(buf, a, as+1); + if (b) + memcpy(buf+as+1, b, bs+1); + char *args[] = { buf, b ? buf+as+1 : 0, 0 }; + channel_mode(0, chan, args); + free(buf); + return 0; +} +static int fn_channel_topic(lua_State *L) +{ + struct channel *chan = *(struct channel **)luaL_checkudata(L, 1, "channel"); + const char *topic = luaL_checkstring(L, 2); + const char *who = luaL_checkstring(L, 3); + time_t when = luaL_optinteger(L, 4, 0); + channel_topic(0, chan, topic, who, when ? when : get_time()); + return 0; +} static int fn_client_chghost(lua_State *L) { struct client_data *cl = *(struct client_data **)luaL_checkudata(L, 1, "client"); @@ -346,6 +388,12 @@ void admin_init(void) lua_setglobal(L, "channel_join"); lua_pushcfunction(L, fn_channel_part); lua_setglobal(L, "channel_part"); + lua_pushcfunction(L, fn_channel_new); + lua_setglobal(L, "channel_new"); + lua_pushcfunction(L, fn_channel_mode); + lua_setglobal(L, "channel_mode"); + lua_pushcfunction(L, fn_channel_topic); + lua_setglobal(L, "channel_topic"); lua_pushcfunction(L, fn_client_chghost); lua_setglobal(L, "client_chghost"); lua_pushcfunction(L, fn_rpl_whoisspecial); diff --git a/src/irc.c b/src/irc.c index 94a1152..4aef464 100644 --- a/src/irc.c +++ b/src/irc.c @@ -580,22 +580,7 @@ saslcleanup: // TODO: membership check, maybe? if (chan->dmode & DMODE_TOPICPROT && !map_get(&chan->o, client->key)) return 0; // FIXME: error 482 - free(chan->topic); - free(chan->topic_who); - if (!*args[1]) { - chan->topic = NULL; - chan->topic_who = NULL; - chan->topic_when = 0; - } else { - chan->topic = mystrdup(args[1]); - if (!chan->topic) abort(); - chan->topic_who = mystrdup(client->nick); - if (!chan->topic_who) abort(); - chan->topic_when = get_time(); - } - msg_topic(client, chan); - chanlog_time(chan->topic_when); - sendbuf_chan(chan); + channel_topic(client, chan, args[1], client->nick, get_time()); } } else if(strcmp(command, "INVITE") == 0) { if (!is_registered(client)) @@ -1455,16 +1440,8 @@ void channel_join(struct client_data *client, const char *channel, const char *c struct channel *chan = map_get(&channel_map, key); int newchan = !chan; if (!chan) { - chan = malloc(sizeof(struct channel)); - if (!chan) abort(); - memset(chan, 0, sizeof(struct channel)); - chan->creation = get_time(); - chan->member_limit = -1; - chan->dmode = DMODE_NOEXTERNAL | DMODE_TOPICPROT; - chan->key = mystrdup(key); - if (!chan->key) abort(); - chan->name = mystrdup(channel); - if (!chan->name) abort(); + chan = channel_new(channel, key, get_time()); + chan->dmode &= ~DMODE_PERSIST; if (map_set(&channel_map, key, chan, NULL) == -1) abort(); if (map_set(&chan->o, client->key, client, NULL) == -1) @@ -1518,6 +1495,20 @@ void channel_join(struct client_data *client, const char *channel, const char *c // send names channel_sendnames(client, chan); } +struct channel *channel_new(const char *channel, const char *key, time_t creation) +{ + struct channel *chan = malloc(sizeof(struct channel)); + if (!chan) abort(); + memset(chan, 0, sizeof(struct channel)); + chan->creation = creation; + chan->member_limit = -1; + chan->dmode = DMODE_NOEXTERNAL | DMODE_TOPICPROT | DMODE_PERSIST; + chan->key = mystrdup(key); + if (!chan->key) abort(); + chan->name = mystrdup(channel); + if (!chan->name) abort(); + return chan; +} void channel_part(struct client_data *client, struct channel *chan, const char *reason, struct client_data *kicker) { if (!map_get(&chan->members, client->key)) @@ -1721,6 +1712,29 @@ void channel_mode(struct client_data *client, struct channel *chan, char *args[] p++; } } +void channel_topic(struct client_data *src, struct channel *chan, const char *topic, const char *who, time_t when) +{ + free(chan->topic); + free(chan->topic_who); + if (!*topic) { + chan->topic = NULL; + chan->topic_who = NULL; + chan->topic_when = 0; + } else { + chan->topic = mystrdup(topic); + if (!chan->topic) abort(); + chan->topic_who = mystrdup(who); + if (!chan->topic_who) abort(); + chan->topic_when = when; + } + if (src) + msg_topic(src, chan); + else + copy_strf(&databuf, ":cia!cia@cia.gov TOPIC %s :%s\r\n", + chan->name, chan->topic ? chan->topic : ""); + chanlog_time(chan->topic_when); + sendbuf_chan(chan); +} struct client_data *findClient(const char *nickname) { char key[MAX_NICKLEN]; diff --git a/src/irc.h b/src/irc.h index b9f88dd..c67286d 100644 --- a/src/irc.h +++ b/src/irc.h @@ -19,8 +19,10 @@ struct channel *findChannel(const char *channel); void channel_sendtopic(struct client_data *client, struct channel *chan, int joining); void channel_sendnames(struct client_data *client, struct channel *chan); void channel_join(struct client_data *client, const char *channel, const char *chankey); +struct channel *channel_new(const char *channel, const char *key, time_t creation); void channel_part(struct client_data *client, struct channel *chan, const char *reason, struct client_data *kicker); void channel_kill(struct channel *chan); void channel_mode(struct client_data *client, struct channel *chan, char *args[]); +void channel_topic(struct client_data *src, struct channel *chan, const char *topic, const char *who, time_t when); extern struct dynarr databuf; #endif