nyxx-discord / nyxx_extensions

Extensions subpackage for nyxx library
Apache License 2.0
3 stars 5 forks source link

GuildChannel.clone #38

Closed doEggi closed 2 months ago

doEggi commented 3 months ago

Is your feature request related to a problem? Please describe. Apparently at the moment it is not possible to clone a channel with all its permissions.

Describe the solution you'd like It would be nice to implement the .clone() function to GuildChannel 's

Describe alternatives you've considered There are no alternatives known to me.

Additional context https://discord.js.org/docs/packages/discord.js/14.15.3/BaseGuildTextChannel:Class#clone

abitofevrything commented 3 months ago

How does this method work? Does it create a new channel with the same properties? Does it create a builder for creating a new channel with the same properties?

MCausc78 commented 3 months ago

they just create a channel from object properties: https://github.com/discordjs/discord.js/blob/14.15.3/packages/discord.js/src/structures/GuildChannel.js#L375-L390

Official Discord client does same:

         333848: function(e, t, n) {
            "use strict";
            n(411104);
            var r = n(990547)
              , i = n(283693)
              , a = n(570140)
              , o = n(408987)
              , s = n(9156)
              , l = n(621600)
              , u = n(573261)
              , c = n(92114)
              , d = n(981631)
              , _ = n(526761);
            t.Z = {
                createChannel(e) {
                    let {guildId: t, type: n, name: E, permissionOverwrites: f=[], bitrate: h, userLimit: p, parentId: m, skuId: I, branchId: T} = e;
                    a.Z.dispatch({
                        type: "CREATE_CHANNEL_MODAL_SUBMIT"
                    });
                    let g = {
                        type: n,
                        name: E,
                        permission_overwrites: f
                    };
                    if (null != h && h !== d.epw && (g.bitrate = h),
                    null != p && p > 0 && (g.user_limit = p),
                    null != m && (g.parent_id = m),
                    n === d.d4z.GUILD_STORE) {
                        if (null == I)
                            throw Error("Unexpected missing SKU");
                        g.sku_id = I,
                        g.branch_id = T
                    }
                    return u.Z.post({
                        url: d.ANM.GUILD_CHANNELS(t),
                        body: g,
                        oldFormErrors: !0,

Submit handler:

                $(this, "handleSubmit", async e=>{
                    let t, s, n;
                    e.preventDefault();
                    let {cloneChannel: a, categoryId: r, user: l, memberRoleIds: i, isAdmin: o, onClose: d, owner: c} = this.props
                      , {name: h, pendingPermissionOverwrites: E, channelType: N, skuId: C, branchId: p, isPrivate: _} = this.state
                      , g = this.getGuildId();
                    if (null != g) {
                        if (null != a)
                            t = u().values(a.permissionOverwrites),
                            s = a.bitrate,
                            n = a.userLimit;
                        else if (N === V.d4z.GUILD_ANNOUNCEMENT)
                            t = (0,
                            w.rt)(g);
                        else {
                            if (_) {
                                t = (0,
                                w.oQ)(g, N, [], !0);
                                let e = (0,
                                S.Tj)(E, N);
                                e.length > 0 && (t = t.concat(e));
                                let s = null != c && l.id === c.id;
                                !(t.some(e=>i.has(e.id)) || o || s) && t.push((0,
                                w.jZ)(l.id, N))
                            }
                            N === V.d4z.GUILD_STAGE_VOICE && (t = [],
                            Object.values(E).forEach(e=>{
                                let {row: s} = e;
                                null != s.id && "" !== s.id && (s.rowType === K.aC.ROLE ? t.push((0,
                                b.createModeratorOverwrite)(s.id, I.BN.ROLE)) : s.rowType === K.aC.MEMBER && t.push((0,
                                b.createModeratorOverwrite)(s.id, I.BN.MEMBER)))
                            }
                            ))
                        }
                        this.setState({
                            errors: {}
                        });
                        try {
                            let e = await m.Z.createChannel({
                                guildId: g,
                                type: N,
                                name: h,
                                permissionOverwrites: t,
                                bitrate: s,
                                userLimit: n,
                                parentId: N !== V.d4z.GUILD_CATEGORY ? r : null,
                                skuId: C,
                                branchId: p
                            });
                            if (null == e || 201 !== e.status)
                                return;
                            let a = e.body;
                            P.xL.has(N) && (0,
                            Z.XU)(a.guild_id, a.id),
                            d()
                        } catch (e) {

In UI, "clone channel" is referred as "Duplicate channel"

abitofevrything commented 3 months ago

Instances of GuildChannel can only represent channels that exist. So this method either has to create a new channel itself, or return a builder. If it doesn't, I'm not really sure what the point is.

If you could give a clear explanation of what you expect this method to do, that would be helpful (discord.js' docs are particularily bad).

doEggi commented 3 months ago

The point would be to get every aspects of the channel (Name, Permissions aso) and create the exact same channel (with a new id of course; empty, so no messages). In my special case I want to use it to clear a whole channel (duplicate, delete the old one, set the origin position to the new one).

abitofevrything commented 3 months ago

Would adding a toBuilder() method work for this? You could achieve the same by then creating a new channel with that builder.

doEggi commented 2 months ago

That would be perfect, with this you even could change specific values of the cloned channel.