]> PatchyGit - patchyircd.git/commitdiff
expose channel creation/MODE/TOPIC in lua
authorEgor <egor@patchysicp.xyz>
Fri, 26 Jan 2024 13:03:33 +0000 (15:03 +0200)
committerEgor <egor@patchysicp.xyz>
Fri, 26 Jan 2024 13:03:33 +0000 (15:03 +0200)
src/admin.c
src/irc.c
src/irc.h

index eb18fe5..e3e99b1 100644 (file)
@@ -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);
index 94a1152..4aef464 100644 (file)
--- 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];
index b9f88dd..c67286d 100644 (file)
--- 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