mirror of
https://github.com/anope/anope.git
synced 2026-06-21 21:36:37 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 331c33c350 | |||
| 10eef1af23 | |||
| 90ff716ed3 | |||
| f67c70e485 | |||
| fd5e10c54c | |||
| 029565c894 | |||
| 9b8862826c | |||
| e2dc77641a | |||
| 7eb710a009 | |||
| b33b5a6630 | |||
| f4d5b1f01d | |||
| b61daf81b0 | |||
| da3f667188 | |||
| 040cd99027 | |||
| 6c7977f239 | |||
| 9b8570a2ee | |||
| 64f386e29e | |||
| 9434be29bc | |||
| 9aff71fb2f | |||
| ba26d9a15c | |||
| 22dc33de9f | |||
| 11d6f58a1a | |||
| f32d6453f5 | |||
| 9834040948 |
@@ -24,7 +24,7 @@ jobs:
|
||||
distro: official
|
||||
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Setup Conan
|
||||
uses: turtlebrowser/get-conan@v1.2
|
||||
|
||||
@@ -29,43 +29,37 @@ Load_Cache () {
|
||||
}
|
||||
|
||||
Run_Build_System () {
|
||||
WITH_INST=""
|
||||
WITH_RUN=""
|
||||
WITH_PERM=""
|
||||
EXTRA_INCLUDE=""
|
||||
EXTRA_LIBS=""
|
||||
BUILD_DIR="${SOURCE_DIR}/build"
|
||||
CMAKE_COMMAND="${CMAKE:-cmake} -B ${BUILD_DIR} -S ${SOURCE_DIR}"
|
||||
|
||||
if [ "$INSTDIR" != "" ] ; then
|
||||
WITH_INST="-DINSTDIR=$INSTDIR"
|
||||
CMAKE_COMMAND="${CMAKE_COMMAND} -D INSTDIR=$INSTDIR"
|
||||
fi
|
||||
|
||||
if [ "$RUNGROUP" != "" ] ; then
|
||||
WITH_RUN="-DRUNGROUP=$RUNGROUP"
|
||||
CMAKE_COMMAND="${CMAKE_COMMAND} -D RUNGROUP=$RUNGROUP"
|
||||
fi
|
||||
|
||||
if [ "$UMASK" != "" ] ; then
|
||||
WITH_PERM="-DDEFUMASK=$UMASK"
|
||||
CMAKE_COMMAND="${CMAKE_COMMAND} -D DEFUMASK=$UMASK"
|
||||
fi
|
||||
|
||||
if [ "$DEBUG" = "yes" ] ; then
|
||||
BUILD_TYPE="-DCMAKE_BUILD_TYPE=Debug"
|
||||
CMAKE_COMMAND="${CMAKE_COMMAND} -D CMAKE_BUILD_TYPE=Debug"
|
||||
else
|
||||
BUILD_TYPE="-DCMAKE_BUILD_TYPE=Release"
|
||||
CMAKE_COMMAND="${CMAKE_COMMAND} -D CMAKE_BUILD_TYPE=Release"
|
||||
fi
|
||||
|
||||
if [ "$EXTRA_INCLUDE_DIRS" != "" ] ; then
|
||||
EXTRA_INCLUDE="-DEXTRA_INCLUDE=$EXTRA_INCLUDE_DIRS"
|
||||
CMAKE_COMMAND="${CMAKE_COMMAND} -D EXTRA_INCLUDE=$EXTRA_INCLUDE_DIRS"
|
||||
fi
|
||||
|
||||
if [ "$EXTRA_LIB_DIRS" != "" ] ; then
|
||||
EXTRA_LIBS="-DEXTRA_LIBS=$EXTRA_LIB_DIRS"
|
||||
CMAKE_COMMAND="${CMAKE_COMMAND} -D EXTRA_LIBS=$EXTRA_LIB_DIRS"
|
||||
fi
|
||||
|
||||
BUILD_PATHS="-B ${SOURCE_DIR}/build ${SOURCE_DIR}"
|
||||
|
||||
CMAKE="cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $BUILD_PATHS"
|
||||
echo $CMAKE
|
||||
$CMAKE
|
||||
echo $CMAKE_COMMAND
|
||||
$CMAKE_COMMAND
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "You should fix these issues and then run ./Config -quick to rerun CMake."
|
||||
@@ -73,11 +67,7 @@ Run_Build_System () {
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ "$PWD" = "${SOURCE_DIR}/build" ]; then
|
||||
echo "Now run make to build Anope."
|
||||
else
|
||||
echo "Now cd build, then run make to build Anope."
|
||||
fi
|
||||
echo "Now run 'make -C ${BUILD_DIR#"$PWD/"} install' to build and install Anope."
|
||||
}
|
||||
|
||||
###########################################################################
|
||||
@@ -98,7 +88,12 @@ CAN_QUICK="no"
|
||||
###########################################################################
|
||||
|
||||
while [ $# -ge 1 ] ; do
|
||||
if [ $1 = "--help" ] ; then
|
||||
OPTION=$1
|
||||
while [ "${OPTION#-}" != "$OPTION" ]; do
|
||||
OPTION="${OPTION#-}"
|
||||
done
|
||||
|
||||
if [ "$OPTION" = "--help" ] ; then
|
||||
echo "Config utility for Anope"
|
||||
echo "------------------------"
|
||||
echo "Syntax: ./Config [options]"
|
||||
@@ -106,15 +101,15 @@ while [ $# -ge 1 ] ; do
|
||||
echo "-nointro Skip intro (disclaimer, etc)"
|
||||
echo "-quick Skip questions, go straight to cmake"
|
||||
exit 0
|
||||
elif [ $1 = "-devel" ] ; then
|
||||
elif [ "$OPTION" = "devel" ] ; then
|
||||
DEBUG="yes"
|
||||
DEVEL="yes"
|
||||
INSTDIR="$SOURCE_DIR/run"
|
||||
elif [ $1 = "-nocache" ] ; then
|
||||
elif [ "$OPTION" = "nocache" ] ; then
|
||||
IGNORE_CACHE="1"
|
||||
elif [ $1 = "-nointro" ] ; then
|
||||
elif [ "$OPTION" = "nointro" ] ; then
|
||||
NO_INTRO="1"
|
||||
elif [ $1 = "-quick" -o $1 = "-q" ] ; then
|
||||
elif [ "$OPTION" = "quick" -o "$OPTION" = "q" ] ; then
|
||||
Load_Cache
|
||||
if [ "$CAN_QUICK" = "yes" ] ; then
|
||||
Run_Build_System
|
||||
|
||||
+1
-21
@@ -1228,7 +1228,7 @@ module
|
||||
* An optional prefix to prepended to the name of each created table.
|
||||
* Do not use the same prefix for other programs.
|
||||
*/
|
||||
#prefix = "anope_db_"
|
||||
#prefix = "anope21_"
|
||||
|
||||
/*
|
||||
* Whether or not to import data from another database module in to SQL on
|
||||
@@ -1248,26 +1248,6 @@ module
|
||||
import = no
|
||||
}
|
||||
|
||||
/*
|
||||
* db_redis.
|
||||
*
|
||||
* This module allows using Redis (https://redis.io/) as a database backend.
|
||||
* This module requires that redis is loaded and configured properly.
|
||||
*
|
||||
* Redis 2.8 supports keyspace notifications which allows Redis to push notifications
|
||||
* to Anope about outside modifications to the database. This module supports this and
|
||||
* will internally reflect any changes made to the database immediately once notified.
|
||||
* See docs/REDIS for more information regarding this.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_redis"
|
||||
|
||||
/*
|
||||
* Redis database to use. This must be configured with redis.
|
||||
*/
|
||||
engine = "redis/main"
|
||||
}
|
||||
|
||||
/*
|
||||
* [RECOMMENDED] Encryption modules.
|
||||
|
||||
@@ -22,7 +22,7 @@ module
|
||||
* An optional prefix to prepended to the name of each created table.
|
||||
* Do not use the same prefix for other programs.
|
||||
*/
|
||||
prefix = "anope_"
|
||||
#prefix = "chanstats21_"
|
||||
|
||||
smileyshappy = ":) :-) ;) ;-) :D :-D :P :-P"
|
||||
smileyssad = ":( :-( ;( ;-("
|
||||
|
||||
@@ -374,30 +374,6 @@ module { name = "help" }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* redis
|
||||
*
|
||||
* This module allows other modules to use Redis.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "redis"
|
||||
|
||||
/* A redis database */
|
||||
redis
|
||||
{
|
||||
/* The name of this service */
|
||||
name = "redis/main"
|
||||
|
||||
/*
|
||||
* The redis database to use. New connections default to 0.
|
||||
*/
|
||||
db = 0
|
||||
|
||||
ip = "127.0.0.1"
|
||||
port = 6379
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* [EXTRA] regex_pcre2
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# Anope Change Log
|
||||
|
||||
## Anope 2.1.24 (unreleased)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* If a database contains duplicate corrupt entries from a prior write failure the oldest ones will now be purged from the database. This is a destructive action so make sure you take a manual backup of your database before upgrading.
|
||||
|
||||
* Removed support for storing the Anope database in Redis. The Redis code was extremely bitrotted, had not been tested in years, and to our knowledge has almost no (if any) users. It is recommended that db_redis users migrate to db_json or db_sql.
|
||||
|
||||
* SQL tables now use versioned prefixes by default. For the SQL database backends the default is `anope21_` and for ChanStats the default is `chanstats21_`. If you do not have a prefix explicitly set in your config you will need to add one it. Alternatively, you may also want to consider exporting to db_json and re-importing to update your SQL schema for the recent database layout changes.
|
||||
|
||||
### Changes
|
||||
|
||||
* Added some helper methods to `CommandSource` to allow quickly translting messages.
|
||||
|
||||
* Changed the Config script to allow multiple dashes in front of options, i.e. `-quick` and `--quick` are now equivalent.
|
||||
|
||||
* Converted some language strings to use format strings instead of concatenation.
|
||||
|
||||
* Fixed a rare crash in the ns_cert module.
|
||||
|
||||
* Fixed building Anope as a unity build.
|
||||
|
||||
* Fixed the ns_cert module erasing certificate entries if using an old database.
|
||||
|
||||
* Fixed users having the wrong real name in log messages on InspIRCd if it has been previously changed with `CHGNAME` or `SETNAME`.
|
||||
|
||||
## Anope 2.1.23 (2026-04-01)
|
||||
|
||||
### Changes
|
||||
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
Anope has Redis database support (https://redis.io/).
|
||||
This document explains the data structure used by Anope, and explains how
|
||||
keyspace notification works.
|
||||
|
||||
This is not a tutorial on how to use Redis, see https://redis.io/documentation
|
||||
for that.
|
||||
|
||||
Table of Contents
|
||||
-----------------
|
||||
1) Data structure
|
||||
2) Keyspace notifications
|
||||
3) Examples of modifying, deleting, and creating objects
|
||||
|
||||
1) Data structure
|
||||
|
||||
There are 4 key namespaces in Anope, they are:
|
||||
|
||||
id - The keys in id are used to atomically create object ids for new
|
||||
objects. For example, if I were to create a new BotInfo I would first:
|
||||
|
||||
redis 127.0.0.1:6379> INCR id:BotInfo
|
||||
|
||||
To get the object ID of the new object.
|
||||
|
||||
ids - The keys in ids contain a set of all object ids of the given type.
|
||||
For example:
|
||||
|
||||
redis 127.0.0.1:6379> SMEMBERS ids:BotInfo
|
||||
|
||||
Returns "1", "2", "3", "4", "5", "6", "7", "8" because I have 8 bots that
|
||||
have IDs 1, 2, 3, 4, 5, 6, 7, and 8, respectively.
|
||||
|
||||
hash - The keys in hash are the actual objects, stored as hashes. For
|
||||
example, if I had just looked up all BotInfo ids and wanted to iterate
|
||||
over all of them, I would start by:
|
||||
|
||||
redis 127.0.0.1:6379> HGETALL hash:BotInfo:1
|
||||
|
||||
Which gets all keys and values from the hash of type BotInfo with id 1.
|
||||
This may return:
|
||||
|
||||
"nick" -> "BotServ"
|
||||
"user" -> "services"
|
||||
"host" -> "services.anope.org"
|
||||
"created" -> "1368704765"
|
||||
|
||||
value - The keys in value only exist to aid looking up object IDs. They
|
||||
are sets of object IDs and are used to map key+value pairs to objects.
|
||||
For example:
|
||||
|
||||
redis 127.0.0.1:6379> SMEMBERS value:NickAlias:nick:Adam
|
||||
|
||||
Returns a set of object ids of NickAlias objects that have the key
|
||||
'nick' set to the value 'Adam' in its hash. Clearly this can only
|
||||
ever contain at most one object, since it is not possible to have
|
||||
more than one registered nick with the same name, but other keys
|
||||
will contain more than one, such as:
|
||||
|
||||
redis 127.0.0.1:6379> SMEMBERS value:NickCore:email:adam@anope.org
|
||||
|
||||
Which would return all accounts with the email "adam@anope.org".
|
||||
|
||||
redis 127.0.0.1:6379> SMEMBERS value:ChanAccess:mask:Adam
|
||||
|
||||
Which would return all access entries set on the account "Adam".
|
||||
|
||||
Behavior similar to SQL's AND, can be achieved using the
|
||||
SINTER command, which does set intersection on one or more sets.
|
||||
|
||||
2) Keyspace notifications
|
||||
|
||||
Redis 2.7 (unstable) and 2.8 (stable) and newer support keyspace notifications
|
||||
(https://redis.io/topics/notifications). This allows Redis to notify Anope of
|
||||
any external changes to objects in the database. Once notified, Anope will
|
||||
immediately update the object. Otherwise, Anope keeps all objects in memory
|
||||
and will not regularly read from the database once started.
|
||||
|
||||
You can use this to modify objects in Redis and have them immediately reflected
|
||||
back into Anope. Additionally you can use this feature to run multiple Anope
|
||||
instances simultaneously from the same database (see also, Redis database
|
||||
replication).
|
||||
|
||||
To use keyspace notifications you MUST execute
|
||||
|
||||
redis 127.0.0.1:6379> CONFIG SET notify-keyspace-events KA
|
||||
OK
|
||||
|
||||
or set notify-keyspace-events in redis.conf properly. Anope always executes
|
||||
CONFIG SET when it first connects.
|
||||
|
||||
If you do not enable keyspace events properly Anope will be UNABLE to see any
|
||||
object modifications you do.
|
||||
|
||||
The key space ids and value are managed entirely by Anope, you do
|
||||
not (and should not) modify them. Once you modify the object (hash), Anope will
|
||||
update them for you to correctly reflect any changes made to the object.
|
||||
|
||||
Finally, always use atomic operations. If you are inserting a new object with
|
||||
multiple commands, or inserting multiple objects at once, specifically if the
|
||||
objects depend on each other, you MUST use a transaction.
|
||||
|
||||
3) Examples of modifying, deleting, and creating objects
|
||||
|
||||
These examples will ONLY work if you meet the criteria in section 2.
|
||||
|
||||
If I want to change the email account 'Adam' to 'Adam@anope.org', I would execute the following:
|
||||
|
||||
redis 127.0.0.1:6379> SMEMBERS value:NickCore:display:Adam
|
||||
|
||||
Which returns a value of "1", which is the object id I want to modify.
|
||||
Now to change the email:
|
||||
|
||||
redis 127.0.0.1:6379> HSET hash:NickCore:1 email Adam@anope.org
|
||||
|
||||
You can now see this in NickServ's INFO command:
|
||||
-NickServ- Email address: Adam@anope.org
|
||||
|
||||
If I want to drop the account "Adam", I would execute the following:
|
||||
|
||||
redis 127.0.0.1:6379> SMEMBERS value:NickCore:display:Adam
|
||||
|
||||
Which returns a value of "1". I would then check:
|
||||
|
||||
redis 127.0.0.1:6379> SMEMBERS value:NickAlias:nc:Adam
|
||||
|
||||
To see what nicknames depend on this account to exist, as I will
|
||||
have to remove those too. This returns the values "2", and "3".
|
||||
|
||||
Finally, I can drop the nick using a transaction via:
|
||||
|
||||
redis 127.0.0.1:6379> MULTI
|
||||
OK
|
||||
redis 127.0.0.1:6379> DEL hash:NickAlias:2
|
||||
QUEUED
|
||||
redis 127.0.0.1:6379> DEL hash:NickAlias:3
|
||||
QUEUED
|
||||
redis 127.0.0.1:6379> DEL hash:NickCore:1
|
||||
QUEUED
|
||||
redis 127.0.0.1:6379> EXEC
|
||||
|
||||
Or alternatively simply:
|
||||
|
||||
redis 127.0.0.1:6379> DEL hash:NickAlias:2 hash:NickAlias:3 hash:NickCore:1
|
||||
|
||||
If I wanted to create a BotServ bot, I would execute the following:
|
||||
|
||||
redis 127.0.0.1:6379> INCR id:BotInfo
|
||||
|
||||
Which returns a new object ID for me, in this example it will be "8".
|
||||
Now I can create the object:
|
||||
|
||||
HMSET hash:BotInfo:8 nick redis user redis host services.anope.org realname "Anope IRC Services"
|
||||
|
||||
Note if you are using HSET instead of HMSET you will need to use a transaction, as shown in the above example.
|
||||
If you are watching your services logs you will immediately see:
|
||||
|
||||
USERS: redis!redis@services.anope.org (Anope IRC Services) connected to the network (services.anope.org)
|
||||
|
||||
And the bot redis will be in BotServ's bot list.
|
||||
Notice how ids:BotInfo and the value keys are updated automatically.
|
||||
@@ -90,6 +90,11 @@ public:
|
||||
void Reply(int count, const char *singular, const char *plural, ...) ATTR_FORMAT(4, 5);
|
||||
void Reply(const Anope::string &message);
|
||||
|
||||
const char *Translate(const char *message);
|
||||
const char *Translate(const Anope::string &message);
|
||||
const char *Translate(int count, const char *single, const char *plural);
|
||||
const char *Translate(int count, const Anope::string &single, const Anope::string &plural);
|
||||
|
||||
bool HasCommand(const Anope::string &cmd);
|
||||
bool HasPriv(const Anope::string &cmd);
|
||||
bool IsServicesOper();
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
// Anope IRC Services <https://www.anope.org/>
|
||||
//
|
||||
// Copyright (C) 2003-2026 Anope Contributors
|
||||
//
|
||||
// Anope is free software. You can use, modify, and/or distribute it under the
|
||||
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
|
||||
// for the complete terms of this license and docs/AUTHORS.txt for a list of
|
||||
// contributors.
|
||||
//
|
||||
// Based on the original code of Epona by Lara
|
||||
// Based on the original code of Services by Andy Church
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Redis
|
||||
{
|
||||
struct Reply final
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
NOT_PARSED,
|
||||
NOT_OK,
|
||||
OK,
|
||||
INT,
|
||||
BULK,
|
||||
MULTI_BULK
|
||||
}
|
||||
type;
|
||||
|
||||
Reply() { Clear(); }
|
||||
~Reply() { Clear(); }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
type = NOT_PARSED;
|
||||
i = 0;
|
||||
bulk.clear();
|
||||
multi_bulk_size = 0;
|
||||
for (const auto *reply : multi_bulk)
|
||||
delete reply;
|
||||
multi_bulk.clear();
|
||||
}
|
||||
|
||||
int64_t i;
|
||||
Anope::string bulk;
|
||||
int multi_bulk_size;
|
||||
std::deque<Reply *> multi_bulk;
|
||||
};
|
||||
|
||||
class Interface
|
||||
{
|
||||
public:
|
||||
Module *owner;
|
||||
|
||||
Interface(Module *m) : owner(m) { }
|
||||
virtual ~Interface() = default;
|
||||
|
||||
virtual void OnResult(const Reply &r) = 0;
|
||||
virtual void OnError(const Anope::string &error) { Log(owner) << error; }
|
||||
};
|
||||
|
||||
class Provider
|
||||
: public Service
|
||||
{
|
||||
public:
|
||||
Provider(Module *c, const Anope::string &n) : Service(c, "Redis::Provider", n) { }
|
||||
|
||||
virtual bool IsSocketDead() = 0;
|
||||
|
||||
virtual void SendCommand(Interface *i, const std::vector<Anope::string> &cmds) = 0;
|
||||
virtual void SendCommand(Interface *i, const Anope::string &str) = 0;
|
||||
|
||||
virtual bool BlockAndProcess() = 0;
|
||||
|
||||
virtual void Subscribe(Interface *i, const Anope::string &pattern) = 0;
|
||||
virtual void Unsubscribe(const Anope::string &pattern) = 0;
|
||||
|
||||
virtual void StartTransaction() = 0;
|
||||
virtual void CommitTransaction() = 0;
|
||||
};
|
||||
}
|
||||
+20
-3
@@ -74,6 +74,8 @@ private:
|
||||
size_t last_commit = 0;
|
||||
/* The last time this object was committed to the database */
|
||||
time_t last_commit_time = 0;
|
||||
/** Whether this object should be committed to the database. */
|
||||
bool should_commit = true;
|
||||
|
||||
protected:
|
||||
Serializable(const Anope::string &serialize_type);
|
||||
@@ -81,6 +83,20 @@ protected:
|
||||
|
||||
Serializable &operator=(const Serializable &);
|
||||
|
||||
template<typename Container,
|
||||
typename Key = typename Container::key_type,
|
||||
typename Value = typename Container::mapped_type>
|
||||
bool InsertUnique(Container &container, const Key &key)
|
||||
{
|
||||
auto res = container.emplace(key, static_cast<Value>(this));
|
||||
if (res.second)
|
||||
return true;
|
||||
|
||||
res.first->second->should_commit = false;
|
||||
res.first->second = static_cast<Value>(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
using Id = uint64_t;
|
||||
virtual ~Serializable();
|
||||
@@ -88,13 +104,13 @@ public:
|
||||
/* Unique ID (per type, not globally) for this object */
|
||||
Id object_id = 0;
|
||||
|
||||
/* Only used by redis, to ignore updates */
|
||||
unsigned short redis_ignore = 0;
|
||||
|
||||
/** Marks the object as potentially being updated "soon".
|
||||
*/
|
||||
void QueueUpdate();
|
||||
|
||||
/** Determines whether the object should be committed to the database. */
|
||||
bool ShouldCommit() const { return this->should_commit; }
|
||||
|
||||
bool IsCached(Serialize::Data &);
|
||||
void UpdateCache(Serialize::Data &);
|
||||
|
||||
@@ -105,6 +121,7 @@ public:
|
||||
* @return The serializable object type
|
||||
*/
|
||||
Serialize::Type *GetSerializableType() const { return this->s_type; }
|
||||
const auto &GetSerializableName() const { return this->s_name; }
|
||||
|
||||
static const std::list<Serializable *> &GetItems();
|
||||
};
|
||||
|
||||
+124
-119
@@ -16,8 +16,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Anope\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-03-19 00:00+0000\n"
|
||||
"PO-Revision-Date: 2026-03-19 00:00+0000\n"
|
||||
"POT-Creation-Date: 2026-04-26 18:25+0100\n"
|
||||
"PO-Revision-Date: 2026-04-26 18:25+0100\n"
|
||||
"Last-Translator: Sadie Powell <sadie@witchery.services>\n"
|
||||
"Language-Team: English\n"
|
||||
"Language: en_US\n"
|
||||
@@ -273,7 +273,7 @@ msgstr ""
|
||||
msgid "%s is already on the ignore list."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_suspend.cpp ../modules/chanserv/cs_suspend.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp ../modules/nickserv/ns_suspend.cpp
|
||||
#, c-format
|
||||
msgid "%s is already suspended."
|
||||
msgstr ""
|
||||
@@ -580,10 +580,10 @@ msgstr ""
|
||||
msgid "botname {ON|OFF}"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_log.cpp ../modules/chanserv/cs_info.cpp
|
||||
#: ../modules/chanserv/cs_sync.cpp ../modules/chanserv/cs_getkey.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp ../modules/chanserv/cs_fantasy_top.cpp
|
||||
#: ../modules/botserv/bs_assign.cpp
|
||||
#: ../modules/botserv/bs_assign.cpp ../modules/chanserv/cs_fantasy_top.cpp
|
||||
#: ../modules/chanserv/cs_getkey.cpp ../modules/chanserv/cs_info.cpp
|
||||
#: ../modules/chanserv/cs_log.cpp ../modules/chanserv/cs_suspend.cpp
|
||||
#: ../modules/chanserv/cs_sync.cpp
|
||||
msgid "channel"
|
||||
msgstr ""
|
||||
|
||||
@@ -603,7 +603,7 @@ msgstr ""
|
||||
msgid "channel modes"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/botserv/bs_assign.cpp
|
||||
#: ../modules/botserv/bs_assign.cpp ../modules/chanserv/cs_set.cpp
|
||||
msgid "channel nick"
|
||||
msgstr ""
|
||||
|
||||
@@ -655,9 +655,9 @@ msgstr ""
|
||||
msgid "channel APPEND topic"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_access.cpp ../modules/chanserv/cs_akick.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_entrymsg.cpp
|
||||
#: ../modules/chanserv/cs_xop.cpp ../modules/botserv/bs_badwords.cpp
|
||||
#: ../modules/botserv/bs_badwords.cpp ../modules/chanserv/cs_access.cpp
|
||||
#: ../modules/chanserv/cs_akick.cpp ../modules/chanserv/cs_entrymsg.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_xop.cpp
|
||||
msgid "channel CLEAR"
|
||||
msgstr ""
|
||||
|
||||
@@ -697,7 +697,7 @@ msgstr ""
|
||||
msgid "channel LIST [mask | entry-num | list]"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_xop.cpp ../modules/botserv/bs_badwords.cpp
|
||||
#: ../modules/botserv/bs_badwords.cpp ../modules/chanserv/cs_xop.cpp
|
||||
msgid "channel LIST [mask | list]"
|
||||
msgstr ""
|
||||
|
||||
@@ -750,12 +750,12 @@ msgstr ""
|
||||
msgid "channel [code]"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/chanserv/cs_register.cpp
|
||||
#: ../modules/chanserv/cs_register.cpp ../modules/chanserv/cs_set.cpp
|
||||
msgid "channel [description]"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_unban.cpp ../modules/chanserv/cs_invite.cpp
|
||||
#: ../modules/chanserv/cs_set.cpp
|
||||
#: ../modules/chanserv/cs_invite.cpp ../modules/chanserv/cs_set.cpp
|
||||
#: ../modules/chanserv/cs_unban.cpp
|
||||
msgid "channel [nick]"
|
||||
msgstr ""
|
||||
|
||||
@@ -787,7 +787,7 @@ msgstr ""
|
||||
msgid "channel [UNLOCK|LOCK]"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/fantasy.cpp ../modules/greet.cpp ../modules/botserv/bs_assign.cpp
|
||||
#: ../modules/botserv/bs_assign.cpp ../modules/fantasy.cpp ../modules/greet.cpp
|
||||
msgid "channel {ON|OFF}"
|
||||
msgstr ""
|
||||
|
||||
@@ -815,13 +815,13 @@ msgstr ""
|
||||
msgid "channel {ON | LEVEL | OFF}"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanstats.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/botserv/bs_kick.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/chanserv/cs_topic.cpp
|
||||
#: ../modules/botserv/bs_kick.cpp
|
||||
#: ../modules/chanstats.cpp
|
||||
msgid "channel {ON | OFF}"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_register.cpp ../modules/nickserv/ns_email.cpp
|
||||
#: ../modules/nickserv/ns_email.cpp ../modules/nickserv/ns_register.cpp
|
||||
msgid "code"
|
||||
msgstr ""
|
||||
|
||||
@@ -829,11 +829,11 @@ msgstr ""
|
||||
msgid "email"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/memoserv/ms_staff.cpp ../modules/memoserv/ms_sendall.cpp
|
||||
#: ../modules/memoserv/ms_sendall.cpp ../modules/memoserv/ms_staff.cpp
|
||||
msgid "memo-text"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_module.cpp ../modules/operserv/os_modinfo.cpp
|
||||
#: ../modules/operserv/os_modinfo.cpp ../modules/operserv/os_module.cpp
|
||||
msgid "modname"
|
||||
msgstr ""
|
||||
|
||||
@@ -849,8 +849,8 @@ msgstr ""
|
||||
msgid "new-password"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_del.cpp ../modules/hostserv/hs_request.cpp
|
||||
#: ../modules/chanserv/cs_fantasy_stats.cpp ../modules/chanserv/cs_seen.cpp
|
||||
#: ../modules/hostserv/hs_del.cpp ../modules/hostserv/hs_request.cpp
|
||||
#: ../modules/memoserv/ms_check.cpp
|
||||
msgid "nick"
|
||||
msgstr ""
|
||||
@@ -936,10 +936,10 @@ msgstr ""
|
||||
msgid "nickname {ON | delay | OFF}"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set.cpp ../modules/nickserv/ns_set_keepmodes.cpp
|
||||
#: ../modules/nickserv/ns_set_op.cpp ../modules/nickserv/ns_cert.cpp
|
||||
#: ../modules/nickserv/ns_set_message.cpp ../modules/nickserv/ns_list.cpp
|
||||
#: ../modules/chanstats.cpp
|
||||
#: ../modules/chanstats.cpp ../modules/nickserv/ns_cert.cpp
|
||||
#: ../modules/nickserv/ns_list.cpp ../modules/nickserv/ns_set.cpp
|
||||
#: ../modules/nickserv/ns_set_keepmodes.cpp
|
||||
#: ../modules/nickserv/ns_set_message.cpp ../modules/nickserv/ns_set_op.cpp
|
||||
msgid "nickname {ON | OFF}"
|
||||
msgstr ""
|
||||
|
||||
@@ -959,7 +959,7 @@ msgstr ""
|
||||
msgid "option nickname parameters"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set.cpp ../modules/memoserv/ms_set.cpp
|
||||
#: ../modules/memoserv/ms_set.cpp ../modules/nickserv/ns_set.cpp
|
||||
msgid "option parameters"
|
||||
msgstr ""
|
||||
|
||||
@@ -1273,8 +1273,8 @@ msgstr ""
|
||||
msgid "%s cannot be the successor on channel %s as they are the founder."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hostserv.cpp ../modules/operserv/operserv.cpp
|
||||
#: ../modules/global/global.cpp
|
||||
#: ../modules/global/global.cpp ../modules/hostserv/hostserv.cpp
|
||||
#: ../modules/operserv/operserv.cpp
|
||||
#, c-format
|
||||
msgid "%s commands:"
|
||||
msgstr ""
|
||||
@@ -1653,7 +1653,7 @@ msgstr ""
|
||||
msgid ". %s is still online."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_register.cpp ../modules/nickserv/ns_email.cpp
|
||||
#: ../modules/nickserv/ns_email.cpp ../modules/nickserv/ns_register.cpp
|
||||
msgid "@nickname"
|
||||
msgstr ""
|
||||
|
||||
@@ -1814,7 +1814,7 @@ msgstr ""
|
||||
msgid "Account"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_identify.cpp ../modules/nickserv/ns_cert.cpp
|
||||
#: ../modules/nickserv/ns_cert.cpp ../modules/nickserv/ns_identify.cpp
|
||||
#, c-format
|
||||
msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
|
||||
msgstr ""
|
||||
@@ -2435,7 +2435,8 @@ msgid "Available timezones in the %s region:"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_enforce.cpp
|
||||
msgid "BANS enforced by "
|
||||
#, c-format
|
||||
msgid "BANS enforced by %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/botserv/bs_kick.cpp
|
||||
@@ -3181,23 +3182,23 @@ msgstr ""
|
||||
msgid "Copy all settings from one channel to another"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/hostserv/hs_list.cpp
|
||||
#: ../modules/hostserv/hs_request.cpp ../modules/nickserv/ns_cert.cpp
|
||||
#: ../modules/chanserv/cs_akick.cpp ../modules/chanserv/cs_mode.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_entrymsg.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp ../modules/operserv/os_news.cpp
|
||||
#: ../modules/botserv/bs_info.cpp
|
||||
#: ../modules/botserv/bs_info.cpp ../modules/chanserv/cs_akick.cpp
|
||||
#: ../modules/chanserv/cs_entrymsg.cpp ../modules/chanserv/cs_flags.cpp
|
||||
#: ../modules/chanserv/cs_mode.cpp ../modules/hostserv/hs_list.cpp
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/hostserv/hs_request.cpp
|
||||
#: ../modules/nickserv/ns_cert.cpp ../modules/operserv/os_akill.cpp
|
||||
#: ../modules/operserv/os_news.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/hostserv/hs_list.cpp
|
||||
#: ../modules/nickserv/ns_cert.cpp ../modules/chanserv/cs_access.cpp
|
||||
#: ../modules/chanserv/cs_akick.cpp ../modules/chanserv/cs_mode.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_entrymsg.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp ../modules/operserv/os_news.cpp
|
||||
#: ../modules/operserv/os_forbid.cpp ../modules/operserv/os_ignore.cpp
|
||||
#: ../modules/chanserv/cs_access.cpp ../modules/chanserv/cs_akick.cpp
|
||||
#: ../modules/chanserv/cs_entrymsg.cpp ../modules/chanserv/cs_flags.cpp
|
||||
#: ../modules/chanserv/cs_mode.cpp ../modules/hostserv/hs_list.cpp
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/nickserv/ns_cert.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_forbid.cpp
|
||||
#: ../modules/operserv/os_ignore.cpp ../modules/operserv/os_news.cpp
|
||||
#: ../modules/operserv/os_session.cpp ../modules/operserv/os_sxline.cpp
|
||||
msgid "Creator"
|
||||
msgstr ""
|
||||
|
||||
@@ -3508,10 +3509,10 @@ msgstr ""
|
||||
msgid "Depooled %s."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_cert.cpp ../modules/nickserv/ns_alist.cpp
|
||||
#: ../modules/chanserv/cs_access.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_info.cpp
|
||||
#: ../modules/chanserv/cs_xop.cpp
|
||||
#: ../modules/chanserv/cs_access.cpp ../modules/chanserv/cs_flags.cpp
|
||||
#: ../modules/chanserv/cs_info.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/chanserv/cs_xop.cpp ../modules/nickserv/ns_alist.cpp
|
||||
#: ../modules/nickserv/ns_cert.cpp
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
@@ -3857,7 +3858,7 @@ msgstr ""
|
||||
msgid "End of list - %d channels shown."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_list.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/chanserv/cs_list.cpp ../modules/nickserv/ns_list.cpp
|
||||
#, c-format
|
||||
msgid "End of list - %d/%d matches shown."
|
||||
msgstr ""
|
||||
@@ -3940,11 +3941,11 @@ msgstr ""
|
||||
msgid "Exception for %s has been updated to %d."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/nickserv/nickserv.cpp
|
||||
#: ../modules/nickserv/ns_group.cpp ../modules/chanserv/chanserv.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp ../modules/operserv/os_forbid.cpp
|
||||
#: ../modules/operserv/os_ignore.cpp
|
||||
#: ../modules/chanserv/chanserv.cpp ../modules/hostserv/hs_offer.cpp
|
||||
#: ../modules/nickserv/nickserv.cpp ../modules/nickserv/ns_group.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_forbid.cpp
|
||||
#: ../modules/operserv/os_ignore.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp
|
||||
msgid "Expires"
|
||||
msgstr ""
|
||||
|
||||
@@ -4075,7 +4076,7 @@ msgstr ""
|
||||
msgid "Forcefully part a user from a channel."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_alist.cpp ../modules/chanserv/cs_info.cpp
|
||||
#: ../modules/chanserv/cs_info.cpp ../modules/nickserv/ns_alist.cpp
|
||||
msgid "Founder"
|
||||
msgstr ""
|
||||
|
||||
@@ -4269,16 +4270,16 @@ msgstr ""
|
||||
msgid "Italics kicker"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set_keepmodes.cpp ../modules/chanserv/cs_set.cpp
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/nickserv/ns_set_keepmodes.cpp
|
||||
msgid "Keep modes"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set_keepmodes.cpp ../modules/chanserv/cs_set.cpp
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/nickserv/ns_set_keepmodes.cpp
|
||||
#, c-format
|
||||
msgid "Keep modes for %s is now off."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set_keepmodes.cpp ../modules/chanserv/cs_set.cpp
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/nickserv/ns_set_keepmodes.cpp
|
||||
#, c-format
|
||||
msgid "Keep modes for %s is now on."
|
||||
msgstr ""
|
||||
@@ -4296,7 +4297,7 @@ msgstr ""
|
||||
msgid "Kick a user from a channel"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_kick.cpp ../modules/chanserv/cs_ban.cpp
|
||||
#: ../modules/chanserv/cs_ban.cpp ../modules/chanserv/cs_kick.cpp
|
||||
#, c-format
|
||||
msgid "Kicked %d/%d users matching %s from %s."
|
||||
msgstr ""
|
||||
@@ -4317,7 +4318,8 @@ msgid "Kill a user"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_enforce.cpp
|
||||
msgid "LIMIT enforced by "
|
||||
#, c-format
|
||||
msgid "LIMIT enforced by %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_enforce.cpp
|
||||
@@ -4341,7 +4343,7 @@ msgstr ""
|
||||
msgid "LIST [mask | list]"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_cert.cpp ../modules/nickserv/ns_ajoin.cpp
|
||||
#: ../modules/nickserv/ns_ajoin.cpp ../modules/nickserv/ns_cert.cpp
|
||||
msgid "LIST [nickname]"
|
||||
msgstr ""
|
||||
|
||||
@@ -4368,7 +4370,7 @@ msgstr ""
|
||||
msgid "Last quit message"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_info.cpp ../modules/chanserv/cs_access.cpp
|
||||
#: ../modules/chanserv/cs_access.cpp ../modules/nickserv/ns_info.cpp
|
||||
msgid "Last seen"
|
||||
msgstr ""
|
||||
|
||||
@@ -4439,7 +4441,7 @@ msgstr ""
|
||||
msgid "List loaded modules"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_list.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/chanserv/cs_list.cpp ../modules/nickserv/ns_list.cpp
|
||||
#, c-format
|
||||
msgid "List of entries matching %s:"
|
||||
msgstr ""
|
||||
@@ -4841,13 +4843,13 @@ msgstr ""
|
||||
msgid "Manipulate the topic of the specified channel"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/botserv/bs_botlist.cpp ../modules/botserv/bs_info.cpp
|
||||
#: ../modules/chanserv/cs_access.cpp ../modules/chanserv/cs_akick.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_xop.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_list.cpp
|
||||
#: ../modules/operserv/os_session.cpp ../modules/operserv/os_sxline.cpp
|
||||
#: ../modules/memoserv/ms_ignore.cpp ../modules/operserv/os_akill.cpp
|
||||
#: ../modules/operserv/os_forbid.cpp ../modules/operserv/os_ignore.cpp
|
||||
#: ../modules/memoserv/ms_ignore.cpp ../modules/botserv/bs_info.cpp
|
||||
#: ../modules/botserv/bs_botlist.cpp
|
||||
#: ../modules/operserv/os_list.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp
|
||||
msgid "Mask"
|
||||
msgstr ""
|
||||
|
||||
@@ -5063,7 +5065,7 @@ msgid "NOTICE: In order to register a channel, you must have first registered yo
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_access.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/operserv/os_list.cpp ../modules/operserv/os_config.cpp
|
||||
#: ../modules/operserv/os_config.cpp ../modules/operserv/os_list.cpp
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
@@ -5084,9 +5086,9 @@ msgstr ""
|
||||
msgid "Never op"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_list.cpp ../modules/hostserv/hs_request.cpp
|
||||
#: ../modules/nickserv/ns_group.cpp ../modules/nickserv/ns_list.cpp
|
||||
#: ../modules/botserv/bs_botlist.cpp
|
||||
#: ../modules/botserv/bs_botlist.cpp ../modules/hostserv/hs_list.cpp
|
||||
#: ../modules/hostserv/hs_request.cpp ../modules/nickserv/ns_group.cpp
|
||||
#: ../modules/nickserv/ns_list.cpp
|
||||
msgid "Nick"
|
||||
msgstr ""
|
||||
|
||||
@@ -5110,7 +5112,7 @@ msgstr ""
|
||||
msgid "Nick %s is an illegal nickname and cannot be used."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_svs.cpp ../modules/botserv/bs_bot.cpp
|
||||
#: ../modules/botserv/bs_bot.cpp ../modules/operserv/os_svs.cpp
|
||||
#, c-format
|
||||
msgid "Nick %s is currently in use."
|
||||
msgstr ""
|
||||
@@ -5237,7 +5239,7 @@ msgstr ""
|
||||
msgid "No bot"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set.cpp ../modules/chanserv/cs_set.cpp
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/nickserv/ns_set.cpp
|
||||
msgid "No expiry"
|
||||
msgstr ""
|
||||
|
||||
@@ -5352,7 +5354,7 @@ msgstr ""
|
||||
msgid "No such info \"%s\" on %s."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_kick.cpp ../modules/chanserv/cs_ban.cpp
|
||||
#: ../modules/chanserv/cs_ban.cpp ../modules/chanserv/cs_kick.cpp
|
||||
#, c-format
|
||||
msgid "No users on %s match %s."
|
||||
msgstr ""
|
||||
@@ -5372,7 +5374,7 @@ msgstr ""
|
||||
msgid "Non-status modes cleared on %s."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_dns.cpp ../modules/botserv/bs_info.cpp
|
||||
#: ../modules/botserv/bs_info.cpp ../modules/operserv/os_dns.cpp
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
@@ -5394,15 +5396,15 @@ msgstr ""
|
||||
msgid "Now"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/hostserv/hs_list.cpp
|
||||
#: ../modules/hostserv/hs_request.cpp ../modules/nickserv/ns_ajoin.cpp
|
||||
#: ../modules/nickserv/ns_alist.cpp ../modules/chanserv/cs_access.cpp
|
||||
#: ../modules/chanserv/cs_log.cpp ../modules/chanserv/cs_akick.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_entrymsg.cpp
|
||||
#: ../modules/chanserv/cs_xop.cpp ../modules/operserv/os_akill.cpp
|
||||
#: ../modules/botserv/bs_badwords.cpp ../modules/chanserv/cs_access.cpp
|
||||
#: ../modules/chanserv/cs_akick.cpp ../modules/chanserv/cs_entrymsg.cpp
|
||||
#: ../modules/chanserv/cs_flags.cpp ../modules/chanserv/cs_log.cpp
|
||||
#: ../modules/chanserv/cs_xop.cpp ../modules/global/gl_queue.cpp
|
||||
#: ../modules/hostserv/hs_list.cpp ../modules/hostserv/hs_offer.cpp
|
||||
#: ../modules/hostserv/hs_request.cpp ../modules/memoserv/ms_list.cpp
|
||||
#: ../modules/nickserv/ns_ajoin.cpp ../modules/nickserv/ns_alist.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_news.cpp
|
||||
#: ../modules/operserv/os_session.cpp ../modules/operserv/os_sxline.cpp
|
||||
#: ../modules/operserv/os_news.cpp ../modules/global/gl_queue.cpp
|
||||
#: ../modules/memoserv/ms_list.cpp ../modules/botserv/bs_badwords.cpp
|
||||
msgid "Number"
|
||||
msgstr ""
|
||||
|
||||
@@ -5640,8 +5642,8 @@ msgstr ""
|
||||
msgid "Prevents users being kicked by services"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_list.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/botserv/bs_info.cpp
|
||||
#: ../modules/botserv/bs_info.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/nickserv/ns_list.cpp
|
||||
msgid "Private"
|
||||
msgstr ""
|
||||
|
||||
@@ -5718,11 +5720,13 @@ msgid "Puts an AKILL for every nick on the specified channel. It uses the entire
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_enforce.cpp
|
||||
msgid "REGONLY enforced by "
|
||||
#, c-format
|
||||
msgid "REGONLY enforced by %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_enforce.cpp
|
||||
msgid "RESTRICTED enforced by "
|
||||
#, c-format
|
||||
msgid "RESTRICTED enforced by %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_noop.cpp
|
||||
@@ -5747,7 +5751,7 @@ msgstr ""
|
||||
msgid "Read a memo or memos"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/botserv/bs_info.cpp ../modules/botserv/bs_botlist.cpp
|
||||
#: ../modules/botserv/bs_botlist.cpp ../modules/botserv/bs_info.cpp
|
||||
msgid "Real name"
|
||||
msgstr ""
|
||||
|
||||
@@ -5755,10 +5759,10 @@ msgstr ""
|
||||
msgid "Realname"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/chanserv/cs_akick.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp ../modules/operserv/os_forbid.cpp
|
||||
#: ../modules/operserv/os_ignore.cpp
|
||||
#: ../modules/chanserv/cs_akick.cpp ../modules/hostserv/hs_offer.cpp
|
||||
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_forbid.cpp
|
||||
#: ../modules/operserv/os_ignore.cpp ../modules/operserv/os_session.cpp
|
||||
#: ../modules/operserv/os_sxline.cpp
|
||||
msgid "Reason"
|
||||
msgstr ""
|
||||
|
||||
@@ -5788,9 +5792,9 @@ msgstr ""
|
||||
msgid "Regex matches are also supported using the %s engine. Enclose your mask in // if this is desired."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_list.cpp ../modules/chanserv/cs_list.cpp
|
||||
#: ../modules/operserv/os_list.cpp ../modules/operserv/os_forbid.cpp
|
||||
#: ../modules/operserv/os_ignore.cpp
|
||||
#: ../modules/chanserv/cs_list.cpp ../modules/nickserv/ns_list.cpp
|
||||
#: ../modules/operserv/os_forbid.cpp ../modules/operserv/os_ignore.cpp
|
||||
#: ../modules/operserv/os_list.cpp
|
||||
#, c-format
|
||||
msgid "Regex matches are also supported using the %s engine. Enclose your pattern in // if this is desired."
|
||||
msgstr ""
|
||||
@@ -5803,7 +5807,7 @@ msgstr ""
|
||||
msgid "Register a nickname"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_group.cpp ../modules/chanserv/cs_info.cpp
|
||||
#: ../modules/chanserv/cs_info.cpp ../modules/nickserv/ns_group.cpp
|
||||
msgid "Registered"
|
||||
msgstr ""
|
||||
|
||||
@@ -6049,7 +6053,8 @@ msgid "SSL only enforced on %s."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_enforce.cpp
|
||||
msgid "SSLONLY enforced by "
|
||||
#, c-format
|
||||
msgid "SSLONLY enforced by %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_shutdown.cpp
|
||||
@@ -6203,7 +6208,7 @@ msgstr ""
|
||||
msgid "Server %s already exists."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_noop.cpp ../modules/operserv/os_dns.cpp
|
||||
#: ../modules/operserv/os_dns.cpp ../modules/operserv/os_noop.cpp
|
||||
#, c-format
|
||||
msgid "Server %s does not exist."
|
||||
msgstr ""
|
||||
@@ -6327,7 +6332,7 @@ msgstr ""
|
||||
msgid "Services ignore list:"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_mode.cpp ../modules/operserv/os_kick.cpp
|
||||
#: ../modules/operserv/os_kick.cpp ../modules/operserv/os_mode.cpp
|
||||
msgid "Services is unable to change modes. Are your servers' U:lines configured correctly?"
|
||||
msgstr ""
|
||||
|
||||
@@ -6746,7 +6751,7 @@ msgstr ""
|
||||
msgid "Stricter control of chanop status"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_alist.cpp ../modules/chanserv/cs_info.cpp
|
||||
#: ../modules/chanserv/cs_info.cpp ../modules/nickserv/ns_alist.cpp
|
||||
msgid "Successor"
|
||||
msgstr ""
|
||||
|
||||
@@ -6768,20 +6773,20 @@ msgstr ""
|
||||
msgid "Suspend a given nick"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_suspend.cpp ../modules/chanserv/cs_suspend.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp ../modules/nickserv/ns_suspend.cpp
|
||||
msgid "Suspend reason"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_list.cpp ../modules/nickserv/ns_suspend.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp ../modules/nickserv/ns_list.cpp
|
||||
#: ../modules/nickserv/ns_suspend.cpp
|
||||
msgid "Suspended"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_suspend.cpp ../modules/chanserv/cs_suspend.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp ../modules/nickserv/ns_suspend.cpp
|
||||
msgid "Suspended by"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_suspend.cpp ../modules/chanserv/cs_suspend.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp ../modules/nickserv/ns_suspend.cpp
|
||||
msgid "Suspended on"
|
||||
msgstr ""
|
||||
|
||||
@@ -6789,7 +6794,7 @@ msgstr ""
|
||||
msgid "Suspends a registered nickname, which prevents it from being used while keeping all the data for that nick. If an expiry is given the nick will be unsuspended after that period of time, else the default expiry from the configuration is used."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_suspend.cpp ../modules/chanserv/cs_suspend.cpp
|
||||
#: ../modules/chanserv/cs_suspend.cpp ../modules/nickserv/ns_suspend.cpp
|
||||
msgid "Suspension expires"
|
||||
msgstr ""
|
||||
|
||||
@@ -7585,7 +7590,7 @@ msgstr ""
|
||||
msgid "Turns chanstats statistics ON or OFF."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/operserv/os_forbid.cpp ../modules/botserv/bs_badwords.cpp
|
||||
#: ../modules/botserv/bs_badwords.cpp ../modules/operserv/os_forbid.cpp
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
@@ -7599,13 +7604,13 @@ msgstr ""
|
||||
msgid "Type %scommand for help on any of the above commands."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/chanserv/cs_set.cpp ../modules/botserv/bs_set.cpp
|
||||
#: ../modules/botserv/bs_set.cpp ../modules/chanserv/cs_set.cpp
|
||||
#, c-format
|
||||
msgid "Type %soption for more information on a particular option."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set.cpp ../modules/nickserv/ns_confirm.cpp
|
||||
#: ../modules/memoserv/ms_set.cpp
|
||||
#: ../modules/memoserv/ms_set.cpp ../modules/nickserv/ns_confirm.cpp
|
||||
#: ../modules/nickserv/ns_set.cpp
|
||||
#, c-format
|
||||
msgid "Type %soption for more information on a specific option."
|
||||
msgstr ""
|
||||
@@ -7828,7 +7833,7 @@ msgstr ""
|
||||
msgid "Users list:"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_offer.cpp ../modules/hostserv/hs_list.cpp
|
||||
#: ../modules/hostserv/hs_list.cpp ../modules/hostserv/hs_offer.cpp
|
||||
#: ../modules/hostserv/hs_request.cpp ../modules/nickserv/ns_info.cpp
|
||||
msgid "VHost"
|
||||
msgstr ""
|
||||
@@ -8457,7 +8462,7 @@ msgstr ""
|
||||
msgid "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/sql_authentication.cpp ../modules/ldap_authentication.cpp
|
||||
#: ../modules/ldap_authentication.cpp ../modules/sql_authentication.cpp
|
||||
#, c-format
|
||||
msgid "Your account %s has been successfully created."
|
||||
msgstr ""
|
||||
@@ -8588,7 +8593,7 @@ msgstr ""
|
||||
msgid "Your vhost %s has been requested. If the requested vhost is for a valid DNS name you can add a TXT record for %s with the value %s and automatically approve your vhost using %s."
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/hostserv/hs_on.cpp ../modules/hostserv/hostserv.cpp
|
||||
#: ../modules/hostserv/hostserv.cpp ../modules/hostserv/hs_on.cpp
|
||||
#, c-format
|
||||
msgid "Your vhost of %s is now activated."
|
||||
msgstr ""
|
||||
@@ -8702,7 +8707,7 @@ msgstr ""
|
||||
msgid "[language]"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/greet.cpp ../modules/global/gl_global.cpp
|
||||
#: ../modules/global/gl_global.cpp ../modules/greet.cpp
|
||||
msgid "[message]"
|
||||
msgstr ""
|
||||
|
||||
@@ -8718,8 +8723,8 @@ msgstr ""
|
||||
msgid "[nickname [REVALIDATE]]"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_info.cpp ../modules/nickserv/ns_group.cpp
|
||||
#: ../modules/nickserv/ns_register.cpp ../modules/nickserv/ns_alist.cpp
|
||||
#: ../modules/nickserv/ns_alist.cpp ../modules/nickserv/ns_group.cpp
|
||||
#: ../modules/nickserv/ns_info.cpp ../modules/nickserv/ns_register.cpp
|
||||
msgid "[nickname]"
|
||||
msgstr ""
|
||||
|
||||
@@ -8785,7 +8790,7 @@ msgstr ""
|
||||
msgid "not assigned yet"
|
||||
msgstr ""
|
||||
|
||||
#: ../modules/nickserv/ns_set_misc.cpp ../modules/chanserv/cs_set_misc.cpp
|
||||
#: ../modules/chanserv/cs_set_misc.cpp ../modules/nickserv/ns_set_misc.cpp
|
||||
msgid "value"
|
||||
msgstr ""
|
||||
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ find ../ \
|
||||
-o -name '*.h' \
|
||||
-o -name '*.conf' \
|
||||
\) \
|
||||
-exec \
|
||||
-print0 | sort -z | xargs -0 -I {} \
|
||||
xgettext \
|
||||
--language=C++ \
|
||||
--sort-output \
|
||||
@@ -32,7 +32,7 @@ find ../ \
|
||||
--keyword \
|
||||
--keyword=_ \
|
||||
--keyword=N_:1,2 \
|
||||
{} +
|
||||
{}
|
||||
|
||||
for f in *.po
|
||||
do
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
info[_("Real name")] = bi->realname;
|
||||
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
|
||||
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
|
||||
info[_("Used on")] = Anope::Format(Language::Translate(source.nc, bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
info[_("Used on")] = Anope::Format(source.Translate(bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
info.SendTo(source);
|
||||
@@ -83,8 +83,8 @@ public:
|
||||
source.Reply(CHAN_INFO_HEADER, ci->name.c_str());
|
||||
info[_("Bot nick")] = ci->bi ? ci->bi->nick : _("not assigned yet");
|
||||
|
||||
Anope::string enabled = Language::Translate(source.nc, _("Enabled"));
|
||||
Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
|
||||
Anope::string enabled = source.Translate(_("Enabled"));
|
||||
Anope::string disabled = source.Translate(_("Disabled"));
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
info.SendTo(source);
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
|
||||
Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str());
|
||||
return Anope::Format(source.Translate(_("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1151,8 +1151,8 @@ public:
|
||||
if (!ci)
|
||||
return;
|
||||
|
||||
Anope::string enabled = Language::Translate(source.nc, _("Enabled"));
|
||||
Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
|
||||
Anope::string enabled = source.Translate(_("Enabled"));
|
||||
Anope::string disabled = source.Translate(_("Disabled"));
|
||||
auto *kd = kickerdata.Get(ci);
|
||||
|
||||
if (kd && kd->badwords)
|
||||
|
||||
@@ -26,10 +26,10 @@ static inline void reset_levels(ChannelInfo *ci)
|
||||
static Anope::string LevelToString(CommandSource &source, int16_t level)
|
||||
{
|
||||
if (level == ACCESS_INVALID)
|
||||
return Language::Translate(source.GetAccount(), _("(disabled)"));
|
||||
return source.Translate(_("(disabled)"));
|
||||
|
||||
if (level == ACCESS_FOUNDER)
|
||||
return Language::Translate(source.GetAccount(), _("(founder only)"));
|
||||
return source.Translate(_("(founder only)"));
|
||||
|
||||
return Anope::ToString(level);
|
||||
}
|
||||
@@ -893,7 +893,7 @@ public:
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Name"] = p.name;
|
||||
entry["Default"] = LevelToString(source, defaultLevels[p.name]);
|
||||
entry["Description"] = Language::Translate(source.nc, p.desc.c_str());
|
||||
entry["Description"] = source.Translate(p.desc.c_str());
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
for (auto *user : users)
|
||||
{
|
||||
Anope::string mask = ci->GetIdealBan(user);
|
||||
Anope::string reason = Language::Translate(user, _("RESTRICTED enforced by ")) + source.GetNick();
|
||||
Anope::string reason = Anope::Format(Language::Translate(user, _("RESTRICTED enforced by %s")), source.GetNick().c_str());
|
||||
ci->c->SetMode(NULL, "BAN", mask);
|
||||
ci->c->Kick(NULL, user, reason);
|
||||
}
|
||||
@@ -92,7 +92,7 @@ private:
|
||||
for (auto *user : users)
|
||||
{
|
||||
Anope::string mask = ci->GetIdealBan(user);
|
||||
Anope::string reason = Language::Translate(user, _("REGONLY enforced by ")) + source.GetNick();
|
||||
Anope::string reason = Anope::Format(Language::Translate(user, _("REGONLY enforced by %s")), source.GetNick().c_str());
|
||||
if (!ci->c->HasMode("REGISTEREDONLY"))
|
||||
ci->c->SetMode(NULL, "BAN", mask);
|
||||
ci->c->Kick(NULL, user, reason);
|
||||
@@ -121,7 +121,7 @@ private:
|
||||
for (auto *user : users)
|
||||
{
|
||||
Anope::string mask = ci->GetIdealBan(user);
|
||||
Anope::string reason = Language::Translate(user, _("SSLONLY enforced by ")) + source.GetNick();
|
||||
Anope::string reason = Anope::Format(Language::Translate(user, _("SSLONLY enforced by %s")), source.GetNick().c_str());
|
||||
if (!ci->c->HasMode("SSL"))
|
||||
ci->c->SetMode(NULL, "BAN", mask);
|
||||
ci->c->Kick(NULL, user, reason);
|
||||
@@ -149,7 +149,7 @@ private:
|
||||
|
||||
for (auto *user : users)
|
||||
{
|
||||
Anope::string reason = Language::Translate(user, _("BANS enforced by ")) + source.GetNick();
|
||||
Anope::string reason = Anope::Format(Language::Translate(user, _("BANS enforced by %s")), source.GetNick().c_str());
|
||||
ci->c->Kick(NULL, user, reason);
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ private:
|
||||
|
||||
for (auto *user : users)
|
||||
{
|
||||
Anope::string reason = Language::Translate(user, _("LIMIT enforced by ")) + source.GetNick();
|
||||
Anope::string reason = Anope::Format(Language::Translate(user, _("LIMIT enforced by %s")), source.GetNick().c_str());
|
||||
ci->c->Kick(NULL, user, reason);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const auto &block = conf.GetModule("chanstats");
|
||||
prefix = block.Get<const Anope::string>("prefix", "anope_");
|
||||
prefix = block.Get<const Anope::string>("prefix", "chanstats21_");
|
||||
this->sql.SetServiceName(block.Get<const Anope::string>("engine"));
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const auto &block = conf.GetModule("chanstats");
|
||||
prefix = block.Get<const Anope::string>("prefix", "anope_");
|
||||
prefix = block.Get<const Anope::string>("prefix", "chanstats21_");
|
||||
this->sql.SetServiceName(block.Get<const Anope::string>("engine"));
|
||||
}
|
||||
|
||||
|
||||
@@ -599,7 +599,7 @@ public:
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(priv);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
source.Reply(" %c - %s", flag, Language::Translate(source.nc, p->desc.c_str()));
|
||||
source.Reply(" %c - %s", flag, source.Translate(p->desc.c_str()));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Name"] = (isnoexpire ? "!" : "") + ci->name;
|
||||
if (ci->HasExt("CS_SUSPENDED"))
|
||||
entry["Description"] = Language::Translate(source.GetAccount(), _("[Suspended]"));
|
||||
entry["Description"] = source.Translate(_("[Suspended]"));
|
||||
else
|
||||
entry["Description"] = ci->desc;
|
||||
list.AddEntry(entry);
|
||||
|
||||
@@ -945,9 +945,9 @@ public:
|
||||
if (!m.second.empty())
|
||||
{
|
||||
if (m.first)
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str());
|
||||
return Anope::Format(source.Translate(_("Gives you or the specified nick %s status on a channel")), m.second.c_str());
|
||||
else
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str());
|
||||
return Anope::Format(source.Translate(_("Removes %s status from you or the specified nick on a channel")), m.second.c_str());
|
||||
}
|
||||
else
|
||||
return "";
|
||||
|
||||
@@ -281,7 +281,7 @@ public:
|
||||
if (u2)
|
||||
onlinestatus = ".";
|
||||
else
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(" but %s mysteriously dematerialized.")), target.c_str());
|
||||
onlinestatus = Anope::Format(source.Translate(_(" but %s mysteriously dematerialized.")), target.c_str());
|
||||
|
||||
Anope::string timebuf = Anope::Duration(Anope::CurTime - info->last, source.nc);
|
||||
Anope::string timebuf2 = Anope::strftime(info->last, source.nc, true);
|
||||
@@ -295,9 +295,9 @@ public:
|
||||
{
|
||||
u2 = User::Find(info->nick2, true);
|
||||
if (u2)
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(". %s is still online.")), u2->nick.c_str());
|
||||
onlinestatus = Anope::Format(source.Translate(_(". %s is still online.")), u2->nick.c_str());
|
||||
else
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(", but %s mysteriously dematerialized.")), info->nick2.c_str());
|
||||
onlinestatus = Anope::Format(source.Translate(_(", but %s mysteriously dematerialized.")), info->nick2.c_str());
|
||||
|
||||
source.Reply(_("%s (%s) was last seen changing nick to %s %s ago%s"),
|
||||
target.c_str(), info->vhost.c_str(), info->nick2.c_str(), timebuf.c_str(), onlinestatus.c_str());
|
||||
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply("%s", Language::Translate(source.nc, it->second.description.c_str()));
|
||||
source.Reply("%s", source.Translate(it->second.description.c_str()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -237,8 +237,8 @@ public:
|
||||
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(Anope::Format(
|
||||
Language::Translate(source.nc, _("\037channel\037 [\037%s\037]")),
|
||||
Language::Translate(source.nc, value)
|
||||
source.Translate(_("\037channel\037 [\037%s\037]")),
|
||||
source.Translate(value)
|
||||
));
|
||||
|
||||
Command::SendSyntax(source);
|
||||
|
||||
@@ -543,7 +543,7 @@ public:
|
||||
|
||||
Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.nobreak().c_str());
|
||||
return Anope::Format(source.Translate(_("Modify the list of %s users")), source.command.nobreak().c_str());
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
|
||||
@@ -509,7 +509,7 @@ public:
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const auto &block = conf.GetModule(this);
|
||||
prefix = block.Get<const Anope::string>("prefix", "anope_");
|
||||
prefix = block.Get<const Anope::string>("prefix", "chanstats21_");
|
||||
SmileysHappy = block.Get<const Anope::string>("SmileysHappy");
|
||||
SmileysSad = block.Get<const Anope::string>("SmileysSad");
|
||||
SmileysOther = block.Get<const Anope::string>("SmileysOther");
|
||||
|
||||
@@ -412,9 +412,18 @@ public:
|
||||
// Step 2: store the new data.
|
||||
for (auto *item : Serializable::GetItems())
|
||||
{
|
||||
if (!item->ShouldCommit())
|
||||
{
|
||||
Log(LOG_DEBUG) << "Not committing dead " << item->GetSerializableName() << " object: " << item;
|
||||
continue; // Non-committable object.
|
||||
}
|
||||
|
||||
auto *s_type = item->GetSerializableType();
|
||||
if (!s_type)
|
||||
{
|
||||
Log(LOG_DEBUG) << "Not committing orphaned " << item->GetSerializableName() << " object: " << item;
|
||||
continue; // Provider has been unloaded.
|
||||
}
|
||||
|
||||
// This should always be found because we create it in the previous step.
|
||||
auto it = databases.find(s_type->GetOwner());
|
||||
|
||||
@@ -1,648 +0,0 @@
|
||||
// Anope IRC Services <https://www.anope.org/>
|
||||
//
|
||||
// Copyright (C) 2003-2026 Anope Contributors
|
||||
//
|
||||
// Anope is free software. You can use, modify, and/or distribute it under the
|
||||
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
|
||||
// for the complete terms of this license and docs/AUTHORS.txt for a list of
|
||||
// contributors.
|
||||
//
|
||||
// Based on the original code of Epona by Lara
|
||||
// Based on the original code of Services by Andy Church
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/redis.h"
|
||||
|
||||
using namespace Redis;
|
||||
|
||||
class DatabaseRedis;
|
||||
static DatabaseRedis *me;
|
||||
|
||||
class Data final
|
||||
: public Serialize::Data
|
||||
{
|
||||
public:
|
||||
Anope::unordered_map<Anope::string> data;
|
||||
|
||||
bool LoadInternal(const Anope::string &key, Anope::string &value) override
|
||||
{
|
||||
auto it = this->data.find(key);
|
||||
if (it == this->data.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StoreInternal(const Anope::string &key, const Anope::string &value) override
|
||||
{
|
||||
this->data[key] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t Hash() const override
|
||||
{
|
||||
size_t hash = 0;
|
||||
for (const auto &[_, value] : this->data)
|
||||
if (!value.empty())
|
||||
hash ^= Anope::hash_cs()(value);
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
class TypeLoader final
|
||||
: public Interface
|
||||
{
|
||||
Anope::string type;
|
||||
public:
|
||||
TypeLoader(Module *creator, const Anope::string &t) : Interface(creator), type(t) { }
|
||||
|
||||
void OnResult(const Reply &r) override;
|
||||
};
|
||||
|
||||
class ObjectLoader final
|
||||
: public Interface
|
||||
{
|
||||
Anope::string type;
|
||||
int64_t id;
|
||||
|
||||
public:
|
||||
ObjectLoader(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
|
||||
|
||||
void OnResult(const Reply &r) override;
|
||||
};
|
||||
|
||||
class IDInterface final
|
||||
: public Interface
|
||||
{
|
||||
Reference<Serializable> o;
|
||||
public:
|
||||
IDInterface(Module *creator, Serializable *obj) : Interface(creator), o(obj) { }
|
||||
|
||||
void OnResult(const Reply &r) override;
|
||||
};
|
||||
|
||||
class Deleter final
|
||||
: public Interface
|
||||
{
|
||||
Anope::string type;
|
||||
int64_t id;
|
||||
public:
|
||||
Deleter(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
|
||||
|
||||
void OnResult(const Reply &r) override;
|
||||
};
|
||||
|
||||
class Updater final
|
||||
: public Interface
|
||||
{
|
||||
Anope::string type;
|
||||
int64_t id;
|
||||
public:
|
||||
Updater(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
|
||||
|
||||
void OnResult(const Reply &r) override;
|
||||
};
|
||||
|
||||
class ModifiedObject final
|
||||
: public Interface
|
||||
{
|
||||
Anope::string type;
|
||||
int64_t id;
|
||||
public:
|
||||
ModifiedObject(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
|
||||
|
||||
void OnResult(const Reply &r) override;
|
||||
};
|
||||
|
||||
class SubscriptionListener final
|
||||
: public Interface
|
||||
{
|
||||
public:
|
||||
SubscriptionListener(Module *creator) : Interface(creator) { }
|
||||
|
||||
void OnResult(const Reply &r) override;
|
||||
};
|
||||
|
||||
class DatabaseRedis final
|
||||
: public Module
|
||||
, public Pipe
|
||||
{
|
||||
SubscriptionListener sl;
|
||||
std::set<Serializable *> updated_items;
|
||||
|
||||
public:
|
||||
ServiceReference<Provider> redis;
|
||||
|
||||
DatabaseRedis(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, DATABASE | VENDOR)
|
||||
, sl(this)
|
||||
, redis("Redis::Provider")
|
||||
{
|
||||
me = this;
|
||||
|
||||
}
|
||||
|
||||
/* Insert or update an object */
|
||||
void InsertObject(Serializable *obj)
|
||||
{
|
||||
Serialize::Type *t = obj->GetSerializableType();
|
||||
|
||||
/* If there is no id yet for this object, get one */
|
||||
if (!obj->object_id)
|
||||
redis->SendCommand(new IDInterface(this, obj), "INCR id:" + t->GetName());
|
||||
else
|
||||
{
|
||||
Data data;
|
||||
t->Serialize(obj, data);
|
||||
|
||||
if (obj->IsCached(data))
|
||||
return;
|
||||
|
||||
obj->UpdateCache(data);
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("HGETALL");
|
||||
args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->object_id));
|
||||
|
||||
/* Get object attrs to clear before updating */
|
||||
redis->SendCommand(new Updater(this, t->GetName(), obj->object_id), args);
|
||||
}
|
||||
}
|
||||
|
||||
void OnNotify() override
|
||||
{
|
||||
for (auto *obj : this->updated_items)
|
||||
{
|
||||
this->InsertObject(obj);
|
||||
}
|
||||
|
||||
this->updated_items.clear();
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const auto &block = conf.GetModule(this);
|
||||
this->redis.SetServiceName(block.Get<const Anope::string>("engine", "redis/main"));
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase() override
|
||||
{
|
||||
if (!redis)
|
||||
{
|
||||
Log(this) << "Unable to load database - unable to find redis provider";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
for (const auto &type_order : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
Serialize::Type *sb = Serialize::Type::Find(type_order);
|
||||
this->OnSerializeTypeCreate(sb);
|
||||
}
|
||||
|
||||
while (!redis->IsSocketDead() && redis->BlockAndProcess());
|
||||
|
||||
if (redis->IsSocketDead())
|
||||
{
|
||||
Log(this) << "I/O error while loading redis database - is it online?";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
redis->Subscribe(&this->sl, "__keyspace@*__:hash:*");
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
void OnSerializeTypeCreate(Serialize::Type *sb) override
|
||||
{
|
||||
if (!redis)
|
||||
return;
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SMEMBERS");
|
||||
args.push_back("ids:" + sb->GetName());
|
||||
|
||||
redis->SendCommand(new TypeLoader(this, sb->GetName()), args);
|
||||
}
|
||||
|
||||
void OnSerializableConstruct(Serializable *obj) override
|
||||
{
|
||||
this->updated_items.insert(obj);
|
||||
this->Notify();
|
||||
}
|
||||
|
||||
void OnSerializableDestruct(Serializable *obj) override
|
||||
{
|
||||
Serialize::Type *t = obj->GetSerializableType();
|
||||
|
||||
if (t == NULL)
|
||||
{
|
||||
/* This is probably the module providing the type unloading.
|
||||
*
|
||||
* The types get registered after the extensible container is
|
||||
* registered so that unserialization on module load can insert
|
||||
* into the extensible container. So, the type destructs prior to
|
||||
* the extensible container, which then triggers this
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("HGETALL");
|
||||
args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->object_id));
|
||||
|
||||
/* Get all of the attributes for this object */
|
||||
redis->SendCommand(new Deleter(this, t->GetName(), obj->object_id), args);
|
||||
|
||||
this->updated_items.erase(obj);
|
||||
t->objects.erase(obj->object_id);
|
||||
this->Notify();
|
||||
}
|
||||
|
||||
void OnSerializableUpdate(Serializable *obj) override
|
||||
{
|
||||
this->updated_items.insert(obj);
|
||||
this->Notify();
|
||||
}
|
||||
};
|
||||
|
||||
void TypeLoader::OnResult(const Reply &r)
|
||||
{
|
||||
if (r.type != Reply::MULTI_BULK || !me->redis)
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto *reply : r.multi_bulk)
|
||||
{
|
||||
if (reply->type != Reply::BULK)
|
||||
continue;
|
||||
|
||||
auto i = Anope::TryConvert<int64_t>(reply->bulk);
|
||||
if (!i)
|
||||
continue;
|
||||
|
||||
auto id = i.value();
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("HGETALL");
|
||||
args.push_back("hash:" + this->type + ":" + Anope::ToString(id));
|
||||
|
||||
me->redis->SendCommand(new ObjectLoader(me, this->type, id), args);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void ObjectLoader::OnResult(const Reply &r)
|
||||
{
|
||||
Serialize::Type *st = Serialize::Type::Find(this->type);
|
||||
|
||||
if (r.type != Reply::MULTI_BULK || r.multi_bulk.empty() || !me->redis || !st)
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
Data data;
|
||||
|
||||
for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
|
||||
{
|
||||
const Reply *key = r.multi_bulk[i],
|
||||
*value = r.multi_bulk[i + 1];
|
||||
|
||||
data.StoreInternal(key->bulk, value->bulk);
|
||||
}
|
||||
|
||||
Serializable *&obj = st->objects[this->id];
|
||||
obj = st->Unserialize(obj, data);
|
||||
if (obj)
|
||||
{
|
||||
obj->object_id = this->id;
|
||||
obj->UpdateCache(data);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void IDInterface::OnResult(const Reply &r)
|
||||
{
|
||||
if (!o || r.type != Reply::INT || !r.i)
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
Serializable *&obj = o->GetSerializableType()->objects[r.i];
|
||||
if (obj)
|
||||
/* This shouldn't be possible */
|
||||
obj->object_id = 0;
|
||||
|
||||
o->object_id = r.i;
|
||||
obj = o;
|
||||
|
||||
/* Now that we have the id, insert this object for real */
|
||||
anope_dynamic_static_cast<DatabaseRedis *>(this->owner)->InsertObject(o);
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void Deleter::OnResult(const Reply &r)
|
||||
{
|
||||
if (r.type != Reply::MULTI_BULK || !me->redis || r.multi_bulk.empty())
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Transaction start */
|
||||
me->redis->StartTransaction();
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("DEL");
|
||||
args.push_back("hash:" + this->type + ":" + Anope::ToString(this->id));
|
||||
|
||||
/* Delete hash object */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
|
||||
args.clear();
|
||||
args.emplace_back("SREM");
|
||||
args.push_back("ids:" + this->type);
|
||||
args.push_back(Anope::ToString(this->id));
|
||||
|
||||
/* Delete id from ids set */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
|
||||
for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
|
||||
{
|
||||
const Reply *key = r.multi_bulk[i],
|
||||
*value = r.multi_bulk[i + 1];
|
||||
|
||||
args.clear();
|
||||
args.emplace_back("SREM");
|
||||
args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
|
||||
args.push_back(Anope::ToString(this->id));
|
||||
|
||||
/* Delete value -> object id */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
}
|
||||
|
||||
/* Transaction end */
|
||||
me->redis->CommitTransaction();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void Updater::OnResult(const Reply &r)
|
||||
{
|
||||
Serialize::Type *st = Serialize::Type::Find(this->type);
|
||||
|
||||
if (!st)
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
Serializable *obj = st->objects[this->id];
|
||||
if (!obj)
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
Data data;
|
||||
st->Serialize(obj, data);
|
||||
|
||||
/* Transaction start */
|
||||
me->redis->StartTransaction();
|
||||
|
||||
for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
|
||||
{
|
||||
const Reply *key = r.multi_bulk[i],
|
||||
*value = r.multi_bulk[i + 1];
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SREM");
|
||||
args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
|
||||
args.push_back(Anope::ToString(this->id));
|
||||
|
||||
/* Delete value -> object id */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
}
|
||||
|
||||
/* Add object id to id set for this type */
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SADD");
|
||||
args.push_back("ids:" + this->type);
|
||||
args.push_back(Anope::ToString(obj->object_id));
|
||||
me->redis->SendCommand(NULL, args);
|
||||
|
||||
args.clear();
|
||||
args.emplace_back("HMSET");
|
||||
args.push_back("hash:" + this->type + ":" + Anope::ToString(obj->object_id));
|
||||
|
||||
for (const auto &[key, value] : data.data)
|
||||
{
|
||||
args.push_back(key);
|
||||
args.emplace_back(value);
|
||||
|
||||
std::vector<Anope::string> args2;
|
||||
|
||||
args2.emplace_back("SADD");
|
||||
args2.push_back("value:" + this->type + ":" + key + ":" + value);
|
||||
args2.push_back(Anope::ToString(obj->object_id));
|
||||
|
||||
/* Add to value -> object id set */
|
||||
me->redis->SendCommand(NULL, args2);
|
||||
}
|
||||
|
||||
++obj->redis_ignore;
|
||||
|
||||
/* Add object */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
|
||||
/* Transaction end */
|
||||
me->redis->CommitTransaction();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
void SubscriptionListener::OnResult(const Reply &r)
|
||||
{
|
||||
/*
|
||||
* [May 15 13:59:35.645839 2013] Debug: pmessage
|
||||
* [May 15 13:59:35.645866 2013] Debug: __keyspace@*__:anope:hash:*
|
||||
* [May 15 13:59:35.645880 2013] Debug: __keyspace@0__:anope:hash:type:id
|
||||
* [May 15 13:59:35.645893 2013] Debug: hset
|
||||
*/
|
||||
if (r.multi_bulk.size() != 4)
|
||||
return;
|
||||
|
||||
size_t sz = r.multi_bulk[2]->bulk.find(':');
|
||||
if (sz == Anope::string::npos)
|
||||
return;
|
||||
|
||||
const Anope::string &key = r.multi_bulk[2]->bulk.substr(sz + 1),
|
||||
&op = r.multi_bulk[3]->bulk;
|
||||
|
||||
sz = key.rfind(':');
|
||||
if (sz == Anope::string::npos)
|
||||
return;
|
||||
|
||||
const Anope::string &id = key.substr(sz + 1);
|
||||
|
||||
size_t sz2 = key.rfind(':', sz - 1);
|
||||
if (sz2 == Anope::string::npos)
|
||||
return;
|
||||
const Anope::string &type = key.substr(sz2 + 1, sz - sz2 - 1);
|
||||
|
||||
Serialize::Type *s_type = Serialize::Type::Find(type);
|
||||
|
||||
if (s_type == NULL)
|
||||
return;
|
||||
|
||||
auto oid = Anope::TryConvert<Serializable::Id>(id);
|
||||
if (!oid.has_value())
|
||||
return;
|
||||
|
||||
auto obj_id = oid.value();
|
||||
if (op == "hset" || op == "hdel")
|
||||
{
|
||||
Serializable *s = s_type->objects[obj_id];
|
||||
|
||||
if (s && s->redis_ignore)
|
||||
{
|
||||
--s->redis_ignore;
|
||||
Log(LOG_DEBUG) << "redis: notify: got modify for object id " << obj_id << " of type " << type << ", but I am ignoring it";
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(LOG_DEBUG) << "redis: notify: got modify for object id " << obj_id << " of type " << type;
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("HGETALL");
|
||||
args.push_back("hash:" + type + ":" + id);
|
||||
|
||||
me->redis->SendCommand(new ModifiedObject(me, type, obj_id), args);
|
||||
}
|
||||
}
|
||||
else if (op == "del")
|
||||
{
|
||||
Serializable *&s = s_type->objects[obj_id];
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
Log(LOG_DEBUG) << "redis: notify: deleting object id " << obj_id << " of type " << type;
|
||||
|
||||
Data data;
|
||||
s_type->Serialize(s, data);
|
||||
|
||||
/* Transaction start */
|
||||
me->redis->StartTransaction();
|
||||
|
||||
for (const auto &[k, value] : data.data)
|
||||
{
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SREM");
|
||||
args.push_back("value:" + type + ":" + k + ":" + value);
|
||||
args.push_back(id);
|
||||
|
||||
/* Delete value -> object id */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SREM");
|
||||
args.push_back("ids:" + type);
|
||||
args.push_back(Anope::ToString(s->object_id));
|
||||
|
||||
/* Delete object from id set */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
|
||||
/* Transaction end */
|
||||
me->redis->CommitTransaction();
|
||||
|
||||
delete s;
|
||||
s = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ModifiedObject::OnResult(const Reply &r)
|
||||
{
|
||||
Serialize::Type *st = Serialize::Type::Find(this->type);
|
||||
|
||||
if (!st)
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
Serializable *&obj = st->objects[this->id];
|
||||
|
||||
/* Transaction start */
|
||||
me->redis->StartTransaction();
|
||||
|
||||
/* Erase old object values */
|
||||
if (obj)
|
||||
{
|
||||
Data data;
|
||||
st->Serialize(obj, data);
|
||||
|
||||
for (auto &[key, value] : data.data)
|
||||
{
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SREM");
|
||||
args.push_back("value:" + st->GetName() + ":" + key + ":" + value);
|
||||
args.push_back(Anope::ToString(this->id));
|
||||
|
||||
/* Delete value -> object id */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
}
|
||||
}
|
||||
|
||||
Data data;
|
||||
|
||||
for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
|
||||
{
|
||||
const Reply *key = r.multi_bulk[i],
|
||||
*value = r.multi_bulk[i + 1];
|
||||
|
||||
data.StoreInternal(key->bulk, value->bulk);
|
||||
}
|
||||
|
||||
obj = st->Unserialize(obj, data);
|
||||
if (obj)
|
||||
{
|
||||
obj->object_id = this->id;
|
||||
obj->UpdateCache(data);
|
||||
|
||||
/* Insert new object values */
|
||||
for (const auto &[key, value] : data.data)
|
||||
{
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SADD");
|
||||
args.push_back("value:" + st->GetName() + ":" + key + ":" + value);
|
||||
args.push_back(Anope::ToString(obj->object_id));
|
||||
|
||||
/* Add to value -> object id set */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("SADD");
|
||||
args.push_back("ids:" + st->GetName());
|
||||
args.push_back(Anope::ToString(obj->object_id));
|
||||
|
||||
/* Add to type -> id set */
|
||||
me->redis->SendCommand(NULL, args);
|
||||
}
|
||||
|
||||
/* Transaction end */
|
||||
me->redis->CommitTransaction();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
MODULE_INIT(DatabaseRedis)
|
||||
@@ -120,6 +120,12 @@ public:
|
||||
{
|
||||
if (this->sql)
|
||||
{
|
||||
if (!obj->ShouldCommit())
|
||||
{
|
||||
OnSerializableDestruct(obj);
|
||||
continue; // Non-committable object.
|
||||
}
|
||||
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
@@ -168,7 +174,7 @@ public:
|
||||
{
|
||||
const auto &block = conf.GetModule(this);
|
||||
this->sql.SetServiceName(block.Get<const Anope::string>("engine"));
|
||||
this->prefix = block.Get<const Anope::string>("prefix", "anope_db_");
|
||||
this->prefix = block.Get<const Anope::string>("prefix", "anope21_");
|
||||
this->import = block.Get<bool>("import");
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,12 @@ public:
|
||||
{
|
||||
if (obj && this->SQL)
|
||||
{
|
||||
if (!obj->ShouldCommit())
|
||||
{
|
||||
OnSerializableDestruct(obj);
|
||||
continue; // Non-committable object.
|
||||
}
|
||||
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
@@ -152,7 +158,7 @@ public:
|
||||
const auto &block = conf.GetModule(this);
|
||||
|
||||
this->SQL.SetServiceName(block.Get<const Anope::string>("engine"));
|
||||
this->prefix = block.Get<const Anope::string>("prefix", "anope_db_");
|
||||
this->prefix = block.Get<const Anope::string>("prefix", "anope21_");
|
||||
}
|
||||
|
||||
void OnSerializableConstruct(Serializable *obj) override
|
||||
|
||||
@@ -669,7 +669,7 @@ public:
|
||||
{
|
||||
if (!show_all)
|
||||
return;
|
||||
mask = Anope::Format(Language::Translate(source.GetAccount(), _("%s [Invalid]")), mask.c_str());
|
||||
mask = Anope::Format(source.Translate(_("%s [Invalid]")), mask.c_str());
|
||||
}
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
@@ -835,7 +835,7 @@ private:
|
||||
{
|
||||
if (!show_all)
|
||||
continue;
|
||||
mask = Anope::Format(Language::Translate(source.GetAccount(), _("%s [Invalid]")), mask.c_str());
|
||||
mask = Anope::Format(source.Translate(_("%s [Invalid]")), mask.c_str());
|
||||
}
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
|
||||
@@ -401,7 +401,7 @@ public:
|
||||
else
|
||||
message = _("Your requested vhost has been rejected.");
|
||||
|
||||
MemoServ::service->Send(source.service->nick, nick, Language::Translate(source.GetAccount(), message.c_str()), true);
|
||||
MemoServ::service->Send(source.service->nick, nick, source.Translate(message.c_str()), true);
|
||||
}
|
||||
|
||||
source.Reply(_("VHost for %s has been rejected."), nick.c_str());
|
||||
|
||||
@@ -63,11 +63,11 @@ public:
|
||||
Anope::string privstr;
|
||||
if (ci->GetFounder() == nc)
|
||||
{
|
||||
privstr = Language::Translate(source.GetAccount(), _("Founder"));
|
||||
privstr = source.Translate(_("Founder"));
|
||||
}
|
||||
else if (ci->GetSuccessor() == nc)
|
||||
{
|
||||
privstr += Language::Translate(source.GetAccount(), _("Successor"));
|
||||
privstr += source.Translate(_("Successor"));
|
||||
}
|
||||
|
||||
AccessGroup access = ci->AccessFor(nc, false);
|
||||
|
||||
@@ -184,8 +184,8 @@ public:
|
||||
FOREACH_MOD(OnNickClearCert, (this->nc));
|
||||
for (const auto *cert : certs)
|
||||
{
|
||||
delete cert;
|
||||
certmap.erase(cert->fingerprint);
|
||||
delete cert;
|
||||
}
|
||||
this->certs.clear();
|
||||
}
|
||||
@@ -207,19 +207,23 @@ public:
|
||||
if (s->GetSerializableType()->GetName() != NICKCORE_TYPE)
|
||||
return;
|
||||
|
||||
const auto certstr = data.Load("cert");
|
||||
if (certstr.empty())
|
||||
return; // Nothing to do.
|
||||
|
||||
auto *nc = anope_dynamic_static_cast<NickCore *>(e);
|
||||
auto *cl = this->Require(nc);
|
||||
|
||||
// Delete the old cert list.
|
||||
for (const auto *cert : cl->certs)
|
||||
{
|
||||
delete cert;
|
||||
certmap.erase(cert->fingerprint);
|
||||
delete cert;
|
||||
}
|
||||
cl->certs.clear();
|
||||
|
||||
// Add the new cert list
|
||||
spacesepstream sep(data.Load("cert"));
|
||||
spacesepstream sep(certstr);
|
||||
for (Anope::string buf; sep.GetToken(buf); )
|
||||
{
|
||||
auto *cert = new NSCertInfo(e);
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
|
||||
InfoFormatter info(source.nc);
|
||||
|
||||
info[_("Account")] = Anope::Format(Language::Translate(source.nc, _("%s (ID: %zu)")), na->nc->display.c_str(), na->nc->GetId());
|
||||
info[_("Account")] = Anope::Format(source.Translate(_("%s (ID: %zu)")), na->nc->display.c_str(), na->nc->GetId());
|
||||
info[_("Account registered")] = Anope::strftime(na->nc->registered, source.GetAccount());
|
||||
info[_("Nick registered")] = Anope::strftime(na->registered, source.GetAccount());
|
||||
|
||||
|
||||
@@ -110,9 +110,9 @@ public:
|
||||
|
||||
auto &status = entry["Status"];
|
||||
if (na->nc->HasExt("NS_SUSPENDED"))
|
||||
status = Language::Translate(source.GetAccount(), _("Suspended"));
|
||||
status = source.Translate(_("Suspended"));
|
||||
else if (na->nc->HasExt("UNCONFIRMED"))
|
||||
status = Language::Translate(source.GetAccount(), _("Unconfirmed"));
|
||||
status = source.Translate(_("Unconfirmed"));
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
++count;
|
||||
|
||||
@@ -253,7 +253,7 @@ public:
|
||||
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply("%s", Language::Translate(source.nc, desc.c_str()));
|
||||
source.Reply("%s", source.Translate(desc.c_str()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ public:
|
||||
value = it->second.syntax.c_str();
|
||||
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(Anope::Format("[\037%s\037]", Language::Translate(source.nc, value)));
|
||||
this->SetSyntax(Anope::Format("[\037%s\037]", source.Translate(value)));
|
||||
|
||||
Command::SendSyntax(source);
|
||||
}
|
||||
@@ -294,8 +294,8 @@ public:
|
||||
|
||||
this->ClearSyntax();
|
||||
this->SetSyntax(Anope::Format(
|
||||
Language::Translate(source.nc, _("\037nickname\037 [\037%s\037]")),
|
||||
Language::Translate(source.nc, value)
|
||||
source.Translate(_("\037nickname\037 [\037%s\037]")),
|
||||
source.Translate(value)
|
||||
));
|
||||
|
||||
Command::SendSyntax(source);
|
||||
|
||||
@@ -253,7 +253,7 @@ class CommandOSDNS final
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Server"] = s->GetName();
|
||||
entry["Limit"] = s->GetLimit() ? Anope::ToString(s->GetLimit()) : Language::Translate(source.GetAccount(), _("None"));
|
||||
entry["Limit"] = s->GetLimit() ? Anope::ToString(s->GetLimit()) : source.Translate(_("None"));
|
||||
|
||||
Anope::string ip_str;
|
||||
for (const auto &ip : s->GetIPs())
|
||||
@@ -264,14 +264,14 @@ class CommandOSDNS final
|
||||
entry["IP"] = ip_str;
|
||||
|
||||
if (s->Active())
|
||||
entry["State"] = Language::Translate(source.GetAccount(), _("Pooled/Active"));
|
||||
entry["State"] = source.Translate(_("Pooled/Active"));
|
||||
else if (s->Pooled())
|
||||
entry["State"] = Language::Translate(source.GetAccount(), _("Pooled/Not Active"));
|
||||
entry["State"] = source.Translate(_("Pooled/Not Active"));
|
||||
else
|
||||
entry["State"] = Language::Translate(source.GetAccount(), _("Unpooled"));
|
||||
entry["State"] = source.Translate(_("Unpooled"));
|
||||
|
||||
if (!srv)
|
||||
entry["State"] += Anope::string(" ") + Language::Translate(source.GetAccount(), _("(Split)"));
|
||||
entry["State"] += Anope::string(" ") + source.Translate(_("(Split)"));
|
||||
|
||||
lf.AddEntry(entry);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
|
||||
Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Login to %s")), source.service->nick.c_str());
|
||||
return Anope::Format(source.Translate(_("Login to %s")), source.service->nick.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
|
||||
Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Logout from %s")), source.service->nick.c_str());
|
||||
return Anope::Format(source.Translate(_("Logout from %s")), source.service->nick.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
|
||||
Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Manipulate the %s list")), source.command.nobreak().c_str());
|
||||
return Anope::Format(source.Translate(_("Manipulate the %s list")), source.command.nobreak().c_str());
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
|
||||
@@ -1709,6 +1709,21 @@ struct IRCDMessageFIdent final
|
||||
}
|
||||
};
|
||||
|
||||
struct IRCDMessageFName final
|
||||
: IRCDMessage
|
||||
{
|
||||
IRCDMessageFName(Module *creator)
|
||||
: IRCDMessage(creator, "FNAME", 1)
|
||||
{
|
||||
SetFlag(FLAG_REQUIRE_USER);
|
||||
}
|
||||
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
source.GetUser()->SetRealname(params[0]);
|
||||
}
|
||||
};
|
||||
|
||||
struct IRCDMessageKick final
|
||||
: IRCDMessage
|
||||
{
|
||||
@@ -2466,6 +2481,7 @@ class ProtoInspIRCd final
|
||||
IRCDMessageEndburst message_endburst;
|
||||
IRCDMessageFHost message_fhost;
|
||||
IRCDMessageFIdent message_fident;
|
||||
IRCDMessageFName message_fname;
|
||||
IRCDMessageFJoin message_fjoin;
|
||||
IRCDMessageFMode message_fmode;
|
||||
IRCDMessageFTopic message_ftopic;
|
||||
@@ -2517,6 +2533,7 @@ public:
|
||||
, message_endburst(this)
|
||||
, message_fhost(this)
|
||||
, message_fident(this)
|
||||
, message_fname(this)
|
||||
, message_fjoin(this)
|
||||
, message_fmode(this)
|
||||
, message_ftopic(this)
|
||||
|
||||
@@ -1,615 +0,0 @@
|
||||
// Anope IRC Services <https://www.anope.org/>
|
||||
//
|
||||
// Copyright (C) 2003-2026 Anope Contributors
|
||||
//
|
||||
// Anope is free software. You can use, modify, and/or distribute it under the
|
||||
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
|
||||
// for the complete terms of this license and docs/AUTHORS.txt for a list of
|
||||
// contributors.
|
||||
//
|
||||
// Based on the original code of Epona by Lara
|
||||
// Based on the original code of Services by Andy Church
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/redis.h"
|
||||
|
||||
using namespace Redis;
|
||||
|
||||
class MyRedisService;
|
||||
|
||||
class RedisSocket final
|
||||
: public BinarySocket
|
||||
, public ConnectionSocket
|
||||
{
|
||||
size_t ParseReply(Reply &r, const char *buf, size_t l);
|
||||
public:
|
||||
MyRedisService *provider;
|
||||
std::deque<Interface *> interfaces;
|
||||
std::map<Anope::string, Interface *> subinterfaces;
|
||||
|
||||
RedisSocket(MyRedisService *pro, bool v6) : Socket(-1, v6 ? AF_INET6 : AF_INET), provider(pro) { }
|
||||
|
||||
~RedisSocket() override;
|
||||
|
||||
void OnConnect() override;
|
||||
void OnError(const Anope::string &error) override;
|
||||
|
||||
bool Read(const char *buffer, size_t l) override;
|
||||
};
|
||||
|
||||
class Transaction final
|
||||
: public Interface
|
||||
{
|
||||
public:
|
||||
std::deque<Interface *> interfaces;
|
||||
|
||||
Transaction(Module *creator) : Interface(creator) { }
|
||||
|
||||
~Transaction() override
|
||||
{
|
||||
for (auto *iface : interfaces)
|
||||
{
|
||||
if (!iface)
|
||||
continue;
|
||||
|
||||
iface->OnError("Interface going away");
|
||||
}
|
||||
}
|
||||
|
||||
void OnResult(const Reply &r) override
|
||||
{
|
||||
/* This is a multi bulk reply of the results of the queued commands
|
||||
* in this transaction
|
||||
*/
|
||||
|
||||
Log(LOG_DEBUG_2) << "redis: transaction complete with " << r.multi_bulk.size() << " results";
|
||||
|
||||
for (auto *result : r.multi_bulk)
|
||||
{
|
||||
if (interfaces.empty())
|
||||
break;
|
||||
|
||||
Interface *inter = interfaces.front();
|
||||
interfaces.pop_front();
|
||||
|
||||
if (inter)
|
||||
inter->OnResult(*result);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MyRedisService final
|
||||
: public Provider
|
||||
{
|
||||
public:
|
||||
Anope::string host;
|
||||
int port;
|
||||
unsigned db;
|
||||
|
||||
RedisSocket *sock = nullptr, *sub = nullptr;
|
||||
|
||||
Transaction ti;
|
||||
bool in_transaction = false;
|
||||
|
||||
MyRedisService(Module *c, const Anope::string &n, const Anope::string &h, int p, unsigned d) : Provider(c, n), host(h), port(p), db(d), ti(c)
|
||||
{
|
||||
sock = new RedisSocket(this, host.find(':') != Anope::string::npos);
|
||||
sock->Connect(host, port);
|
||||
|
||||
sub = new RedisSocket(this, host.find(':') != Anope::string::npos);
|
||||
sub->Connect(host, port);
|
||||
}
|
||||
|
||||
~MyRedisService() override
|
||||
{
|
||||
if (sock)
|
||||
{
|
||||
sock->flags[SF_DEAD] = true;
|
||||
sock->provider = NULL;
|
||||
}
|
||||
|
||||
if (sub)
|
||||
{
|
||||
sub->flags[SF_DEAD] = true;
|
||||
sub->provider = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static inline void Pack(std::vector<char> &buffer, const char *buf, size_t sz = 0)
|
||||
{
|
||||
if (!sz)
|
||||
sz = strlen(buf);
|
||||
|
||||
size_t old_size = buffer.size();
|
||||
buffer.resize(old_size + sz);
|
||||
std::copy(buf, buf + sz, buffer.begin() + old_size);
|
||||
}
|
||||
|
||||
void Send(RedisSocket *s, Interface *i, const std::vector<std::pair<const char *, size_t> > &args)
|
||||
{
|
||||
std::vector<char> buffer;
|
||||
|
||||
Pack(buffer, "*");
|
||||
Pack(buffer, Anope::ToString(args.size()).c_str());
|
||||
Pack(buffer, "\r\n");
|
||||
|
||||
for (const auto &[key, value] : args)
|
||||
{
|
||||
Pack(buffer, "$");
|
||||
Pack(buffer, Anope::ToString(value).c_str());
|
||||
Pack(buffer, "\r\n");
|
||||
|
||||
Pack(buffer, key, value);
|
||||
Pack(buffer, "\r\n");
|
||||
}
|
||||
|
||||
if (buffer.empty())
|
||||
return;
|
||||
|
||||
s->Write(&buffer[0], buffer.size());
|
||||
if (in_transaction)
|
||||
{
|
||||
ti.interfaces.push_back(i);
|
||||
s->interfaces.push_back(NULL); // For the +Queued response
|
||||
}
|
||||
else
|
||||
s->interfaces.push_back(i);
|
||||
}
|
||||
|
||||
public:
|
||||
bool IsSocketDead() override
|
||||
{
|
||||
return this->sock && this->sock->flags[SF_DEAD];
|
||||
}
|
||||
|
||||
void SendCommand(RedisSocket *s, Interface *i, const std::vector<Anope::string> &cmds)
|
||||
{
|
||||
std::vector<std::pair<const char *, size_t> > args;
|
||||
for (const auto &cmd : cmds)
|
||||
args.emplace_back(cmd.c_str(), cmd.length());
|
||||
this->Send(s, i, args);
|
||||
}
|
||||
|
||||
void SendCommand(RedisSocket *s, Interface *i, const Anope::string &str)
|
||||
{
|
||||
std::vector<Anope::string> args;
|
||||
spacesepstream(str).GetTokens(args);
|
||||
this->SendCommand(s, i, args);
|
||||
}
|
||||
|
||||
void Send(Interface *i, const std::vector<std::pair<const char *, size_t> > &args)
|
||||
{
|
||||
if (!sock)
|
||||
{
|
||||
sock = new RedisSocket(this, host.find(':') != Anope::string::npos);
|
||||
sock->Connect(host, port);
|
||||
}
|
||||
|
||||
this->Send(sock, i, args);
|
||||
}
|
||||
|
||||
void SendCommand(Interface *i, const std::vector<Anope::string> &cmds) override
|
||||
{
|
||||
std::vector<std::pair<const char *, size_t> > args;
|
||||
for (const auto &cmd : cmds)
|
||||
args.emplace_back(cmd.c_str(), cmd.length());
|
||||
this->Send(i, args);
|
||||
}
|
||||
|
||||
void SendCommand(Interface *i, const Anope::string &str) override
|
||||
{
|
||||
std::vector<Anope::string> args;
|
||||
spacesepstream(str).GetTokens(args);
|
||||
this->SendCommand(i, args);
|
||||
}
|
||||
|
||||
public:
|
||||
bool BlockAndProcess() override
|
||||
{
|
||||
if (!this->sock->ProcessWrite())
|
||||
this->sock->flags[SF_DEAD] = true;
|
||||
this->sock->SetBlocking(true);
|
||||
if (!this->sock->ProcessRead())
|
||||
this->sock->flags[SF_DEAD] = true;
|
||||
this->sock->SetBlocking(false);
|
||||
return !this->sock->interfaces.empty();
|
||||
}
|
||||
|
||||
void Subscribe(Interface *i, const Anope::string &pattern) override
|
||||
{
|
||||
if (sub == NULL)
|
||||
{
|
||||
sub = new RedisSocket(this, host.find(':') != Anope::string::npos);
|
||||
sub->Connect(host, port);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> args;
|
||||
args.emplace_back("PSUBSCRIBE");
|
||||
args.push_back(pattern);
|
||||
this->SendCommand(sub, NULL, args);
|
||||
|
||||
sub->subinterfaces[pattern] = i;
|
||||
}
|
||||
|
||||
void Unsubscribe(const Anope::string &pattern) override
|
||||
{
|
||||
if (sub)
|
||||
sub->subinterfaces.erase(pattern);
|
||||
}
|
||||
|
||||
void StartTransaction() override
|
||||
{
|
||||
if (in_transaction)
|
||||
throw ModuleException("Tried to start a transaction while one was already in progress");
|
||||
|
||||
this->SendCommand(NULL, "MULTI");
|
||||
in_transaction = true;
|
||||
}
|
||||
|
||||
void CommitTransaction() override
|
||||
{
|
||||
/* The result of the transaction comes back to the reply of EXEC as a multi bulk.
|
||||
* The reply to the individual commands that make up the transaction when executed
|
||||
* is a simple +QUEUED
|
||||
*/
|
||||
in_transaction = false;
|
||||
this->SendCommand(&this->ti, "EXEC");
|
||||
}
|
||||
};
|
||||
|
||||
RedisSocket::~RedisSocket()
|
||||
{
|
||||
if (provider)
|
||||
{
|
||||
if (provider->sock == this)
|
||||
provider->sock = NULL;
|
||||
else if (provider->sub == this)
|
||||
provider->sub = NULL;
|
||||
}
|
||||
|
||||
for (auto *iface : interfaces)
|
||||
{
|
||||
if (!iface)
|
||||
continue;
|
||||
|
||||
iface->OnError("Interface going away");
|
||||
}
|
||||
}
|
||||
|
||||
void RedisSocket::OnConnect()
|
||||
{
|
||||
Log() << "redis: Successfully connected to " << provider->name << (this == this->provider->sub ? " (sub)" : "");
|
||||
|
||||
this->provider->SendCommand(NULL, "CLIENT SETNAME Anope");
|
||||
this->provider->SendCommand(NULL, "SELECT " + Anope::ToString(provider->db));
|
||||
|
||||
if (this != this->provider->sub)
|
||||
{
|
||||
this->provider->SendCommand(this, NULL, "CONFIG SET notify-keyspace-events KA");
|
||||
}
|
||||
}
|
||||
|
||||
void RedisSocket::OnError(const Anope::string &error)
|
||||
{
|
||||
Log() << "redis: Error on " << provider->name << (this == this->provider->sub ? " (sub)" : "") << ": " << error;
|
||||
}
|
||||
|
||||
size_t RedisSocket::ParseReply(Reply &r, const char *buffer, size_t l)
|
||||
{
|
||||
size_t used = 0;
|
||||
|
||||
if (!l)
|
||||
return used;
|
||||
|
||||
if (r.type == Reply::MULTI_BULK)
|
||||
goto multi_bulk_cont;
|
||||
|
||||
switch (*buffer)
|
||||
{
|
||||
case '+':
|
||||
{
|
||||
Anope::string reason(buffer, 1, l - 1);
|
||||
size_t nl = reason.find("\r\n");
|
||||
Log(LOG_DEBUG_2) << "redis: status ok: " << reason.substr(0, nl);
|
||||
if (nl != Anope::string::npos)
|
||||
{
|
||||
r.type = Reply::OK;
|
||||
used = 1 + nl + 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '-':
|
||||
{
|
||||
Anope::string reason(buffer, 1, l - 1);
|
||||
size_t nl = reason.find("\r\n");
|
||||
Log(LOG_DEBUG) << "redis: status error: " << reason.substr(0, nl);
|
||||
if (nl != Anope::string::npos)
|
||||
{
|
||||
r.type = Reply::NOT_OK;
|
||||
used = 1 + nl + 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ':':
|
||||
{
|
||||
Anope::string ibuf(buffer, 1, l - 1);
|
||||
size_t nl = ibuf.find("\r\n");
|
||||
if (nl != Anope::string::npos)
|
||||
{
|
||||
if (auto i = Anope::TryConvert<int64_t>(ibuf.substr(0, nl)))
|
||||
r.i = i.value();
|
||||
|
||||
r.type = Reply::INT;
|
||||
used = 1 + nl + 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '$':
|
||||
{
|
||||
Anope::string reply(buffer + 1, l - 1);
|
||||
/* This assumes one bulk can always fit in our recv buffer */
|
||||
size_t nl = reply.find("\r\n");
|
||||
if (nl != Anope::string::npos)
|
||||
{
|
||||
if (auto l = Anope::TryConvert<int>(reply.substr(0, nl)))
|
||||
{
|
||||
int len = l.value();
|
||||
if (len >= 0)
|
||||
{
|
||||
if (1 + nl + 2 + len + 2 <= l)
|
||||
{
|
||||
used = 1 + nl + 2 + len + 2;
|
||||
r.bulk = reply.substr(nl + 2, len);
|
||||
r.type = Reply::BULK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
used = 1 + nl + 2 + 2;
|
||||
r.type = Reply::BULK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
multi_bulk_cont:
|
||||
case '*':
|
||||
{
|
||||
if (r.type != Reply::MULTI_BULK)
|
||||
{
|
||||
Anope::string reply(buffer + 1, l - 1);
|
||||
size_t nl = reply.find("\r\n");
|
||||
if (nl != Anope::string::npos)
|
||||
{
|
||||
r.type = Reply::MULTI_BULK;
|
||||
if (auto size = Anope::TryConvert<int>(reply.substr(0, nl)))
|
||||
r.multi_bulk_size = size.value();
|
||||
used = 1 + nl + 2;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else if (r.multi_bulk_size >= 0 && r.multi_bulk.size() == static_cast<unsigned>(r.multi_bulk_size))
|
||||
{
|
||||
/* This multi bulk is already complete, so check the sub bulks */
|
||||
for (auto &bulk : r.multi_bulk)
|
||||
if (bulk->type == Reply::MULTI_BULK)
|
||||
ParseReply(*bulk, buffer + used, l - used);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = r.multi_bulk.size(); i < r.multi_bulk_size; ++i)
|
||||
{
|
||||
auto *reply = new Reply();
|
||||
size_t u = ParseReply(*reply, buffer + used, l - used);
|
||||
if (!u)
|
||||
{
|
||||
Log(LOG_DEBUG) << "redis: ran out of data to parse";
|
||||
delete reply;
|
||||
break;
|
||||
}
|
||||
r.multi_bulk.push_back(reply);
|
||||
used += u;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Log(LOG_DEBUG) << "redis: unknown reply " << *buffer;
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
bool RedisSocket::Read(const char *buffer, size_t l)
|
||||
{
|
||||
static std::vector<char> save;
|
||||
std::vector<char> copy;
|
||||
|
||||
if (!save.empty())
|
||||
{
|
||||
std::copy(buffer, buffer + l, std::back_inserter(save));
|
||||
|
||||
copy = save;
|
||||
|
||||
buffer = ©[0];
|
||||
l = copy.size();
|
||||
}
|
||||
|
||||
while (l)
|
||||
{
|
||||
static Reply r;
|
||||
|
||||
size_t used = this->ParseReply(r, buffer, l);
|
||||
if (!used)
|
||||
{
|
||||
Log(LOG_DEBUG) << "redis: used == 0 ?";
|
||||
r.Clear();
|
||||
break;
|
||||
}
|
||||
else if (used > l)
|
||||
{
|
||||
Log(LOG_DEBUG) << "redis: used > l ?";
|
||||
r.Clear();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Full result is not here yet */
|
||||
if (r.type == Reply::MULTI_BULK && static_cast<unsigned>(r.multi_bulk_size) != r.multi_bulk.size())
|
||||
{
|
||||
buffer += used;
|
||||
l -= used;
|
||||
break;
|
||||
}
|
||||
|
||||
if (this == provider->sub)
|
||||
{
|
||||
if (r.multi_bulk.size() == 4)
|
||||
{
|
||||
/* pmessage
|
||||
* pattern subscribed to
|
||||
* __keyevent@0__:set
|
||||
* key
|
||||
*/
|
||||
auto it = this->subinterfaces.find(r.multi_bulk[1]->bulk);
|
||||
if (it != this->subinterfaces.end())
|
||||
it->second->OnResult(r);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->interfaces.empty())
|
||||
{
|
||||
Log(LOG_DEBUG) << "redis: no interfaces?";
|
||||
}
|
||||
else
|
||||
{
|
||||
Interface *i = this->interfaces.front();
|
||||
this->interfaces.pop_front();
|
||||
|
||||
if (i)
|
||||
{
|
||||
if (r.type != Reply::NOT_OK)
|
||||
i->OnResult(r);
|
||||
else
|
||||
i->OnError(r.bulk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer += used;
|
||||
l -= used;
|
||||
|
||||
r.Clear();
|
||||
}
|
||||
|
||||
if (l)
|
||||
{
|
||||
save.resize(l);
|
||||
std::copy(buffer, buffer + l, save.begin());
|
||||
}
|
||||
else
|
||||
std::vector<char>().swap(save);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
class ModuleRedis final
|
||||
: public Module
|
||||
{
|
||||
std::map<Anope::string, MyRedisService *> services;
|
||||
|
||||
public:
|
||||
ModuleRedis(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
|
||||
{
|
||||
}
|
||||
|
||||
~ModuleRedis() override
|
||||
{
|
||||
for (auto &[_, p] : services)
|
||||
{
|
||||
delete p->sock;
|
||||
p->sock = NULL;
|
||||
|
||||
delete p->sub;
|
||||
p->sub = NULL;
|
||||
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const auto &block = conf.GetModule(this);
|
||||
std::vector<Anope::string> new_services;
|
||||
|
||||
for (int i = 0; i < block.CountBlock("redis"); ++i)
|
||||
{
|
||||
const auto &redis = block.GetBlock("redis", i);
|
||||
|
||||
const Anope::string &n = redis.Get<const Anope::string>("name"),
|
||||
&ip = redis.Get<const Anope::string>("ip");
|
||||
int port = redis.Get<int>("port");
|
||||
auto db = redis.Get<unsigned>("db");
|
||||
|
||||
delete services[n];
|
||||
services[n] = new MyRedisService(this, n, ip, port, db);
|
||||
new_services.push_back(n);
|
||||
}
|
||||
|
||||
for (auto it = services.begin(); it != services.end();)
|
||||
{
|
||||
Provider *p = it->second;
|
||||
++it;
|
||||
|
||||
if (std::find(new_services.begin(), new_services.end(), p->name) == new_services.end())
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void OnModuleUnload(User *, Module *m) override
|
||||
{
|
||||
for (auto &[_, p] : services)
|
||||
{
|
||||
if (p->sock)
|
||||
for (unsigned i = p->sock->interfaces.size(); i > 0; --i)
|
||||
{
|
||||
Interface *inter = p->sock->interfaces[i - 1];
|
||||
|
||||
if (inter && inter->owner == m)
|
||||
{
|
||||
inter->OnError(m->name + " being unloaded");
|
||||
p->sock->interfaces.erase(p->sock->interfaces.begin() + i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (p->sub)
|
||||
for (unsigned i = p->sub->interfaces.size(); i > 0; --i)
|
||||
{
|
||||
Interface *inter = p->sub->interfaces[i - 1];
|
||||
|
||||
if (inter && inter->owner == m)
|
||||
{
|
||||
inter->OnError(m->name + " being unloaded");
|
||||
p->sub->interfaces.erase(p->sub->interfaces.begin() + i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = p->ti.interfaces.size(); i > 0; --i)
|
||||
{
|
||||
Interface *inter = p->ti.interfaces[i - 1];
|
||||
|
||||
if (inter && inter->owner == m)
|
||||
{
|
||||
inter->OnError(m->name + " being unloaded");
|
||||
p->ti.interfaces.erase(p->ti.interfaces.begin() + i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(ModuleRedis)
|
||||
+26
-8
@@ -112,7 +112,7 @@ bool CommandSource::IsOper()
|
||||
|
||||
void CommandSource::Reply(const char *message, ...)
|
||||
{
|
||||
const char *translated_message = Language::Translate(this->nc, message);
|
||||
const char *translated_message = Translate(message);
|
||||
|
||||
Anope::string buf;
|
||||
ANOPE_FORMAT(message, translated_message, buf);
|
||||
@@ -121,7 +121,7 @@ void CommandSource::Reply(const char *message, ...)
|
||||
|
||||
void CommandSource::Reply(int count, const char *single, const char *plural, ...)
|
||||
{
|
||||
const char *translated_message = Language::Translate(this->nc, count, single, plural);
|
||||
const char *translated_message = Translate(count, single, plural);
|
||||
|
||||
Anope::string buf;
|
||||
ANOPE_FORMAT(plural, translated_message, buf);
|
||||
@@ -130,10 +130,30 @@ void CommandSource::Reply(int count, const char *single, const char *plural, ...
|
||||
|
||||
void CommandSource::Reply(const Anope::string &message)
|
||||
{
|
||||
const char *translated_message = Language::Translate(this->nc, message.c_str());
|
||||
const char *translated_message = Translate(message.c_str());
|
||||
this->reply->SendMessage(*this, translated_message);
|
||||
}
|
||||
|
||||
const char *CommandSource::Translate(const char *message)
|
||||
{
|
||||
return Language::Translate(GetAccount(), message);
|
||||
}
|
||||
|
||||
const char *CommandSource::Translate(const Anope::string &message)
|
||||
{
|
||||
return Language::Translate(GetAccount(), message.c_str());
|
||||
}
|
||||
|
||||
const char *CommandSource::Translate(int count, const Anope::string &single, const Anope::string &plural)
|
||||
{
|
||||
return Language::Translate(GetAccount(), count, single.c_str(), plural.c_str());
|
||||
}
|
||||
|
||||
const char *CommandSource::Translate(int count, const char *single, const char *plural)
|
||||
{
|
||||
return Language::Translate(GetAccount(), count, single, plural);
|
||||
}
|
||||
|
||||
Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(o)
|
||||
{
|
||||
}
|
||||
@@ -160,7 +180,7 @@ void Command::SendSyntax(CommandSource &source)
|
||||
const auto *monospace = !flexible && sourcenc && sourcenc->HasExt("NS_MONOSPACE") ? "\021" : "";
|
||||
|
||||
auto first = true;
|
||||
Anope::string prefix = Language::Translate(source.GetAccount(), _("Syntax"));
|
||||
Anope::string prefix = source.Translate(_("Syntax"));
|
||||
Anope::string padding(prefix.utf8length(), ' ');
|
||||
for (const auto &[syntax, predicate] : this->syntax)
|
||||
{
|
||||
@@ -171,14 +191,12 @@ void Command::SendSyntax(CommandSource &source)
|
||||
{
|
||||
first = false;
|
||||
source.Reply("%s%s: \002%s %s\002", monospace, prefix.c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
Language::Translate(source.GetAccount(), syntax.c_str()));
|
||||
source.command.nobreak().c_str(), source.Translate(syntax));
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply("%s%s \002%s %s\002", monospace, padding.c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
Language::Translate(source.GetAccount(), syntax.c_str()));
|
||||
source.command.nobreak().c_str(), source.Translate(syntax));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+56
-60
@@ -23,31 +23,27 @@
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
|
||||
using Configuration::File;
|
||||
using Configuration::Conf;
|
||||
using Configuration::Block;
|
||||
using Configuration::Uplink;
|
||||
Configuration::File ServicesConf("anope.conf", false); // Configuration file name
|
||||
|
||||
File ServicesConf("anope.conf", false); // Configuration file name
|
||||
Conf *Config = NULL;
|
||||
Configuration::Conf *Config = NULL;
|
||||
|
||||
Block Block::EmptyBlock("");
|
||||
Configuration::Block Configuration::Block::EmptyBlock("");
|
||||
|
||||
Block::Block(const Anope::string &n) : name(n), linenum(-1)
|
||||
Configuration::Block::Block(const Anope::string &n) : name(n), linenum(-1)
|
||||
{
|
||||
}
|
||||
|
||||
const Anope::string &Block::GetName() const
|
||||
const Anope::string &Configuration::Block::GetName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
int Block::CountBlock(const Anope::string &bname) const
|
||||
int Configuration::Block::CountBlock(const Anope::string &bname) const
|
||||
{
|
||||
return blocks.count(bname);
|
||||
}
|
||||
|
||||
const Block &Block::GetBlock(const Anope::string &bname, int num) const
|
||||
const Configuration::Block &Configuration::Block::GetBlock(const Anope::string &bname, int num) const
|
||||
{
|
||||
std::pair<block_map::const_iterator, block_map::const_iterator> it = blocks.equal_range(bname);
|
||||
|
||||
@@ -57,7 +53,7 @@ const Block &Block::GetBlock(const Anope::string &bname, int num) const
|
||||
return EmptyBlock;
|
||||
}
|
||||
|
||||
Block *Block::GetMutableBlock(const Anope::string &bname, int num)
|
||||
Configuration::Block *Configuration::Block::GetMutableBlock(const Anope::string &bname, int num)
|
||||
{
|
||||
std::pair<block_map::iterator, block_map::iterator> it = blocks.equal_range(bname);
|
||||
|
||||
@@ -67,18 +63,18 @@ Block *Block::GetMutableBlock(const Anope::string &bname, int num)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Block::Set(const Anope::string &tag, const Anope::string &value)
|
||||
bool Configuration::Block::Set(const Anope::string &tag, const Anope::string &value)
|
||||
{
|
||||
items[tag] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Block::item_map &Block::GetItems() const
|
||||
const Configuration::Block::item_map &Configuration::Block::GetItems() const
|
||||
{
|
||||
return items;
|
||||
}
|
||||
|
||||
template<> const Anope::string Block::Get(const Anope::string &tag, const Anope::string &def) const
|
||||
template<> const Anope::string Configuration::Block::Get(const Anope::string &tag, const Anope::string &def) const
|
||||
{
|
||||
auto it = items.find(tag);
|
||||
if (it != items.end())
|
||||
@@ -87,12 +83,12 @@ template<> const Anope::string Block::Get(const Anope::string &tag, const Anope:
|
||||
return def;
|
||||
}
|
||||
|
||||
template<> time_t Block::Get(const Anope::string &tag, const Anope::string &def) const
|
||||
template<> time_t Configuration::Block::Get(const Anope::string &tag, const Anope::string &def) const
|
||||
{
|
||||
return Anope::DoTime(Get<const Anope::string>(tag, def));
|
||||
}
|
||||
|
||||
template<> bool Block::Get(const Anope::string &tag, const Anope::string &def) const
|
||||
template<> bool Configuration::Block::Get(const Anope::string &tag, const Anope::string &def) const
|
||||
{
|
||||
const Anope::string &str = Get<const Anope::string>(tag, def);
|
||||
return !str.empty() && !str.equals_ci("no") && !str.equals_ci("off") && !str.equals_ci("false") && !str.equals_ci("0");
|
||||
@@ -122,7 +118,7 @@ template<typename T> static void ValidateNotZero(const Anope::string &block, con
|
||||
throw ConfigException("The value for <" + block + ":" + name + "> cannot be zero!");
|
||||
}
|
||||
|
||||
Conf::Conf() : Block("")
|
||||
Configuration::Conf::Conf() : Configuration::Block("")
|
||||
{
|
||||
ReadTimeout = 0;
|
||||
DefPrivmsg = false;
|
||||
@@ -131,12 +127,12 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("include"); ++i)
|
||||
{
|
||||
const Block &include = this->GetBlock("include", i);
|
||||
const auto &include = this->GetBlock("include", i);
|
||||
|
||||
const Anope::string &type = include.Get<const Anope::string>("type"),
|
||||
&file = include.Get<const Anope::string>("name");
|
||||
|
||||
File f(file, type == "executable");
|
||||
Configuration::File f(file, type == "executable");
|
||||
this->LoadConf(f);
|
||||
}
|
||||
|
||||
@@ -168,7 +164,7 @@ Conf::Conf() : Block("")
|
||||
}
|
||||
}
|
||||
|
||||
const Block &serverinfo = this->GetBlock("serverinfo"), &options = this->GetBlock("options"),
|
||||
const auto &serverinfo = this->GetBlock("serverinfo"), &options = this->GetBlock("options"),
|
||||
&mail = this->GetBlock("mail"), &networkinfo = this->GetBlock("networkinfo");
|
||||
|
||||
const Anope::string &servername = serverinfo.Get<Anope::string>("name");
|
||||
@@ -211,7 +207,7 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("uplink"); ++i)
|
||||
{
|
||||
const Block &uplink = this->GetBlock("uplink", i);
|
||||
const auto &uplink = this->GetBlock("uplink", i);
|
||||
|
||||
int protocol;
|
||||
const Anope::string &protocolstr = uplink.Get<const Anope::string>("protocol", "ipv4");
|
||||
@@ -244,7 +240,7 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("module"); ++i)
|
||||
{
|
||||
const Block &module = this->GetBlock("module", i);
|
||||
const auto &module = this->GetBlock("module", i);
|
||||
|
||||
const Anope::string &modname = module.Get<const Anope::string>("name");
|
||||
|
||||
@@ -255,7 +251,7 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("opertype"); ++i)
|
||||
{
|
||||
const Block &opertype = this->GetBlock("opertype", i);
|
||||
const auto &opertype = this->GetBlock("opertype", i);
|
||||
|
||||
const Anope::string &oname = opertype.Get<const Anope::string>("name"),
|
||||
&modes = opertype.Get<const Anope::string>("modes"),
|
||||
@@ -298,7 +294,7 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("oper"); ++i)
|
||||
{
|
||||
const Block &oper = this->GetBlock("oper", i);
|
||||
const auto &oper = this->GetBlock("oper", i);
|
||||
|
||||
const Anope::string &nname = oper.Get<const Anope::string>("name"),
|
||||
&type = oper.Get<const Anope::string>("type"),
|
||||
@@ -336,7 +332,7 @@ Conf::Conf() : Block("")
|
||||
bi->conf = false;
|
||||
for (int i = 0; i < this->CountBlock("service"); ++i)
|
||||
{
|
||||
const Block &service = this->GetBlock("service", i);
|
||||
const auto &service = this->GetBlock("service", i);
|
||||
|
||||
const Anope::string &nick = service.Get<const Anope::string>("nick"),
|
||||
&user = service.Get<const Anope::string>("user", nick.lower()),
|
||||
@@ -427,7 +423,7 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("log"); ++i)
|
||||
{
|
||||
const Block &log = this->GetBlock("log", i);
|
||||
const auto &log = this->GetBlock("log", i);
|
||||
|
||||
int logage = log.Get<int>("logage");
|
||||
bool rawio = log.Get<bool>("rawio");
|
||||
@@ -453,7 +449,7 @@ Conf::Conf() : Block("")
|
||||
bi->commands.clear();
|
||||
for (int i = 0; i < this->CountBlock("command"); ++i)
|
||||
{
|
||||
const Block &command = this->GetBlock("command", i);
|
||||
const auto &command = this->GetBlock("command", i);
|
||||
|
||||
const Anope::string &service = command.Get<const Anope::string>("service"),
|
||||
&nname = command.Get<const Anope::string>("name"),
|
||||
@@ -478,7 +474,7 @@ Conf::Conf() : Block("")
|
||||
PrivilegeManager::ClearPrivileges();
|
||||
for (int i = 0; i < this->CountBlock("privilege"); ++i)
|
||||
{
|
||||
const Block &privilege = this->GetBlock("privilege", i);
|
||||
const auto &privilege = this->GetBlock("privilege", i);
|
||||
|
||||
const Anope::string &nname = privilege.Get<const Anope::string>("name"),
|
||||
&desc = privilege.Get<const Anope::string>("desc");
|
||||
@@ -489,7 +485,7 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("fantasy"); ++i)
|
||||
{
|
||||
const Block &fantasy = this->GetBlock("fantasy", i);
|
||||
const auto &fantasy = this->GetBlock("fantasy", i);
|
||||
|
||||
const Anope::string &nname = fantasy.Get<const Anope::string>("name"),
|
||||
&service = fantasy.Get<const Anope::string>("command"),
|
||||
@@ -510,7 +506,7 @@ Conf::Conf() : Block("")
|
||||
|
||||
for (int i = 0; i < this->CountBlock("command_group"); ++i)
|
||||
{
|
||||
const Block &command_group = this->GetBlock("command_group", i);
|
||||
const auto &command_group = this->GetBlock("command_group", i);
|
||||
|
||||
const Anope::string &nname = command_group.Get<const Anope::string>("name"),
|
||||
&description = command_group.Get<const Anope::string>("description");
|
||||
@@ -567,7 +563,7 @@ Conf::Conf() : Block("")
|
||||
Anope::CaseMapRebuild();
|
||||
}
|
||||
|
||||
Conf::~Conf()
|
||||
Configuration::Conf::~Conf()
|
||||
{
|
||||
for (const auto *opertype : MyOperTypes)
|
||||
delete opertype;
|
||||
@@ -576,7 +572,7 @@ Conf::~Conf()
|
||||
delete oper;
|
||||
}
|
||||
|
||||
void Conf::Post(Conf *old)
|
||||
void Configuration::Conf::Post(Configuration::Conf *old)
|
||||
{
|
||||
/* Apply module changes */
|
||||
for (const auto &mod : old->ModulesAutoLoad)
|
||||
@@ -625,7 +621,7 @@ void Conf::Post(Conf *old)
|
||||
}
|
||||
}
|
||||
|
||||
Anope::string Uplink::str() const
|
||||
Anope::string Configuration::Uplink::str() const
|
||||
{
|
||||
switch (protocol)
|
||||
{
|
||||
@@ -642,26 +638,26 @@ Anope::string Uplink::str() const
|
||||
}
|
||||
|
||||
|
||||
Block &Conf::GetModule(const Module *m)
|
||||
Configuration::Block &Configuration::Conf::GetModule(const Module *m)
|
||||
{
|
||||
if (!m)
|
||||
return Block::EmptyBlock;
|
||||
return Configuration::Block::EmptyBlock;
|
||||
|
||||
return GetModule(m->name);
|
||||
}
|
||||
|
||||
Block &Conf::GetModule(const Anope::string &mname)
|
||||
Configuration::Block &Configuration::Conf::GetModule(const Anope::string &mname)
|
||||
{
|
||||
auto it = modules.find(mname);
|
||||
if (it != modules.end())
|
||||
return *it->second;
|
||||
|
||||
Block *&block = modules[mname];
|
||||
auto *&block = modules[mname];
|
||||
|
||||
/* Search for the block */
|
||||
for (std::pair<block_map::iterator, block_map::iterator> iters = blocks.equal_range("module"); iters.first != iters.second; ++iters.first)
|
||||
{
|
||||
Block &b = iters.first->second;
|
||||
auto &b = iters.first->second;
|
||||
|
||||
if (b.Get<const Anope::string>("name") == mname)
|
||||
{
|
||||
@@ -671,70 +667,70 @@ Block &Conf::GetModule(const Anope::string &mname)
|
||||
}
|
||||
|
||||
if (!block)
|
||||
block = &Block::EmptyBlock;
|
||||
block = &Configuration::Block::EmptyBlock;
|
||||
|
||||
return GetModule(mname);
|
||||
}
|
||||
|
||||
BotInfo *Conf::GetClient(const Anope::string &cname)
|
||||
BotInfo *Configuration::Conf::GetClient(const Anope::string &cname)
|
||||
{
|
||||
auto it = bots.find(cname);
|
||||
if (it != bots.end())
|
||||
return BotInfo::Find(!it->second.empty() ? it->second : cname, true);
|
||||
|
||||
Block &block = GetModule(cname.lower());
|
||||
auto &block = GetModule(cname.lower());
|
||||
const Anope::string &client = block.Get<const Anope::string>("client");
|
||||
bots[cname] = client;
|
||||
return GetClient(cname);
|
||||
}
|
||||
|
||||
const Block &Conf::GetCommand(CommandSource &source)
|
||||
const Configuration::Block &Configuration::Conf::GetCommand(CommandSource &source)
|
||||
{
|
||||
const Anope::string &block_name = source.c ? "fantasy" : "command";
|
||||
|
||||
for (std::pair<block_map::iterator, block_map::iterator> iters = blocks.equal_range(block_name); iters.first != iters.second; ++iters.first)
|
||||
{
|
||||
Block &b = iters.first->second;
|
||||
auto &b = iters.first->second;
|
||||
|
||||
if (b.Get<Anope::string>("name") == source.command)
|
||||
return b;
|
||||
}
|
||||
|
||||
return Block::EmptyBlock;
|
||||
return Configuration::Block::EmptyBlock;
|
||||
}
|
||||
|
||||
File::File(const Anope::string &n, bool e) : name(n), executable(e)
|
||||
Configuration::File::File(const Anope::string &n, bool e) : name(n), executable(e)
|
||||
{
|
||||
}
|
||||
|
||||
File::~File()
|
||||
Configuration::File::~File()
|
||||
{
|
||||
this->Close();
|
||||
}
|
||||
|
||||
const Anope::string &File::GetName() const
|
||||
const Anope::string &Configuration::File::GetName() const
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
Anope::string File::GetPath() const
|
||||
Anope::string Configuration::File::GetPath() const
|
||||
{
|
||||
return this->executable ? this->name : Anope::ExpandConfig(this->name);
|
||||
}
|
||||
|
||||
bool File::IsOpen() const
|
||||
bool Configuration::File::IsOpen() const
|
||||
{
|
||||
return this->fp != NULL;
|
||||
}
|
||||
|
||||
bool File::Open()
|
||||
bool Configuration::File::Open()
|
||||
{
|
||||
this->Close();
|
||||
this->fp = (this->executable ? popen(GetPath().c_str(), "r") : fopen(GetPath().c_str(), "r"));
|
||||
return this->fp != NULL;
|
||||
}
|
||||
|
||||
void File::Close()
|
||||
void Configuration::File::Close()
|
||||
{
|
||||
if (this->fp != NULL)
|
||||
{
|
||||
@@ -746,12 +742,12 @@ void File::Close()
|
||||
}
|
||||
}
|
||||
|
||||
bool File::End() const
|
||||
bool Configuration::File::End() const
|
||||
{
|
||||
return !this->IsOpen() || feof(this->fp);
|
||||
}
|
||||
|
||||
Anope::string File::Read()
|
||||
Anope::string Configuration::File::Read()
|
||||
{
|
||||
Anope::string ret;
|
||||
char buf[1024];
|
||||
@@ -773,19 +769,19 @@ Anope::string File::Read()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Conf::LoadConf(File &file)
|
||||
void Configuration::Conf::LoadConf(Configuration::File &file)
|
||||
{
|
||||
if (file.GetName().empty())
|
||||
return;
|
||||
|
||||
if (!file.Open())
|
||||
{
|
||||
throw ConfigException(Anope::Format("File %s could not be opened: %s.",
|
||||
throw ConfigException(Anope::Format("Configuration::File %s could not be opened: %s.",
|
||||
file.GetPath().c_str(), strerror(errno)));
|
||||
}
|
||||
|
||||
Anope::string itemname, wordbuffer;
|
||||
std::stack<Block *> block_stack;
|
||||
std::stack<Configuration::Block *> block_stack;
|
||||
int linenumber = 0;
|
||||
bool in_word = false, in_quote = false, in_comment = false;
|
||||
|
||||
@@ -894,7 +890,7 @@ void Conf::LoadConf(File &file)
|
||||
continue;
|
||||
}
|
||||
|
||||
Block *b = block_stack.empty() ? this : block_stack.top();
|
||||
auto *b = block_stack.empty() ? this : block_stack.top();
|
||||
auto it = b->blocks.emplace(wordbuffer, Configuration::Block(wordbuffer));
|
||||
b = &it->second;
|
||||
b->linenum = linenumber;
|
||||
@@ -946,7 +942,7 @@ void Conf::LoadConf(File &file)
|
||||
throw ConfigException("Stray ';' outside of block: " + file.GetName() + ":" + Anope::ToString(linenumber));
|
||||
}
|
||||
|
||||
Block *b = block_stack.top();
|
||||
auto *b = block_stack.top();
|
||||
if (b)
|
||||
{
|
||||
Log(LOG_DEBUG) << "ln " << linenumber << " EOL: s='" << b->name << "' '" << itemname << "' set to '" << wordbuffer << "'";
|
||||
@@ -988,7 +984,7 @@ void Conf::LoadConf(File &file)
|
||||
}
|
||||
}
|
||||
|
||||
Anope::string Conf::ReplaceVars(const Anope::string &str, const File &file, int linenumber)
|
||||
Anope::string Configuration::Conf::ReplaceVars(const Anope::string &str, const Configuration::File &file, int linenumber)
|
||||
{
|
||||
Anope::string ret;
|
||||
for (auto it = str.begin(); it != str.end(); )
|
||||
|
||||
+22
-24
@@ -24,14 +24,12 @@
|
||||
#include "channels.h"
|
||||
#include "numeric.h"
|
||||
|
||||
using namespace Message;
|
||||
|
||||
void Away::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Away::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
source.GetUser()->SetAway(params.empty() ? "" : params[0]);
|
||||
}
|
||||
|
||||
void Capab::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Capab::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
if (params.size() == 1)
|
||||
{
|
||||
@@ -47,26 +45,26 @@ void Capab::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
}
|
||||
}
|
||||
|
||||
void Error::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Error::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
Anope::QuitReason = "Received an error from the uplink: " + params.back();
|
||||
Anope::Quitting = true;
|
||||
Log(LOG_TERMINAL) << Anope::QuitReason;
|
||||
}
|
||||
|
||||
Ignore::Ignore(Module *creator, const Anope::string &mname)
|
||||
Message::Ignore::Ignore(Module *creator, const Anope::string &mname)
|
||||
: IRCDMessage(creator, mname, 0)
|
||||
{
|
||||
SetFlag(FLAG_SOFT_LIMIT);
|
||||
}
|
||||
|
||||
void Ignore::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Ignore::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
Log(LOG_DEBUG_3) << "Intentionally ignoring " << name << " message";
|
||||
}
|
||||
|
||||
|
||||
void Invite::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Invite::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
User *targ = User::Find(params[0]);
|
||||
Channel *c = Channel::Find(params[1]);
|
||||
@@ -77,7 +75,7 @@ void Invite::Run(MessageSource &source, const std::vector<Anope::string> ¶ms
|
||||
FOREACH_MOD(OnInvite, (source.GetUser(), c, targ));
|
||||
}
|
||||
|
||||
void Join::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Join::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
User *user = source.GetUser();
|
||||
const Anope::string &channels = params[0];
|
||||
@@ -111,7 +109,7 @@ void Join::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
}
|
||||
}
|
||||
|
||||
void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::vector<Anope::string> &modeparams, const std::list<SJoinUser> &users)
|
||||
void Message::Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::vector<Anope::string> &modeparams, const std::list<SJoinUser> &users)
|
||||
{
|
||||
bool created;
|
||||
Channel *c = Channel::FindOrCreate(chan, created, ts ? ts : Anope::CurTime);
|
||||
@@ -177,7 +175,7 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co
|
||||
}
|
||||
}
|
||||
|
||||
void Kick::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Kick::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
const Anope::string &channel = params[0];
|
||||
const Anope::string &users = params[1];
|
||||
@@ -194,7 +192,7 @@ void Kick::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
c->KickInternal(source, user, reason);
|
||||
}
|
||||
|
||||
void Kill::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Kill::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
User *u = User::Find(params[0]);
|
||||
BotInfo *bi;
|
||||
@@ -237,7 +235,7 @@ void Message::Mode::Run(MessageSource &source, const std::vector<Anope::string>
|
||||
}
|
||||
|
||||
/* XXX We should cache the file somewhere not open/read/close it on every request */
|
||||
void MOTD::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::MOTD::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
Server *s = Server::Find(params[0]);
|
||||
if (s != Me)
|
||||
@@ -257,7 +255,7 @@ void MOTD::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
IRCD->SendNumeric(RPL_ENDOFMOTD, source.GetSource(), "End of /MOTD command.");
|
||||
}
|
||||
|
||||
void Notice::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Notice::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
Anope::string message = params[1];
|
||||
|
||||
@@ -273,7 +271,7 @@ void Notice::Run(MessageSource &source, const std::vector<Anope::string> ¶ms
|
||||
}
|
||||
}
|
||||
|
||||
void Part::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Part::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
User *u = source.GetUser();
|
||||
const Anope::string &reason = params.size() > 1 ? params[1] : "";
|
||||
@@ -295,12 +293,12 @@ void Part::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
}
|
||||
}
|
||||
|
||||
void Ping::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Ping::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
IRCD->SendPong(params.size() > 1 ? params[1] : Me->GetSID(), params[0]);
|
||||
}
|
||||
|
||||
void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Privmsg::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
const Anope::string &receiver = params[0];
|
||||
Anope::string message = params[1];
|
||||
@@ -358,7 +356,7 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> ¶m
|
||||
return;
|
||||
}
|
||||
|
||||
void Quit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Quit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
const Anope::string &reason = params[0];
|
||||
User *user = source.GetUser();
|
||||
@@ -368,7 +366,7 @@ void Quit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
user->Quit(reason);
|
||||
}
|
||||
|
||||
void SQuit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::SQuit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
Server *s = Server::Find(params[0]);
|
||||
|
||||
@@ -389,7 +387,7 @@ void SQuit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
s->Delete(s->GetName() + " " + s->GetUplink()->GetName());
|
||||
}
|
||||
|
||||
void Stats::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Stats::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
User *u = source.GetUser();
|
||||
|
||||
@@ -439,7 +437,7 @@ void Stats::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
return;
|
||||
}
|
||||
|
||||
void Time::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Time::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
const auto *tm = localtime(&Anope::CurTime);
|
||||
char timebuf[64];
|
||||
@@ -448,7 +446,7 @@ void Time::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
IRCD->SendNumeric(RPL_TIME, source.GetSource(), Me->GetName(), timestr);
|
||||
}
|
||||
|
||||
void Topic::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Topic::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
Channel *c = Channel::Find(params[0]);
|
||||
if (c)
|
||||
@@ -457,14 +455,14 @@ void Topic::Run(MessageSource &source, const std::vector<Anope::string> ¶ms,
|
||||
return;
|
||||
}
|
||||
|
||||
void Version::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Version::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
|
||||
IRCD->SendNumeric(RPL_VERSION, source.GetSource(), "Anope-" + Anope::Version(), Me->GetName(), Anope::Format("%s -(%s) -- %s",
|
||||
IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)", Anope::VersionBuildString().c_str()));
|
||||
}
|
||||
|
||||
void Whois::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
void Message::Whois::Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
User *u = User::Find(params[0]);
|
||||
|
||||
|
||||
+3
-3
@@ -340,8 +340,8 @@ void ExampleWrapper::SendTo(CommandSource &source)
|
||||
header = false;
|
||||
}
|
||||
|
||||
const auto *trans_example = Language::Translate(source.nc, entry.example.c_str());
|
||||
const auto *trans_description = Language::Translate(source.nc, entry.description.c_str());
|
||||
const auto *trans_example = source.Translate(entry.example);
|
||||
const auto *trans_description = source.Translate(entry.description);
|
||||
if (flexible)
|
||||
{
|
||||
source.Reply("\002%s%s%s\002: %s", source.command.c_str(), *trans_example ? " " : "",
|
||||
@@ -381,7 +381,7 @@ void HelpWrapper::SendTo(CommandSource &source)
|
||||
|
||||
for (const auto &[entry_name, entry_desc] : entries)
|
||||
{
|
||||
const auto *trans_desc = Language::Translate(source.nc, entry_desc.c_str());
|
||||
const auto *trans_desc = source.Translate(entry_desc);
|
||||
if (flexible)
|
||||
{
|
||||
source.Reply("\002%s\002: %s", entry_name.c_str(), trans_desc);
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ NickAlias::NickAlias(const Anope::string &nickname, NickCore *nickcore)
|
||||
if (this->nick.equals_ci(nickcore->display))
|
||||
nickcore->na = this;
|
||||
|
||||
if (!NickAliasList->insert_or_assign(this->nick, this).second)
|
||||
if (!this->InsertUnique(*NickAliasList, this->nick))
|
||||
Log(LOG_DEBUG) << "Duplicate nick " << this->nick << " in NickAlias table";
|
||||
|
||||
if (this->nc->o == NULL)
|
||||
|
||||
+2
-2
@@ -31,11 +31,11 @@ NickCore::NickCore(const Anope::string &coredisplay, uint64_t coreid)
|
||||
if (coredisplay.empty())
|
||||
throw CoreException("Empty display passed to NickCore constructor");
|
||||
|
||||
if (!NickCoreList->insert_or_assign(this->display, this).second)
|
||||
if (!this->InsertUnique(*NickCoreList, this->display))
|
||||
Log(LOG_DEBUG) << "Duplicate account " << this->display << " in NickCore table";
|
||||
|
||||
// Upgrading users may not have an account identifier.
|
||||
if (this->uniqueid && !NickCoreIdList->insert_or_assign(this->uniqueid, this).second)
|
||||
if (this->uniqueid && !this->InsertUnique(*NickCoreIdList, this->uniqueid))
|
||||
Log(LOG_DEBUG) << "Duplicate account id " << this->uniqueid << " in NickCore table";
|
||||
|
||||
FOREACH_MOD(OnNickCoreCreate, (this));
|
||||
|
||||
@@ -395,6 +395,7 @@ Anope::string IRCDProto::NormalizeMask(const Anope::string &mask)
|
||||
void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
auto newtags = tags;
|
||||
newtags["+channel-context"] = context->name;
|
||||
newtags["+draft/channel-context"] = context->name;
|
||||
IRCD->SendNotice(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), newtags);
|
||||
}
|
||||
@@ -402,6 +403,7 @@ void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, c
|
||||
void IRCDProto::SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map<Anope::string> &tags)
|
||||
{
|
||||
auto newtags = tags;
|
||||
newtags["+channel-context"] = context->name;
|
||||
newtags["+draft/channel-context"] = context->name;
|
||||
IRCD->SendPrivmsg(bi, target->GetUID(), Anope::Format("[%s] %s", context->name.c_str(), msg.c_str()), newtags);
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ ChannelInfo::ChannelInfo(const Anope::string &chname)
|
||||
if (this->c)
|
||||
this->c->ci = this;
|
||||
|
||||
if (!RegisteredChannelList->insert_or_assign(this->name, this).second)
|
||||
if (!this->InsertUnique(*RegisteredChannelList, this->name))
|
||||
Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in registered channel table?";
|
||||
|
||||
FOREACH_MOD(OnCreateChan, (this));
|
||||
|
||||
+10
-10
@@ -22,10 +22,10 @@
|
||||
#include "xline.h"
|
||||
#include "access.h"
|
||||
|
||||
using namespace Serialize;
|
||||
std::vector<Anope::string> Serialize::Type::TypeOrder;
|
||||
|
||||
std::map<Anope::string, Serialize::Type *> Serialize::Type::Types;
|
||||
|
||||
std::vector<Anope::string> Type::TypeOrder;
|
||||
std::map<Anope::string, Type *> Serialize::Type::Types;
|
||||
std::list<Serializable *> *Serializable::SerializableItems;
|
||||
|
||||
void Serialize::RegisterTypes()
|
||||
@@ -62,7 +62,7 @@ void Serialize::CheckTypes()
|
||||
|
||||
Serializable::Serializable(const Anope::string &serialize_type)
|
||||
: s_name(serialize_type)
|
||||
, s_type(Type::Find(serialize_type))
|
||||
, s_type(Serialize::Type::Find(serialize_type))
|
||||
{
|
||||
if (SerializableItems == NULL)
|
||||
SerializableItems = new std::list<Serializable *>();
|
||||
@@ -145,7 +145,7 @@ void Serialize::Data::SetType(const Anope::string &key, Serialize::DataType dt)
|
||||
this->types[key] = dt;
|
||||
}
|
||||
|
||||
Type::Type(const Anope::string &n, Module *o)
|
||||
Serialize::Type::Type(const Anope::string &n, Module *o)
|
||||
: name(n)
|
||||
, owner(o)
|
||||
{
|
||||
@@ -166,7 +166,7 @@ Type::Type(const Anope::string &n, Module *o)
|
||||
}
|
||||
}
|
||||
|
||||
Type::~Type()
|
||||
Serialize::Type::~Type()
|
||||
{
|
||||
auto it = std::find(TypeOrder.begin(), TypeOrder.end(), this->name);
|
||||
if (it != TypeOrder.end())
|
||||
@@ -187,7 +187,7 @@ Type::~Type()
|
||||
}
|
||||
}
|
||||
|
||||
void Type::Create()
|
||||
void Serialize::Type::Create()
|
||||
{
|
||||
if (created)
|
||||
return;
|
||||
@@ -196,17 +196,17 @@ void Type::Create()
|
||||
created = true;
|
||||
}
|
||||
|
||||
void Type::Check()
|
||||
void Serialize::Type::Check()
|
||||
{
|
||||
FOREACH_MOD(OnSerializeTypeCheck, (this));
|
||||
}
|
||||
|
||||
void Type::UpdateTimestamp()
|
||||
void Serialize::Type::UpdateTimestamp()
|
||||
{
|
||||
this->timestamp = Anope::CurTime;
|
||||
}
|
||||
|
||||
Type *Serialize::Type::Find(const Anope::string &name)
|
||||
Serialize::Type *Serialize::Type::Find(const Anope::string &name)
|
||||
{
|
||||
auto it = Types.find(name);
|
||||
if (it != Types.end())
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
|
||||
VERSION_MAJOR=2
|
||||
VERSION_MINOR=1
|
||||
VERSION_PATCH=23
|
||||
VERSION_PATCH=24
|
||||
VERSION_EXTRA=""
|
||||
|
||||
Reference in New Issue
Block a user