aboutsummaryrefslogtreecommitdiff
path: root/src/modules/m_geoclass.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2019-05-15 15:11:31 +0100
committerGravatar Sadie Powell2019-05-15 15:26:55 +0100
commit1d5b18de82a90317291a10acb3b9132324c0e98b (patch)
treebe49087463332fcb617dd88567afce5cea6eb8c6 /src/modules/m_geoclass.cpp
parentMerge branch 'insp3' into master. (diff)
parentDocument the --disable-auto-extras configure option. (diff)
Merge branch 'insp3' into master.
Diffstat (limited to 'src/modules/m_geoclass.cpp')
-rw-r--r--src/modules/m_geoclass.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/modules/m_geoclass.cpp b/src/modules/m_geoclass.cpp
new file mode 100644
index 000000000..a03e1b7cd
--- /dev/null
+++ b/src/modules/m_geoclass.cpp
@@ -0,0 +1,109 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2019 Peter Powell <petpow@saberuk.com>
+ *
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "inspircd.h"
+#include "modules/geolocation.h"
+#include "modules/stats.h"
+
+enum
+{
+ // InspIRCd-specific.
+ RPL_STATSCOUNTRY = 801
+};
+
+class ModuleGeoClass
+ : public Module
+ , public Stats::EventListener
+{
+ private:
+ Geolocation::API geoapi;
+
+ public:
+ ModuleGeoClass()
+ : Stats::EventListener(this)
+ , geoapi(this)
+ {
+ }
+
+ Version GetVersion() override
+ {
+ return Version("Provides a way to assign users to connect classes by country", VF_VENDOR);
+ }
+
+ ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) override
+ {
+ const std::string country = myclass->config->getString("country");
+ if (country.empty())
+ return MOD_RES_PASSTHRU;
+
+ // If we can't find the location of this user then we can't assign
+ // them to a location-specific connect class.
+ Geolocation::Location* location = geoapi ? geoapi->GetLocation(user) : NULL;
+ const std::string code = location ? location->GetCode() : "XX";
+
+ irc::spacesepstream codes(country);
+ for (std::string token; codes.GetToken(token); )
+ {
+ // If the user matches this country code then they can use this
+ // connect class.
+ if (stdalgo::string::equalsci(token, code))
+ return MOD_RES_PASSTHRU;
+ }
+
+ // A list of country codes were specified but the user didn't match
+ // any of them.
+ return MOD_RES_DENY;
+ }
+
+ ModResult OnStats(Stats::Context& stats) override
+ {
+ if (stats.GetSymbol() != 'G')
+ return MOD_RES_PASSTHRU;
+
+ // Counter for the number of users in each country.
+ typedef std::map<Geolocation::Location*, size_t> CountryCounts;
+ CountryCounts counts;
+
+ // Counter for the number of users in an unknown country.
+ size_t unknown = 0;
+
+ const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
+ for (UserManager::LocalList::const_iterator iter = list.begin(); iter != list.end(); ++iter)
+ {
+ Geolocation::Location* location = geoapi ? geoapi->GetLocation(*iter) : NULL;
+ if (location)
+ counts[location]++;
+ else
+ unknown++;
+ }
+
+ for (CountryCounts::const_iterator iter = counts.begin(); iter != counts.end(); ++iter)
+ {
+ Geolocation::Location* location = iter->first;
+ stats.AddRow(RPL_STATSCOUNTRY, iter->second, location->GetCode(), location->GetName());
+ }
+
+ if (unknown)
+ stats.AddRow(RPL_STATSCOUNTRY, unknown, "*", "Unknown Country");
+
+ return MOD_RES_DENY;
+ }
+};
+
+MODULE_INIT(ModuleGeoClass)