]> jfr.im git - irc/evilnet/znc.git/commitdiff
Add MoveChan and SwapChans commands
authornjhanley <redacted>
Sun, 30 Aug 2020 22:20:36 +0000 (18:20 -0400)
committernjhanley <redacted>
Tue, 29 Sep 2020 23:32:45 +0000 (19:32 -0400)
include/znc/IRCNetwork.h
src/ClientCommand.cpp
src/IRCNetwork.cpp
test/integration/tests/core.cpp

index a9c3deeece7aee87fc743c98890cc8836c79dcdc..6be956317c8f79e8b4f774aa7380b97acc69f3fb 100644 (file)
@@ -93,6 +93,9 @@ class CIRCNetwork : private CCoreTranslationMixin {
     bool AddChan(CChan* pChan);
     bool AddChan(const CString& sName, bool bInConfig);
     bool DelChan(const CString& sName);
+    bool MoveChan(const CString& sChan, unsigned int index, CString& sError);
+    bool SwapChans(const CString& sChan1, const CString& sChan2,
+                   CString& sError);
     void JoinChans();
     void JoinChans(std::set<CChan*>& sChans);
 
index 0809304fa45015c574ba568c21bc9bd4379200fd..cd768af03d1cc468a3a57e4baaab096a1f824e03 100644 (file)
@@ -453,6 +453,46 @@ void CClient::UserCommand(CString& sLine) {
             PutStatus(t_p("Disabled {1} channel", "Disabled {1} channels",
                           uDisabled)(uDisabled));
         }
+    } else if (sCommand.Equals("MOVECHAN")) {
+        if (!m_pNetwork) {
+            PutStatus(t_s(
+                "You must be connected with a network to use this command"));
+            return;
+        }
+
+        const auto sChan = sLine.Token(1);
+        const auto sTarget = sLine.Token(2);
+        if (sChan.empty() || sTarget.empty()) {
+            PutStatus(t_s("Usage: MoveChan <#chan> <index>"));
+            return;
+        }
+
+        unsigned int uIndex = sTarget.ToUInt();
+
+        CString sError;
+        if (m_pNetwork->MoveChan(sChan, uIndex - 1, sError))
+            PutStatus(t_f("Moved channel {1} to index {2}")(sChan, uIndex));
+        else
+            PutStatus(sError);
+    } else if (sCommand.Equals("SWAPCHANS")) {
+        if (!m_pNetwork) {
+            PutStatus(t_s(
+                "You must be connected with a network to use this command"));
+            return;
+        }
+
+        const auto sChan1 = sLine.Token(1);
+        const auto sChan2 = sLine.Token(2);
+        if (sChan1.empty() || sChan2.empty()) {
+            PutStatus(t_s("Usage: SwapChans <#chan1> <#chan2>"));
+            return;
+        }
+
+        CString sError;
+        if (m_pNetwork->SwapChans(sChan1, sChan2, sError))
+            PutStatus(t_f("Swapped channels {1} and {2}")(sChan1, sChan2));
+        else
+            PutStatus(sError);
     } else if (sCommand.Equals("LISTCHANS")) {
         if (!m_pNetwork) {
             PutStatus(t_s(
@@ -1786,6 +1826,11 @@ void CClient::HelpUser(const CString& sFilter) {
                    t_s("Enable channels", "helpcmd|EnableChan|desc"));
     AddCommandHelp("DisableChan", t_s("<#chans>", "helpcmd|DisableChan|args"),
                    t_s("Disable channels", "helpcmd|DisableChan|desc"));
+    AddCommandHelp("MoveChan", t_s("<#chan> <index>", "helpcmd|MoveChan|args"),
+                   t_s("Move channel in sort order", "helpcmd|MoveChan|desc"));
+    AddCommandHelp(
+        "SwapChans", t_s("<#chan1> <#chan2>", "helpcmd|SwapChans|args"),
+        t_s("Swap channels in sort order", "helpcmd|SwapChans|desc"));
     AddCommandHelp("Attach", t_s("<#chans>", "helpcmd|Attach|args"),
                    t_s("Attach to channels", "helpcmd|Attach|desc"));
     AddCommandHelp("Detach", t_s("<#chans>", "helpcmd|Detach|args"),
index 2855f526055879b88d7e8acf1952f840dd6987c0..cbe0d538abcd54054cddc465104fe6b93bfe3d47 100644 (file)
@@ -942,6 +942,49 @@ bool CIRCNetwork::DelChan(const CString& sName) {
     return false;
 }
 
+bool CIRCNetwork::MoveChan(const CString& sChan, unsigned int uIndex,
+                           CString& sError) {
+    if (uIndex >= m_vChans.size()) {
+        sError = t_s("Invalid index");
+        return false;
+    }
+
+    auto it = m_vChans.begin();
+    for (; it != m_vChans.end(); ++it)
+        if ((*it)->GetName().Equals(sChan)) break;
+    if (it == m_vChans.end()) {
+        sError = t_f("You are not on {1}")(sChan);
+        return false;
+    }
+
+    const auto pChan = *it;
+    m_vChans.erase(it);
+    m_vChans.insert(m_vChans.begin() + uIndex, pChan);
+    return true;
+}
+
+bool CIRCNetwork::SwapChans(const CString& sChan1, const CString& sChan2,
+                            CString& sError) {
+    auto it1 = m_vChans.begin();
+    for (; it1 != m_vChans.end(); ++it1)
+        if ((*it1)->GetName().Equals(sChan1)) break;
+    if (it1 == m_vChans.end()) {
+        sError = t_f("You are not on {1}")(sChan1);
+        return false;
+    }
+
+    auto it2 = m_vChans.begin();
+    for (; it2 != m_vChans.end(); ++it2)
+        if ((*it2)->GetName().Equals(sChan2)) break;
+    if (it2 == m_vChans.end()) {
+        sError = t_f("You are not on {1}")(sChan2);
+        return false;
+    }
+
+    std::swap(*it1, *it2);
+    return true;
+}
+
 void CIRCNetwork::JoinChans() {
     // Avoid divsion by zero, it's bad!
     if (m_vChans.empty()) return;
index f50a32c7bc2c0f71ab5c9a282dfb312a76bfb4d1..c5531d059c24720ae0692c1ab358bd65d0b470c7 100644 (file)
@@ -307,5 +307,41 @@ TEST_F(ZNCTest, StatusEchoMessage) {
     client3.ReadUntil(":*status!znc@znc.in PRIVMSG nick :Unknown command");
 }
 
+TEST_F(ZNCTest, MoveChannels) {
+    auto znc = Run();
+    auto ircd = ConnectIRCd();
+
+    auto client = LoginClient();
+    client.Write("JOIN #foo,#bar");
+    client.Close();
+
+    ircd.Write(":server 001 nick :Hello");
+    ircd.ReadUntil("JOIN #foo,#bar");
+    ircd.Write(":nick JOIN :#foo");
+    ircd.Write(":server 353 nick #foo :nick");
+    ircd.Write(":server 366 nick #foo :End of /NAMES list");
+    ircd.Write(":nick JOIN :#bar");
+    ircd.Write(":server 353 nick #bar :nick");
+    ircd.Write(":server 366 nick #bar :End of /NAMES list");
+
+    client = LoginClient();
+    client.ReadUntil(":nick JOIN :#foo");
+    client.ReadUntil(":nick JOIN :#bar");
+    client.Write("znc movechan #foo 2");
+    client.ReadUntil("Moved channel #foo to index 2");
+    client.Close();
+
+    client = LoginClient();
+    client.ReadUntil(":nick JOIN :#bar");
+    client.ReadUntil(":nick JOIN :#foo");
+    client.Write("znc swapchans #foo #bar");
+    client.ReadUntil("Swapped channels #foo and #bar");
+    client.Close();
+
+    client = LoginClient();
+    client.ReadUntil(":nick JOIN :#foo");
+    client.ReadUntil(":nick JOIN :#bar");
+}
+
 }  // namespace
 }  // namespace znc_inttest