mirror of
https://github.com/anope/anope.git
synced 2026-06-17 02:04:47 +02:00
Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b51c6453ae | |||
| 8a44b9c0ea | |||
| 0dd5430c94 | |||
| 046fa5c848 | |||
| 551f3504c8 | |||
| c11638db98 | |||
| 9ca69a7b49 | |||
| 459c7947ce | |||
| fad0a4a0e8 | |||
| 1630ccedb1 | |||
| 36d69b1e5c | |||
| 627b89ec7b | |||
| 9373677610 | |||
| bbb65ddc33 | |||
| 508bbe11e6 | |||
| 095ed3c8c8 | |||
| f3743cd37d | |||
| 0c155e0c05 | |||
| f362959834 | |||
| f5a85c69d2 | |||
| c8b3819767 | |||
| e6a1982922 | |||
| 40a1dc9536 | |||
| 70bf013ef0 | |||
| 18dfa62626 | |||
| d815906393 | |||
| 452e62c050 | |||
| 4916e1dbfc | |||
| fa7ed12aad | |||
| 94c20f3084 | |||
| 597d4a1aee | |||
| 1e95d0f536 | |||
| ad0b4d1aa0 | |||
| 74e9a9d2fe | |||
| d2aee394ea | |||
| 3e696fae0f | |||
| ce362854a3 | |||
| a883b616a1 | |||
| b421ba258e | |||
| 3691887297 | |||
| 75e2501500 | |||
| 1c6db37681 | |||
| 5c2fc1cedd | |||
| d891f2bcbd | |||
| 5eb13f4420 | |||
| bd9d3b0f7d | |||
| cbb41241d4 | |||
| b9acaa6d51 | |||
| 9d18fdf0f6 | |||
| d04a312d0d | |||
| 099f0ce43a | |||
| 07bd1bbec9 | |||
| aa0a687a58 | |||
| b89cc47642 | |||
| d87fa4d781 | |||
| 9351debd73 | |||
| 40d558ef21 | |||
| e1224ac486 | |||
| ddd33e65b4 | |||
| e4f88d44cd | |||
| 063b4a9918 | |||
| c6065ff0f3 | |||
| a5aae4f41d | |||
| d019da673d | |||
| 4d7adbf2b7 | |||
| 404bf77ef5 | |||
| 69393a5f14 | |||
| 97c63822fc | |||
| 698dd78ef8 | |||
| 0b36ddfaf3 | |||
| 947ddc9e1b | |||
| 59d516d5b0 | |||
| 2ecb667d1c | |||
| c21f6ac597 | |||
| 390d0482fc | |||
| 65bb0a374b | |||
| ea4877dc16 | |||
| 4024598bd8 | |||
| a154532e98 | |||
| 665b0fdef8 | |||
| 0802d9d3ff | |||
| 8d3b8c08b3 | |||
| f3e5ccf353 | |||
| b5213d5a81 | |||
| dc09408f1a | |||
| 49d86527ef | |||
| 65183c3c49 | |||
| c60477384c | |||
| 25c3fd51b7 | |||
| a40eaeb2a3 | |||
| e14a650cb9 | |||
| 6401e328bb | |||
| 43dc6f7509 | |||
| 8f0ee6f383 | |||
| 1adbce61cb | |||
| fe60c9a085 | |||
| 39bb5825ad | |||
| 602ff60e21 | |||
| 8d0399e356 | |||
| a4d0213bcb | |||
| ecbf53ba6c | |||
| 6d72fd67d8 | |||
| 0a11bc7693 | |||
| e86fa67e38 | |||
| 1fc2642034 | |||
| 1641f6415a | |||
| bb1f93f150 | |||
| 85fbc500d8 | |||
| 99bcc6d3b7 | |||
| 5fd2145821 | |||
| 4700d48b35 | |||
| 019b2aafef | |||
| 3744649320 | |||
| 30593321f4 | |||
| 3b35199a53 | |||
| 5ac5e1068e | |||
| 0ebc43f0dc | |||
| 5ff86ea2c5 | |||
| 1bdc9c0a64 | |||
| d0d46408bc | |||
| fdc33b0f6d | |||
| 6a43370e13 | |||
| 1fcd045aff | |||
| b4d068b01a | |||
| 23d548336a | |||
| 82371dc279 | |||
| fd6770373f | |||
| 645f969d70 | |||
| 3187233783 | |||
| 8b932dc459 | |||
| a357ba38fb | |||
| 9f8525e3b2 | |||
| ace82596d8 | |||
| 09e10d2a02 | |||
| 9ec3f6abd6 | |||
| e7b18609f6 | |||
| cdcf0e2f9a | |||
| 718f2e922a | |||
| 2b2b6f75a1 | |||
| 883367c1d2 | |||
| 2276c62ff0 | |||
| fb0ee27df0 | |||
| b14befc77c | |||
| 64fd5a862a | |||
| 0ff170c671 | |||
| ea0d5c4d70 | |||
| b96dbfc9ba | |||
| e221c7642a | |||
| b8c28419da | |||
| 1c4f9042e7 | |||
| a3f483ad87 | |||
| 6e90a8ea55 | |||
| 6d7fe69cdf | |||
| 314ef60900 | |||
| 1e8ac58bb4 | |||
| badcf31499 | |||
| c98602bf19 | |||
| 50bec959e5 | |||
| 62bfa33464 | |||
| b4ab7dadb9 | |||
| df0cd3ef3e | |||
| 9e37a643f1 | |||
| b30bfb5d2b | |||
| cccdf0431b | |||
| 0005ebbbc3 | |||
| 161841925d | |||
| e099180d8f | |||
| 2091dc68bc | |||
| 9926ac5a05 | |||
| 14342f6375 | |||
| a0a9d433dc | |||
| c88fac1a20 | |||
| 64d26f7c61 | |||
| 34896cefe9 | |||
| c0c7046a6d | |||
| 937ea7dab4 | |||
| bfd2b0fa8e | |||
| 7f2c281121 | |||
| 224caf32c7 | |||
| 5828cdba45 | |||
| 4526fbed96 | |||
| f9911dde52 | |||
| a5e5eb5eb0 | |||
| 82aecd6c7e | |||
| b448a20f40 |
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Thanks for taking the time to fill out this bug report! Please make sure to answer the questions properly and don't just enter the same text into every field as this will make it harder for us to fix your bug.
|
||||
|
||||
If you're looking for help with setting up your services please post on [our support forum](https://github.com/orgs/anope/discussions/categories/support) instead.
|
||||
|
||||
|
||||
@@ -24,3 +24,16 @@ I have tested this pull request on:
|
||||
|
||||
**Operating system name and version:** <!-- e.g. Linux 3.11 -->
|
||||
**Compiler name and version:** <!-- e.g. GCC 4.2.0 -->
|
||||
|
||||
## Checks
|
||||
|
||||
<!--
|
||||
Tick the boxes for the checks you have made.
|
||||
-->
|
||||
|
||||
I have ensured that:
|
||||
|
||||
- [ ] The code I am submitting is my own work and/or I have permission from the author to share it.
|
||||
- [ ] Generative AI (Copilot, ChatGPT, etc) was not used to create any part of this pull request.
|
||||
- [ ] I have documented any features added by this pull request.
|
||||
- [ ] This pull request does not introduce any incompatible API changes (stable branches only, delete if not applicable).
|
||||
|
||||
@@ -10,10 +10,18 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
if: "!contains(github.event.head_commit.message, '[skip windows ci]')"
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2025
|
||||
env:
|
||||
BUILD_TYPE: ${{ github.event_name == 'release' && 'Release' || 'Debug' }}
|
||||
CONAN_USER_HOME: ${{ github.workspace }}/win/build
|
||||
CONAN_USER_HOME_SHORT: None
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup NSIS
|
||||
run: |-
|
||||
choco install nsis
|
||||
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
@@ -22,20 +30,34 @@ jobs:
|
||||
with:
|
||||
version: 1.64.0
|
||||
|
||||
- name: Try to restore libraries from the cache
|
||||
uses: actions/cache/restore@v4
|
||||
id: library-cache
|
||||
with:
|
||||
key: conan-${{ hashFiles('src/win32/conanfile.txt') }}
|
||||
path: ${{ env.CONAN_USER_HOME }}/.conan
|
||||
|
||||
- name: Install libraries
|
||||
run: |
|
||||
conan install ${{ github.workspace }}\src\win32 --build=missing
|
||||
|
||||
- name: Save libraries to the cache
|
||||
if: ${{ steps.library-cache.outputs.cache-hit != 'true' }}
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
key: ${{ steps.library-cache.outputs.cache-primary-key }}
|
||||
path: ${{ env.CONAN_USER_HOME }}/.conan
|
||||
|
||||
- name: Run CMake
|
||||
run: |
|
||||
mkdir ${{ github.workspace }}\build
|
||||
cd ${{ github.workspace }}\build
|
||||
cmake -A "x64" -D "CMAKE_BUILD_TYPE=${{ github.event_name == 'release' && 'Release' || 'Debug' }}" -G "Visual Studio 16 2019" ..
|
||||
cmake -A x64 -D "CMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}" -G "Visual Studio 17 2022" ..
|
||||
|
||||
- name: Build Anope
|
||||
working-directory: ${{ github.workspace }}\build
|
||||
run: |
|
||||
msbuild PACKAGE.vcxproj /M:3 /P:Configuration=${{ github.event_name == 'release' && 'Release' || 'Debug' }} /P:Platform=x64 /VERBOSITY:MINIMAL
|
||||
msbuild PACKAGE.vcxproj /M:5 /P:Configuration=${{ env.BUILD_TYPE }} /P:Platform=x64 /VERBOSITY:MINIMAL
|
||||
|
||||
- name: Upload installer
|
||||
if: "${{ github.event_name == 'release' }}"
|
||||
|
||||
@@ -12,39 +12,49 @@ Charles Kingsley <chaz@anope.org>
|
||||
Charles Kingsley <chaz@anope.org> <sjaz@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Cronus <cronus@nite-serv.com>
|
||||
Daniel Engel <dane@zero.org> <dane dane@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
David Robson <rob@anope.org> <robbeh@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
David Robson <rob@anope.org> <rob rob@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
David Robson <rob@anope.org> <robbeh@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Dennis Friis <peavey@inspircd.org> <peavey peavey@inspircd.org@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Dragone2 <dragone2@risposteinformatiche.it> <davide.paolini8@gmail.com>
|
||||
Fabio Scotoni <cculex@gmail.com>
|
||||
Filippo Cortigiani <simos@simosnap.org> <devel@devel.crtnet.it>
|
||||
Filippo Cortigiani <simos@simosnap.org> <simos@H7-25.fritz.box>
|
||||
Florian Schulze <certus@anope.org> <certus certus@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Gabriel Acevedo H. <drstein@anope.org> <drstein drstein@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Harakiri <harakiri@overstack.fr>
|
||||
Hendrik Jäger <gitcommit@henk.geekmail.org> <github@henk.geekmail.org>
|
||||
Jan Milants <viper@anope.org>
|
||||
Jan Milants <viper@anope.org> <jantje_85@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Jan Milants <viper@anope.org> <viper viper@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Jens Voss <dukepyrolator@anope.org> <anope@s15355730.onlinehome-server.info>
|
||||
Jens Voss <dukepyrolator@anope.org> <DukePyrolator@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Jens Voss <dukepyrolator@anope.org> <DukePyrolator@anope.org>
|
||||
Jens Voss <dukepyrolator@anope.org> Jens Voß <jens@pyrobook.(none)>
|
||||
Jens Voss <dukepyrolator@anope.org> <jens@pyrobook.(none)>
|
||||
k4be <k4be@pirc.pl> <34816207+k4bek4be@users.noreply.github.com>
|
||||
Lee Holmes <lethality@anope.org>
|
||||
Lee Holmes <lethality@anope.org> <lee@lethality.me.uk>
|
||||
Mark Summers <mark@goopler.net> <mark mark@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Matt Schatz <genius3000@g3k.solutions>
|
||||
Matt Ullman <matt@airraidsirens.com> <blindsight@gamesurge.net>
|
||||
Michael Hazell <michaelhazell@hotmail.com> <Techman-@users.noreply.github.com>
|
||||
Michael Stapelberg <michael@robustirc.net> <stapelberg@users.noreply.github.com>
|
||||
Michael Wobst <wobst.michael@web.de>
|
||||
Michael Wobst <wobst.michael@web.de> <michael@static.163.129.251.148.clients.your-server.de>
|
||||
Michael Wobst <wobst.michael@web.de> <michael@wobst.at>
|
||||
Naram Qashat <cyberbotx@anope.org> <cyberbotx@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Naram Qashat <cyberbotx@anope.org> <cyberbotx@cyberbotx.com>
|
||||
Naram Qashat <cyberbotx@anope.org> <Naram Qashat cyberbotx@cyberbotx.com@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
PeGaSuS <droider.pc@gmail.com>
|
||||
PeGaSuS <droider.pc@gmail.com> <25697531+TehPeGaSuS@users.noreply.github.com>
|
||||
Pieter Bootsma <geniusdex@anope.org> <geniusdex geniusdex@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Robby <robby@chatbelgie.be> <robby@anope.org>
|
||||
Robby <robby@chatbelgie.be> <robby@chat.be>
|
||||
Robert Scheck <robert@fedoraproject.org> <robert-scheck@users.noreply.github.com>
|
||||
Robin Burchell <w00t@inspircd.org> <rburchell@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Robin Burchell <w00t@inspircd.org> <Robin Burchell w00t@inspircd.org@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Sadie Powell <sadie@witchery.services> Peter Powell <petpow@saberuk.com>
|
||||
Sadie Powell <sadie@witchery.services> <petpow@saberuk.com>
|
||||
Sebastian Barfurth <github@afreshmelon.com>
|
||||
Sebastian V. <hal9000@denorastats.org>
|
||||
Sebastian V. <hal9000@denorastats.org> <pimpmylinux@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Trystan S. Lee <trystan@nomadirc.net> <trystan trystan@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Val Lorentz <progval+git@progval.net> <progval+git@progval.net>
|
||||
|
||||
+10
-15
@@ -1,5 +1,5 @@
|
||||
# This usage of CMake requires at least version 3.8
|
||||
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
|
||||
# This usage of CMake requires at least version 3.20
|
||||
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
|
||||
|
||||
# Set the project as C++ primarily, but have C enabled for the checks required later
|
||||
project(Anope CXX)
|
||||
@@ -142,11 +142,6 @@ include_directories(
|
||||
${Anope_SOURCE_DIR}/vendor
|
||||
)
|
||||
|
||||
# Pass on REPRODUCIBLE_BUILD
|
||||
if(REPRODUCIBLE_BUILD)
|
||||
add_definitions(-DREPRODUCIBLE_BUILD)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# If using Windows, include the windows specific folder for anope_windows.h
|
||||
include_directories(${Anope_SOURCE_DIR}/src/win32)
|
||||
@@ -321,14 +316,6 @@ if(${Anope_SOURCE_DIR} STREQUAL ${Anope_BINARY_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Go into the following directories and run their CMakeLists.txt as well
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(docs)
|
||||
add_subdirectory(language)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(modules)
|
||||
add_subdirectory(include)
|
||||
|
||||
# Get the filename of the Anope binary, to use later
|
||||
set(SERVICES_BINARY "$<TARGET_FILE:${PROGRAM_NAME}>")
|
||||
get_filename_component(SERVICES_BINARY ${SERVICES_BINARY} NAME)
|
||||
@@ -401,3 +388,11 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
|
||||
set(CPACK_MONOLITHIC_INSTALL TRUE)
|
||||
include(CPack)
|
||||
endif()
|
||||
|
||||
# Go into the following directories and run their CMakeLists.txt as well
|
||||
add_subdirectory(data)
|
||||
add_subdirectory(docs)
|
||||
add_subdirectory(language)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(modules)
|
||||
add_subdirectory(include)
|
||||
|
||||
@@ -113,6 +113,7 @@ while [ $# -ge 1 ] ; do
|
||||
exit 0
|
||||
elif [ $1 = "-devel" ] ; then
|
||||
DEBUG="yes"
|
||||
DEVEL="yes"
|
||||
INSTDIR="$SOURCE_DIR/run"
|
||||
elif [ $1 = "-nocache" ] ; then
|
||||
IGNORE_CACHE="1"
|
||||
@@ -138,7 +139,7 @@ done
|
||||
cmake --version 2>&1 > /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
clear
|
||||
echo "Anope requires CMake 3.8 or newer, which can be downloaded at https://cmake.org/ or through your system's package manager."
|
||||
echo "Anope requires CMake 3.20 or newer, which can be downloaded at https://cmake.org/ or through your system's package manager."
|
||||
echo "If you have installed CMake already, ensure it is in your PATH environment variable."
|
||||
exit 0
|
||||
fi
|
||||
@@ -171,6 +172,33 @@ export ok INPUT
|
||||
|
||||
####
|
||||
|
||||
TEMP_YN="n"
|
||||
if [ "$DEVEL" = "yes" ] ; then
|
||||
TEMP_YN="y"
|
||||
fi
|
||||
echo "You are building the 2.1 development branch. This branch is not as well tested"
|
||||
echo "as the 2.0 stable branch and may have compatibility breaks without notice. Are"
|
||||
echo "you sure you want to use this version?"
|
||||
echo -n "[$TEMP_YN] "
|
||||
read YN
|
||||
if [ "$YN" ] ; then
|
||||
if [ "$YN" = "y" ] ; then
|
||||
DEVEL="yes"
|
||||
else
|
||||
DEVEL="no"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if [ "$DEVEL" != "yes" ] ; then
|
||||
echo "If you are building from Git you can run \`git checkout 2.0\` to get the latest"
|
||||
echo "stable code. Otherwise, you can download the latest 2.0 release tarball from"
|
||||
echo "https://github.com/anope/anope/releases/latest"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
####
|
||||
|
||||
ok=0
|
||||
echo "In what directory should Anope be installed?"
|
||||
while [ $ok -eq 0 ] ; do
|
||||
@@ -337,6 +365,7 @@ INSTDIR="$INSTDIR"
|
||||
RUNGROUP="$RUNGROUP"
|
||||
UMASK=$UMASK
|
||||
DEBUG="$DEBUG"
|
||||
DEVEL="$DEVEL"
|
||||
EXTRA_INCLUDE_DIRS="$EXTRA_INCLUDE_DIRS"
|
||||
EXTRA_LIB_DIRS="$EXTRA_LIB_DIRS"
|
||||
EXTRA_CONFIG_ARGS="$EXTRA_CONFIG_ARGS"
|
||||
|
||||
+126
-42
@@ -79,13 +79,16 @@
|
||||
/*
|
||||
* [OPTIONAL] Defines
|
||||
*
|
||||
* You can define values to other values, which can be used to easily change
|
||||
* many values in the configuration at once.
|
||||
* You can use defines for repeated information, which can be used to easily change many
|
||||
* values in the configuration at once.
|
||||
*
|
||||
* To use a define called foo.bar you use ${foo.bar} in your config file. You can also use
|
||||
* environment variables by prefixing their name with "env." like ${env.USER}.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for services clients hostnames.
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
*/
|
||||
define
|
||||
{
|
||||
@@ -211,7 +214,7 @@ serverinfo
|
||||
* other server names on the rest of your IRC network. Note that it does not have
|
||||
* to be an existing hostname, just one that isn't on your network already.
|
||||
*/
|
||||
name = "services.example.com"
|
||||
name = "${services.host}"
|
||||
|
||||
/*
|
||||
* The text which should appear as the server's information in /WHOIS and similar
|
||||
@@ -328,7 +331,7 @@ networkinfo
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
vhost_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-"
|
||||
vhost_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-/"
|
||||
|
||||
/*
|
||||
* If set to true, allows vHosts to not contain dots (.).
|
||||
@@ -476,6 +479,26 @@ options
|
||||
*/
|
||||
didyoumeandifference = 4
|
||||
|
||||
/*
|
||||
* The length of codes used for confirming actions like dropping a channel or a
|
||||
* nickname.
|
||||
*
|
||||
* Defaults to 15 if not set.
|
||||
*/
|
||||
codelength = 15
|
||||
|
||||
/*
|
||||
* If set, the maximum number of bytes after which to wrap services messages. This
|
||||
* can be set a bit higher than the default but should be well under the maximum
|
||||
* message length imposed by your IRC server or messages will end up truncated.
|
||||
*
|
||||
* NOTE: this currently only applies to tables but will be expanded to all messages
|
||||
* in a later release.
|
||||
*
|
||||
* Defaults to 100 if not set.
|
||||
*/
|
||||
linelength = 100
|
||||
|
||||
/* The regex engine to use, as provided by the regex modules.
|
||||
* Leave commented to disable regex matching.
|
||||
*
|
||||
@@ -746,8 +769,8 @@ log
|
||||
* nickserv/getemail nickserv/suspend nickserv/ajoin nickserv/list
|
||||
*
|
||||
* nickserv/saset/autoop nickserv/saset/display nickserv/saset/email nickserv/saset/greet
|
||||
* nickserv/saset/kill nickserv/saset/keepmodes nickserv/saset/language nickserv/saset/message
|
||||
* nickserv/saset/neverop nickserv/saset/noexpire nickserv/saset/password nickserv/saset/private
|
||||
* nickserv/saset/keepmodes nickserv/saset/language nickserv/saset/message nickserv/saset/neverop
|
||||
* nickserv/saset/noexpire nickserv/saset/password nickserv/saset/private nickserv/saset/protect
|
||||
* nickserv/saset/url
|
||||
*
|
||||
* hostserv/set hostserv/del hostserv/list
|
||||
@@ -852,6 +875,16 @@ opertype
|
||||
/* An optional password. If defined, the user must login using "/OPERSERV LOGIN" first */
|
||||
#password = "secret"
|
||||
|
||||
/*
|
||||
* The algorithm which the above password is hashed with. If this is not set then services will
|
||||
* assume the above password is not hashed.
|
||||
*
|
||||
* You will need to have the appropriate encryption module (e.g. enc_bcrypt) loaded in order
|
||||
* for this to work.
|
||||
*
|
||||
*/
|
||||
#password_hash = "bcrypt"
|
||||
|
||||
/* An optional SSL fingerprint. If defined, it's required to be able to use this opertype. */
|
||||
#certfp = "ed3383b3f7d74e89433ddaa4a6e5b2d7"
|
||||
|
||||
@@ -952,76 +985,76 @@ mail
|
||||
* The subject and message of emails sent to users when they register accounts.
|
||||
*
|
||||
* Available tokens for this template are:
|
||||
* %n - Gets replaced with the nickname
|
||||
* %N - Gets replaced with the network name
|
||||
* %c - Gets replaced with the confirmation code
|
||||
* {nick} - Gets replaced with the nickname
|
||||
* {network} - Gets replaced with the network name
|
||||
* {code} - Gets replaced with the confirmation code
|
||||
*/
|
||||
registration_subject = "Nickname registration for %n"
|
||||
registration_subject = "Nickname registration for {nick}"
|
||||
registration_message = "Hi,
|
||||
|
||||
You have requested to register the nickname %n on %N.
|
||||
Please type \" /msg NickServ CONFIRM %c \" to complete registration.
|
||||
You have requested to register the nickname {nick} on {network}.
|
||||
Please type \" /msg NickServ CONFIRM {code} \" to complete registration.
|
||||
|
||||
If you don't know why this mail was sent to you, please ignore it silently.
|
||||
|
||||
%N administrators."
|
||||
{network} administrators."
|
||||
|
||||
/*
|
||||
* The subject and message of emails sent to users when they request a new password.
|
||||
*
|
||||
* Available tokens for this template are:
|
||||
* %n - Gets replaced with the nickname
|
||||
* %N - Gets replaced with the network name
|
||||
* %c - Gets replaced with the confirmation code
|
||||
* {nick} - Gets replaced with the nickname
|
||||
* {network} - Gets replaced with the network name
|
||||
* {code} - Gets replaced with the confirmation code
|
||||
*/
|
||||
reset_subject = "Reset password request for %n"
|
||||
reset_subject = "Reset password request for {nick}"
|
||||
reset_message = "Hi,
|
||||
|
||||
You have requested to have the password for %n reset.
|
||||
To reset your password, type \" /msg NickServ CONFIRM %n %c \"
|
||||
You have requested to have the password for {nick} reset.
|
||||
To reset your password, type \" /msg NickServ CONFIRM {nick} {code} \"
|
||||
|
||||
If you don't know why this mail was sent to you, please ignore it silently.
|
||||
|
||||
%N administrators."
|
||||
{network} administrators."
|
||||
|
||||
/*
|
||||
* The subject and message of emails sent to users when they request a new email address.
|
||||
*
|
||||
* Available tokens for this template are:
|
||||
* %e - Gets replaced with the old email address
|
||||
* %E - Gets replaced with the new email address
|
||||
* %n - Gets replaced with the nickname
|
||||
* %N - Gets replaced with the network name
|
||||
* %c - Gets replaced with the confirmation code
|
||||
* {old_email} - Gets replaced with the old email address
|
||||
* {new_email} - Gets replaced with the new email address
|
||||
* {account} - Gets replaced with the nickname
|
||||
* {network} - Gets replaced with the network name
|
||||
* {code} - Gets replaced with the confirmation code
|
||||
*/
|
||||
emailchange_subject = "Email confirmation"
|
||||
emailchange_message = "Hi,
|
||||
|
||||
You have requested to change your email address from %e to %E.
|
||||
Please type \" /msg NickServ CONFIRM %c \" to confirm this change.
|
||||
You have requested to change your email address from {old_email} to {new_email}.
|
||||
Please type \" /msg NickServ CONFIRM {code} \" to confirm this change.
|
||||
|
||||
If you don't know why this mail was sent to you, please ignore it silently.
|
||||
|
||||
%N administrators."
|
||||
{network} administrators."
|
||||
|
||||
/*
|
||||
* The subject and message of emails sent to users when they receive a new memo.
|
||||
*
|
||||
* Available tokens for this template are:
|
||||
* %n - Gets replaced with the nickname
|
||||
* %s - Gets replaced with the sender's nickname
|
||||
* %d - Gets replaced with the memo number
|
||||
* %t - Gets replaced with the memo text
|
||||
* %N - Gets replaced with the network name
|
||||
* {receiver} - Gets replaced with the receiver's nickname
|
||||
* {sender} - Gets replaced with the sender's nickname
|
||||
* {number} - Gets replaced with the memo number
|
||||
* {text} - Gets replaced with the memo text
|
||||
* {network} - Gets replaced with the network name
|
||||
*/
|
||||
memo_subject = "New memo"
|
||||
memo_message = "Hi %n,
|
||||
memo_message = "Hi {receiver},
|
||||
|
||||
You've just received a new memo from %s. This is memo number %d.
|
||||
You've just received a new memo from {sender}. This is memo number {number}.
|
||||
|
||||
Memo text:
|
||||
|
||||
%t"
|
||||
{text}"
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1087,11 +1120,9 @@ module
|
||||
* Sets the number of days backups of databases are kept. If you don't give it,
|
||||
* or if you set it to 0, Anope won't backup the databases.
|
||||
*
|
||||
* NOTE: Anope must run 24 hours a day for this feature to work.
|
||||
*
|
||||
* This directive is optional, but recommended.
|
||||
*/
|
||||
keepbackups = 3
|
||||
keepbackups = 7
|
||||
|
||||
/*
|
||||
* Allows Anope to continue file write operations (i.e. database saving)
|
||||
@@ -1116,6 +1147,59 @@ module
|
||||
fork = no
|
||||
}
|
||||
|
||||
/*
|
||||
* db_json
|
||||
*
|
||||
* Stores your data in a JSON file. This is currently experimental and has not
|
||||
* been fully tested so make sure you have db_flatfile loaded as a secondary
|
||||
* database module if you use this.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_json"
|
||||
|
||||
/*
|
||||
* The file that db_json will write your main database to.
|
||||
*
|
||||
* This is relative to your data directory.
|
||||
*/
|
||||
database = "anope.json"
|
||||
|
||||
/*
|
||||
* The file that db_json will write third-party databases to.
|
||||
*
|
||||
* {name} will be replaced with the name of the module.
|
||||
*
|
||||
* This is relative to your data directory.
|
||||
*/
|
||||
module_database = "{name}.module.json"
|
||||
|
||||
/*
|
||||
* Sets how many days and months worth of backups should be kept.
|
||||
*
|
||||
* It is recommended that at the very least you keep one backup. Failure to
|
||||
* do so may result in total data loss if you ever run out of disk space or
|
||||
* have a power failure during a database write. However, if you're *REALLY*
|
||||
* sure this won't happen you can disable backups by setting these to 0.
|
||||
*/
|
||||
daily_backups = 7
|
||||
monthly_backups = 3
|
||||
|
||||
/*
|
||||
* The directory in which backups are kept.
|
||||
*
|
||||
* This is relative to your data directory.
|
||||
*/
|
||||
backup_directory = "backups"
|
||||
|
||||
/*
|
||||
* Allows Anope to continue writing the database even if the original can
|
||||
* not be backed up. This is not recommended as it may result in total data
|
||||
* loss during the circumstances described above.
|
||||
*/
|
||||
#ignore_backup_failure = yes
|
||||
}
|
||||
|
||||
/*
|
||||
* db_sql and db_sql_live
|
||||
*
|
||||
@@ -1207,9 +1291,9 @@ module
|
||||
name = "enc_sha2"
|
||||
|
||||
/** The sub-algorithm to use. Can be set to sha224 for SHA-224, sha256 for
|
||||
* SHA-256, sha284 for SHA-384, or sha512 for SHA-512. Defaults to sha256.
|
||||
* SHA-256, sha384 for SHA-384, or sha512 for SHA-512. Defaults to sha512.
|
||||
*/
|
||||
#algorithm = "sha256"
|
||||
#algorithm = "sha512"
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -31,7 +31,7 @@ service
|
||||
/*
|
||||
* The hostname of the BotServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the BotServ client.
|
||||
@@ -410,6 +410,7 @@ fantasy { name = "SUSPEND"; command = "chanserv/suspend"; permission = "chanserv
|
||||
fantasy { name = "SYNC"; command = "chanserv/sync"; }
|
||||
fantasy { name = "TOPIC"; command = "chanserv/topic"; }
|
||||
fantasy { name = "UNBAN"; command = "chanserv/unban"; }
|
||||
fantasy { name = "UNMUTE"; command = "chanserv/unban"; mode = "QUIET"; }
|
||||
fantasy { name = "UNSUSPEND"; command = "chanserv/unsuspend"; permission = "chanserv/suspend"; }
|
||||
fantasy { name = "UP"; command = "chanserv/up"; }
|
||||
fantasy { name = "VOICE"; command = "chanserv/modes"; }
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the ChanServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the ChanServ client.
|
||||
@@ -102,10 +102,10 @@ module
|
||||
* to be a registered nick, otherwise the channel will be dropped.
|
||||
* - none: No defaults
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to keeptopic, peace,
|
||||
* securefounder, and signkick. If you really want no defaults, use "none" by itself as the option.
|
||||
* This directive is optional, if left blank, the options will default to cs_keep_modes, keeptopic, peace,
|
||||
* persist, securefounder, and signkick. If you really want no defaults, use "none" by itself as the option.
|
||||
*/
|
||||
defaults = "keeptopic peace securefounder signkick"
|
||||
defaults = "cs_keep_modes keeptopic peace persist securefounder signkick"
|
||||
|
||||
/*
|
||||
* The maximum number of channels which may be registered to a single nickname.
|
||||
@@ -163,10 +163,10 @@ module
|
||||
|
||||
/*
|
||||
* The message formatting to use for signed kick messages.
|
||||
* %n is the nick of the kicker
|
||||
* %m is the message specified
|
||||
* {nick} is the nick of the kicker
|
||||
* {message} is the message specified
|
||||
*/
|
||||
signkickformat = "%m (%n)"
|
||||
signkickformat = "{message} ({nick})"
|
||||
|
||||
/*
|
||||
* If set, prevents channel access entries from containing hostmasks.
|
||||
@@ -1182,7 +1182,7 @@ module
|
||||
simple = false
|
||||
|
||||
/* Sets the time to keep seen entries in the seen database. */
|
||||
purgetime = "30d"
|
||||
purgetime = 90d
|
||||
}
|
||||
command { service = "OperServ"; name = "SEEN"; command = "operserv/seen"; permission = "operserv/seen"; }
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the Global client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the Global client.
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the HostServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the HostServ client.
|
||||
|
||||
@@ -18,7 +18,7 @@ service
|
||||
/*
|
||||
* The hostname of the StatServ client.
|
||||
*/
|
||||
host = "stats.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the StatServ client.
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the MemoServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the MemoServ client.
|
||||
|
||||
+65
-29
@@ -119,15 +119,15 @@ module { name = "help" }
|
||||
time = 4h
|
||||
|
||||
/* Reason for akill.
|
||||
* %n is the nick of the user
|
||||
* %u is the ident/username of the user
|
||||
* %g is the realname of the user
|
||||
* %h is the hostname of the user
|
||||
* %i is the IP of the user
|
||||
* %r is the reply reason (configured below). Will be nothing if not configured.
|
||||
* %N is the network name set in networkinfo:networkname
|
||||
* {nick} is the nick of the user
|
||||
* {user} is the ident/username of the user
|
||||
* {real} is the realname of the user
|
||||
* {host} is the hostname of the user
|
||||
* {ip} is the IP of the user
|
||||
* {reply} is the reply reason (configured below). Will be nothing if not configured.
|
||||
* {network} is the network name set in networkinfo:networkname
|
||||
*/
|
||||
reason = "You are listed in the EFnet RBL, visit https://rbl.efnetrbl.org/?i=%i for info"
|
||||
reason = "You are listed in the EFnet RBL, visit https://rbl.efnetrbl.org/?i={ip} for info"
|
||||
|
||||
/* Replies to ban and their reason. If no replies are configured, all replies get banned. */
|
||||
reply
|
||||
@@ -171,7 +171,7 @@ module { name = "help" }
|
||||
{
|
||||
name = "dnsbl.dronebl.org"
|
||||
time = 4h
|
||||
reason = "You have a host listed in the DroneBL. For more information, visit https://dronebl.org/lookup_branded?ip=%i&network=%N"
|
||||
reason = "You have a host listed in the DroneBL. For more information, visit https://dronebl.org/lookup?ip={ip}&network={network}"
|
||||
}
|
||||
|
||||
/* Exempt localhost from DNSBL checks */
|
||||
@@ -270,10 +270,10 @@ module { name = "help" }
|
||||
|
||||
/*
|
||||
* The search filter used to look up users's accounts.
|
||||
* %account is replaced with the user's account.
|
||||
* %object_class is replaced with the object_class configured below.
|
||||
* {account} is replaced with the user's account.
|
||||
* {object_class} is replaced with the object_class configured below.
|
||||
*/
|
||||
search_filter = "(&(uid=%account)(objectClass=%object_class))"
|
||||
search_filter = "(&(uid={account})(objectClass={object_class}))"
|
||||
|
||||
/*
|
||||
* The object class used by LDAP to store user account information.
|
||||
@@ -327,7 +327,7 @@ module { name = "help" }
|
||||
|
||||
/*
|
||||
* An optional binddn to use when searching for groups.
|
||||
* %a is replaced with the account name of the user.
|
||||
* {account} is replaced with the account name of the user.
|
||||
*/
|
||||
#binddn = "cn=Manager,dc=anope,dc=org"
|
||||
|
||||
@@ -343,9 +343,9 @@ module { name = "help" }
|
||||
|
||||
/*
|
||||
* The filter to use when searching for users.
|
||||
* %a is replaced with the account name of the user.
|
||||
* {account} is replaced with the account name of the user.
|
||||
*/
|
||||
filter = "(member=uid=%a,ou=users,dc=anope,dc=org)"
|
||||
filter = "(member=uid={account},ou=users,dc=anope,dc=org)"
|
||||
|
||||
/*
|
||||
* The attribute of the group that is the name of the opertype.
|
||||
@@ -550,24 +550,14 @@ module
|
||||
|
||||
/*
|
||||
* The reason to ban the user for.
|
||||
* %h is replaced with the type of proxy found.
|
||||
* %i is replaced with the IP of proxy found.
|
||||
* %p is replaced with the port.
|
||||
* {type} is replaced with the type of proxy found.
|
||||
* {ip} is replaced with the IP of proxy found.
|
||||
* {port} is replaced with the port.
|
||||
*/
|
||||
reason = "You have an open proxy running on your host (%t:%i:%p)"
|
||||
reason = "You have an open proxy running on your host ({type}:{ip}:{port})"
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sasl
|
||||
*
|
||||
* Some IRCds allow "SASL" authentication to let users identify to services
|
||||
* during the IRCd user registration process. If this module is loaded, Anope will allow
|
||||
* authenticating users through this mechanism. Supported mechanisms are:
|
||||
* PLAIN, EXTERNAL.
|
||||
*/
|
||||
module { name = "sasl" }
|
||||
|
||||
/*
|
||||
* ssl_gnutls [EXTRA]
|
||||
*
|
||||
@@ -680,6 +670,23 @@ module { name = "sasl" }
|
||||
*/
|
||||
query = "SELECT `email_addr` AS `email` FROM `my_users` WHERE `username` = @a@ AND `password` = MD5(CONCAT('salt', @p@))"
|
||||
|
||||
/*
|
||||
* If your database uses a password hashing algorithm that can not be compared using a simple
|
||||
* comparison function then you can specify it here to compare locally.
|
||||
*
|
||||
* You will need to have the appropriate encryption module (e.g. enc_bcrypt) loaded in order
|
||||
* for this to work.
|
||||
*/
|
||||
#password_hash = "bcrypt"
|
||||
|
||||
/*
|
||||
* If using the password_hash field (above) you will need to specify the name of the field to
|
||||
* fetch the password from.
|
||||
*
|
||||
* Defaults to "password" if not set.
|
||||
*/
|
||||
#password_field = "password"
|
||||
|
||||
/*
|
||||
* If set, the reason to give the users who try to "/msg NickServ REGISTER".
|
||||
* If not set, then registration is not blocked.
|
||||
@@ -815,6 +822,20 @@ module { name = "sasl" }
|
||||
|
||||
/* Web service to use. Requires httpd. */
|
||||
server = "httpd/main"
|
||||
|
||||
/*
|
||||
* Whether to enable the use of XML-RPC extensions.
|
||||
*
|
||||
* By default Anope will use some extended XML-RPC types. If your XML-RPC
|
||||
* client can not handle these you will need to disable them.
|
||||
*
|
||||
* If i8 is disabled a string will be used for values outside of the range
|
||||
* supported by the 32-bit int data type.
|
||||
*
|
||||
* If nil is disabled an empty struct will be used instead.
|
||||
*/
|
||||
#enable_i8 = no
|
||||
#enable_nil = no
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -822,6 +843,7 @@ module { name = "sasl" }
|
||||
*
|
||||
* Adds support for the following RPC methods:
|
||||
*
|
||||
* anope.listAccounts anope.account
|
||||
* anope.listChannels anope.channel
|
||||
* anope.listOpers anope.oper
|
||||
* anope.listServers anope.server
|
||||
@@ -841,6 +863,20 @@ module { name = "sasl" }
|
||||
*/
|
||||
#module { name = "rpc_main" }
|
||||
|
||||
/*
|
||||
* rpc_message
|
||||
*
|
||||
* Adds support for the following RPC methods:
|
||||
*
|
||||
* anope.messageNetwork anope.messageServer
|
||||
* anope.messageUser
|
||||
*
|
||||
* Requires either the jsonrpc or xmlrpc module.
|
||||
*
|
||||
* See docs/RPC/rpc_message.md for API documentation.
|
||||
*/
|
||||
#module { name = "rpc_message" }
|
||||
|
||||
/*
|
||||
* rpc_system
|
||||
*
|
||||
|
||||
+60
-35
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the NickServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the NickServ client.
|
||||
@@ -93,7 +93,7 @@ module
|
||||
#confirmemailchanges = yes
|
||||
|
||||
/*
|
||||
* A message sent to users on connect if they use an unregistered nick. %n will be replaced with the user's nickname.
|
||||
* A message sent to users on connect if they use an unregistered nick. {nick} will be replaced with the user's nickname.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
@@ -105,11 +105,6 @@ module
|
||||
* by spaces.
|
||||
*
|
||||
* The options are:
|
||||
* - killprotect: Kill nick if not identified within 60 seconds
|
||||
* - kill_quick: Kill nick if not identified within 20 seconds, this one overrides the killprotect
|
||||
* option and the killprotect option must be specified with this one
|
||||
* - kill_immed: Kill nick immediately if not identified, this one overrides both the killprotect
|
||||
* and kill_quick options and the killprotect option must be specified with this one
|
||||
* - ns_private: Hide the nick from NickServ's LIST command
|
||||
* - hide_email: Hide the nick's email address from NickServ's INFO command
|
||||
* - hide_mask: Hide the nick's last or current user@host from NickServ's INFO command
|
||||
@@ -122,11 +117,12 @@ module
|
||||
* - neverop: User can not be added to access lists
|
||||
* - msg: Messages will be sent as PRIVMSGs instead of NOTICEs
|
||||
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
|
||||
* - protect: Protects the registered nickname from use by unidentified users.
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to memo_signon, and
|
||||
* memo_receive. If you really want no defaults, use "none" by itself as the option.
|
||||
*/
|
||||
defaults = "killprotect ns_private hide_email hide_mask memo_signon memo_receive autoop"
|
||||
defaults = "autoop hide_email hide_mask memo_receive memo_signon ns_private protect"
|
||||
|
||||
/*
|
||||
* The minimum length of time between consecutive uses of NickServ's REGISTER command. This
|
||||
@@ -171,11 +167,25 @@ module
|
||||
hidenetsplitquit = no
|
||||
|
||||
/*
|
||||
* If set, is the length of time NickServ's killquick and kill options wait before
|
||||
* forcing users off of protected nicknames.
|
||||
* The default period to force users to stop using a protected nickname after.
|
||||
*
|
||||
* Defaults to 1 minute.
|
||||
*/
|
||||
killquick = 20s
|
||||
kill = 60s
|
||||
defaultprotect = 1m
|
||||
|
||||
/*
|
||||
* The minimum period that a user can have a user forced off their protected nickname after.
|
||||
*
|
||||
* Defaults to 10 seconds.
|
||||
*/
|
||||
minprotect = 10s
|
||||
|
||||
/*
|
||||
* The maximum period that a user can have a user forced off their protected nickname after.
|
||||
*
|
||||
* Defaults to 10 minutes.
|
||||
*/
|
||||
maxprotect = 10m
|
||||
|
||||
/*
|
||||
* If set, forbids the registration of nicks that contain an existing
|
||||
@@ -196,7 +206,7 @@ module
|
||||
* hold a nickname.
|
||||
*/
|
||||
enforceruser = "enforcer"
|
||||
enforcerhost = "services.host"
|
||||
enforcerhost = "${services.host}"
|
||||
|
||||
/*
|
||||
* The length of time Anope should hold nicknames for.
|
||||
@@ -519,6 +529,27 @@ command { service = "NickServ"; name = "RESEND"; command = "nickserv/resend"; }
|
||||
module { name = "ns_resetpass" }
|
||||
command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpass"; }
|
||||
|
||||
/*
|
||||
* ns_sasl
|
||||
*
|
||||
* Provides support for authentication to services via IRCv3 SASL. This is a standardised
|
||||
* alternative to ns_identify that is supported by several IRCds.
|
||||
*
|
||||
* You will need to configure your IRCd to use SASL. See the following links for details:
|
||||
*
|
||||
* InspIRCd: https://docs.inspircd.org/4/modules/sasl/
|
||||
* UnrealIRCd: https://www.unrealircd.org/docs/SASL#Enabling_SASL_on_the_server
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "ns_sasl"
|
||||
|
||||
/*
|
||||
* The nick of the client which operates as the SASL agent.
|
||||
*/
|
||||
#agent = "NickServ"
|
||||
}
|
||||
|
||||
/*
|
||||
* ns_set
|
||||
*
|
||||
@@ -575,28 +606,6 @@ module
|
||||
command { service = "NickServ"; name = "SET KEEPMODES"; command = "nickserv/set/keepmodes"; }
|
||||
command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/saset/keepmodes"; permission = "nickserv/saset/keepmodes"; }
|
||||
|
||||
/*
|
||||
* ns_set_kill
|
||||
*
|
||||
* Provides the commands nickserv/set/kill and kickserv/saset/kill.
|
||||
*
|
||||
* Used for configuring nickname protection.
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "ns_set_kill"
|
||||
|
||||
/*
|
||||
* Allow the use of the IMMED option in the NickServ SET KILL command.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
#allowkillimmed = yes
|
||||
}
|
||||
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
|
||||
|
||||
/*
|
||||
* ns_set_language
|
||||
*
|
||||
@@ -641,6 +650,22 @@ command { service = "NickServ"; name = "SASET URL"; command = "nickserv/saset/mi
|
||||
#command { service = "NickServ"; name = "SET TIMEZONE"; command = "nickserv/set/misc"; misc_description = _("Associate a time zone with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET TIMEZONE"; command = "nickserv/saset/misc"; misc_description = _("Associate a time zone with this account"); permission = "nickserv/saset/timezone"; group = "nickserv/admin"; }
|
||||
|
||||
/*
|
||||
* ns_set_protect
|
||||
*
|
||||
* Provides the commands nickserv/set/protect and kickserv/saset/protect.
|
||||
*
|
||||
* Used for configuring nickname protection.
|
||||
*/
|
||||
module { name = "ns_set_protect" }
|
||||
|
||||
command { service = "NickServ"; name = "SET PROTECT"; command = "nickserv/set/protect"; }
|
||||
command { service = "NickServ"; name = "SASET PROTECT"; command = "nickserv/saset/protect"; permission = "nickserv/saset/kill"; }
|
||||
|
||||
# For compatibility with Anope 2.0.
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/protect"; hide = true; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/protect"; permission = "nickserv/saset/protect"; hide = true; }
|
||||
|
||||
/*
|
||||
* ns_suspend
|
||||
*
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the OperServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the OperServ client.
|
||||
@@ -502,6 +502,13 @@ module
|
||||
* This directive is optional, if not set it will default to 3.
|
||||
*/
|
||||
#newscount = 3
|
||||
|
||||
/*
|
||||
* Whether to show the datetime at which the news entry was added.
|
||||
*
|
||||
* This directive is optional, if not set it will default to yes.
|
||||
*/
|
||||
#showdate = yes
|
||||
}
|
||||
command { service = "OperServ"; name = "LOGONNEWS"; command = "operserv/logonnews"; permission = "operserv/news"; }
|
||||
command { service = "OperServ"; name = "OPERNEWS"; command = "operserv/opernews"; permission = "operserv/news"; }
|
||||
@@ -580,7 +587,7 @@ module
|
||||
*
|
||||
* This directive is optional, if not set, nothing will be sent.
|
||||
*/
|
||||
sessionlimitexceeded = "The session limit for your IP %IP% has been exceeded."
|
||||
sessionlimitexceeded = "The session limit for your IP {ip} has been exceeded."
|
||||
|
||||
/*
|
||||
* Same as above, but should be used to provide a website address where users can find out more
|
||||
|
||||
@@ -79,17 +79,20 @@
|
||||
/*
|
||||
* [OPTIONAL] Defines
|
||||
*
|
||||
* You can define values to other values, which can be used to easily change
|
||||
* many values in the configuration at once.
|
||||
* You can use defines for repeated information, which can be used to easily change many
|
||||
* values in the configuration at once.
|
||||
*
|
||||
* To use a define called foo.bar you use ${foo.bar} in your config file. You can also use
|
||||
* environment variables by prefixing their name with "env." like ${env.USER}.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The stats.host define is used in multiple different locations throughout the
|
||||
* configuration for the stats client hostname.
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
*/
|
||||
define
|
||||
{
|
||||
name = "stats.host"
|
||||
name = "services.host"
|
||||
value = "stats.example.com"
|
||||
}
|
||||
|
||||
@@ -208,7 +211,7 @@ serverinfo
|
||||
* other server names on the rest of your IRC network. Note that it does not have
|
||||
* to be an existing hostname, just one that isn't on your network already.
|
||||
*/
|
||||
name = "stats.example.com"
|
||||
name = "${services.host}"
|
||||
|
||||
/*
|
||||
* The text which should appear as the server's information in /WHOIS and similar
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
Since the first commit in March 2004 88 people have submitted patches, commits,
|
||||
and other useful contributions to Anope. These people, ordered by the number of
|
||||
contributions they have made, are:
|
||||
|
||||
* Adam <adam@anope.org>
|
||||
* Sadie Powell <sadie@witchery.services>
|
||||
* Robin Burchell <w00t@inspircd.org>
|
||||
* Naram Qashat <cyberbotx@anope.org>
|
||||
* Pieter Bootsma <geniusdex@anope.org>
|
||||
* Jens Voss <dukepyrolator@anope.org>
|
||||
* David Robson <rob@anope.org>
|
||||
* Florian Schulze <certus@anope.org>
|
||||
* Daniel Engel <dane@zero.org>
|
||||
* Trystan S. Lee <trystan@nomadirc.net>
|
||||
* Robby <robby@chatbelgie.be>
|
||||
* Charles Kingsley <chaz@anope.org>
|
||||
* Lee Holmes <lethality@anope.org>
|
||||
* Gabriel Acevedo H. <drstein@anope.org>
|
||||
* Jan Milants <viper@anope.org>
|
||||
* Adam Kramer <ribosome@anope.org>
|
||||
* Attila Molnar <attilamolnar@hush.com>
|
||||
* Michael Wobst <wobst.michael@web.de>
|
||||
* Mark Summers <mark@goopler.net>
|
||||
* Matt Schatz <genius3000@g3k.solutions>
|
||||
* Daniel Vassdal <shutter@canternet.org>
|
||||
* MatthewM <mcm@they-got.us>
|
||||
* PeGaSuS <droider.pc@gmail.com>
|
||||
* Sebastian V. <hal9000@denorastats.org>
|
||||
* Alvaro Toledo <atoledo@keldon.org>
|
||||
* Dragone2 <dragone2@risposteinformatiche.it>
|
||||
* Björn Stiddien <keeper@anope.org>
|
||||
* n0kS Phr33d0m <god@politeia.in>
|
||||
* Hendrik Jäger <gitcommit@henk.geekmail.org>
|
||||
* k4be <k4be@pirc.pl>
|
||||
* Thomas Fargeix <t.fargeix@gmail.com>
|
||||
* Bram Matthys <syzop@vulnscan.org>
|
||||
* Federico G. Schwindt <fgsch@lodoss.net>
|
||||
* Val Lorentz <progval+git@progval.net>
|
||||
* Alexander Barton <alex@barton.de>
|
||||
* CaPa CuL <capacul@gmail.com>
|
||||
* Cronus <cronus@nite-serv.com>
|
||||
* H7-25 <simos@simosnap.org>
|
||||
* Jyzee <jyzee.git@gmail.com>
|
||||
* Sebastian Barfurth <github@afreshmelon.com>
|
||||
* Zantox <jyoerger10@msn.com>
|
||||
* Zoddo <zoddo.ino@gmail.com>
|
||||
* Dominic Hargreaves <dom@earth.li>
|
||||
* Michael Hazell <michaelhazell@hotmail.com>
|
||||
* Robert Scheck <robert@fedoraproject.org>
|
||||
* Dennis Friis <peavey@inspircd.org>
|
||||
* Filippo Cortigiani <simos@simosnap.org>
|
||||
* Michał Zegan <webczat_200@poczta.onet.pl>
|
||||
* AlphaTech <alphat3ch@icloud.com>
|
||||
* Austin Ellis <siniStar@IRC4Fun.net>
|
||||
* bonnedav <theD_2011@hotmail.com>
|
||||
* Denis M. (Phr33d0m) <god@politeia.in>
|
||||
* Harakiri <harakiri@overstack.fr>
|
||||
* Marcin Łabanowski <marcin@6irc.net>
|
||||
* Matt Ullman <matt@airraidsirens.com>
|
||||
* Michael Stapelberg <michael@robustirc.net>
|
||||
* Alexander Maassen <outsider@twingoversum.scarynet.org>
|
||||
* artemiiav <artemiiav@gmail.com>
|
||||
* blackbeard420 <blackbeard@blackbeard420.me>
|
||||
* BoGu5 <bogus@onzin.org>
|
||||
* Chris Langsenkamp <chris@langsenkamp.com>
|
||||
* Clem Morton
|
||||
* Daniel Oaks <danneh@danneh.net>
|
||||
* Fabio Scotoni <cculex@gmail.com>
|
||||
* ItsOnlyBinary
|
||||
* Jason Foster <retsofaj@gmail.com>
|
||||
* Jeremy <jeremy@ssnet.ca>
|
||||
* Josh Soref
|
||||
* KindOne <ineedalifetoday@live.com>
|
||||
* linuxdaemon
|
||||
* Mantas Mikulėnas <grawity@gmail.com>
|
||||
* Matthew Beeching <jobe@mdbnet.co.uk>
|
||||
* Michael <michaelhazell@hotmail.com>
|
||||
* Mingjie Shen <shen497@purdue.edu>
|
||||
* nekoswag
|
||||
* Peter Tseng <pht24@cornell.edu>
|
||||
* Romain Rivière <lecoyote@lecoyote.org>
|
||||
* Sam James (sam_c) <sam@cmpct.info>
|
||||
* ShutterQuick <shutter@canternet.org>
|
||||
* Sketch <denverfreeburn@outlook.com>
|
||||
* Tim Gunter <tim@vanillaforums.com>
|
||||
* Toni Kaija <diftraku@gmail.com>
|
||||
* Victor Coss <gtaxl@gtaxl.net>
|
||||
* VisioN <vision@myirc.us>
|
||||
* westor <westor7@gmail.com>
|
||||
* Wilson Birney <wpb@360scada.com>
|
||||
* Yann Sionneau <yann@sionneau.net>
|
||||
* Zach Bloomquist <zrbq@live.com>
|
||||
@@ -1,3 +1,62 @@
|
||||
Anope Version 2.1.14-git
|
||||
------------------------
|
||||
Added a detail specifier to the anope.list{Channels,Opers,Servers,Users} RPC methods.
|
||||
Added a matcher for the InspIRCd oper extban.
|
||||
Added support for hashed operator passwords.
|
||||
Added support for hiding the date news was added in os_news.
|
||||
Added support for local password comparison to the sql_authentication module.
|
||||
Added support for monthly backups to db_json.
|
||||
Added support for unbanning virtual modes using cs_unban.
|
||||
Added the !unmute fantasy command.
|
||||
Added the anope.account and anope.listAccounts RPC methods to the rpc_data module.
|
||||
Added the protection time to the INFO output.
|
||||
Allowed unprivileged channel successors to remove themselves from succession.
|
||||
Bumped the minimum required CMake version to 3.20.
|
||||
Changed deletion callbacks to specify the mask that was deleted if only one was.
|
||||
Changed nickserv/alist to show all permissions not just the highest ranked one.
|
||||
Fixed NEVEROP not being respected in chanserv/set/founder and chanserv/set/successor.
|
||||
Fixed stripping IRC formatting codes from messages.
|
||||
Messages are now automatically line wrapped to options:linelength.
|
||||
Redocumented the ns_sasl module.
|
||||
Removed hardcoded command names from several messages.
|
||||
Updated the Windows CI to Windows Server 2025 and Visual Studio 2022.
|
||||
|
||||
Anope Version 2.1.13
|
||||
--------------------
|
||||
Added a Config check to ensure users actually want to use the development branch.
|
||||
Added a flag to the version string when Anope is compiled in reproducible mode.
|
||||
Added a warning on rehash when the max password is longer than the maximum bcrypt password length.
|
||||
Added an ALLTIME handler on InspIRCd.
|
||||
Added an opt-out for extended XML-RPC types.
|
||||
Added RPC messages for sending global messages.
|
||||
Added support for importing cs_set_misc and ns_set_misc data from Atheme.
|
||||
Added support for importing news from Atheme.
|
||||
Added support for oper-only quit messages.
|
||||
Added support for the experimental "services cloak" system from the InspIRCd development branch.
|
||||
Added support for using defines from the environment.
|
||||
Added support for using defines within the value of a variable.
|
||||
Blacklisted an old version of an UnrealIRCd module that is known to send malformed S2S messages.
|
||||
Changed RPC events to be registered as core services.
|
||||
Changed the database to refer to accounts by their account identifier instead of their display nick.
|
||||
Changed the syntax of defines from "foo" to "${foo}".
|
||||
Deduplicated JSON generation code in the jsonrpc module.
|
||||
Fixed a warning when importing an Atheme account that uses external authentication.
|
||||
Fixed counting email addresses in ns_maxemail.
|
||||
Fixed db_atheme creating duplicate accounts, bots, and nicks when importing over an existing database.
|
||||
Fixed deleting old database backups after Anope has been restarted.
|
||||
Fixed importing user metadata from Anope 1.8.
|
||||
Fixed including a port in uplink messages when connecting to a UNIX socket endpoint.
|
||||
Fixed memo ignores being erroneously case sensitive.
|
||||
Fixed modules with third-party dependencies writing generic log messages instead of module log messages.
|
||||
Fixed not performing SQL database updates in some rare circumstances.
|
||||
Fixed sending global messages with the default sender.
|
||||
Imported mkauthors from InspIRCd and used it to generate docs/AUTHORS.txt
|
||||
Moved around a bunch of module headers.
|
||||
Moved database serialization from the serializable to the serializable type.
|
||||
Moved the SASL protocol interface to its own service.
|
||||
Refactored handling S2S metadata on InspIRCd.
|
||||
Updated more messages to use gettext plural forms.
|
||||
|
||||
Anope Version 2.1.12
|
||||
--------------------
|
||||
Added an example JavaScript library for accessing the RPC interface.
|
||||
|
||||
+54
-23
@@ -1,3 +1,35 @@
|
||||
Anope Version 2.1.14-git
|
||||
------------------------
|
||||
Added oper:password_hash.
|
||||
Added options:codelength (defaults to 15).
|
||||
Added {os_news}:showdate (defaults to yes).
|
||||
Added {sql_authentication}:password_field (defaults to "password").
|
||||
Added {sql_authentication}:password_hash.
|
||||
Changed the default value for options:linelength to "100".
|
||||
Changed the default value for {enc_sha2}:algorithm to "sha512".
|
||||
Changed the default value for {ns_seen}:purgetime to "90d".
|
||||
Changed the syntax for template variables in mail:emailchange_message, mail:emailchange_subject, mail:memo_message, mail:memo_subject, mail:registration_message, mail:registration_subject,, mail:reset_message, mail:reset_subject, {chanserv}:signkickformat, {dnsbl}:blacklist:reason, {ldap_authentication}:search_filter, {ldap_oper}:binddn, {ldap_oper}:search_filter, {nickserv}:unregistered_notice, {os_session}:sessionlimitexceeded, {proxyscan}:proxyscan:reason.
|
||||
|
||||
Anope Version 2.1.13
|
||||
--------------------
|
||||
Added options:linelength (defaults to 120).
|
||||
Added the db_json module.
|
||||
Added the rpc_message module.
|
||||
Added {nickserv}:defaultprotect (defaults to 1m).
|
||||
Added {nickserv}:maxprotect (defaults to 10m).
|
||||
Added {nickserv}:minprotect (defaults to 10s)
|
||||
Added {xmlrpc}:enable_i8 (defaults to yes).
|
||||
Added {xmlrpc}:enable_nil (defaults to yes).
|
||||
Changed the syntax for using defines (all existing defines will need to be updated).
|
||||
Removed {nickserv}:kill (replaced by custom protection timer durations).
|
||||
Removed {nickserv}:killquick (replaced by custom protection timer durations).
|
||||
Removed {ns_set_kill}:allowkillimmed (replaced by custom protection timer durations).
|
||||
Renamed the nickserv/saset/kill command to nickserv/saset/protect.
|
||||
Renamed the nickserv/saset/kill oper privilege to nickserv/saset/protect.
|
||||
Renamed the nickserv/set/kill command to nickserv/set/protect.
|
||||
Renamed the ns_set_kill module to ns_set_protect.
|
||||
Renamed the sasl module to ns_sasl and moved it to nickserv.example.conf.
|
||||
|
||||
Anope Version 2.1.12
|
||||
--------------------
|
||||
Added the jsonrpc module.
|
||||
@@ -11,16 +43,16 @@ Renamed the xmlrpc_main module to rpc_main.
|
||||
|
||||
Anope Version 2.1.11
|
||||
--------------------
|
||||
Moved {ns_set}:allowkillimmed to {ns_set_kill}:allowkillimmed.
|
||||
Moved nickserv/set/kill and nickserv/saset/kill to the ns_set_kill module.
|
||||
Replaced {nickserv}:guestnickprefix with {nickserv}:guestnick.
|
||||
Moved {ns_set}:allowkillimmed to {ns_set_kill}:allowkillimmed.
|
||||
Replaced {nickserv}:guestnickprefix with {nickserv}:guestnick (defaults to Guest####).
|
||||
|
||||
Anope Version 2.1.10
|
||||
--------------------
|
||||
Added options:servicealias.
|
||||
Added options:servicealias (defaults to no)
|
||||
Moved nickserv/set/message and nickserv/saset/message to the ns_set_message module.
|
||||
Removed options:useprivmsg.
|
||||
Removed options:usestrictprivmsg.
|
||||
Removed options:useprivmsg (replaced by loading the ns_set_message module to enable).
|
||||
Removed options:usestrictprivmsg (feature unusable on modern servers, consider migrating to options:servicealias instead).
|
||||
|
||||
Anope Version 2.1.9
|
||||
-------------------
|
||||
@@ -28,14 +60,14 @@ No significant changes.
|
||||
|
||||
Anope Version 2.1.8
|
||||
-------------------
|
||||
Added {nickserv}:preservedisplay.
|
||||
Added the nickserv/drop/display oper privilege.
|
||||
Added {nickserv}:preservedisplay (defaults to no).
|
||||
|
||||
Anope Version 2.1.7
|
||||
-------------------
|
||||
Moved nickserv/set/language and nickserv/saset/language to the ns_set_language module.
|
||||
Renamed the FANTASIA channel privilege to FANTASY.
|
||||
Renamed {cs_suspend}:expire to {cs_suspend}:suspendexpire.
|
||||
Renamed the FANTASIA privilege to FANTASY.
|
||||
|
||||
Anope Version 2.1.6
|
||||
-------------------
|
||||
@@ -55,8 +87,8 @@ Added the enc_posix module.
|
||||
Added the enc_sha2 module.
|
||||
Added the gl_queue module.
|
||||
Added the gl_server module.
|
||||
Added the global/queue operator privilege.
|
||||
Added the global/server operator privilege.
|
||||
Added the global/queue oper privilege.
|
||||
Added the global/server oper privilege.
|
||||
Changed serverinfo:motd to be relative to the config directory.
|
||||
Changed serverinfo:pid to be relative to the data directory.
|
||||
Changed the default value of mail:sendmailpath to "/usr/sbin/sendmail -it".
|
||||
@@ -64,13 +96,12 @@ Changed the default value of {chanserv}:accessmax to 1000.
|
||||
Changed the default value of {chanserv}:inhabit to 1 minute.
|
||||
Changed the default value of {cs_mode}:max to 50.
|
||||
Changed the default value of {ms_ignore}:max to 50.
|
||||
Removed options:seed.
|
||||
Replaced {webcpanel}:template with {webcpanel}:template_dir.
|
||||
|
||||
Removed options:seed (not needed with modern random number generation).
|
||||
Replaced {webcpanel}:template with {webcpanel}:template_dir (defaults to webcpanel/templates/default).
|
||||
|
||||
Anope Version 2.1.3
|
||||
-------------------
|
||||
Added options:didyoumeandifference.
|
||||
Added options:didyoumeandifference (defaults to 4).
|
||||
Added support for multiple SSL fingerprints in oper:certfp.
|
||||
Added the chanserv/cert oper privilege for modifying other user's certificate lists.
|
||||
Changed networkinfo:chanlen to default to 32 if not set.
|
||||
@@ -80,21 +111,21 @@ Changed networkinfo:nicklen to default to 31 if not set.
|
||||
Changed networkinfo:userlen to default to 10 if not set.
|
||||
Increased the default maximum password length to 50 characters.
|
||||
Increased the default minimum password length to 10 characters.
|
||||
Removed the cs_secure option in {chanserv}:defaults (now always enabled).
|
||||
Removed the nickserv/saset/secure command.
|
||||
Removed the nickserv/saset/secure oper privilege.
|
||||
Removed the nickserv/set/secure command.
|
||||
Removed the nickserv/status command.
|
||||
Removed the ns_access module.
|
||||
Removed the ns_secure option in {nickserv}:defaults (now always enabled).
|
||||
Removed the cs_secure option in {chanserv}:defaults (now always enabled as support for nick access lists has been removed).
|
||||
Removed the nickserv/saset/secure command (support for nick access lists has been removed).
|
||||
Removed the nickserv/saset/secure oper privilege (support for nick access lists has been removed).
|
||||
Removed the nickserv/set/secure command (support for nick access lists has been removed).
|
||||
Removed the nickserv/status command (obsolete with modern IRCv3 extensions and the removal of nick access lists).
|
||||
Removed the ns_access module (support for nick access lists has been removed).
|
||||
Removed the ns_secure option in {nickserv}:defaults (now always enabled as support for nick access lists has been removed).
|
||||
|
||||
Anope Version 2.1.2
|
||||
-------------------
|
||||
Added {ssl_openssl}:tlsv10 for configuring whether TLSv1.0 is usable (defaults to no).
|
||||
Added {ssl_openssl}:tlsv11 for configuring whether TLSv1.1 is usable (defaults to yes).
|
||||
Added {ssl_openssl}:tlsv12 for configuring whether TLSv1.2 is usable (defaults to yes).
|
||||
Removed {ssl_openssl}:sslv3 (now always disabled).
|
||||
Removed the m_ prefix from the names of the chanstats, dns, dnsbl, helpchan, httpd, ldap, ldap_oper, mysql, proxyscan, redis, regex_pcre2, regex_posix, regex_stdlib, regex_tre, rewrite, sasl, sql_log, sql_oper, sqlite, ssl_gnutls, ssl_openssl, xmlrpc, and xmlrpc_main modules.
|
||||
Removed {ssl_openssl}:sslv3 (now always disabled).
|
||||
|
||||
Anope Version 2.1.1
|
||||
-------------------
|
||||
@@ -104,7 +135,7 @@ Removed the m_regex_pcre module (use m_regex_pcre2 instead).
|
||||
Anope Version 2.1.0
|
||||
-------------------
|
||||
Added nickserv:minpasslen for configuring the minimum password length (defaults to 8).
|
||||
Removed nickserv:strictpasswords as it is obsolete now nickserv:minpasslen exists.
|
||||
Removed nickserv:strictpasswords (obsolete now nickserv:minpasslen exists).
|
||||
Removed the inspircd12 and inspircd20 modules (use inspircd instead).
|
||||
Removed the ns_getpass module (no supported encryption modules).
|
||||
Removed the os_oline module (no supported IRCds).
|
||||
@@ -113,4 +144,4 @@ Renamed nickserv:passlen to nickserv:maxpasslen.
|
||||
Renamed the charybdis module to solanum.
|
||||
Renamed the inspircd3 module to inspircd.
|
||||
Renamed the unreal4 module to unrealircd.
|
||||
Replaced uplink:ipv6 with uplink:protocol.
|
||||
Replaced uplink:ipv6 with uplink:protocol (defaults to ipv4).
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ Note: You should also read the README and FAQ files!
|
||||
cmake --version
|
||||
|
||||
If it's installed, you will get a line that says something similar to
|
||||
"cmake version 2.8.12.2". If the version is less than 2.4 or you get
|
||||
"cmake version 3.28.3". If the version is less than 3.20.0 or you get
|
||||
an error saying the command was not found, you will not be able to use
|
||||
CMake unless you install it yourself into your home directory. CMake
|
||||
can be downloaded from:
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
|
||||
cmake --version
|
||||
|
||||
Si CMake est installé, vous aurez une ligne qui dit quelque chose comme
|
||||
"cmake version 2.8.12.2". Si la version est inférieure à 2.4 ou si vous
|
||||
"cmake version 3.28.3". Si la version est inférieure à 3.20.0 ou si vous
|
||||
obtenez une erreur disant que la commande n'a pas été trouvée, vous ne
|
||||
pourrez pas utiliser CMake à moins de l'installer vous-même dans votre
|
||||
répertoire home. CMake peut être téléchargé ici :
|
||||
|
||||
+3
-4
@@ -34,10 +34,9 @@ Anope Multi Language Support
|
||||
Poedit (https://poedit.net/) is a popular po file editor, and we recommend using it or another editor designed to edit
|
||||
po files (especially on Windows).
|
||||
|
||||
If you have finished a language file translation and you want others to use it, please send it to team@anope.org
|
||||
(don't forget to mention clearly your (nick)name, your email and the language name). You'll of course get full credit for it.
|
||||
|
||||
NOTE: There is no guarantee we will use your work so please do not be offended if we say no thanks.
|
||||
If you have finished a language file translation and you want others to use it, please file a pull request on GitHub
|
||||
or send it to team@anope.org (don't forget to mention clearly your (nick)name, your email and the language name).
|
||||
You'll of course get full credit for it.
|
||||
|
||||
3) Using languages with modules
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ command - Takes three parameters, a service name (BotServ, ChanServ, NickServ),
|
||||
|
||||
stats - Takes no parameters, returns miscellaneous stats that can be found in the /operserv stats command.
|
||||
|
||||
notice - Takes three parameters, source user, target user, and message. Sends a message to the user.
|
||||
|
||||
RPC was designed to be used with db_sql, and will not return any information that can be pulled from the SQL
|
||||
database, such as accounts and registered channel information. It is instead used for pulling realtime data such
|
||||
as users and channels currently online. For examples on how to use these calls in PHP, see xmlrpc.php in docs/RPC.
|
||||
|
||||
+88
-8
@@ -44,18 +44,47 @@ class AnopeRPC {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of accounts.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of account names.
|
||||
*/
|
||||
listAccounts(detail = "name") {
|
||||
return this.run("anope.listAccounts", detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified account.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the account.
|
||||
* @returns {object} An object containing information about the account.
|
||||
*/
|
||||
account(name) {
|
||||
return this.run("anope.account", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of channels.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of channel names.
|
||||
*/
|
||||
listChannels() {
|
||||
return this.run("anope.listChannels");
|
||||
listChannels(detail = "name") {
|
||||
return this.run("anope.listChannels", detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified channel.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the channel.
|
||||
* @returns {object} An object containing information about the channel.
|
||||
*/
|
||||
@@ -66,15 +95,20 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves a list of services operators.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of channel names.
|
||||
*/
|
||||
listOpers() {
|
||||
return this.run("anope.listOpers");
|
||||
listOpers(detail = "name") {
|
||||
return this.run("anope.listOpers", detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified services operator.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the services operator.
|
||||
* @returns {object} An object containing information about the services operator.
|
||||
*/
|
||||
@@ -85,15 +119,20 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves a list of servers.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of servers names.
|
||||
*/
|
||||
listServers() {
|
||||
return this.run("anope.listServers");
|
||||
listServers(detail = "name") {
|
||||
return this.run("anope.listServers", detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified server.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the server.
|
||||
* @returns {object} An object containing information about the server.
|
||||
*/
|
||||
@@ -104,21 +143,62 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves a list of users.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} The level of detail to request.
|
||||
* @returns {array} An array of channel names.
|
||||
*/
|
||||
listUsers() {
|
||||
return this.run("anope.listUsers");
|
||||
listUsers(detail = "name") {
|
||||
return this.run("anope.listUsers", detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about the specified user.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} nick The nick of the user.
|
||||
* @returns {object} An object containing information about the user.
|
||||
*/
|
||||
user(nick) {
|
||||
return this.run("anope.user", nick);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to every user on the network.
|
||||
*
|
||||
* Requires the rpc_message module to be loaded.
|
||||
*
|
||||
* @param {...*} messages One or more messages to send.
|
||||
*/
|
||||
messageNetwork(...messages) {
|
||||
return this.run("anope.messageNetwork", ...messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to every user on the specified server.
|
||||
*
|
||||
* Requires the rpc_message module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the server.
|
||||
* @param {...*} messages One or more messages to send.
|
||||
*/
|
||||
messageServer(server, ...messages) {
|
||||
return this.run("anope.messageServer", server, ...messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the specified user.
|
||||
*
|
||||
* Requires the rpc_message module to be loaded.
|
||||
*
|
||||
* @param {string} source The source pseudoclient to send the message from.
|
||||
* @param {string} target The target user to send the message to.
|
||||
* @param {...*} messages One or more messages to send.
|
||||
*/
|
||||
messageUser(source, target, ...messages) {
|
||||
return this.run("anope.messageUser", source, target, ...messages);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -132,7 +132,7 @@ class AnopeRPC
|
||||
*/
|
||||
public function notice($source, $target, $message)
|
||||
{
|
||||
return $this->run("notice", [$source, $target, $message]);
|
||||
return $this->run("anope.messageUser", [$source, $target, $message]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+165
-17
@@ -1,20 +1,151 @@
|
||||
# Anope `rpc_data` RPC interface
|
||||
|
||||
## `anope.listAccounts`
|
||||
|
||||
Lists all accounts that exist on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all information or "name" to just retrieve the account names. Defaults to "name".
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified detail level does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
If the detail level is not specified or is "name" then an array of account names.
|
||||
|
||||
If the detail level is "full" then a mapping of account names to information about the account. See `anope.account` for more information on the data structure.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
["account1", "account2", "account3"]
|
||||
```
|
||||
|
||||
## `anope.account`
|
||||
|
||||
Retrieves information about the specified account.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | A nickname belonging to the account.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified account does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
Returns a map containing information about the account.
|
||||
|
||||
Key | Type | Description
|
||||
--- | ---- | -----------
|
||||
display | string | The display nickname of the account.
|
||||
email | string or null | The email address associated with the account or null if one has not been specified.
|
||||
extensions | map | A key-value map of the extensions set on this account by modules.
|
||||
language | string or null | The language associated with the account or null if the account uses the default language.
|
||||
lastmail | int | The time at which an email was last sent for this account.
|
||||
nicks | map | Information about nicknames that belong to the account keyed by the nickname.
|
||||
nicks.\*.extensions | map | A key-value map of the extensions set on this nickname by modules.
|
||||
nicks.\*.lastseen | int | The time at which this nickname was last used.
|
||||
nicks.\*.registered | int | The time at which this nickname was registered.
|
||||
nicks.\*.vhost | map or null | The vhost associated with the account or null if the user has no vhost.
|
||||
nicks.\*.vhost.created | int | The time at which the vhost was created.
|
||||
nicks.\*.vhost.creator | string | The nickname of the creator of the vhost.
|
||||
nicks.\*.vhost.host | string | The host segment of the vhost.
|
||||
nicks.\*.vhost.ident | string or null | The ident segment of the vhost or null if there is not one.
|
||||
nicks.\*.vhost.mask | string | The user@host or host mask of the vhost.
|
||||
opertype | map or null | The oper type associated with the account or null if they are not a services operator.
|
||||
opertype.commands | array[string] | The commands that the services operator type can use.
|
||||
opertype.name | string | The name of the services operator type.
|
||||
opertype.privileges | array[string] | The privileges that the services operator type has.
|
||||
registered | int | The time at which the account was registered.
|
||||
uniqueid | uint | The unique immutable identifier of the account.
|
||||
users | array[string] | The IRC users who are currently logged in to this account.
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"display": "foo",
|
||||
"email": "example@example.com",
|
||||
"extensions": {
|
||||
"AUTOOP": true,
|
||||
"HIDE_EMAIL": true,
|
||||
"HIDE_MASK": true,
|
||||
"MEMO_RECEIVE": true,
|
||||
"MEMO_SIGNON": true,
|
||||
"NS_PRIVATE": true,
|
||||
"PROTECT": true,
|
||||
"PROTECT_AFTER": 69
|
||||
},
|
||||
"language": null,
|
||||
"lastmail": 1745071858,
|
||||
"nicks": {
|
||||
"foo": {
|
||||
"extensions": {
|
||||
"NS_NO_EXPIRE": true
|
||||
},
|
||||
"lastseen": 1745074153,
|
||||
"registered": 1745071857,
|
||||
"vhost": null
|
||||
},
|
||||
"bar": {
|
||||
"extensions": {},
|
||||
"lastseen": 1745072602,
|
||||
"registered": 1745071857,
|
||||
"vhost": {
|
||||
"created": 1745072653,
|
||||
"creator": "foo",
|
||||
"host": "bar.baz",
|
||||
"ident": "foo",
|
||||
"mask": "foo@bar.baz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"opertype": {
|
||||
"commands": ["hostserv/*", "operserv/session"],
|
||||
"name": "Helper",
|
||||
"privileges": ["chanserv/no-register-limit"]
|
||||
},
|
||||
"registered": 1745071857,
|
||||
"uniqueid": 11085415958920757000,
|
||||
"users": [
|
||||
"foo"
|
||||
]
|
||||
}
|
||||
```
|
||||
## `anope.listChannels`
|
||||
|
||||
Lists all channels that exist on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
*None*
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all information or "name" to just retrieve the channel names. Defaults to "name".
|
||||
|
||||
### Errors
|
||||
|
||||
*Only standard RPC errors*
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified detail level does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
Returns an array of channel names.
|
||||
If the detail level is not specified or is "name" then an array of channel names.
|
||||
|
||||
If the detail level is "full" then a mapping of channel names to information about the channel. See `anope.channel` for more information on the data structure.
|
||||
|
||||
#### Example
|
||||
|
||||
@@ -44,13 +175,13 @@ Returns a map containing information about the channel.
|
||||
|
||||
Key | Type | Description
|
||||
--- | ---- | -----------
|
||||
created | uint | The UNIX time at which the channel was originally created.
|
||||
created | int | The UNIX time at which the channel was originally created.
|
||||
listmodes | map | List modes which are set on the channel keyed by the mode character.
|
||||
modes | array[string] | Flag and parameter modes which are set on the channel.
|
||||
name | string | The name of the channel.
|
||||
registered | boolean | Whether the channel is registered.
|
||||
topic | map or null | The channel topic or null if no topic is set.
|
||||
topic.setat | uint | The time at which the topic was set.
|
||||
topic.setat | int | The time at which the topic was set.
|
||||
topic.setby | string | The nick or nuh of the user who set the topic.
|
||||
topic.value | string | The text of the topic.
|
||||
users | array[string] | The users that are current in the channel prefixed by their status mode prefixes.
|
||||
@@ -81,15 +212,21 @@ Lists all services operators that exist on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
*None*
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all information or "name" to just retrieve the services operator nicknames. Defaults to "name".
|
||||
|
||||
### Errors
|
||||
|
||||
*Only standard RPC errors*
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified detail level does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
Returns an array of services operator names.
|
||||
If the detail level is not specified or is "name" then an array of services operator names.
|
||||
|
||||
If the detail level is "full" then a mapping of services operator names to information about the services operator. See `anope.oper` for more information on the data structure.
|
||||
|
||||
#### Example
|
||||
|
||||
@@ -123,7 +260,7 @@ fingerprints | array[string] or null | The client certificate fingerprint
|
||||
hosts | array[string] or null | The user@ip and user@ip masks that a user must be connecting from to log in as this services operator or null if there are no host restrictions.
|
||||
name | string | The name of the services operator.
|
||||
operonly | boolean | Whether a user has to be a server operator to log in as this services operator.
|
||||
opertype | map | The oper type associated with the services operator opertype.
|
||||
opertype | map | The oper type associated with the services operator.
|
||||
opertype.commands | array[string] | The commands that the services operator type can use.
|
||||
opertype.name | string | The name of the services operator type.
|
||||
opertype.privileges | array[string] | The privileges that the services operator type has.
|
||||
@@ -154,15 +291,21 @@ Lists all servers that exist on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
*None*
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all information or "name" to just retrieve the server names. Defaults to "name".
|
||||
|
||||
### Errors
|
||||
|
||||
*Only standard RPC errors*
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified detail level does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
Returns an array of server names.
|
||||
If the detail level is not specified or is "name" then an array of server names.
|
||||
|
||||
If the detail level is "full" then a mapping of server names to information about the server. See `anope.server` for more information on the data structure.
|
||||
|
||||
#### Example
|
||||
|
||||
@@ -222,16 +365,21 @@ Lists all users that exist on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
*None*
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all information or "name" to just retrieve the user nicknames. Defaults to "name".
|
||||
|
||||
### Errors
|
||||
|
||||
*Only standard RPC errors*
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified detail level does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
Returns an array of user nicknames.
|
||||
If the detail level is not specified or is "name" then an array of user nicknames.
|
||||
|
||||
If the detail level is "full" then a mapping of user nicknames to information about the user. See `anope.user` for more information on the data structure.
|
||||
|
||||
#### Example
|
||||
|
||||
@@ -273,10 +421,10 @@ host | string | The real hostname of the user.
|
||||
ident | string | The username (ident) of the user.
|
||||
modes | array[string] | Flag and parameter modes which are set on the user.
|
||||
nick | string | The nickname of the user.
|
||||
nickchanged | uint | The time at which the user last changed their nickname.
|
||||
nickchanged | int | The time at which the user last changed their nickname.
|
||||
real | string | The real name of the user.
|
||||
server | string | The server that the user is connected to.
|
||||
signon | uint | The time at which the user connected to the network.
|
||||
signon | int | The time at which the user connected to the network.
|
||||
uid | string or null | The unique immutable identifier of the user or null if the IRCd does not use UIDs.
|
||||
vhost | string or null | The virtual host of the user or null if they have no vhost.
|
||||
vident | string or null | The virtual ident (username) of the user or null if they have no vident.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# Anope `rpc_message` RPC interface
|
||||
|
||||
## `anope.messageNetwork`
|
||||
|
||||
Sends a message to all users on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0+ | One or more messages to send.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The global service is not available.
|
||||
|
||||
### Result
|
||||
|
||||
This procedure returns no result.
|
||||
|
||||
## `anope.messageServer`
|
||||
|
||||
Sends a message to all users on the specified server.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | The name of the server to message users on.
|
||||
1+ | One or more messages to send.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The global service is not available.
|
||||
-32098 | The specified server does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
This procedure returns no result.
|
||||
|
||||
## `anope.messageUser`
|
||||
|
||||
Sends a message to the specified user.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | The source pseudoclient to send the message from.
|
||||
1 | The target user to send the message to.
|
||||
2+ | One or more messages to send.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified source does not exist.
|
||||
-32098 | The specified target does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
This procedure returns no result.
|
||||
|
||||
+10
-3
@@ -74,6 +74,16 @@ public:
|
||||
class CoreExport ChanAccess
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
Anope::string mask;
|
||||
/* account this access entry is for, if any */
|
||||
Serialize::Reference<NickCore> nc;
|
||||
@@ -97,9 +107,6 @@ public:
|
||||
const Anope::string &Mask() const;
|
||||
NickCore *GetAccount() const;
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
static const unsigned int MAX_DEPTH = 4;
|
||||
|
||||
/** Check if this access entry matches the given user or account
|
||||
|
||||
+24
-8
@@ -32,6 +32,16 @@ class CoreExport NickAlias final
|
||||
: public Serializable
|
||||
, public Extensible
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
Anope::string vhost_ident, vhost_host, vhost_creator;
|
||||
time_t vhost_created = 0;
|
||||
|
||||
@@ -43,7 +53,7 @@ public:
|
||||
Anope::string last_usermask;
|
||||
/* Last uncloaked usermask, requires nickserv/auspex to see */
|
||||
Anope::string last_realhost;
|
||||
time_t time_registered = Anope::CurTime;
|
||||
time_t registered = Anope::CurTime;
|
||||
time_t last_seen = Anope::CurTime;
|
||||
|
||||
/* Account this nick is tied to. Multiple nicks can be tied to a single account. */
|
||||
@@ -56,9 +66,6 @@ public:
|
||||
NickAlias(const Anope::string &nickname, NickCore *nickcore);
|
||||
~NickAlias();
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Set a vhost for the user
|
||||
* @param ident The ident
|
||||
* @param host The host
|
||||
@@ -106,6 +113,7 @@ public:
|
||||
* @return the nick, if found
|
||||
*/
|
||||
static NickAlias *Find(const Anope::string &nick);
|
||||
static NickAlias *FindId(uint64_t id);
|
||||
};
|
||||
|
||||
/* A registered account. Each account must have a NickAlias with the same nick as the
|
||||
@@ -116,6 +124,16 @@ class CoreExport NickCore final
|
||||
: public Serializable
|
||||
, public Extensible
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
/* Channels which reference this core in some way (this is on their access list, akick list, is founder, successor, etc) */
|
||||
Serialize::Checker<std::map<ChannelInfo *, int> > chanaccess;
|
||||
/* Unique identifier for the account. */
|
||||
@@ -131,7 +149,7 @@ public:
|
||||
/* Last time an email was sent to this user */
|
||||
time_t lastmail = 0;
|
||||
/* The time this account was registered */
|
||||
time_t time_registered = Anope::CurTime;
|
||||
time_t registered = Anope::CurTime;
|
||||
MemoInfo memos;
|
||||
std::map<Anope::string, Anope::string> last_modes;
|
||||
|
||||
@@ -159,9 +177,6 @@ public:
|
||||
NickCore(const Anope::string &nickdisplay, uint64_t nickid = 0);
|
||||
~NickCore();
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Changes the display for this account
|
||||
* @param na The new display, must be grouped to this account.
|
||||
*/
|
||||
@@ -180,6 +195,7 @@ public:
|
||||
* @return The account, if it exists
|
||||
*/
|
||||
static NickCore *Find(const Anope::string &nick);
|
||||
static NickCore *FindId(uint64_t id);
|
||||
|
||||
void AddChannelReference(ChannelInfo *ci);
|
||||
void RemoveChannelReference(ChannelInfo *ci);
|
||||
|
||||
+16
-1
@@ -221,6 +221,14 @@ namespace Anope
|
||||
inline bool is_number_only() const { return this->find_first_not_of("0123456789.-") == npos; }
|
||||
inline bool is_pos_number_only() const { return this->find_first_not_of("0123456789.") == npos; }
|
||||
|
||||
/**
|
||||
* In IRC messages we use a substitute (ASCII 0x1A) instead of a space
|
||||
* (ASCII 0x20) so it doesn't get line wrapped when put into a message.
|
||||
* The line wrapper will convert this to a space before it is sent to
|
||||
* clients.
|
||||
*/
|
||||
inline Anope::string nobreak() const { return this->replace_all_cs("\x20", "\x1A"); }
|
||||
|
||||
/**
|
||||
* Replace parts of the string.
|
||||
*/
|
||||
@@ -346,7 +354,7 @@ namespace Anope
|
||||
template<typename T>
|
||||
using unordered_map = std::unordered_map<string, T, hash_ci, compare>;
|
||||
|
||||
#ifndef REPRODUCIBLE_BUILD
|
||||
#if !REPRODUCIBLE_BUILD
|
||||
static const char *const compiled = __TIME__ " " __DATE__;
|
||||
#endif
|
||||
|
||||
@@ -608,6 +616,13 @@ namespace Anope
|
||||
* @return True if the message was a well formed CTCP; otherwise, false.
|
||||
*/
|
||||
extern CoreExport bool ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body);
|
||||
|
||||
/** Replaces template variables within a string with values from a map.
|
||||
* @param str The string to template from.
|
||||
* @param vars The variables to replace within the string.
|
||||
* @return The specified string with all variables replaced within it.
|
||||
*/
|
||||
extern CoreExport Anope::string Template(const Anope::string &str, const Anope::map<Anope::string> &vars);
|
||||
}
|
||||
|
||||
/** sepstream allows for splitting token separated lists.
|
||||
|
||||
+11
-1
@@ -23,6 +23,16 @@ class CoreExport BotInfo final
|
||||
: public User
|
||||
, public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
/* Channels this bot is assigned to */
|
||||
Serialize::Checker<std::set<ChannelInfo *> > channels;
|
||||
public:
|
||||
@@ -129,7 +139,7 @@ public:
|
||||
CommandInfo *GetCommand(const Anope::string &cname);
|
||||
|
||||
/** Get the command that users can use to send a message to this bot. */
|
||||
Anope::string GetQueryCommand() const;
|
||||
Anope::string GetQueryCommand(const Anope::string &command = "", const Anope::string &extra = "") const;
|
||||
|
||||
/** Find a bot by nick
|
||||
* @param nick The nick
|
||||
|
||||
+10
-10
@@ -48,11 +48,11 @@ public:
|
||||
/* Set if this channel is registered. ci->c == this. Contains information relevant to the registered channel */
|
||||
Serialize::Reference<ChannelInfo> ci;
|
||||
/* When the channel was created */
|
||||
time_t creation_time;
|
||||
time_t created;
|
||||
/* If the channel has just been created in a netjoin */
|
||||
bool syncing;
|
||||
bool syncing = false;
|
||||
/* Is configured in the conf as a channel bots should be in */
|
||||
bool botchannel;
|
||||
bool botchannel = false;
|
||||
|
||||
/* Users in the channel */
|
||||
typedef std::map<User *, ChanUserContainer *> ChanUserList;
|
||||
@@ -66,15 +66,15 @@ public:
|
||||
* This is the time the topic was *originally set*. When we restore the topic we want to change the TS back
|
||||
* to this, but we can only do this on certain IRCds.
|
||||
*/
|
||||
time_t topic_ts;
|
||||
time_t topic_ts = 0;
|
||||
/* The actual time the topic was set, probably close to Anope::CurTime */
|
||||
time_t topic_time;
|
||||
time_t topic_time = 0;
|
||||
|
||||
time_t server_modetime; /* Time of last server MODE */
|
||||
time_t chanserv_modetime; /* Time of last check_modes() */
|
||||
int16_t server_modecount; /* Number of server MODEs this second */
|
||||
int16_t chanserv_modecount; /* Number of check_mode()'s this sec */
|
||||
int16_t bouncy_modes; /* Did we fail to set modes here? */
|
||||
time_t server_modetime = 0; /* Time of last server MODE */
|
||||
time_t chanserv_modetime = 0; /* Time of last check_modes() */
|
||||
int16_t server_modecount = 0; /* Number of server MODEs this second */
|
||||
int16_t chanserv_modecount = 0; /* Number of check_mode()'s this sec */
|
||||
bool bouncy_modes = false; /* Did we fail to set modes here? */
|
||||
|
||||
private:
|
||||
/** Constructor
|
||||
|
||||
+5
-4
@@ -14,6 +14,7 @@
|
||||
#include "service.h"
|
||||
#include "anope.h"
|
||||
#include "channels.h"
|
||||
#include "textproc.h"
|
||||
|
||||
struct CommandGroup final
|
||||
{
|
||||
@@ -96,7 +97,7 @@ class CoreExport Command
|
||||
: public Service
|
||||
{
|
||||
Anope::string desc;
|
||||
std::vector<Anope::string> syntax;
|
||||
std::vector<std::pair<Anope::string, std::function<bool(CommandSource&)>>> syntax;
|
||||
/* Allow unregistered users to use this command */
|
||||
bool allow_unregistered;
|
||||
/* Command requires that a user is executing it */
|
||||
@@ -128,7 +129,7 @@ protected:
|
||||
void SetDesc(const Anope::string &d);
|
||||
|
||||
void ClearSyntax();
|
||||
void SetSyntax(const Anope::string &s);
|
||||
void SetSyntax(const Anope::string &s, const std::function<bool(CommandSource&)> &p = nullptr);
|
||||
void SendSyntax(CommandSource &);
|
||||
|
||||
void AllowUnregistered(bool b);
|
||||
@@ -150,10 +151,10 @@ public:
|
||||
*/
|
||||
virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0;
|
||||
|
||||
/** Called when HELP is requested for the client this command is on.
|
||||
/** Called when help is requested for the client this command is on.
|
||||
* @param source The source
|
||||
*/
|
||||
virtual void OnServHelp(CommandSource &source);
|
||||
virtual void OnServHelp(CommandSource &source, HelpWrapper &help);
|
||||
|
||||
/** Requested when the user is requesting help on this command. Help on this command should be sent to the user.
|
||||
* @param source The source
|
||||
|
||||
+13
-13
@@ -18,11 +18,9 @@
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
class CoreExport Block
|
||||
{
|
||||
friend struct Configuration::Conf;
|
||||
friend class Configuration::Conf;
|
||||
|
||||
public:
|
||||
typedef Anope::map<Anope::string> item_map;
|
||||
@@ -41,7 +39,7 @@ namespace Configuration
|
||||
Block(const Anope::string &);
|
||||
const Anope::string &GetName() const;
|
||||
int CountBlock(const Anope::string &name) const;
|
||||
const Block *GetBlock(const Anope::string &name, int num = 0) const;
|
||||
const Block &GetBlock(const Anope::string &name, int num = 0) const;
|
||||
Block *GetMutableBlock(const Anope::string &name, int num = 0);
|
||||
|
||||
template<typename T> T Get(const Anope::string &tag, const Anope::string &def = "") const
|
||||
@@ -56,10 +54,6 @@ namespace Configuration
|
||||
template<> CoreExport const Anope::string Block::Get(const Anope::string &tag, const Anope::string &def) const;
|
||||
template<> CoreExport time_t Block::Get(const Anope::string &tag, const Anope::string &def) const;
|
||||
template<> CoreExport bool Block::Get(const Anope::string &tag, const Anope::string &def) const;
|
||||
} // namespace Internal
|
||||
|
||||
typedef const Internal::Block Block;
|
||||
typedef Internal::Block MutableBlock;
|
||||
|
||||
/** Represents a configuration file
|
||||
*/
|
||||
@@ -83,9 +77,14 @@ namespace Configuration
|
||||
|
||||
struct Uplink;
|
||||
|
||||
struct CoreExport Conf final
|
||||
: Block
|
||||
class CoreExport Conf final
|
||||
: public Block
|
||||
{
|
||||
private:
|
||||
/** Replaces defined variables within a string. */
|
||||
Anope::string ReplaceVars(const Anope::string &str, const File &file, int linenumber);
|
||||
|
||||
public:
|
||||
/* options:readtimeout */
|
||||
time_t ReadTimeout;
|
||||
/* If we should default to privmsging clients */
|
||||
@@ -126,12 +125,12 @@ namespace Configuration
|
||||
void LoadConf(File &file);
|
||||
void Post(Conf *old);
|
||||
|
||||
Block *GetModule(const Module *);
|
||||
Block *GetModule(const Anope::string &name);
|
||||
Block &GetModule(const Module *);
|
||||
Block &GetModule(const Anope::string &name);
|
||||
|
||||
BotInfo *GetClient(const Anope::string &name);
|
||||
|
||||
const Block *GetCommand(CommandSource &);
|
||||
const Block &GetCommand(CommandSource &);
|
||||
};
|
||||
|
||||
struct Uplink final
|
||||
@@ -144,6 +143,7 @@ namespace Configuration
|
||||
Uplink(const Anope::string &_host, int _port, const Anope::string &_password, int _protocol) : host(_host), port(_port), password(_password), protocol(_protocol) { }
|
||||
inline bool operator==(const Uplink &other) const { return host == other.host && port == other.port && password == other.password && protocol == other.protocol; }
|
||||
inline bool operator!=(const Uplink &other) const { return !(*this == other); }
|
||||
Anope::string str() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ struct ChanUserContainer;
|
||||
class ClientSocket;
|
||||
class Command;
|
||||
class CommandSource;
|
||||
namespace Configuration { struct Conf; }
|
||||
namespace Configuration { class Conf; }
|
||||
class ConnectionSocket;
|
||||
namespace DNS { struct Query; }
|
||||
class Entry;
|
||||
|
||||
+11
-11
@@ -100,18 +100,18 @@ namespace Language
|
||||
} // namespace Language
|
||||
|
||||
/* Commonly used language strings */
|
||||
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s DROP %s %s\002")
|
||||
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s\032%s\032%s\002")
|
||||
#define SERVICE_UNAVAILABLE _("Sorry, %s is temporarily unavailable.")
|
||||
#define MORE_INFO _("\002%s HELP %s\002 for more information.")
|
||||
#define MORE_INFO _("\002%s\002 for more information.")
|
||||
#define BAD_USERHOST_MASK _("Mask must be in the form \037user\037@\037host\037.")
|
||||
#define BAD_EXPIRY_TIME _("Invalid expiry time.")
|
||||
#define USERHOST_MASK_TOO_WIDE _("%s coverage is too wide; Please use a more specific mask.")
|
||||
#define READ_ONLY_MODE _("Services are temporarily in read-only mode.")
|
||||
#define PASSWORD_INCORRECT _("Password incorrect.")
|
||||
#define ACCESS_DENIED _("Access denied.")
|
||||
#define MORE_OBSCURE_PASSWORD _("Please try again with a more obscure password. Passwords should not be\n" \
|
||||
"something that could be easily guessed (e.g. your real name or your nick) and\n" \
|
||||
"cannot contain the space or tab characters.\n")
|
||||
#define MORE_OBSCURE_PASSWORD _("Please try again with a more obscure password. Passwords should not be " \
|
||||
"something that could be easily guessed (e.g. your real name or your nick) and " \
|
||||
"cannot contain the space or tab characters.")
|
||||
#define PASSWORD_TOO_SHORT _("Your password is too short. It must be longer than %u characters.")
|
||||
#define PASSWORD_TOO_LONG _("Your password is too long. It must be shorter than %u characters.")
|
||||
#define NICK_NOT_REGISTERED _("Your nick isn't registered.")
|
||||
@@ -127,8 +127,8 @@ namespace Language
|
||||
#define UNKNOWN _("<unknown>")
|
||||
#define NO_EXPIRE _("does not expire")
|
||||
#define LIST_INCORRECT_RANGE _("Incorrect range specified. The correct syntax is \002#\037from\037-\037to\037\002.")
|
||||
#define NICK_IS_SECURE _("This nickname is registered and protected. If it is your\n" \
|
||||
"nick, type \002%s IDENTIFY \037password\037\002. Otherwise,\n" \
|
||||
#define NICK_IS_SECURE _("This nickname is registered and protected. If it is your " \
|
||||
"nick, type \002%s\032\037password\037\002. Otherwise, " \
|
||||
"please choose a different nick.")
|
||||
#define FORCENICKCHANGE_NOW _("This nickname has been registered; you may not use it.")
|
||||
#define NICK_CANNOT_BE_REGISTERED _("Nickname \002%s\002 may not be registered.")
|
||||
@@ -145,10 +145,10 @@ namespace Language
|
||||
#define CHAN_ACCESS_LEVEL_RANGE _("Access level must be between %d and %d inclusive.")
|
||||
#define CHAN_INFO_HEADER _("Information about channel \002%s\002:")
|
||||
#define CHAN_EXCEPTED _("\002%s\002 matches an except on %s and cannot be banned until the except has been removed.")
|
||||
#define MEMO_NEW_X_MEMO_ARRIVED _("There is a new memo on channel %s.\n" \
|
||||
"Type \002%s READ %s %zu\002 to read it.")
|
||||
#define MEMO_NEW_MEMO_ARRIVED _("You have a new memo from %s.\n" \
|
||||
"Type \002%s READ %zu\002 to read it.")
|
||||
#define MEMO_NEW_X_MEMO_ARRIVED _("There is a new memo on channel %s. " \
|
||||
"Type \002%s\032%s\032%zu\002 to read it.")
|
||||
#define MEMO_NEW_MEMO_ARRIVED _("You have a new memo from %s. " \
|
||||
"Type \002%s\032%zu\002 to read it.")
|
||||
#define MEMO_HAVE_NO_MEMOS _("You have no memos.")
|
||||
#define MEMO_X_HAS_NO_MEMOS _("%s has no memos.")
|
||||
#define MEMO_HAVE_NO_NEW_MEMOS _("You have no new memos.")
|
||||
|
||||
+9
-4
@@ -18,15 +18,20 @@ class CoreExport Memo final
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
MemoInfo *mi;
|
||||
bool unread;
|
||||
bool receipt;
|
||||
Memo();
|
||||
~Memo();
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
Anope::string owner;
|
||||
/* When it was sent */
|
||||
time_t time;
|
||||
@@ -41,7 +46,7 @@ struct CoreExport MemoInfo final
|
||||
{
|
||||
int16_t memomax = 0;
|
||||
Serialize::Checker<std::vector<Memo *> > memos;
|
||||
std::vector<Anope::string> ignores;
|
||||
std::set<Anope::string, ci::less> ignores;
|
||||
|
||||
MemoInfo();
|
||||
Memo *GetMemo(unsigned index) const;
|
||||
|
||||
@@ -45,6 +45,13 @@ namespace Message
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override;
|
||||
};
|
||||
|
||||
struct CoreExport Ignore final
|
||||
: IRCDMessage
|
||||
{
|
||||
Ignore(Module *creator, const Anope::string &mname);
|
||||
void Run(MessageSource &source, const std::vector<Anope::string> ¶ms, const Anope::map<Anope::string> &tags) override;
|
||||
};
|
||||
|
||||
struct CoreExport Invite
|
||||
: IRCDMessage
|
||||
{
|
||||
|
||||
+4
-4
@@ -45,7 +45,7 @@
|
||||
#include "users.h"
|
||||
#include "xline.h"
|
||||
|
||||
#include "modules/pseudoclients/chanserv.h"
|
||||
#include "modules/pseudoclients/global.h"
|
||||
#include "modules/pseudoclients/memoserv.h"
|
||||
#include "modules/pseudoclients/nickserv.h"
|
||||
#include "modules/chanserv/service.h"
|
||||
#include "modules/global/service.h"
|
||||
#include "modules/memoserv/service.h"
|
||||
#include "modules/nickserv/service.h"
|
||||
|
||||
+133
-22
@@ -305,7 +305,7 @@ public:
|
||||
* @param conf The config that is being built now and will replace the global Config object
|
||||
* @throws A ConfigException to abort the config (re)loading process.
|
||||
*/
|
||||
virtual void OnReload(Configuration::Conf *conf) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
|
||||
virtual void OnReload(Configuration::Conf &conf) { throw NotImplementedException(); }
|
||||
|
||||
/** Called before a bot is assigned to a channel.
|
||||
* @param sender The user assigning the bot
|
||||
@@ -1068,28 +1068,139 @@ public:
|
||||
|
||||
enum Implementation
|
||||
{
|
||||
I_IsServicesOper,
|
||||
I_OnAccessAdd,
|
||||
I_OnAccessClear,
|
||||
I_OnAccessDel,
|
||||
I_OnAddXLine,
|
||||
I_OnAkickAdd,
|
||||
I_OnAkickDel,
|
||||
I_OnBadWordAdd,
|
||||
I_OnBadWordDel,
|
||||
I_OnBotAssign,
|
||||
I_OnBotBan,
|
||||
I_OnBotChange,
|
||||
I_OnBotCreate,
|
||||
I_OnBotDelete,
|
||||
I_OnBotFantasy,
|
||||
I_OnBotInfo,
|
||||
I_OnBotKick,
|
||||
I_OnBotNoFantasyAccess,
|
||||
I_OnBotNotice,
|
||||
I_OnBotPrivmsg,
|
||||
I_OnBotUnAssign,
|
||||
I_OnCanSet,
|
||||
I_OnChanDrop,
|
||||
I_OnChanExpire,
|
||||
I_OnChangeCoreDisplay,
|
||||
I_OnChanInfo,
|
||||
I_OnChannelCreate,
|
||||
I_OnChannelDelete,
|
||||
I_OnChannelModeAdd,
|
||||
I_OnChannelModeSet,
|
||||
I_OnChannelModeUnset,
|
||||
I_OnChannelSync,
|
||||
I_OnChanRegistered,
|
||||
I_OnChanSuspend,
|
||||
I_OnChanUnsuspend,
|
||||
I_OnCheckAuthentication,
|
||||
I_OnCheckDelete,
|
||||
I_OnCheckKick,
|
||||
I_OnCheckModes,
|
||||
I_OnCheckPriv,
|
||||
I_OnCreateBot,
|
||||
I_OnCreateChan,
|
||||
I_OnDecrypt,
|
||||
I_OnDefconLevel,
|
||||
I_OnDelBot,
|
||||
I_OnDelChan,
|
||||
I_OnDelCore,
|
||||
I_OnDeleteVHost,
|
||||
I_OnDelNick,
|
||||
I_OnDelXLine,
|
||||
I_OnDnsRequest,
|
||||
I_OnEncrypt,
|
||||
I_OnExceptionAdd,
|
||||
I_OnExceptionDel,
|
||||
I_OnExpireTick,
|
||||
I_OnFingerprint,
|
||||
I_OnGroupCheckPriv,
|
||||
I_OnInvite,
|
||||
I_OnJoinChannel,
|
||||
I_OnLeaveChannel,
|
||||
I_OnLevelChange,
|
||||
I_OnLoadDatabase,
|
||||
I_OnLog,
|
||||
I_OnLogMessage,
|
||||
I_OnMemoDel,
|
||||
I_OnMemoSend,
|
||||
I_OnMessage,
|
||||
I_OnMLock,
|
||||
I_OnModuleLoad,
|
||||
I_OnModuleUnload,
|
||||
I_OnNewServer,
|
||||
I_OnNickAddCert,
|
||||
I_OnNickClearCert,
|
||||
I_OnNickConfirm,
|
||||
I_OnNickCoreCreate,
|
||||
I_OnNickDrop,
|
||||
I_OnNickEraseCert,
|
||||
I_OnNickExpire,
|
||||
I_OnNickGroup,
|
||||
I_OnNickIdentify,
|
||||
I_OnNickInfo,
|
||||
I_OnNickLogout,
|
||||
I_OnNickRegister,
|
||||
I_OnNickSuspend,
|
||||
I_OnNickUnsuspended,
|
||||
I_OnNickUpdate,
|
||||
I_OnNickValidate,
|
||||
I_OnPartChannel,
|
||||
I_OnPostCommand,
|
||||
I_OnPostHelp,
|
||||
I_OnPostInit,
|
||||
I_OnPreUserKicked, I_OnUserKicked, I_OnReload, I_OnPreBotAssign, I_OnBotAssign, I_OnBotUnAssign, I_OnUserConnect,
|
||||
I_OnNewServer, I_OnUserNickChange, I_OnPreHelp, I_OnPostHelp, I_OnPreCommand, I_OnPostCommand, I_OnSaveDatabase,
|
||||
I_OnLoadDatabase, I_OnEncrypt, I_OnDecrypt, I_OnBotFantasy, I_OnBotNoFantasyAccess, I_OnBotBan, I_OnBadWordAdd,
|
||||
I_OnBadWordDel, I_OnCreateBot, I_OnDelBot, I_OnBotKick, I_OnPrePartChannel, I_OnPartChannel, I_OnLeaveChannel,
|
||||
I_OnJoinChannel, I_OnTopicUpdated, I_OnPreChanExpire, I_OnChanExpire, I_OnPreServerConnect, I_OnServerConnect,
|
||||
I_OnPreUplinkSync, I_OnServerDisconnect, I_OnRestart, I_OnShutdown, I_OnPreNickExpire, I_OnNickExpire, I_OnDefconLevel,
|
||||
I_OnExceptionAdd, I_OnExceptionDel, I_OnAddXLine, I_OnDelXLine, I_IsServicesOper, I_OnServerQuit, I_OnUserQuit,
|
||||
I_OnPreUserLogoff, I_OnPostUserLogoff, I_OnBotCreate, I_OnBotChange, I_OnBotDelete, I_OnAccessDel, I_OnAccessAdd,
|
||||
I_OnAccessClear, I_OnLevelChange, I_OnChanDrop, I_OnChanRegistered, I_OnChanSuspend, I_OnChanUnsuspend,
|
||||
I_OnCreateChan, I_OnDelChan, I_OnChannelCreate, I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick,
|
||||
I_OnChanInfo, I_OnCheckPriv, I_OnGroupCheckPriv, I_OnNickDrop, I_OnNickGroup, I_OnNickIdentify,
|
||||
I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickConfirm, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate,
|
||||
I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearCert,
|
||||
I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnBotInfo, I_OnCheckAuthentication, I_OnNickUpdate,
|
||||
I_OnFingerprint, I_OnUserAway, I_OnInvite, I_OnDeleteVHost, I_OnSetVHost, I_OnSetDisplayedHost, I_OnMemoSend, I_OnMemoDel,
|
||||
I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd,
|
||||
I_OnMLock, I_OnUnMLock, I_OnModuleLoad, I_OnModuleUnload, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnBotNotice,
|
||||
I_OnPrivmsg, I_OnLog, I_OnLogMessage, I_OnDnsRequest, I_OnCheckModes, I_OnChannelSync, I_OnSetCorrectModes,
|
||||
I_OnSerializeCheck, I_OnSerializableConstruct, I_OnSerializableDestruct, I_OnSerializableUpdate,
|
||||
I_OnSerializeTypeCreate, I_OnSetChannelOption, I_OnSetNickOption, I_OnMessage, I_OnCanSet, I_OnCheckDelete,
|
||||
I_OnExpireTick, I_OnNickValidate,
|
||||
I_OnPostUserLogoff,
|
||||
I_OnPreBotAssign,
|
||||
I_OnPreChanExpire,
|
||||
I_OnPreCommand,
|
||||
I_OnPreHelp,
|
||||
I_OnPreNickExpire,
|
||||
I_OnPrePartChannel,
|
||||
I_OnPreServerConnect,
|
||||
I_OnPreUplinkSync,
|
||||
I_OnPreUserKicked,
|
||||
I_OnPreUserLogoff,
|
||||
I_OnPrivmsg,
|
||||
I_OnReload,
|
||||
I_OnRestart,
|
||||
I_OnSaveDatabase,
|
||||
I_OnSerializableConstruct,
|
||||
I_OnSerializableDestruct,
|
||||
I_OnSerializableUpdate,
|
||||
I_OnSerializeCheck,
|
||||
I_OnSerializeTypeCreate,
|
||||
I_OnServerConnect,
|
||||
I_OnServerDisconnect,
|
||||
I_OnServerQuit,
|
||||
I_OnServerSync,
|
||||
I_OnSetChannelOption,
|
||||
I_OnSetCorrectModes,
|
||||
I_OnSetDisplayedHost,
|
||||
I_OnSetNickOption,
|
||||
I_OnSetVHost,
|
||||
I_OnShutdown,
|
||||
I_OnTopicUpdated,
|
||||
I_OnUnMLock,
|
||||
I_OnUplinkSync,
|
||||
I_OnUserAway,
|
||||
I_OnUserConnect,
|
||||
I_OnUserKicked,
|
||||
I_OnUserLogin,
|
||||
I_OnUserModeAdd,
|
||||
I_OnUserModeSet,
|
||||
I_OnUserModeUnset,
|
||||
I_OnUserNickChange,
|
||||
I_OnUserQuit,
|
||||
I_SIZE
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2014-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace SASL
|
||||
{
|
||||
class Mechanism;
|
||||
struct Message;
|
||||
class ProtocolInterface;
|
||||
struct Service;
|
||||
struct Session;
|
||||
|
||||
/** The SASL interface implemented by the protocol modules. */
|
||||
static ServiceReference<SASL::ProtocolInterface> protocol_interface("SASL::ProtocolInterface", "sasl");
|
||||
|
||||
/** The SASL interface implemented by ns_sasl. */
|
||||
static ServiceReference<SASL::Service> service("SASL::Service", "sasl");
|
||||
}
|
||||
|
||||
/** Represents a single SASL message. */
|
||||
struct SASL::Message final
|
||||
{
|
||||
/** The source UID or name. */
|
||||
Anope::string source;
|
||||
|
||||
/** The target UID or name. */
|
||||
Anope::string target;
|
||||
|
||||
/** The type of message. */
|
||||
Anope::string type;
|
||||
|
||||
/** One or more data parameters. */
|
||||
std::vector<Anope::string> data;
|
||||
};
|
||||
|
||||
/** Sends IRCd messages used by the SASL module. */
|
||||
class SASL::ProtocolInterface
|
||||
: public ::Service
|
||||
{
|
||||
protected:
|
||||
ProtocolInterface(Module *o)
|
||||
: ::Service(o, "SASL::ProtocolInterface", "sasl")
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/** Sends the list of SASL mechanisms to the IRCd
|
||||
* @param mechs The list of SASL mechanisms.
|
||||
*/
|
||||
virtual void SendSASLMechanisms(std::vector<Anope::string> &mechs) { };
|
||||
|
||||
/** Sends a SASL message to the IRCd.
|
||||
* @param message The SASL message to send.
|
||||
*/
|
||||
virtual void SendSASLMessage(const SASL::Message &message) = 0;
|
||||
|
||||
/** Sends a login or logout for \p uid to \p na.
|
||||
* @param uid The uid of the user to log in.
|
||||
* @param na The nick alias to log the user in as or logout if nullptr.
|
||||
*/
|
||||
virtual void SendSVSLogin(const Anope::string &uid, NickAlias *na) = 0;
|
||||
};
|
||||
|
||||
/** SASL service interface. */
|
||||
struct SASL::Service
|
||||
: ::Service
|
||||
{
|
||||
Service(Module *o)
|
||||
: ::Service(o, "SASL::Service", "sasl")
|
||||
{
|
||||
}
|
||||
|
||||
virtual void DeleteSessions(Mechanism *mech, bool da = false) = 0;
|
||||
|
||||
/** Fails a SASL session. This notifies the client and increments the
|
||||
* failed attempt counter which may kill the client if the bad password
|
||||
* limit has been reached.
|
||||
*
|
||||
* @param sess The session to fail.
|
||||
*/
|
||||
virtual void Fail(Session *sess) = 0;
|
||||
|
||||
/** Retrieves the session for the specified user identifier. */
|
||||
virtual Session *GetSession(const Anope::string &uid) = 0;
|
||||
|
||||
/** Processes a SASL authentication message from the uplink.
|
||||
* @param m The message to process.
|
||||
*/
|
||||
virtual void ProcessMessage(const Message &m) = 0;
|
||||
|
||||
/** Removes the specified SASL session from the service.
|
||||
* @param sess The session to remove.
|
||||
*/
|
||||
virtual void RemoveSession(Session *sess) = 0;
|
||||
|
||||
/** Sends a SASL message for the specified session.
|
||||
* @param type The type of message to send.
|
||||
* @param data The contents of the SASL message.
|
||||
*/
|
||||
virtual void SendMessage(SASL::Session *sess, const Anope::string &type, const Anope::string &data) = 0;
|
||||
|
||||
/** Completes a successful authentication.
|
||||
* @param sess The session which finished authentication.
|
||||
* @param nc The account which has been logged into.
|
||||
*/
|
||||
virtual void Succeed(Session *sess, NickCore *nc) = 0;
|
||||
};
|
||||
|
||||
/** Represents a single SASL session. */
|
||||
struct SASL::Session
|
||||
{
|
||||
/** The time at which the session was created. */
|
||||
const time_t created;
|
||||
|
||||
/** The hostname and IP address of the authenticating user. */
|
||||
Anope::string hostname, ip;
|
||||
|
||||
/** A reference to the mechanism that the session is authenticating using. */
|
||||
Reference<Mechanism> mech;
|
||||
|
||||
/** The unique identifier of the authenticating user. */
|
||||
const Anope::string uid;
|
||||
|
||||
/** Creates a new authentication session.
|
||||
* @param m The mechanism that the session is authenticating with.
|
||||
* @param u The unique identifier of the authenticating user.
|
||||
*/
|
||||
Session(Mechanism *m, const Anope::string &u)
|
||||
: created(Anope::CurTime)
|
||||
, mech(m)
|
||||
, uid(u)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Session()
|
||||
{
|
||||
if (service)
|
||||
service->RemoveSession(this);
|
||||
}
|
||||
|
||||
/** Retrieves a description of the user this session is associated with. */
|
||||
inline Anope::string GetUserInfo()
|
||||
{
|
||||
auto *u = User::Find(uid);
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return "A user";
|
||||
};
|
||||
};
|
||||
|
||||
/* Represents an authentication mechanism. */
|
||||
class SASL::Mechanism
|
||||
: public ::Service
|
||||
{
|
||||
protected:
|
||||
/** Creates a new authentication mechanism.
|
||||
* @param o The module that owns this instance.
|
||||
* @param sname The name of the authentication mechanism (e.g. PLAIN).
|
||||
*/
|
||||
Mechanism(Module *o, const Anope::string &sname)
|
||||
: Service(o, "SASL::Mechanism", sname)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~Mechanism()
|
||||
{
|
||||
if (service)
|
||||
service->DeleteSessions(this, true);
|
||||
}
|
||||
|
||||
/** Creates a new SASL session.
|
||||
* @param uid The unique identifier of the authenticating user.
|
||||
*/
|
||||
virtual Session *CreateSession(const Anope::string &uid)
|
||||
{
|
||||
return new Session(this, uid);
|
||||
}
|
||||
|
||||
/** Processes an authentication message from the authenticating user.
|
||||
* @param session The session for which the message applies.
|
||||
* @param m The message sent by the user.
|
||||
* @return True if the message was processed successfully or false if
|
||||
* the session should be aborted.
|
||||
*/
|
||||
virtual bool ProcessMessage(Session *sess, const Message &m) = 0;
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2011-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct MyOper final
|
||||
: Oper
|
||||
, Serializable
|
||||
{
|
||||
MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
|
||||
};
|
||||
@@ -28,8 +28,6 @@ struct Exception final
|
||||
time_t expires; /* Time when it expires. 0 == no expiry */
|
||||
|
||||
Exception() : Serializable("Exception") { }
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
class SessionService
|
||||
@@ -59,35 +57,3 @@ public:
|
||||
};
|
||||
|
||||
static ServiceReference<SessionService> session_service("SessionService", "session");
|
||||
|
||||
void Exception::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
data.Store("mask", this->mask);
|
||||
data.Store("limit", this->limit);
|
||||
data.Store("who", this->who);
|
||||
data.Store("reason", this->reason);
|
||||
data.Store("time", this->time);
|
||||
data.Store("expires", this->expires);
|
||||
}
|
||||
|
||||
Serializable *Exception::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
if (!session_service)
|
||||
return NULL;
|
||||
|
||||
Exception *ex;
|
||||
if (obj)
|
||||
ex = anope_dynamic_static_cast<Exception *>(obj);
|
||||
else
|
||||
ex = new Exception;
|
||||
data["mask"] >> ex->mask;
|
||||
data["limit"] >> ex->limit;
|
||||
data["who"] >> ex->who;
|
||||
data["reason"] >> ex->reason;
|
||||
data["time"] >> ex->time;
|
||||
data["expires"] >> ex->expires;
|
||||
|
||||
if (!obj)
|
||||
session_service->AddException(ex);
|
||||
return ex;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2011-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct MyOper final
|
||||
: Oper
|
||||
, Serializable
|
||||
{
|
||||
MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
{
|
||||
data.Store("name", this->name);
|
||||
data.Store("type", this->ot->GetName());
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
Anope::string stype, sname;
|
||||
|
||||
data["type"] >> stype;
|
||||
data["name"] >> sname;
|
||||
|
||||
OperType *ot = OperType::Find(stype);
|
||||
if (ot == NULL)
|
||||
return NULL;
|
||||
NickCore *nc = NickCore::Find(sname);
|
||||
if (nc == NULL)
|
||||
return NULL;
|
||||
|
||||
MyOper *myo;
|
||||
if (obj)
|
||||
myo = anope_dynamic_static_cast<MyOper *>(obj);
|
||||
else
|
||||
myo = new MyOper(nc->display, ot);
|
||||
nc->o = myo;
|
||||
Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
|
||||
return myo;
|
||||
}
|
||||
};
|
||||
+7
-16
@@ -21,9 +21,6 @@ namespace RPC
|
||||
class ServiceInterface;
|
||||
class Value;
|
||||
|
||||
/** Represents a list of registered events. */
|
||||
using Events = Anope::map<Event *>;
|
||||
|
||||
/** Represents possible types of RPC value. */
|
||||
using ValueUnion = std::variant<Array, Map, Anope::string, std::nullptr_t, bool, double, int64_t, uint64_t>;
|
||||
|
||||
@@ -169,15 +166,17 @@ public:
|
||||
inline const auto &GetRoot() const { return this->root; }
|
||||
};
|
||||
|
||||
#define RPC_EVENT "RPC::Event"
|
||||
|
||||
class RPC::Event
|
||||
: public Service
|
||||
{
|
||||
private:
|
||||
Anope::string event;
|
||||
size_t minparams;
|
||||
|
||||
protected:
|
||||
Event(const Anope::string& e, size_t mp = 0)
|
||||
: event(e)
|
||||
Event(Module *o, const Anope::string& e, size_t mp = 0)
|
||||
: Service(o, RPC_EVENT, e)
|
||||
, minparams(mp)
|
||||
{
|
||||
}
|
||||
@@ -185,8 +184,6 @@ protected:
|
||||
public:
|
||||
virtual ~Event() = default;
|
||||
|
||||
const auto &GetEvent() const { return event; }
|
||||
|
||||
const auto &GetMinParams() const { return minparams; }
|
||||
|
||||
virtual bool Run(ServiceInterface *iface, HTTPClient *client, Request &request) = 0;
|
||||
@@ -196,17 +193,11 @@ class RPC::ServiceInterface
|
||||
: public Service
|
||||
{
|
||||
public:
|
||||
ServiceInterface(Module *creator, const Anope::string &sname)
|
||||
: Service(creator, "RPCServiceInterface", sname)
|
||||
ServiceInterface(Module *creator)
|
||||
: Service(creator, "RPC::ServiceInterface", "rpc")
|
||||
{
|
||||
}
|
||||
|
||||
virtual const Events &GetEvents() = 0;
|
||||
|
||||
virtual bool Register(Event *event) = 0;
|
||||
|
||||
virtual bool Unregister(Event *event) = 0;
|
||||
|
||||
virtual void Reply(Request &request) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2014-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace SASL
|
||||
{
|
||||
struct Message final
|
||||
{
|
||||
Anope::string source;
|
||||
Anope::string target;
|
||||
Anope::string type;
|
||||
std::vector<Anope::string> data;
|
||||
};
|
||||
|
||||
class Mechanism;
|
||||
struct Session;
|
||||
|
||||
class Service
|
||||
: public ::Service
|
||||
{
|
||||
public:
|
||||
Service(Module *o) : ::Service(o, "SASL::Service", "sasl") { }
|
||||
|
||||
virtual void ProcessMessage(const Message &) = 0;
|
||||
|
||||
virtual Anope::string GetAgent() = 0;
|
||||
|
||||
virtual Session *GetSession(const Anope::string &uid) = 0;
|
||||
|
||||
virtual void SendMessage(SASL::Session *session, const Anope::string &type, const Anope::string &data) = 0;
|
||||
|
||||
virtual void Succeed(Session *, NickCore *) = 0;
|
||||
virtual void Fail(Session *) = 0;
|
||||
virtual void SendMechs(Session *) = 0;
|
||||
virtual void DeleteSessions(Mechanism *, bool = false) = 0;
|
||||
virtual void RemoveSession(Session *) = 0;
|
||||
};
|
||||
|
||||
static ServiceReference<SASL::Service> sasl("SASL::Service", "sasl");
|
||||
|
||||
struct Session
|
||||
{
|
||||
time_t created;
|
||||
Anope::string uid;
|
||||
Anope::string hostname, ip;
|
||||
Reference<Mechanism> mech;
|
||||
|
||||
Session(Mechanism *m, const Anope::string &u) : created(Anope::CurTime), uid(u), mech(m) { }
|
||||
|
||||
inline Anope::string GetUserInfo()
|
||||
{
|
||||
auto *u = User::Find(uid);
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return "A user";
|
||||
};
|
||||
|
||||
virtual ~Session()
|
||||
{
|
||||
if (sasl)
|
||||
sasl->RemoveSession(this);
|
||||
}
|
||||
};
|
||||
|
||||
/* PLAIN, EXTERNAL, etc */
|
||||
class Mechanism
|
||||
: public ::Service
|
||||
{
|
||||
public:
|
||||
Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { }
|
||||
|
||||
virtual Session *CreateSession(const Anope::string &uid) { return new Session(this, uid); }
|
||||
|
||||
virtual bool ProcessMessage(Session *session, const Message &) = 0;
|
||||
|
||||
virtual ~Mechanism()
|
||||
{
|
||||
if (sasl)
|
||||
sasl->DeleteSessions(this, true);
|
||||
}
|
||||
};
|
||||
|
||||
class IdentifyRequest
|
||||
: public ::IdentifyRequest
|
||||
{
|
||||
Anope::string uid;
|
||||
Anope::string hostname;
|
||||
|
||||
inline Anope::string GetUserInfo()
|
||||
{
|
||||
auto *u = User::Find(uid);
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !GetAddress().empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), GetAddress().c_str());
|
||||
return "A user";
|
||||
};
|
||||
|
||||
public:
|
||||
IdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass, const Anope::string &h, const Anope::string &i)
|
||||
: ::IdentifyRequest(m, acc, pass, i)
|
||||
, uid(id)
|
||||
, hostname(h)
|
||||
{
|
||||
}
|
||||
|
||||
void OnSuccess() override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
NickAlias *na = NickAlias::Find(GetAccount());
|
||||
if (!na || na->nc->HasExt("NS_SUSPENDED") || na->nc->HasExt("UNCONFIRMED"))
|
||||
return OnFail();
|
||||
|
||||
unsigned int maxlogins = Config->GetModule("ns_identify")->Get<unsigned int>("maxlogins");
|
||||
if (maxlogins && na->nc->users.size() >= maxlogins)
|
||||
return OnFail();
|
||||
|
||||
Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
{
|
||||
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << GetUserInfo() << " identified to account " << this->GetAccount() << " using SASL";
|
||||
sasl->Succeed(s, na->nc);
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFail() override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
{
|
||||
sasl->Fail(s);
|
||||
delete s;
|
||||
}
|
||||
|
||||
Anope::string accountstatus;
|
||||
NickAlias *na = NickAlias::Find(GetAccount());
|
||||
if (!na)
|
||||
accountstatus = "nonexistent ";
|
||||
else if (na->nc->HasExt("NS_SUSPENDED"))
|
||||
accountstatus = "suspended ";
|
||||
else if (na->nc->HasExt("UNCONFIRMED"))
|
||||
accountstatus = "unconfirmed ";
|
||||
|
||||
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << GetUserInfo() << " failed to identify for " << accountstatus << "account " << this->GetAccount() << " using SASL";
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,7 +19,6 @@ namespace SQL
|
||||
public:
|
||||
typedef std::map<Anope::string, std::stringstream *> Map;
|
||||
Map data;
|
||||
std::map<Anope::string, Serialize::DataType> types;
|
||||
|
||||
~Data()
|
||||
{
|
||||
@@ -59,19 +58,6 @@ namespace SQL
|
||||
delete value;
|
||||
this->data.clear();
|
||||
}
|
||||
|
||||
void SetType(const Anope::string &key, Serialize::DataType dt) override
|
||||
{
|
||||
this->types[key] = dt;
|
||||
}
|
||||
|
||||
Serialize::DataType GetType(const Anope::string &key) const override
|
||||
{
|
||||
auto it = this->types.find(key);
|
||||
if (it != this->types.end())
|
||||
return it->second;
|
||||
return Serialize::DataType::TEXT;
|
||||
}
|
||||
};
|
||||
|
||||
/** A SQL exception, can be thrown at various points
|
||||
|
||||
@@ -23,6 +23,7 @@ struct CoreExport Oper
|
||||
/* Whether the user must be an IRC operator (umode +o) to be considered a services operator */
|
||||
bool require_oper = true;
|
||||
Anope::string password;
|
||||
Anope::string password_hash;
|
||||
std::vector<Anope::string> certfp;
|
||||
/* Hosts allowed to use this operator block */
|
||||
std::vector<Anope::string> hosts;
|
||||
|
||||
+5
-9
@@ -107,8 +107,8 @@ public:
|
||||
/* If this IRCd has unique ids, whether the IDs and nicknames are ambiguous */
|
||||
bool AmbiguousID = false;
|
||||
|
||||
/** Can we ask the server to unban a user? */
|
||||
bool CanClearBans = false;
|
||||
/** Can we ask the server to remove list modes matching a user? */
|
||||
std::set<Anope::string> CanClearModes;
|
||||
|
||||
/** Can we send tag messages? */
|
||||
bool CanTagMessage = false;
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
virtual void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
|
||||
virtual void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
|
||||
|
||||
virtual void SendQuit(User *u, const Anope::string &msg);
|
||||
virtual void SendQuit(User *u, const Anope::string &msg = "", const Anope::string &opermsg = "");
|
||||
virtual void SendPing(const Anope::string &servname, const Anope::string &who);
|
||||
virtual void SendPong(const Anope::string &servname, const Anope::string &who);
|
||||
|
||||
@@ -304,11 +304,7 @@ public:
|
||||
*/
|
||||
virtual void SendOper(User *u);
|
||||
|
||||
virtual void SendClearBans(const MessageSource &user, Channel *c, User* u) { }
|
||||
|
||||
virtual void SendSASLMechanisms(std::vector<Anope::string> &) { }
|
||||
virtual void SendSASLMessage(const SASL::Message &) { }
|
||||
virtual void SendSVSLogin(const Anope::string &uid, NickAlias *na) { }
|
||||
virtual void SendClearModes(const MessageSource &user, Channel *c, User* u, const Anope::string &mode) { }
|
||||
|
||||
virtual bool IsNickValid(const Anope::string &);
|
||||
virtual bool IsChannelValid(const Anope::string &);
|
||||
@@ -366,7 +362,7 @@ public:
|
||||
FLAG_MAX,
|
||||
};
|
||||
|
||||
private:
|
||||
protected:
|
||||
/** The name of the message (e.g. PRIVMSG). */
|
||||
const Anope::string name;
|
||||
|
||||
|
||||
+22
-10
@@ -25,6 +25,14 @@ class CoreExport AutoKick final
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
/* Channel this autokick is on */
|
||||
Serialize::Reference<ChannelInfo> ci;
|
||||
|
||||
@@ -38,8 +46,6 @@ public:
|
||||
|
||||
AutoKick();
|
||||
~AutoKick();
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
};
|
||||
|
||||
/* It matters that Base is here before Extensible (it is inherited by Serializable)
|
||||
@@ -48,9 +54,18 @@ class CoreExport ChannelInfo final
|
||||
: public Serializable
|
||||
, public Extensible
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
/* channels who reference this one */
|
||||
Anope::map<int> references;
|
||||
private:
|
||||
Serialize::Reference<NickCore> founder; /* Channel founder */
|
||||
Serialize::Reference<NickCore> successor; /* Who gets the channel if the founder nick is dropped or expires */
|
||||
Serialize::Checker<std::vector<ChanAccess *> > access; /* List of authorized users */
|
||||
@@ -64,16 +79,16 @@ public:
|
||||
Anope::string name; /* Channel name */
|
||||
Anope::string desc;
|
||||
|
||||
time_t time_registered;
|
||||
time_t registered;
|
||||
time_t last_used;
|
||||
|
||||
Anope::string last_topic; /* The last topic that was set on this channel */
|
||||
Anope::string last_topic_setter; /* Setter */
|
||||
time_t last_topic_time; /* Time */
|
||||
time_t last_topic_time = 0; /* Time */
|
||||
|
||||
Channel::ModeList last_modes; /* The last modes set on this channel */
|
||||
|
||||
int16_t bantype;
|
||||
int16_t bantype = 2;
|
||||
|
||||
MemoInfo memos;
|
||||
|
||||
@@ -82,7 +97,7 @@ public:
|
||||
/* For BotServ */
|
||||
Serialize::Reference<BotInfo> bi; /* Bot used on this channel */
|
||||
|
||||
time_t banexpire; /* Time bans expire in */
|
||||
time_t banexpire = 0; /* Time bans expire in */
|
||||
|
||||
/** Constructor
|
||||
* @param chname The channel name
|
||||
@@ -97,9 +112,6 @@ public:
|
||||
~ChannelInfo();
|
||||
ChannelInfo &operator=(const ChannelInfo &) = default;
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Change the founder of the channel
|
||||
* @params nc The new founder
|
||||
*/
|
||||
|
||||
+93
-57
@@ -16,6 +16,16 @@
|
||||
#include "anope.h"
|
||||
#include "base.h"
|
||||
|
||||
/** Names of serialization types implemented in the core. */
|
||||
#define AUTOKICK_TYPE "AutoKick"
|
||||
#define BOTINFO_TYPE "BotInfo"
|
||||
#define CHANACCESS_TYPE "ChanAccess"
|
||||
#define CHANNELINFO_TYPE "ChannelInfo"
|
||||
#define MEMO_TYPE "Memo"
|
||||
#define NICKALIAS_TYPE "NickAlias"
|
||||
#define NICKCORE_TYPE "NickCore"
|
||||
#define XLINE_TYPE "XLine"
|
||||
|
||||
namespace Serialize
|
||||
{
|
||||
enum class DataType
|
||||
@@ -28,8 +38,11 @@ namespace Serialize
|
||||
UINT,
|
||||
};
|
||||
|
||||
class Data
|
||||
class CoreExport Data
|
||||
{
|
||||
protected:
|
||||
std::map<Anope::string, Serialize::DataType> types;
|
||||
|
||||
public:
|
||||
virtual ~Data() = default;
|
||||
|
||||
@@ -54,8 +67,8 @@ namespace Serialize
|
||||
|
||||
virtual size_t Hash() const { throw CoreException("Not supported"); }
|
||||
|
||||
virtual void SetType(const Anope::string &key, DataType dt) { }
|
||||
virtual DataType GetType(const Anope::string &key) const { return DataType::TEXT; }
|
||||
Serialize::DataType GetType(const Anope::string &key) const;
|
||||
void SetType(const Anope::string &key, Serialize::DataType dt);
|
||||
};
|
||||
|
||||
extern void RegisterTypes();
|
||||
@@ -97,10 +110,11 @@ protected:
|
||||
Serializable &operator=(const Serializable &);
|
||||
|
||||
public:
|
||||
using Id = uint64_t;
|
||||
virtual ~Serializable();
|
||||
|
||||
/* Unique ID (per type, not globally) for this object */
|
||||
uint64_t id = 0;
|
||||
Id id = 0;
|
||||
|
||||
/* Only used by redis, to ignore updates */
|
||||
unsigned short redis_ignore = 0;
|
||||
@@ -120,82 +134,104 @@ public:
|
||||
*/
|
||||
Serialize::Type *GetSerializableType() const { return this->s_type; }
|
||||
|
||||
virtual void Serialize(Serialize::Data &data) const = 0;
|
||||
|
||||
static const std::list<Serializable *> &GetItems();
|
||||
};
|
||||
|
||||
/* A serializable type. There should be one of these classes for each type
|
||||
* of class that inherits from Serializable. Used for unserializing objects
|
||||
* of this type, as it requires a function pointer to a static member function.
|
||||
/* A serializable type. There should be a single instance of a subclass of this
|
||||
* for each subclass of Serializable as this is what is used to serialize and
|
||||
* deserialize data from the database.
|
||||
*/
|
||||
class CoreExport Serialize::Type final
|
||||
class CoreExport Serialize::Type
|
||||
: public Base
|
||||
{
|
||||
typedef Serializable *(*unserialize_func)(Serializable *obj, Serialize::Data &);
|
||||
|
||||
static std::vector<Anope::string> TypeOrder;
|
||||
static std::map<Anope::string, Serialize::Type *> Types;
|
||||
|
||||
/* The name of this type, should be a class name */
|
||||
private:
|
||||
/** The name of this type in the database (e.g. NickAlias). */
|
||||
Anope::string name;
|
||||
unserialize_func unserialize;
|
||||
/* Owner of this type. Used for placing objects of this type in separate databases
|
||||
* based on what module, if any, owns it.
|
||||
|
||||
/** The module which owns this type, or nullptr if it belongs to the core.
|
||||
* Some database backends use this to put third-party module data into their
|
||||
* own database.
|
||||
*/
|
||||
Module *owner;
|
||||
|
||||
/* The timestamp for this type. All objects of this type are as up to date as
|
||||
* this timestamp. if curtime == timestamp then we have the most up to date
|
||||
* version of every object of this type.
|
||||
/** The time at which this type was last synchronised with the database.
|
||||
* Only used by live database backends like db_sql_live.
|
||||
*/
|
||||
time_t timestamp = 0;
|
||||
|
||||
public:
|
||||
/* Map of Serializable::id to Serializable objects */
|
||||
std::map<uint64_t, Serializable *> objects;
|
||||
/* The names of currently registered types in order of registration. */
|
||||
static std::vector<Anope::string> TypeOrder;
|
||||
|
||||
/** Creates a new serializable type
|
||||
* @param n Type name
|
||||
* @param f Func to unserialize objects
|
||||
* @param owner Owner of this type. Leave NULL for the core.
|
||||
/** The currently registered types. */
|
||||
static std::map<Anope::string, Serialize::Type *> Types;
|
||||
|
||||
protected:
|
||||
/** Creates a new serializable type.
|
||||
* @param n The name of the type . This should match the value passed in the
|
||||
* constructor of the equivalent Serializable type.
|
||||
* @param o The module which owns this type, or nullptr if it belongs to the
|
||||
* core.
|
||||
*/
|
||||
Type(const Anope::string &n, unserialize_func f, Module *owner = NULL);
|
||||
Type(const Anope::string &n, Module *o = nullptr);
|
||||
|
||||
public:
|
||||
/* Map of Serializable objects of this type keyed by their object id. */
|
||||
std::map<Serializable::Id, Serializable *> objects;
|
||||
|
||||
/** Destroys a serializable type. */
|
||||
~Type();
|
||||
|
||||
/** Gets the name for this type
|
||||
* @return The name, eg "NickAlias"
|
||||
*/
|
||||
const Anope::string &GetName() { return this->name; }
|
||||
|
||||
/** Unserialized an object.
|
||||
* @param obj NULL if this object doesn't yet exist. If this isn't NULL, instead
|
||||
* update the contents of this object.
|
||||
* @param data The data to unserialize
|
||||
* @return The unserialized object. If obj != NULL this should be obj.
|
||||
*/
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
|
||||
/** Check if this object type has any pending changes and update them.
|
||||
*/
|
||||
/** Checks for and applies any pending object updates for this type. */
|
||||
void Check();
|
||||
|
||||
/** Gets the timestamp for the object type. That is, the time we know
|
||||
* all objects of this type are updated at least to.
|
||||
/** Attempts to find a serializable type with the specified name.
|
||||
* @param n The name of the serializable type to find.
|
||||
*/
|
||||
time_t GetTimestamp() const;
|
||||
static Serialize::Type *Find(const Anope::string &n);
|
||||
|
||||
/** Bumps object type timestamp to current time
|
||||
/** Retrieves the name of this type in the database (e.g. NickAlias). */
|
||||
inline const auto &GetName() const { return this->name; }
|
||||
|
||||
/** Retrieves the module which owns this type, or nullptr if it belongs to
|
||||
* the core. Some database backends use this to put third-party module data
|
||||
* into their own database.
|
||||
*/
|
||||
inline auto *GetOwner() const { return this->owner; }
|
||||
|
||||
/** Retrieves the time at which this type was last synchronised with the
|
||||
* database. Only used by live database backends like db_sql_live.
|
||||
*/
|
||||
inline auto GetTimestamp() const { return this->timestamp; };
|
||||
|
||||
/** Retrieves the names of currently registered types in order of
|
||||
* registration.
|
||||
*/
|
||||
inline static const auto &GetTypeOrder() { return TypeOrder; }
|
||||
|
||||
/** Retrieves the currently registered types. */
|
||||
inline static const auto &GetTypes() { return Types; }
|
||||
|
||||
/** Serializes the specified object to the database.
|
||||
* @param obj The object to serialise. This is guaranteed to be the correct
|
||||
* type so you can cast it without any checks.
|
||||
* @param data The database to serialize to.
|
||||
*/
|
||||
virtual void Serialize(const Serializable *obj, Serialize::Data &data) const = 0;
|
||||
|
||||
/** Unserializes the specified object from the database.
|
||||
* @param obj The object to unserialize into. If the object has not been
|
||||
* unserialized yet this will be nullptr. This is guaranteed to
|
||||
* be the correct type so you can cast it without any checks.
|
||||
* @param data The database to unserialize from.
|
||||
* @return The object specified in obj or a new object it if was nullptr.
|
||||
*/
|
||||
virtual Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const = 0;
|
||||
|
||||
/** Updates the time at which this type was last synchronised with the
|
||||
* database to the current time. Only used by live database backends like
|
||||
* db_sql_live.
|
||||
*/
|
||||
void UpdateTimestamp();
|
||||
|
||||
Module *GetOwner() const { return this->owner; }
|
||||
|
||||
static Serialize::Type *Find(const Anope::string &name);
|
||||
|
||||
static const std::vector<Anope::string> &GetTypeOrder();
|
||||
|
||||
static const std::map<Anope::string, Serialize::Type *>& GetTypes();
|
||||
};
|
||||
|
||||
/** Should be used to hold lists and other objects of a specific type,
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <deque>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
// Whether the umask() function is available.
|
||||
#cmakedefine01 HAVE_UMASK
|
||||
|
||||
// Whether Anope was built in a reproducible way.
|
||||
#cmakedefine01 REPRODUCIBLE_BUILD
|
||||
|
||||
#ifdef _WIN32
|
||||
# define popen _popen
|
||||
# define pclose _pclose
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2003-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class CoreExport HelpWrapper final
|
||||
{
|
||||
private:
|
||||
std::vector<std::pair<Anope::string, Anope::string>> entries;
|
||||
size_t longest = 0;
|
||||
|
||||
public:
|
||||
void AddEntry(const Anope::string &name, const Anope::string &desc);
|
||||
void SendTo(CommandSource &source);
|
||||
};
|
||||
|
||||
class CoreExport LineWrapper final
|
||||
{
|
||||
private:
|
||||
std::vector<Anope::string> formatting;
|
||||
const size_t max_length;
|
||||
Anope::string text;
|
||||
|
||||
public:
|
||||
LineWrapper(const Anope::string &t, size_t ml = 0);
|
||||
bool GetLine(Anope::string &out);
|
||||
};
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ protected:
|
||||
Serialize::Reference<NickCore> nc;
|
||||
|
||||
/* # of invalid password attempts */
|
||||
unsigned short invalid_pw_count;
|
||||
unsigned invalid_pw_count;
|
||||
/* Time of last invalid password */
|
||||
time_t invalid_pw_time;
|
||||
|
||||
|
||||
+10
-3
@@ -16,6 +16,16 @@
|
||||
class CoreExport XLine final
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
void Init();
|
||||
Anope::string nick, user, host, real;
|
||||
public:
|
||||
@@ -43,9 +53,6 @@ public:
|
||||
|
||||
bool HasNickOrReal() const;
|
||||
bool IsRegex() const;
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
/* Managers XLines. There is one XLineManager per type of XLine. */
|
||||
|
||||
+815
-1805
File diff suppressed because it is too large
Load Diff
+58
-40
@@ -23,9 +23,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const Anope::string &bsnick = conf->GetModule(this)->Get<const Anope::string>("client");
|
||||
const Anope::string &bsnick = conf.GetModule(this).Get<const Anope::string>("client");
|
||||
BotServ = BotInfo::Find(bsnick, true);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
/* Do not allow removing bot modes on our service bots */
|
||||
if (chan->ci && chan->ci->bi == user)
|
||||
{
|
||||
const Anope::string &botmodes = Config->GetModule(this)->Get<const Anope::string>("botmodes");
|
||||
const Anope::string &botmodes = Config->GetModule(this).Get<const Anope::string>("botmodes");
|
||||
for (auto botmode : botmodes)
|
||||
chan->SetMode(chan->ci->bi, ModeManager::FindChannelModeByChar(botmode), chan->ci->bi->GetUID());
|
||||
}
|
||||
@@ -42,9 +42,9 @@ public:
|
||||
|
||||
void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) override
|
||||
{
|
||||
if (ci->c && ci->c->users.size() >= Config->GetModule(this)->Get<unsigned>("minusers"))
|
||||
if (ci->c && ci->c->users.size() >= Config->GetModule(this).Get<unsigned>("minusers"))
|
||||
{
|
||||
ChannelStatus status(Config->GetModule(this)->Get<const Anope::string>("botmodes"));
|
||||
ChannelStatus status(Config->GetModule(this).Get<const Anope::string>("botmodes"));
|
||||
bi->Join(ci->c, &status);
|
||||
}
|
||||
}
|
||||
@@ -55,12 +55,12 @@ public:
|
||||
return;
|
||||
|
||||
BotInfo *bi = user->server == Me ? dynamic_cast<BotInfo *>(user) : NULL;
|
||||
if (bi && Config->GetModule(this)->Get<bool>("smartjoin"))
|
||||
if (bi && Config->GetModule(this).Get<bool>("smartjoin"))
|
||||
{
|
||||
if (IRCD->CanClearBans)
|
||||
if (IRCD->CanClearModes.count("BAN"))
|
||||
{
|
||||
// We can ask the IRCd to clear bans.
|
||||
IRCD->SendClearBans(bi, c, bi);
|
||||
IRCD->SendClearModes(bi, c, bi, "BAN");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,9 +99,9 @@ public:
|
||||
* legit users - Rob
|
||||
**/
|
||||
/* This is before the user has joined the channel, so check usercount + 1 */
|
||||
if (c->users.size() + 1 >= Config->GetModule(this)->Get<unsigned>("minusers") && !c->FindUser(c->ci->bi))
|
||||
if (c->users.size() + 1 >= Config->GetModule(this).Get<unsigned>("minusers") && !c->FindUser(c->ci->bi))
|
||||
{
|
||||
ChannelStatus status(Config->GetModule(this)->Get<const Anope::string>("botmodes"));
|
||||
ChannelStatus status(Config->GetModule(this).Get<const Anope::string>("botmodes"));
|
||||
c->ci->bi->Join(c, &status);
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
return;
|
||||
|
||||
/* This is called prior to removing the user from the channel, so c->users.size() - 1 should be safe */
|
||||
if (c->ci && c->ci->bi && u != *c->ci->bi && c->users.size() - 1 <= Config->GetModule(this)->Get<unsigned>("minusers") && c->FindUser(c->ci->bi))
|
||||
if (c->ci && c->ci->bi && u != *c->ci->bi && c->users.size() - 1 <= Config->GetModule(this).Get<unsigned>("minusers") && c->FindUser(c->ci->bi))
|
||||
c->ci->bi->Part(c->ci->c);
|
||||
}
|
||||
|
||||
@@ -135,29 +135,41 @@ public:
|
||||
|
||||
if (source.c)
|
||||
{
|
||||
source.Reply(_("\002%s\002 allows you to execute \"fantasy\" commands in the channel.\n"
|
||||
"Fantasy commands are commands that can be executed from messaging a\n"
|
||||
"channel, and provide a more convenient way to execute commands. Commands that\n"
|
||||
"require a channel as a parameter will automatically have that parameter\n"
|
||||
"given.\n"), source.service->nick.c_str());
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy")->Get<const Anope::string>("fantasycharacter", "!");
|
||||
source.Reply(_(
|
||||
"\002%s\002 allows you to execute \"fantasy\" commands in the channel. "
|
||||
"Fantasy commands are commands that can be executed from messaging a "
|
||||
"channel, and provide a more convenient way to execute commands. Commands that "
|
||||
"require a channel as a parameter will automatically have that parameter "
|
||||
"given."
|
||||
),
|
||||
source.service->nick.c_str());
|
||||
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy").Get<const Anope::string>("fantasycharacter", "!");
|
||||
if (!fantasycharacters.empty())
|
||||
source.Reply(_(" \n"
|
||||
"Fantasy commands may be prefixed with one of the following characters: %s\n"), fantasycharacters.c_str());
|
||||
source.Reply(_(" \n"
|
||||
"Available commands are:"));
|
||||
{
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Fantasy commands may be prefixed with one of the following characters: %s"),
|
||||
fantasycharacters.c_str());
|
||||
}
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Available commands are:"));
|
||||
}
|
||||
else if (*source.service == BotServ)
|
||||
{
|
||||
source.Reply(_("\002%s\002 allows you to have a bot on your own channel.\n"
|
||||
"It has been created for users that can't host or\n"
|
||||
"configure a bot, or for use on networks that don't\n"
|
||||
"allow user bots. Available commands are listed\n"
|
||||
"below; to use them, type \002%s \037command\037\002. For\n"
|
||||
"more information on a specific command, type\n"
|
||||
"\002%s %s \037command\037\002.\n"),
|
||||
BotServ->nick.c_str(), BotServ->GetQueryCommand().c_str(),
|
||||
BotServ->GetQueryCommand().c_str(), source.command.c_str());
|
||||
source.Reply(_(
|
||||
"\002%s\002 allows you to have a bot on your own channel. "
|
||||
"It has been created for users that can't host or "
|
||||
"configure a bot, or for use on networks that don't "
|
||||
"allow user bots. Available commands are listed "
|
||||
"below; to use them, type \002%s\032\037command\037\002. For "
|
||||
"more information on a specific command, type "
|
||||
"\002%s\032\037command\037\002."
|
||||
),
|
||||
BotServ->nick.c_str(),
|
||||
BotServ->GetQueryCommand().c_str(),
|
||||
BotServ->GetQueryCommand({}, source.command).c_str());
|
||||
|
||||
source.Reply(" ");
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
@@ -168,19 +180,25 @@ public:
|
||||
if (!params.empty() || source.c || source.service != *BotServ)
|
||||
return;
|
||||
|
||||
source.Reply(_(" \n"
|
||||
"Bot will join a channel whenever there is at least\n"
|
||||
"\002%d\002 user(s) on it."), Config->GetModule(this)->Get<unsigned>("minusers"));
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy")->Get<const Anope::string>("fantasycharacter", "!");
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Bot will join a channel whenever there is at least \002%d\002 user(s) on it."),
|
||||
Config->GetModule(this).Get<unsigned>("minusers"));
|
||||
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy").Get<const Anope::string>("fantasycharacter", "!");
|
||||
if (!fantasycharacters.empty())
|
||||
source.Reply(_("Additionally, if fantasy is enabled fantasy commands\n"
|
||||
"can be executed by prefixing the command name with\n"
|
||||
"one of the following characters: %s"), fantasycharacters.c_str());
|
||||
{
|
||||
source.Reply(_(
|
||||
"Additionally, if fantasy is enabled fantasy commands "
|
||||
"can be executed by prefixing the command name with "
|
||||
"one of the following characters: %s"
|
||||
),
|
||||
fantasycharacters.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string ¶m) override
|
||||
{
|
||||
if (source.GetUser() && !source.GetBot() && Config->GetModule(this)->Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
|
||||
if (source.GetUser() && !source.GetBot() && Config->GetModule(this).Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
|
||||
{
|
||||
BotInfo *bi = c->ci->bi;
|
||||
|
||||
@@ -195,7 +213,7 @@ public:
|
||||
void OnCreateChan(ChannelInfo *ci) override
|
||||
{
|
||||
/* Set default bot flags */
|
||||
spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("defaults", "greet fantasy"));
|
||||
spacesepstream sep(Config->GetModule(this).Get<const Anope::string>("defaults", "greet fantasy"));
|
||||
for (Anope::string token; sep.GetToken(token);)
|
||||
ci->Extend<bool>("BS_" + token.upper());
|
||||
}
|
||||
@@ -211,7 +229,7 @@ public:
|
||||
void OnCreateBot(BotInfo *bi) override
|
||||
{
|
||||
if (bi->botmodes.empty())
|
||||
bi->botmodes = Config->GetModule(this)->Get<const Anope::string>("botumodes");
|
||||
bi->botmodes = Config->GetModule(this).Get<const Anope::string>("botumodes");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -76,9 +76,11 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Assigns the specified bot to a channel. You\n"
|
||||
"can then configure the bot for the channel so it fits\n"
|
||||
"your needs."));
|
||||
source.Reply(_(
|
||||
"Assigns the specified bot to a channel. You "
|
||||
"can then configure the bot for the channel so it fits "
|
||||
"your needs."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -138,11 +140,13 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Unassigns a bot from a channel. When you use this command,\n"
|
||||
"the bot won't join the channel anymore. However, bot\n"
|
||||
"configuration for the channel is kept, so you will always\n"
|
||||
"be able to reassign a bot later without having to reconfigure\n"
|
||||
"it entirely."));
|
||||
source.Reply(_(
|
||||
"Unassigns a bot from a channel. When you use this command, "
|
||||
"the bot won't join the channel anymore. However, bot "
|
||||
"configuration for the channel is kept, so you will always "
|
||||
"be able to reassign a bot later without having to reconfigure "
|
||||
"it entirely."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -197,10 +201,12 @@ public:
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(_(" \n"
|
||||
"This option makes a channel unassignable. If a bot\n"
|
||||
"is already assigned to the channel, it is unassigned\n"
|
||||
"automatically when you enable it."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"This option makes a channel unassignable. If a bot "
|
||||
"is already assigned to the channel, it is unassigned "
|
||||
"automatically when you enable it."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
|
||||
void OnChanRegistered(ChannelInfo *ci) override
|
||||
{
|
||||
const Anope::string &bot = Config->GetModule(this)->Get<const Anope::string>("bot");
|
||||
const Anope::string &bot = Config->GetModule(this).Get<const Anope::string>("bot");
|
||||
if (bot.empty())
|
||||
return;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
|
||||
struct BadWordImpl final
|
||||
: BadWord
|
||||
@@ -18,15 +18,25 @@ struct BadWordImpl final
|
||||
{
|
||||
BadWordImpl() : Serializable("BadWord") { }
|
||||
~BadWordImpl() override;
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct BadWordTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
BadWordTypeImpl()
|
||||
: Serialize::Type("BadWord")
|
||||
{
|
||||
data.Store("ci", this->chan);
|
||||
data.Store("word", this->word);
|
||||
data.Store("type", this->type);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *bw = static_cast<const BadWordImpl *>(obj);
|
||||
data.Store("ci", bw->chan);
|
||||
data.Store("word", bw->word);
|
||||
data.Store("type", bw->type);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &) const override;
|
||||
};
|
||||
|
||||
struct BadWordsImpl final
|
||||
@@ -117,7 +127,7 @@ BadWordImpl::~BadWordImpl()
|
||||
}
|
||||
}
|
||||
|
||||
Serializable *BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
Serializable *BadWordTypeImpl::Unserialize(Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
Anope::string sci, sword;
|
||||
|
||||
@@ -155,6 +165,7 @@ class BadwordsDelCallback final
|
||||
BadWords *bw;
|
||||
Command *c;
|
||||
unsigned deleted = 0;
|
||||
Anope::string lastdeleted;
|
||||
bool override = false;
|
||||
public:
|
||||
BadwordsDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c)
|
||||
@@ -166,12 +177,20 @@ public:
|
||||
|
||||
~BadwordsDelCallback() override
|
||||
{
|
||||
if (!deleted)
|
||||
source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str());
|
||||
else if (deleted == 1)
|
||||
source.Reply(_("Deleted 1 entry from %s bad words list."), ci->name.c_str());
|
||||
else
|
||||
source.Reply(_("Deleted %d entries from %s bad words list."), deleted, ci->name.c_str());
|
||||
switch (deleted)
|
||||
{
|
||||
case 0:
|
||||
source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str());
|
||||
break;
|
||||
|
||||
case 1:
|
||||
source.Reply(_("Deleted %s from %s bad words list."), lastdeleted.c_str(), ci->name.c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s bad words list.", "Deleted %d entries from %s bad words list."), deleted, ci->name.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleNumber(unsigned Number) override
|
||||
@@ -179,7 +198,8 @@ public:
|
||||
if (!bw || !Number || Number > bw->GetBadWordCount())
|
||||
return;
|
||||
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "DEL " << bw->GetBadWord(Number - 1)->word;
|
||||
lastdeleted = bw->GetBadWord(Number - 1)->word;
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "DEL " << lastdeleted;
|
||||
++deleted;
|
||||
bw->EraseBadWord(Number - 1);
|
||||
}
|
||||
@@ -286,14 +306,14 @@ private:
|
||||
realword = word.substr(0, pos);
|
||||
}
|
||||
|
||||
unsigned badwordsmax = Config->GetModule(this->module)->Get<unsigned>("badwordsmax");
|
||||
unsigned badwordsmax = Config->GetModule(this->module).Get<unsigned>("badwordsmax");
|
||||
if (badwords->GetBadWordCount() >= badwordsmax)
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d bad words entries on a channel."), badwordsmax);
|
||||
return;
|
||||
}
|
||||
|
||||
bool casesensitive = Config->GetModule(this->module)->Get<bool>("casesensitive");
|
||||
bool casesensitive = Config->GetModule(this->module).Get<bool>("casesensitive");
|
||||
|
||||
for (unsigned i = 0, end = badwords->GetBadWordCount(); i < end; ++i)
|
||||
{
|
||||
@@ -427,34 +447,38 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Maintains the \002bad words list\002 for a channel. The bad\n"
|
||||
"words list determines which words are to be kicked\n"
|
||||
"when the bad words kicker is enabled. For more information,\n"
|
||||
"type \002%s HELP KICK %s\002.\n"
|
||||
" \n"
|
||||
"The \002ADD\002 command adds the given word to the\n"
|
||||
"bad words list. If SINGLE is specified, a kick will be\n"
|
||||
"done only if a user says the entire word. If START is\n"
|
||||
"specified, a kick will be done if a user says a word\n"
|
||||
"that starts with \037word\037. If END is specified, a kick\n"
|
||||
"will be done if a user says a word that ends with\n"
|
||||
"\037word\037. If you don't specify anything, a kick will\n"
|
||||
"be issued every time \037word\037 is said by a user.\n"
|
||||
" \n"), source.service->GetQueryCommand().c_str(), source.command.c_str());
|
||||
source.Reply(_("The \002DEL\002 command removes the given word from the\n"
|
||||
"bad words list. If a list of entry numbers is given, those\n"
|
||||
"entries are deleted. (See the example for LIST below.)\n"
|
||||
" \n"
|
||||
"The \002LIST\002 command displays the bad words list. If\n"
|
||||
"a wildcard mask is given, only those entries matching the\n"
|
||||
"mask are displayed. If a list of entry numbers is given,\n"
|
||||
source.Reply(_(
|
||||
"Maintains the \002bad words list\002 for a channel. The bad "
|
||||
"words list determines which words are to be kicked "
|
||||
"when the bad words kicker is enabled. For more information, "
|
||||
"type \002%s\032KICK\032%s\002."
|
||||
"\n\n"
|
||||
"The \002ADD\002 command adds the given word to the "
|
||||
"bad words list. If SINGLE is specified, a kick will be "
|
||||
"done only if a user says the entire word. If START is "
|
||||
"specified, a kick will be done if a user says a word "
|
||||
"that starts with \037word\037. If END is specified, a kick "
|
||||
"will be done if a user says a word that ends with "
|
||||
"\037word\037. If you don't specify anything, a kick will "
|
||||
"be issued every time \037word\037 is said by a user."
|
||||
"\n\n"
|
||||
"The \002DEL\002 command removes the given word from the "
|
||||
"bad words list. If a list of entry numbers is given, those "
|
||||
"entries are deleted. (See the example for LIST below.)"
|
||||
"\n\n"
|
||||
"The \002LIST\002 command displays the bad words list. If "
|
||||
"a wildcard mask is given, only those entries matching the "
|
||||
"mask are displayed. If a list of entry numbers is given, "
|
||||
"only those entries are shown; for example:\n"
|
||||
" \002#channel LIST 2-5,7-9\002\n"
|
||||
" \002#channel\032LIST\0322-5,7-9\002\n"
|
||||
" Lists bad words entries numbered 2 through 5 and\n"
|
||||
" 7 through 9.\n"
|
||||
" \n"
|
||||
"The \002CLEAR\002 command clears all entries from the\n"
|
||||
"bad words list."));
|
||||
" 7 through 9."
|
||||
"\n\n"
|
||||
"The \002CLEAR\002 command clears all entries from the "
|
||||
"bad words list."
|
||||
),
|
||||
source.service->GetQueryCommand("generic/help").c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -464,11 +488,13 @@ class BSBadwords final
|
||||
{
|
||||
CommandBSBadwords commandbsbadwords;
|
||||
ExtensibleItem<BadWordsImpl> badwords;
|
||||
Serialize::Type badword_type;
|
||||
BadWordTypeImpl badword_type;
|
||||
|
||||
public:
|
||||
BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandbsbadwords(this), badwords(this, "badwords"), badword_type("BadWord", BadWordImpl::Unserialize)
|
||||
BSBadwords(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandbsbadwords(this)
|
||||
, badwords(this, "badwords")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
+26
-21
@@ -142,7 +142,10 @@ private:
|
||||
* And we must finally check that the nick is not already
|
||||
* taken by another bot.
|
||||
*/
|
||||
if (nick.equals_cs(bi->nick) && (!user.empty() ? user.equals_cs(bi->GetIdent()) : 1) && (!host.empty() ? host.equals_cs(bi->host) : 1) && (!real.empty() ? real.equals_cs(bi->realname) : 1))
|
||||
if (nick.equals_cs(bi->nick)
|
||||
&& (user.empty() || user.equals_cs(bi->GetIdent()))
|
||||
&& (host.empty() || host.equals_cs(bi->host))
|
||||
&& (real.empty() || real.equals_cs(bi->realname)))
|
||||
{
|
||||
source.Reply(_("The old information is the same as the new information specified."));
|
||||
return;
|
||||
@@ -179,10 +182,7 @@ private:
|
||||
source.Reply(_("Nick \002%s\002 is currently in use."), nick.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nick.equals_ci(bi->nick))
|
||||
{
|
||||
/* We check whether the nick is registered, and inform the user
|
||||
* if so. You need to drop the nick manually before you can use
|
||||
* it as a bot nick from now on -GD
|
||||
@@ -347,23 +347,28 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Allows Services Operators to create, modify, and delete\n"
|
||||
"bots that users will be able to use on their own\n"
|
||||
"channels.\n"
|
||||
" \n"
|
||||
"\002BOT ADD\002 adds a bot with the given nickname, username,\n"
|
||||
"hostname and realname. Since no integrity checks are done\n"
|
||||
"for these settings, be really careful.\n"
|
||||
" \n"
|
||||
"\002BOT CHANGE\002 allows you to change the nickname, username, hostname\n"
|
||||
"or realname of a bot without deleting it (and\n"
|
||||
"all the data associated with it).\n"
|
||||
" \n"
|
||||
"\002BOT DEL\002 removes the given bot from the bot list.\n"
|
||||
" \n"
|
||||
"\002Note\002: You cannot create a bot with a nick that is\n"
|
||||
"currently registered. If an unregistered user is currently\n"
|
||||
"using the nick, they will be killed."));
|
||||
source.Reply(_(
|
||||
"Allows Services Operators to create, modify, and delete "
|
||||
"bots that users will be able to use on their own "
|
||||
"channels."
|
||||
"\n\n"
|
||||
"\002%s\032ADD\002 adds a bot with the given nickname, username, "
|
||||
"hostname and realname. Since no integrity checks are done "
|
||||
"for these settings, be really careful."
|
||||
"\n\n"
|
||||
"\002%s\032CHANGE\002 allows you to change the nickname, username, hostname "
|
||||
"or realname of a bot without deleting it (and "
|
||||
"all the data associated with it)."
|
||||
"\n\n"
|
||||
"\002%s\032DEL\002 removes the given bot from the bot list."
|
||||
"\n\n"
|
||||
"\002Note\002: You cannot create a bot with a nick that is "
|
||||
"currently registered. If an unregistered user is currently "
|
||||
"using the nick, they will be killed."
|
||||
),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,8 +70,12 @@ public:
|
||||
list.Process(replies);
|
||||
|
||||
if (!count)
|
||||
source.Reply(_("There are no bots available at this time.\n"
|
||||
"Ask a Services Operator to create one!"));
|
||||
{
|
||||
source.Reply(_(
|
||||
"There are no bots available at this time. "
|
||||
"Ask a Services Operator to create one!"
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
source.Reply(_("Bot list:"));
|
||||
@@ -87,15 +91,17 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Lists all available bots on this network.\n"
|
||||
"\n"
|
||||
"If the OPERONLY, UNUSED or VANITY options are given only\n"
|
||||
"bots which, respectively, are oper-only, unused or were\n"
|
||||
"added at runtime will be displayed. If multiple options are\n"
|
||||
"given, all nicks matching at least one option will be\n"
|
||||
"displayed.\n"
|
||||
"\n"
|
||||
"Note that these options are limited to \037Services Operators\037."));
|
||||
source.Reply(_(
|
||||
"Lists all available bots on this network."
|
||||
"\n\n"
|
||||
"If the OPERONLY, UNUSED or VANITY options are given only "
|
||||
"bots which, respectively, are oper-only, unused or were "
|
||||
"added at runtime will be displayed. If multiple options are "
|
||||
"given, all nicks matching at least one option will be "
|
||||
"displayed."
|
||||
"\n\n"
|
||||
"Note that these options are limited to \037Services Operators\037."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,8 +122,10 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Makes the bot do the equivalent of a \"/me\" command\n"
|
||||
"on the specified channel using the specified text."));
|
||||
source.Reply(_(
|
||||
"Makes the bot do the equivalent of a \"/me\" command "
|
||||
"on the specified channel using the specified text."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -104,11 +104,13 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Allows you to see %s information about a channel or a bot.\n"
|
||||
"If the parameter is a channel, then you'll get information\n"
|
||||
"such as enabled kickers. If the parameter is a nick,\n"
|
||||
"you'll get information about a bot, such as creation\n"
|
||||
"time or number of channels it is on."), source.service->nick.c_str());
|
||||
source.Reply(_(
|
||||
"Allows you to see %s information about a channel or a bot. "
|
||||
"If the parameter is a channel, then you'll get information "
|
||||
"such as enabled kickers. If the parameter is a nick, "
|
||||
"you'll get information about a bot, such as creation "
|
||||
"time or number of channels it is on."
|
||||
), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+188
-117
@@ -10,8 +10,8 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/bs_kick.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/botserv/kick.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
|
||||
static Module *me;
|
||||
|
||||
@@ -45,7 +45,7 @@ struct KickerDataImpl final
|
||||
|
||||
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
|
||||
{
|
||||
if (s->GetSerializableType()->GetName() != "ChannelInfo")
|
||||
if (s->GetSerializableType()->GetName() != CHANNELINFO_TYPE)
|
||||
return;
|
||||
|
||||
const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(e);
|
||||
@@ -79,7 +79,7 @@ struct KickerDataImpl final
|
||||
|
||||
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
|
||||
{
|
||||
if (s->GetSerializableType()->GetName() != "ChannelInfo")
|
||||
if (s->GetSerializableType()->GetName() != CHANNELINFO_TYPE)
|
||||
return;
|
||||
|
||||
ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(e);
|
||||
@@ -139,6 +139,7 @@ public:
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Configures bot kickers. \037option\037 can be one of:"));
|
||||
|
||||
HelpWrapper help;
|
||||
Anope::string this_name = source.command;
|
||||
for (const auto &[c_name, info] : source.service->commands)
|
||||
{
|
||||
@@ -148,17 +149,20 @@ public:
|
||||
if (command)
|
||||
{
|
||||
source.command = c_name;
|
||||
command->OnServHelp(source);
|
||||
command->OnServHelp(source, help);
|
||||
}
|
||||
}
|
||||
}
|
||||
help.SendTo(source);
|
||||
|
||||
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
|
||||
"on a specific option.\n"
|
||||
" \n"
|
||||
"Note: access to this command is controlled by the\n"
|
||||
"level SET."), source.service->GetQueryCommand().c_str(), this_name.c_str());
|
||||
|
||||
source.Reply(_(
|
||||
"Type \002%s\032\037option\037\002 for more information "
|
||||
"on a specific option."
|
||||
"\n\n"
|
||||
"Note: access to this command is controlled by the "
|
||||
"level SET."
|
||||
),
|
||||
source.service->GetQueryCommand("generic/help", this_name).c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -220,8 +224,10 @@ protected:
|
||||
|
||||
val = true;
|
||||
if (kd->ttb[ttb_idx])
|
||||
source.Reply(_("Bot will now kick for \002%s\002, and will place a ban\n"
|
||||
"after %d kicks for the same user."), optname.c_str(), kd->ttb[ttb_idx]);
|
||||
{
|
||||
source.Reply(_("Bot will now kick for \002%s\002, and will place a ban after %d kicks for the same user."),
|
||||
optname.c_str(), kd->ttb[ttb_idx]);
|
||||
}
|
||||
else
|
||||
source.Reply(_("Bot will now kick for \002%s\002."), optname.c_str());
|
||||
|
||||
@@ -267,13 +273,16 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
BotInfo *bi = Config->GetClient("BotServ");
|
||||
source.Reply(_("Sets the AMSG kicker on or off. When enabled, the bot will\n"
|
||||
"kick users who send the same message to multiple channels\n"
|
||||
"where %s bots are.\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before they get banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."), bi ? bi->nick.c_str() : "BotServ");
|
||||
source.Reply(_(
|
||||
"Sets the AMSG kicker on or off. When enabled, the bot will "
|
||||
"kick users who send the same message to multiple channels "
|
||||
"where %s bots are."
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before they get banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
),
|
||||
bi ? bi->nick.c_str() : "BotServ");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -304,16 +313,20 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the bad words kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who say certain words\n"
|
||||
"on the channels.\n"
|
||||
"You can define bad words for your channel using the\n"
|
||||
"\002BADWORDS\002 command. Type \002%s HELP BADWORDS\002 for\n"
|
||||
"more information.\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."), source.service->GetQueryCommand().c_str());
|
||||
source.Reply(_(
|
||||
"Sets the bad words kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who say certain words "
|
||||
"on the channels."
|
||||
"\n\n"
|
||||
"You can define bad words for your channel using the "
|
||||
"\002BADWORDS\002 command. Type \002%s\032BADWORDS\002 for "
|
||||
"more information."
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
),
|
||||
source.service->GetQueryCommand("generic/help").c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -343,12 +356,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the bolds kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who use bolds.\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the bolds kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who use bolds."
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -400,12 +415,23 @@ public:
|
||||
|
||||
kd->caps = true;
|
||||
if (kd->ttb[TTB_CAPS])
|
||||
source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n"
|
||||
"%d characters and %d%% of the entire message), and will\n"
|
||||
"place a ban after %d kicks for the same user."), kd->capsmin, kd->capspercent, kd->ttb[TTB_CAPS]);
|
||||
{
|
||||
source.Reply(_(
|
||||
"Bot will now kick for \002caps\002 (they must constitute at least "
|
||||
"%d characters and %d%% of the entire message), and will "
|
||||
"place a ban after %d kicks for the same user."
|
||||
),
|
||||
kd->capsmin,
|
||||
kd->capspercent,
|
||||
kd->ttb[TTB_CAPS]);
|
||||
}
|
||||
else
|
||||
source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n"
|
||||
"%d characters and %d%% of the entire message)."), kd->capsmin, kd->capspercent);
|
||||
source.Reply(_(
|
||||
"Bot will now kick for \002caps\002 (they must constitute at least "
|
||||
"%d characters and %d%% of the entire message)."
|
||||
),
|
||||
kd->capsmin,
|
||||
kd->capspercent);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -420,17 +446,20 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the caps kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who are talking in\n"
|
||||
"CAPS.\n"
|
||||
"The bot kicks only if there are at least \002min\002 caps\n"
|
||||
"and they constitute at least \002percent\002%% of the total\n"
|
||||
"text line (if not given, it defaults to 10 characters\n"
|
||||
"and 25%%).\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the caps kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who are talking in "
|
||||
"CAPS."
|
||||
"\n\n"
|
||||
"The bot kicks only if there are at least \002min\002 caps "
|
||||
"and they constitute at least \002percent\002%% of the total "
|
||||
"text line (if not given, it defaults to 10 characters "
|
||||
"and 25%%)."
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -460,12 +489,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the colors kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who use colors.\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the colors kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who use colors."
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -515,13 +546,20 @@ public:
|
||||
if (kd->floodsecs < 1)
|
||||
kd->floodsecs = 10;
|
||||
|
||||
if (kd->floodsecs > Config->GetModule(me)->Get<time_t>("keepdata"))
|
||||
kd->floodsecs = Config->GetModule(me)->Get<time_t>("keepdata");
|
||||
if (kd->floodsecs > Config->GetModule(me).Get<time_t>("keepdata"))
|
||||
kd->floodsecs = Config->GetModule(me).Get<time_t>("keepdata");
|
||||
|
||||
kd->flood = true;
|
||||
if (kd->ttb[TTB_FLOOD])
|
||||
source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds\n"
|
||||
"and will place a ban after %d kicks for the same user."), kd->floodlines, kd->floodsecs, kd->ttb[TTB_FLOOD]);
|
||||
{
|
||||
source.Reply(_(
|
||||
"Bot will now kick for \002flood\002 (%d lines in %d seconds "
|
||||
"and will place a ban after %d kicks for the same user."
|
||||
),
|
||||
kd->floodlines,
|
||||
kd->floodsecs,
|
||||
kd->ttb[TTB_FLOOD]);
|
||||
}
|
||||
else
|
||||
source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds)."), kd->floodlines, kd->floodsecs);
|
||||
}
|
||||
@@ -540,14 +578,15 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the flood kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who are flooding\n"
|
||||
"the channel using at least \002ln\002 lines in \002secs\002 seconds\n"
|
||||
"(if not given, it defaults to 6 lines in 10 seconds).\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the flood kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who are flooding "
|
||||
"the channel using at least \002ln\002 lines in \002secs\002 seconds "
|
||||
"(if not given, it defaults to 6 lines in 10 seconds). "
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -577,12 +616,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the italics kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who use italics.\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the italics kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who use italics. "
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -631,22 +672,42 @@ public:
|
||||
if (kd->ttb[TTB_REPEAT])
|
||||
{
|
||||
if (kd->repeattimes != 1)
|
||||
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
|
||||
"same message %d times), and will place a ban after %d\n"
|
||||
"kicks for the same user."), kd->repeattimes, kd->ttb[TTB_REPEAT]);
|
||||
{
|
||||
source.Reply(_(
|
||||
"Bot will now kick for \002repeats\002 (users that repeat the "
|
||||
"same message %d times), and will place a ban after %d "
|
||||
"kicks for the same user."
|
||||
),
|
||||
kd->repeattimes,
|
||||
kd->ttb[TTB_REPEAT]);
|
||||
}
|
||||
else
|
||||
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
|
||||
"same message %d time), and will place a ban after %d\n"
|
||||
"kicks for the same user."), kd->repeattimes, kd->ttb[TTB_REPEAT]);
|
||||
source.Reply(_(
|
||||
"Bot will now kick for \002repeats\002 (users that repeat the "
|
||||
"same message %d time), and will place a ban after %d "
|
||||
"kicks for the same user."
|
||||
),
|
||||
kd->repeattimes,
|
||||
kd->ttb[TTB_REPEAT]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (kd->repeattimes != 1)
|
||||
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
|
||||
"same message %d times)."), kd->repeattimes);
|
||||
{
|
||||
source.Reply(_(
|
||||
"Bot will now kick for \002repeats\002 (users that repeat the "
|
||||
"same message %d times)."
|
||||
),
|
||||
kd->repeattimes);
|
||||
}
|
||||
else
|
||||
source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n"
|
||||
"same message %d time)."), kd->repeattimes);
|
||||
{
|
||||
source.Reply(_(
|
||||
"Bot will now kick for \002repeats\002 (users that repeat the "
|
||||
"same message %d time)."
|
||||
),
|
||||
kd->repeattimes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (params[1].equals_ci("OFF"))
|
||||
@@ -664,14 +725,16 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the repeat kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who are repeating\n"
|
||||
"themselves \002num\002 times (if num is not given, it\n"
|
||||
"defaults to 3).\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the repeat kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who are repeating "
|
||||
"themselves \002num\002 times (if num is not given, it "
|
||||
"defaults to 3)."
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -701,12 +764,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the reverses kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who use reverses.\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the reverses kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who use reverses. "
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -736,12 +801,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Sets the underlines kicker on or off. When enabled, this\n"
|
||||
"option tells the bot to kick users who use underlines.\n"
|
||||
" \n"
|
||||
"\037ttb\037 is the number of times a user can be kicked\n"
|
||||
"before it gets banned. Don't give ttb to disable\n"
|
||||
"the ban system once activated."));
|
||||
source.Reply(_(
|
||||
"Sets the underlines kicker on or off. When enabled, this "
|
||||
"option tells the bot to kick users who use underlines. "
|
||||
"\n\n"
|
||||
"\037ttb\037 is the number of times a user can be kicked "
|
||||
"before it gets banned. Don't give ttb to disable "
|
||||
"the ban system once activated."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -804,10 +871,12 @@ public:
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(_(" \n"
|
||||
"Enables or disables \002ops protection\002 mode on a channel.\n"
|
||||
"When it is enabled, ops won't be kicked by the bot\n"
|
||||
"even if they don't match the NOKICK level."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Enables or disables \002ops protection\002 mode on a channel. "
|
||||
"When it is enabled, ops won't be kicked by the bot "
|
||||
"even if they don't match the NOKICK level."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -870,10 +939,12 @@ public:
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(_(" \n"
|
||||
"Enables or disables \002voices protection\002 mode on a channel.\n"
|
||||
"When it is enabled, voices won't be kicked by the bot\n"
|
||||
"even if they don't match the NOKICK level."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Enables or disables \002voices protection\002 mode on a channel. "
|
||||
"When it is enabled, voices won't be kicked by the bot "
|
||||
"even if they don't match the NOKICK level."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -913,7 +984,7 @@ public:
|
||||
|
||||
void purge()
|
||||
{
|
||||
time_t keepdata = Config->GetModule(me)->Get<time_t>("keepdata");
|
||||
time_t keepdata = Config->GetModule(me).Get<time_t>("keepdata");
|
||||
for (data_type::iterator it = data_map.begin(), it_end = data_map.end(); it != it_end;)
|
||||
{
|
||||
const Anope::string &user = it->first;
|
||||
@@ -1299,7 +1370,7 @@ public:
|
||||
|
||||
/* Normalize the buffer */
|
||||
Anope::string nbuf = Anope::NormalizeBuffer(realbuf);
|
||||
bool casesensitive = Config->GetModule("botserv")->Get<bool>("casesensitive");
|
||||
bool casesensitive = Config->GetModule("botserv").Get<bool>("casesensitive");
|
||||
|
||||
/* Normalize can return an empty string if this only contains control codes etc */
|
||||
if (badwords && !nbuf.empty())
|
||||
@@ -1368,7 +1439,7 @@ public:
|
||||
if (mustkick)
|
||||
{
|
||||
check_ban(ci, u, kd, TTB_BADWORDS);
|
||||
if (Config->GetModule(me)->Get<bool>("gentlebadwordreason"))
|
||||
if (Config->GetModule(me).Get<bool>("gentlebadwordreason"))
|
||||
bot_kick(ci, u, _("Watch your language!"));
|
||||
else
|
||||
bot_kick(ci, u, _("Don't use the word \"%s\" on this channel!"), bw->word.c_str());
|
||||
|
||||
+26
-16
@@ -30,11 +30,15 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Configures bot options.\n"
|
||||
" \n"
|
||||
"Available options:"));
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
|
||||
source.Reply(_(
|
||||
"Configures bot options."
|
||||
"\n\n"
|
||||
"Available options:"
|
||||
));
|
||||
bool hide_privileged_commands = Config->GetBlock("options").Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options").Get<bool>("hideregisteredcommands");
|
||||
|
||||
HelpWrapper help;
|
||||
Anope::string this_name = source.command;
|
||||
for (const auto &[c_name, info] : source.service->commands)
|
||||
{
|
||||
@@ -54,12 +58,14 @@ public:
|
||||
continue;
|
||||
|
||||
source.command = c_name;
|
||||
command->OnServHelp(source);
|
||||
command->OnServHelp(source, help);
|
||||
}
|
||||
}
|
||||
}
|
||||
source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information on a\n"
|
||||
"particular option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
|
||||
help.SendTo(source);
|
||||
|
||||
source.Reply(_("Type \002%s\032\037option\037\002 for more information on a particular option."),
|
||||
source.service->GetQueryCommand("generic/help", this_name).c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -150,11 +156,13 @@ public:
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(_(" \n"
|
||||
"Sets the time bot bans expire in. If enabled, any bans placed by\n"
|
||||
"bots, such as flood kicker, badwords kicker, etc. will automatically\n"
|
||||
"be removed after the given time. Set to 0 to disable bans from\n"
|
||||
"automatically expiring."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Sets the time bot bans expire in. If enabled, any bans placed by "
|
||||
"bots, such as flood kicker, badwords kicker, etc. will automatically "
|
||||
"be removed after the given time. Set to 0 to disable bans from "
|
||||
"automatically expiring."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -203,9 +211,11 @@ public:
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(_(" \n"
|
||||
"This option prevents a bot from being assigned to a\n"
|
||||
"channel by users that aren't IRC Operators."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"This option prevents a bot from being assigned to a "
|
||||
"channel by users that aren't IRC Operators."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
inline static Anope::string BotModes()
|
||||
{
|
||||
return Config->GetModule("botserv")->Get<Anope::string>("botmodes",
|
||||
Config->GetModule("chanserv")->Get<Anope::string>("botmodes", "o")
|
||||
return Config->GetModule("botserv").Get<Anope::string>("botmodes",
|
||||
Config->GetModule("chanserv").Get<Anope::string>("botmodes", "o")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
* @param chan The channel
|
||||
*/
|
||||
ChanServTimer(Reference<BotInfo> &cs, ExtensibleItem<bool> &i, Module *m, Channel *chan)
|
||||
: Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "1m"))
|
||||
: Timer(m, Config->GetModule(m).Get<time_t>("inhabit", "1m"))
|
||||
, ChanServ(cs)
|
||||
, inhabit(i)
|
||||
, c(chan)
|
||||
@@ -103,9 +103,9 @@ public:
|
||||
new ChanServTimer(ChanServ, inhabit, this->owner, c);
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const Anope::string &channick = conf->GetModule(this)->Get<const Anope::string>("client");
|
||||
const Anope::string &channick = conf.GetModule(this).Get<const Anope::string>("client");
|
||||
|
||||
if (channick.empty())
|
||||
throw ConfigException(Module::name + ": <client> must be defined");
|
||||
@@ -116,18 +116,21 @@ public:
|
||||
|
||||
ChanServ = bi;
|
||||
|
||||
spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "keeptopic peace securefounder signkick")).GetTokens(defaults);
|
||||
spacesepstream(conf.GetModule(this).Get<const Anope::string>("defaults")).GetTokens(defaults);
|
||||
if (defaults.empty())
|
||||
{
|
||||
defaults.emplace_back("KEEPTOPIC");
|
||||
defaults.emplace_back("PEACE");
|
||||
defaults.emplace_back("SECUREFOUNDER");
|
||||
defaults.emplace_back("SIGNKICK");
|
||||
defaults = {
|
||||
"CS_KEEP_MODES",
|
||||
"KEEPTOPIC",
|
||||
"PEACE",
|
||||
"SECUREFOUNDER",
|
||||
"SIGNKICK",
|
||||
};
|
||||
}
|
||||
else if (defaults[0].equals_ci("none"))
|
||||
defaults.clear();
|
||||
|
||||
always_lower = conf->GetModule(this)->Get<bool>("always_lower_ts");
|
||||
always_lower = conf.GetModule(this).Get<bool>("always_lower_ts");
|
||||
}
|
||||
|
||||
void OnBotDelete(BotInfo *bi) override
|
||||
@@ -138,7 +141,7 @@ public:
|
||||
|
||||
EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
if (bi == ChanServ && Config->GetModule(this)->Get<bool>("opersonly") && !u->HasMode("OPER"))
|
||||
if (bi == ChanServ && Config->GetModule(this).Get<bool>("opersonly") && !u->HasMode("OPER"))
|
||||
{
|
||||
u->SendMessage(bi, ACCESS_DENIED);
|
||||
return EVENT_STOP;
|
||||
@@ -151,7 +154,7 @@ public:
|
||||
{
|
||||
std::deque<ChannelInfo *> chans;
|
||||
nc->GetChannelReferences(chans);
|
||||
int max_reg = Config->GetModule(this)->Get<int>("maxregistered");
|
||||
int max_reg = Config->GetModule(this).Get<int>("maxregistered");
|
||||
|
||||
for (auto *ci : chans)
|
||||
{
|
||||
@@ -247,7 +250,7 @@ public:
|
||||
{
|
||||
ci->c->RemoveMode(ci->WhoSends(), "REGISTERED", "", false);
|
||||
|
||||
const Anope::string &require = Config->GetModule(this)->Get<const Anope::string>("require");
|
||||
const Anope::string &require = Config->GetModule(this).Get<const Anope::string>("require");
|
||||
if (!require.empty())
|
||||
ci->c->SetModes(ci->WhoSends(), false, "-%s", require.c_str());
|
||||
}
|
||||
@@ -257,14 +260,19 @@ public:
|
||||
{
|
||||
if (!params.empty() || source.c || source.service != *ChanServ)
|
||||
return EVENT_CONTINUE;
|
||||
source.Reply(_("\002%s\002 allows you to register and control various\n"
|
||||
"aspects of channels. %s can often prevent\n"
|
||||
"malicious users from \"taking over\" channels by limiting\n"
|
||||
"who is allowed channel operator privileges. Available\n"
|
||||
"commands are listed below; to use them, type\n"
|
||||
"\002%s \037command\037\002. For more information on a\n"
|
||||
"specific command, type \002%s HELP \037command\037\002.\n"),
|
||||
ChanServ->nick.c_str(), ChanServ->nick.c_str(), ChanServ->GetQueryCommand().c_str(), ChanServ->GetQueryCommand().c_str());
|
||||
source.Reply(_(
|
||||
"\002%s\002 allows you to register and control various "
|
||||
"aspects of channels. %s can often prevent "
|
||||
"malicious users from \"taking over\" channels by limiting "
|
||||
"who is allowed channel operator privileges. Available "
|
||||
"commands are listed below; to use them, type "
|
||||
"\002%s\032\037command\037\002. For more information on a "
|
||||
"specific command, type \002%s\032\037command\037\002."
|
||||
),
|
||||
ChanServ->nick.c_str(),
|
||||
ChanServ->nick.c_str(),
|
||||
ChanServ->GetQueryCommand().c_str(),
|
||||
ChanServ->GetQueryCommand("generic/help").c_str());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -272,17 +280,27 @@ public:
|
||||
{
|
||||
if (!params.empty() || source.c || source.service != *ChanServ)
|
||||
return;
|
||||
time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
|
||||
if (chanserv_expire >= 86400)
|
||||
source.Reply(_(" \n"
|
||||
"Note that any channel which is not used for %lu days\n"
|
||||
"(i.e. which no user on the channel's access list enters\n"
|
||||
"for that period of time) will be automatically dropped."), (unsigned long)chanserv_expire / 86400);
|
||||
|
||||
time_t chanserv_expire = Config->GetModule(this).Get<time_t>("expire", "30d");
|
||||
if (chanserv_expire)
|
||||
{
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Note that any channel which is not used for %s "
|
||||
"(i.e. which no user on the channel's access list enters "
|
||||
"for that period of time) will be automatically dropped."
|
||||
),
|
||||
Anope::Duration(chanserv_expire, source.nc).c_str());
|
||||
}
|
||||
if (source.IsServicesOper())
|
||||
source.Reply(_(" \n"
|
||||
"Services Operators can also, depending on their access drop\n"
|
||||
"any channel, view (and modify) the access, levels and akick\n"
|
||||
"lists and settings for any channel."));
|
||||
{
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Services Operators can also, depending on their access drop "
|
||||
"any channel, view (and modify) the access, levels and akick "
|
||||
"lists and settings for any channel."
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void OnCheckModes(Reference<Channel> &c) override
|
||||
@@ -295,7 +313,7 @@ public:
|
||||
else
|
||||
c->RemoveMode(c->WhoSends(), "REGISTERED", "", false);
|
||||
|
||||
const Anope::string &require = Config->GetModule(this)->Get<const Anope::string>("require");
|
||||
const Anope::string &require = Config->GetModule(this).Get<const Anope::string>("require");
|
||||
if (!require.empty())
|
||||
{
|
||||
if (c->ci)
|
||||
@@ -314,8 +332,8 @@ public:
|
||||
|
||||
EventReturn OnCanSet(User *u, const ChannelMode *cm) override
|
||||
{
|
||||
if (Config->GetModule(this)->Get<const Anope::string>("nomlock").find(cm->mchar) != Anope::string::npos
|
||||
|| Config->GetModule(this)->Get<const Anope::string>("require").find(cm->mchar) != Anope::string::npos)
|
||||
if (Config->GetModule(this).Get<const Anope::string>("nomlock").find(cm->mchar) != Anope::string::npos
|
||||
|| Config->GetModule(this).Get<const Anope::string>("require").find(cm->mchar) != Anope::string::npos)
|
||||
return EVENT_STOP;
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
@@ -337,7 +355,7 @@ public:
|
||||
|
||||
void OnExpireTick() override
|
||||
{
|
||||
time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
|
||||
time_t chanserv_expire = Config->GetModule(this).Get<time_t>("expire", "30d");
|
||||
|
||||
if (!chanserv_expire || Anope::NoExpire || Anope::ReadOnly)
|
||||
return;
|
||||
@@ -399,7 +417,7 @@ public:
|
||||
continue;
|
||||
|
||||
bool c;
|
||||
ci->c = Channel::FindOrCreate(ci->name, c, ci->time_registered);
|
||||
ci->c = Channel::FindOrCreate(ci->name, c, ci->registered);
|
||||
ci->c->syncing |= created;
|
||||
|
||||
if (perm)
|
||||
@@ -434,10 +452,10 @@ public:
|
||||
|
||||
void OnJoinChannel(User *u, Channel *c) override
|
||||
{
|
||||
if (always_lower && c->ci && c->creation_time > c->ci->time_registered)
|
||||
if (always_lower && c->ci && c->created > c->ci->registered)
|
||||
{
|
||||
Log(LOG_DEBUG) << "Changing TS of " << c->name << " from " << c->creation_time << " to " << c->ci->time_registered;
|
||||
c->creation_time = c->ci->time_registered;
|
||||
Log(LOG_DEBUG) << "Changing TS of " << c->name << " from " << c->created << " to " << c->ci->registered;
|
||||
c->created = c->ci->registered;
|
||||
IRCD->SendChannel(c);
|
||||
c->Reset();
|
||||
}
|
||||
@@ -445,7 +463,7 @@ public:
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override
|
||||
{
|
||||
if (!always_lower && Anope::CurTime == c->creation_time && c->ci && setter.GetUser() && !setter.GetUser()->server->IsULined())
|
||||
if (!always_lower && Anope::CurTime == c->created && c->ci && setter.GetUser() && !setter.GetUser()->server->IsULined())
|
||||
{
|
||||
ChanUserContainer *cu = c->FindUser(setter.GetUser());
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName("OP");
|
||||
@@ -467,7 +485,7 @@ public:
|
||||
if (!show_all)
|
||||
return;
|
||||
|
||||
time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
|
||||
time_t chanserv_expire = Config->GetModule(this).Get<time_t>("expire", "30d");
|
||||
if (!ci->HasExt("CS_NO_EXPIRE") && chanserv_expire && !Anope::NoExpire && ci->last_used != Anope::CurTime)
|
||||
info[_("Expires")] = Anope::strftime(ci->last_used + chanserv_expire, source.GetAccount());
|
||||
}
|
||||
|
||||
+142
-126
@@ -84,6 +84,38 @@ AccessAccessProvider *AccessAccessProvider::me;
|
||||
class CommandCSAccess final
|
||||
: public Command
|
||||
{
|
||||
private:
|
||||
static void AddEntry(ListFormatter &list, const ChannelInfo *ci, const ChanAccess *access, unsigned number)
|
||||
{
|
||||
Anope::string timebuf;
|
||||
if (ci->c)
|
||||
{
|
||||
for (const auto &[_, cuc] : ci->c->users)
|
||||
{
|
||||
ChannelInfo *p;
|
||||
if (access->Matches(cuc->user, cuc->user->Account(), p))
|
||||
timebuf = "Now";
|
||||
}
|
||||
}
|
||||
if (timebuf.empty())
|
||||
{
|
||||
if (access->last_seen == 0)
|
||||
timebuf = "Never";
|
||||
else
|
||||
timebuf = Anope::strftime(access->last_seen, NULL, true);
|
||||
}
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Number"] = Anope::ToString(number);
|
||||
entry["Level"] = access->AccessSerialize();
|
||||
entry["Mask"] = access->Mask();
|
||||
entry["By"] = access->creator;
|
||||
entry["Last seen"] = timebuf;
|
||||
entry["Description"] = access->description;
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
|
||||
void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
Anope::string mask = params[2];
|
||||
@@ -134,7 +166,7 @@ class CommandCSAccess final
|
||||
|
||||
if (IRCD->IsChannelValid(mask))
|
||||
{
|
||||
if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access"))
|
||||
if (Config->GetModule("chanserv").Get<bool>("disallow_channel_access"))
|
||||
{
|
||||
source.Reply(_("Channels may not be on access lists."));
|
||||
return;
|
||||
@@ -158,7 +190,7 @@ class CommandCSAccess final
|
||||
{
|
||||
na = NickAlias::Find(mask);
|
||||
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
if (!na && Config->GetModule("chanserv").Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
return;
|
||||
@@ -205,7 +237,7 @@ class CommandCSAccess final
|
||||
}
|
||||
}
|
||||
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
|
||||
unsigned access_max = Config->GetModule("chanserv").Get<unsigned>("accessmax", "1000");
|
||||
if (access_max && ci->GetDeepAccessCount() >= access_max)
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
|
||||
@@ -284,11 +316,11 @@ class CommandCSAccess final
|
||||
else
|
||||
{
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << Nicks;
|
||||
|
||||
if (deleted == 1)
|
||||
source.Reply(_("Deleted 1 entry from %s access list."), ci->name.c_str());
|
||||
source.Reply(_("Deleted %s from %s access list."), Nicks.c_str(), ci->name.c_str());
|
||||
|
||||
else
|
||||
source.Reply(_("Deleted %d entries from %s access list."), deleted, ci->name.c_str());
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s access list.", "Deleted %d entries from %s access list."), deleted, ci->name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,32 +413,7 @@ class CommandCSAccess final
|
||||
|
||||
const ChanAccess *access = ci->GetAccess(number - 1);
|
||||
|
||||
Anope::string timebuf;
|
||||
if (ci->c)
|
||||
{
|
||||
for (const auto &[_, cuc] : ci->c->users)
|
||||
{
|
||||
ChannelInfo *p;
|
||||
if (access->Matches(cuc->user, cuc->user->Account(), p))
|
||||
timebuf = "Now";
|
||||
}
|
||||
}
|
||||
if (timebuf.empty())
|
||||
{
|
||||
if (access->last_seen == 0)
|
||||
timebuf = "Never";
|
||||
else
|
||||
timebuf = Anope::strftime(access->last_seen, NULL, true);
|
||||
}
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Number"] = Anope::ToString(number);
|
||||
entry["Level"] = access->AccessSerialize();
|
||||
entry["Mask"] = access->Mask();
|
||||
entry["By"] = access->creator;
|
||||
entry["Last seen"] = timebuf;
|
||||
entry["Description"] = access->description;
|
||||
this->list.AddEntry(entry);
|
||||
AddEntry(this->list, ci, access, number);
|
||||
}
|
||||
}
|
||||
nl_list(list, ci, nick);
|
||||
@@ -421,32 +428,7 @@ class CommandCSAccess final
|
||||
if (!nick.empty() && !Anope::Match(access->Mask(), nick))
|
||||
continue;
|
||||
|
||||
Anope::string timebuf;
|
||||
if (ci->c)
|
||||
{
|
||||
for (auto &[_, cuc] : ci->c->users)
|
||||
{
|
||||
ChannelInfo *p;
|
||||
if (access->Matches(cuc->user, cuc->user->Account(), p))
|
||||
timebuf = "Now";
|
||||
}
|
||||
}
|
||||
if (timebuf.empty())
|
||||
{
|
||||
if (access->last_seen == 0)
|
||||
timebuf = "Never";
|
||||
else
|
||||
timebuf = Anope::strftime(access->last_seen, NULL, true);
|
||||
}
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Number"] = Anope::ToString(i + 1);
|
||||
entry["Level"] = access->AccessSerialize();
|
||||
entry["Mask"] = access->Mask();
|
||||
entry["By"] = access->creator;
|
||||
entry["Last seen"] = timebuf;
|
||||
entry["Description"] = access->description;
|
||||
list.AddEntry(entry);
|
||||
AddEntry(list, ci, access, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,52 +568,76 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Maintains the \002access list\002 for a channel. The access\n"
|
||||
"list specifies which users are allowed chanop status or\n"
|
||||
"access to %s commands on the channel. Different\n"
|
||||
"user levels allow for access to different subsets of\n"
|
||||
"privileges. Any registered user not on the access list has\n"
|
||||
"a user level of 0, and any unregistered user has a user level\n"
|
||||
"of -1."), source.service->nick.c_str());
|
||||
source.Reply(_(
|
||||
"Maintains the \002access list\002 for a channel. The access "
|
||||
"list specifies which users are allowed chanop status or "
|
||||
"access to %s commands on the channel. Different "
|
||||
"user levels allow for access to different subsets of "
|
||||
"privileges. Any registered user not on the access list has "
|
||||
"a user level of 0, and any unregistered user has a user level "
|
||||
"of -1."
|
||||
"\n\n"
|
||||
"The \002%s\032ADD\002 command adds the given mask to the "
|
||||
"access list with the given user level; if the mask is "
|
||||
"already present on the list, its access level is changed to "
|
||||
"the level specified in the command. The \037level\037 specified "
|
||||
"may be a numerical level or the name of a privilege (eg AUTOOP). "
|
||||
"When a user joins the channel the access they receive is from the "
|
||||
"highest level entry in the access list."
|
||||
),
|
||||
source.service->nick.c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
|
||||
if (!Config->GetModule("chanserv").Get<bool>("disallow_channel_access"))
|
||||
{
|
||||
source.Reply(_(
|
||||
"The given mask may also be a channel, which will use the "
|
||||
"access list from the other channel up to the given \037level\037."
|
||||
));
|
||||
}
|
||||
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ACCESS ADD\002 command adds the given mask to the\n"
|
||||
"access list with the given user level; if the mask is\n"
|
||||
"already present on the list, its access level is changed to\n"
|
||||
"the level specified in the command. The \037level\037 specified\n"
|
||||
"may be a numerical level or the name of a privilege (eg AUTOOP).\n"
|
||||
"When a user joins the channel the access they receive is from the\n"
|
||||
"highest level entry in the access list."));
|
||||
if (!Config->GetModule("chanserv")->Get<bool>("disallow_channel_access"))
|
||||
source.Reply(_("The given mask may also be a channel, which will use the\n"
|
||||
"access list from the other channel up to the given \037level\037."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ACCESS DEL\002 command removes the given nick from the\n"
|
||||
"access list. If a list of entry numbers is given, those\n"
|
||||
"entries are deleted. (See the example for LIST below.)\n"
|
||||
"You may remove yourself from an access list, even if you\n"
|
||||
"do not have access to modify that list otherwise."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ACCESS LIST\002 command displays the access list. If\n"
|
||||
"a wildcard mask is given, only those entries matching the\n"
|
||||
"mask are displayed. If a list of entry numbers is given,\n"
|
||||
source.Reply(_(
|
||||
"The \002%s\032DEL\002 command removes the given nick from the "
|
||||
"access list. If a list of entry numbers is given, those "
|
||||
"entries are deleted. (See the example for LIST below.) "
|
||||
"You may remove yourself from an access list, even if you "
|
||||
"do not have access to modify that list otherwise."
|
||||
"\n\n"
|
||||
"The \002%s\032LIST\002 command displays the access list. If "
|
||||
"a wildcard mask is given, only those entries matching the "
|
||||
"mask are displayed. If a list of entry numbers is given, "
|
||||
"only those entries are shown; for example:\n"
|
||||
" \002ACCESS #channel LIST 2-5,7-9\002\n"
|
||||
" \002%s\032#channel\032LIST\0322-5,7-9\002\n"
|
||||
" Lists access entries numbered 2 through 5 and\n"
|
||||
" 7 through 9.\n"
|
||||
" \n"
|
||||
"The \002ACCESS VIEW\002 command displays the access list similar\n"
|
||||
"to \002ACCESS LIST\002 but shows the creator and last used time.\n"
|
||||
" \n"
|
||||
"The \002ACCESS CLEAR\002 command clears all entries of the\n"
|
||||
"access list."));
|
||||
source.Reply(" ");
|
||||
" 7 through 9."
|
||||
"\n\n"
|
||||
"The \002%s\032VIEW\002 command displays the access list similar "
|
||||
"to \002%s\032LIST\002 but shows the creator and last used time."
|
||||
"\n\n"
|
||||
"The \002%s\032CLEAR\002 command clears all entries of the "
|
||||
"access list."
|
||||
),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
|
||||
BotInfo *bi;
|
||||
Anope::string cmd;
|
||||
if (Command::FindCommandFromService("chanserv/levels", bi, cmd))
|
||||
source.Reply(_("\002User access levels\002 can be seen by using the\n"
|
||||
"\002%s\002 command; type \002%s HELP LEVELS\002 for\n"
|
||||
"information."), cmd.c_str(), bi->GetQueryCommand().c_str());
|
||||
{
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"\002User access levels\002 can be seen by using the "
|
||||
"\002%s\002 command; type \002%s\032LEVELS\002 for "
|
||||
"information."
|
||||
),
|
||||
cmd.c_str(),
|
||||
bi->GetQueryCommand("generic/help").c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -666,8 +672,8 @@ class CommandCSLevels final
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(what);
|
||||
if (p == NULL)
|
||||
{
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s HELP LEVELS\002 for a list of valid settings."),
|
||||
what.c_str(), source.service->GetQueryCommand().c_str());
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s\032LEVELS\002 for a list of valid settings."),
|
||||
what.c_str(), source.service->GetQueryCommand("generic/help").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -709,8 +715,8 @@ class CommandCSLevels final
|
||||
return;
|
||||
}
|
||||
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s HELP LEVELS\002 for a list of valid settings."),
|
||||
what.c_str(), source.service->GetQueryCommand().c_str());
|
||||
source.Reply(_("Setting \002%s\002 not known. Type \002%s\032LEVELS\002 for a list of valid settings."),
|
||||
what.c_str(), source.service->GetQueryCommand("generic/help").c_str());
|
||||
}
|
||||
|
||||
static void DoList(CommandSource &source, ChannelInfo *ci)
|
||||
@@ -839,25 +845,35 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002LEVELS\002 command allows fine control over the meaning of\n"
|
||||
"the numeric access levels used for channels. With this\n"
|
||||
"command, you can define the access level required for most\n"
|
||||
"of %s's functions. (The \002SET FOUNDER\002 and this command\n"
|
||||
"are always restricted to the channel founder.)\n"
|
||||
" \n"
|
||||
"\002LEVELS SET\002 allows the access level for a function or group of\n"
|
||||
"functions to be changed. \002LEVELS DISABLE\002 (or \002DIS\002 for short)\n"
|
||||
"disables an automatic feature or disallows access to a\n"
|
||||
"function by anyone, INCLUDING the founder (although, the founder\n"
|
||||
"can always re-enable it). Use \002LEVELS SET founder\002 to make a level\n"
|
||||
"founder only.\n"
|
||||
" \n"
|
||||
"\002LEVELS LIST\002 shows the current levels for each function or\n"
|
||||
"group of functions. \002LEVELS RESET\002 resets the levels to the\n"
|
||||
"default levels of a newly-created channel.\n"
|
||||
" \n"
|
||||
"For a list of the features and functions whose levels can be\n"
|
||||
"set, see \002HELP LEVELS DESC\002."), source.service->nick.c_str());
|
||||
source.Reply(_(
|
||||
"The \002%s\002 command allows fine control over the meaning of "
|
||||
"the numeric access levels used for channels. With this "
|
||||
"command, you can define the access level required for most "
|
||||
"of %s's functions. (The \002SET\032FOUNDER\002 and this command "
|
||||
"are always restricted to the channel founder)."
|
||||
"\n\n"
|
||||
"\002%s\032SET\002 allows the access level for a function or group of "
|
||||
"functions to be changed. \002%s\032DISABLE\002 (or \002DIS\002 for short) "
|
||||
"disables an automatic feature or disallows access to a "
|
||||
"function by anyone, INCLUDING the founder (although, the founder "
|
||||
"can always re-enable it). Use \002%s\032SET founder\002 to make a level "
|
||||
"founder only."
|
||||
"\n\n"
|
||||
"\002%s\032LIST\002 shows the current levels for each function or "
|
||||
"group of functions. \002%s\032RESET\002 resets the levels to the "
|
||||
"default levels of a newly-created channel."
|
||||
"\n\n"
|
||||
"For a list of the features and functions whose levels can be "
|
||||
"set, see \002HELP\032%s\032DESC\002."
|
||||
),
|
||||
source.service->nick.c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -878,21 +894,21 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
defaultLevels.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("privilege"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
|
||||
{
|
||||
Configuration::Block *priv = conf->GetBlock("privilege", i);
|
||||
const auto &priv = conf.GetBlock("privilege", i);
|
||||
|
||||
const Anope::string &pname = priv->Get<const Anope::string>("name");
|
||||
const Anope::string &pname = priv.Get<const Anope::string>("name");
|
||||
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(pname);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
const Anope::string &value = priv->Get<const Anope::string>("level");
|
||||
const Anope::string &value = priv.Get<const Anope::string>("level");
|
||||
if (value.empty())
|
||||
continue;
|
||||
else if (value.equals_ci("founder"))
|
||||
@@ -900,7 +916,7 @@ public:
|
||||
else if (value.equals_ci("disabled"))
|
||||
defaultLevels[p->name] = ACCESS_INVALID;
|
||||
else
|
||||
defaultLevels[p->name] = priv->Get<int16_t>("level");
|
||||
defaultLevels[p->name] = priv.Get<int16_t>("level");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class CommandCSAKick final
|
||||
const NickAlias *na = NickAlias::Find(mask);
|
||||
NickCore *nc = NULL;
|
||||
const AutoKick *akick;
|
||||
unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
|
||||
unsigned reasonmax = Config->GetModule("chanserv").Get<unsigned>("reasonmax", "200");
|
||||
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
@@ -170,9 +170,9 @@ class CommandCSAKick final
|
||||
}
|
||||
}
|
||||
|
||||
if (ci->GetAkickCount() >= Config->GetModule(this->owner)->Get<unsigned>("autokickmax"))
|
||||
if (ci->GetAkickCount() >= Config->GetModule(this->owner).Get<unsigned>("autokickmax"))
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d autokick masks on a channel."), Config->GetModule(this->owner)->Get<unsigned>("autokickmax"));
|
||||
source.Reply(_("Sorry, you can only have %d autokick masks on a channel."), Config->GetModule(this->owner).Get<unsigned>("autokickmax"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -211,6 +211,7 @@ class CommandCSAKick final
|
||||
ChannelInfo *ci;
|
||||
Command *c;
|
||||
unsigned deleted = 0;
|
||||
Anope::string lastdeleted;
|
||||
AccessGroup ag;
|
||||
public:
|
||||
AkickDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), ag(source.AccessFor(ci))
|
||||
@@ -219,12 +220,20 @@ class CommandCSAKick final
|
||||
|
||||
~AkickDelCallback() override
|
||||
{
|
||||
if (!deleted)
|
||||
source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str());
|
||||
else if (deleted == 1)
|
||||
source.Reply(_("Deleted 1 entry from %s autokick list."), ci->name.c_str());
|
||||
else
|
||||
source.Reply(_("Deleted %d entries from %s autokick list."), deleted, ci->name.c_str());
|
||||
switch (deleted)
|
||||
{
|
||||
case 0:
|
||||
source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str());
|
||||
break;
|
||||
|
||||
case 1:
|
||||
source.Reply(_("Deleted %s from %s autokick list."), lastdeleted.c_str(), ci->name.c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s autokick list.", "Deleted %d entries from %s autokick list."), deleted, ci->name.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleNumber(unsigned number) override
|
||||
@@ -237,7 +246,8 @@ class CommandCSAKick final
|
||||
FOREACH_MOD(OnAkickDel, (source, ci, akick));
|
||||
|
||||
bool override = !ag.HasPriv("AKICK");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << (akick->nc ? akick->nc->display : akick->mask);
|
||||
lastdeleted = (akick->nc ? akick->nc->display : akick->mask);
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << lastdeleted;
|
||||
|
||||
++deleted;
|
||||
ci->EraseAkick(number - 1);
|
||||
@@ -490,40 +500,51 @@ public:
|
||||
BotInfo *bi = Config->GetClient("NickServ");
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Maintains the \002AutoKick list\002 for a channel. If a user\n"
|
||||
"on the AutoKick list attempts to join the channel,\n"
|
||||
"%s will ban that user from the channel, then kick\n"
|
||||
"the user.\n"
|
||||
" \n"
|
||||
"The \002AKICK ADD\002 command adds the given nick or usermask\n"
|
||||
"to the AutoKick list. If a \037reason\037 is given with\n"
|
||||
"the command, that reason will be used when the user is\n"
|
||||
"kicked; if not, the default reason is \"User has been\n"
|
||||
"banned from the channel\".\n"
|
||||
"When akicking a \037registered nick\037 the %s account\n"
|
||||
"will be added to the akick list instead of the mask.\n"
|
||||
"All users within that nickgroup will then be akicked.\n"),
|
||||
source.service->nick.c_str(), bi ? bi->nick.c_str() : "NickServ");
|
||||
source.Reply(_(
|
||||
" \n"
|
||||
"The \002AKICK DEL\002 command removes the given nick or mask\n"
|
||||
"from the AutoKick list. It does not, however, remove any\n"
|
||||
"bans placed by an AutoKick; those must be removed\n"
|
||||
"manually.\n"
|
||||
" \n"
|
||||
"The \002AKICK LIST\002 command displays the AutoKick list, or\n"
|
||||
"optionally only those AutoKick entries which match the\n"
|
||||
"given mask.\n"
|
||||
" \n"
|
||||
"The \002AKICK VIEW\002 command is a more verbose version of the\n"
|
||||
"\002AKICK LIST\002 command.\n"
|
||||
" \n"
|
||||
"The \002AKICK ENFORCE\002 command causes %s to enforce the\n"
|
||||
"current AKICK list by removing those users who match an\n"
|
||||
"AKICK mask.\n"
|
||||
" \n"
|
||||
"The \002AKICK CLEAR\002 command clears all entries of the\n"
|
||||
"akick list."), source.service->nick.c_str());
|
||||
"Maintains the \002AutoKick list\002 for a channel. If a user "
|
||||
"on the AutoKick list attempts to join the channel, "
|
||||
"%s will ban that user from the channel, then kick "
|
||||
"the user."
|
||||
"\n\n"
|
||||
"The \002%s\032ADD\002 command adds the given nick or usermask "
|
||||
"to the AutoKick list. If a \037reason\037 is given with "
|
||||
"the command, that reason will be used when the user is "
|
||||
"kicked; if not, the default reason is \"User has been "
|
||||
"banned from the channel\". "
|
||||
"When akicking a \037registered nick\037 the %s account "
|
||||
"will be added to the akick list instead of the mask. "
|
||||
"All users within that nickgroup will then be akicked. "
|
||||
"\n\n"
|
||||
"The \002%s\032DEL\002 command removes the given nick or mask "
|
||||
"from the AutoKick list. It does not, however, remove any "
|
||||
"bans placed by an AutoKick; those must be removed "
|
||||
"manually."
|
||||
"\n\n"
|
||||
"The \002%s\032LIST\002 command displays the AutoKick list, or "
|
||||
"optionally only those AutoKick entries which match the "
|
||||
"given mask."
|
||||
"\n\n"
|
||||
"The \002%s\032VIEW\002 command is a more verbose version of the "
|
||||
"\002%s\032LIST\002 command."
|
||||
"\n\n"
|
||||
"The \002%s\032ENFORCE\002 command causes %s to enforce the "
|
||||
"current akick list by removing those users who match an "
|
||||
"akick mask."
|
||||
"\n\n"
|
||||
"The \002%s\032CLEAR\002 command clears all entries of the "
|
||||
"akick list."
|
||||
),
|
||||
source.service->nick.c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
bi ? bi->nick.c_str() : "NickServ",
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -568,9 +589,11 @@ public:
|
||||
reason = autokick->reason;
|
||||
if (reason.empty())
|
||||
{
|
||||
reason = Language::Translate(u, Config->GetModule(this)->Get<const Anope::string>("autokickreason").c_str());
|
||||
reason = reason.replace_all_cs("%n", u->nick)
|
||||
.replace_all_cs("%c", c->name);
|
||||
reason = Language::Translate(u, Config->GetModule(this).Get<const Anope::string>("autokickreason").c_str());
|
||||
reason = Anope::Template(reason, {
|
||||
{ "channel", c->name },
|
||||
{ "nick", u->nick },
|
||||
});
|
||||
}
|
||||
if (reason.empty())
|
||||
reason = Language::Translate(u, _("User has been banned from the channel"));
|
||||
|
||||
+22
-15
@@ -50,8 +50,8 @@ public:
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
Configuration::Block *block = Config->GetCommand(source);
|
||||
const Anope::string &mode = block->Get<Anope::string>("mode", "BAN");
|
||||
const auto &block = Config->GetCommand(source);
|
||||
const Anope::string &mode = block.Get<Anope::string>("mode", "BAN");
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(mode);
|
||||
if (cm == NULL)
|
||||
return;
|
||||
@@ -107,12 +107,11 @@ public:
|
||||
reason += " " + params[3];
|
||||
}
|
||||
|
||||
unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
|
||||
unsigned reasonmax = Config->GetModule("chanserv").Get<unsigned>("reasonmax", "200");
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
|
||||
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
|
||||
auto signkickformat = Config->GetModule("chanserv").Get<Anope::string>("signkickformat", "{message} ({nick})");
|
||||
|
||||
User *u = source.GetUser();
|
||||
User *u2 = User::Find(target, true);
|
||||
@@ -156,11 +155,14 @@ public:
|
||||
if (!c->FindUser(u2))
|
||||
return;
|
||||
|
||||
if (block->Get<bool>("kick", "yes"))
|
||||
if (block.Get<bool>("kick", "yes"))
|
||||
{
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
|
||||
{
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
signkickformat = Anope::Template(signkickformat, {
|
||||
{ "message", reason },
|
||||
{ "nick", source.GetNick() },
|
||||
});
|
||||
c->Kick(ci->WhoSends(), u2, signkickformat);
|
||||
}
|
||||
else
|
||||
@@ -209,13 +211,16 @@ public:
|
||||
else if (uc->user->IsProtected())
|
||||
continue;
|
||||
|
||||
if (block->Get<bool>("kick", "yes"))
|
||||
if (block.Get<bool>("kick", "yes"))
|
||||
{
|
||||
++kicked;
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
{
|
||||
reason += " (Matches " + mask + ")";
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
signkickformat = Anope::Template(signkickformat, {
|
||||
{ "message", reason },
|
||||
{ "nick", source.GetNick() },
|
||||
});
|
||||
c->Kick(ci->WhoSends(), uc->user, signkickformat);
|
||||
}
|
||||
else
|
||||
@@ -235,12 +240,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Bans a given nick or mask on a channel. An optional expiry may\n"
|
||||
"be given to cause services to remove the ban after a set amount\n"
|
||||
"of time.\n"
|
||||
" \n"
|
||||
"By default, limited to AOPs or those with level 5 access\n"
|
||||
"and above on the channel. Channel founders may ban masks."));
|
||||
source.Reply(_(
|
||||
"Bans a given nick or mask on a channel. An optional expiry may "
|
||||
"be given to cause services to remove the ban after a set amount "
|
||||
"of time."
|
||||
"\n\n"
|
||||
"By default, limited to AOPs or those with level 5 access "
|
||||
"and above on the channel. Channel founders may ban masks."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
|
||||
class CommandCSClone final
|
||||
: public Command
|
||||
@@ -24,7 +24,7 @@ class CommandCSClone final
|
||||
static void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
|
||||
{
|
||||
std::set<Anope::string> masks;
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
|
||||
unsigned access_max = Config->GetModule("chanserv").Get<unsigned>("accessmax", "1000");
|
||||
unsigned count = 0;
|
||||
|
||||
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
delete target_ci;
|
||||
target_ci = new ChannelInfo(*ci);
|
||||
target_ci->name = target;
|
||||
target_ci->time_registered = Anope::CurTime;
|
||||
target_ci->registered = Anope::CurTime;
|
||||
(*RegisteredChannelList)[target_ci->name] = target_ci;
|
||||
target_ci->c = Channel::Find(target_ci->name);
|
||||
|
||||
@@ -239,10 +239,12 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Copies all settings, access, akicks, etc from \002channel\002 to the\n"
|
||||
"\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, \002BADWORDS\002,\n"
|
||||
"or \002LEVELS\002 then only the respective settings are cloned.\n"
|
||||
"You must be the founder of \037channel\037 and \037target\037."));
|
||||
source.Reply(_(
|
||||
"Copies all settings, access, akicks, etc from \002channel\002 to the "
|
||||
"\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, \002BADWORDS\002, "
|
||||
"or \002LEVELS\002 then only the respective settings are cloned. "
|
||||
"You must be the founder of \037channel\037 and \037target\037."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -55,10 +55,10 @@ public:
|
||||
if (!code)
|
||||
{
|
||||
code = ci->Extend<Anope::string>("channel-dropcode");
|
||||
*code = Anope::Random(15);
|
||||
*code = Anope::Random(Config->GetBlock("options").Get<size_t>("codelength", 15));
|
||||
}
|
||||
|
||||
source.Reply(CONFIRM_DROP, ci->name.c_str(), source.service->GetQueryCommand().c_str(),
|
||||
source.Reply(CONFIRM_DROP, ci->name.c_str(), source.service->GetQueryCommand("chanserv/drop").c_str(),
|
||||
ci->name.c_str(), code->c_str());
|
||||
return;
|
||||
}
|
||||
@@ -88,16 +88,28 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
if (source.IsServicesOper())
|
||||
source.Reply(_("Unregisters the specified channel. Only \002Services Operators\002\n"
|
||||
"can drop a channel of which they are not the founder of."));
|
||||
{
|
||||
source.Reply(_(
|
||||
"Unregisters the specified channel. Only \002Services Operators\002 "
|
||||
"can drop a channel of which they are not the founder of."
|
||||
));
|
||||
}
|
||||
else
|
||||
source.Reply(_("Unregisters the named channel. Can only be used by\n"
|
||||
"the \002channel founder\002."));
|
||||
{
|
||||
source.Reply(_(
|
||||
"Unregisters the named channel. Can only be used by "
|
||||
"the \002channel founder\002."
|
||||
));
|
||||
}
|
||||
|
||||
source.Reply(" ");
|
||||
if (source.HasPriv("chanserv/drop/override"))
|
||||
source.Reply(_("Additionally, Services Operators with the \037chanserv/drop/override\037 permission can\n"
|
||||
"replace \037code\037 with \002OVERRIDE\002 to drop without a confirmation code."));
|
||||
{
|
||||
source.Reply(_(
|
||||
"Additionally, Services Operators with the \037chanserv/drop/override\037 permission can "
|
||||
"replace \037code\037 with \002OVERRIDE\002 to drop without a confirmation code."
|
||||
));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -240,19 +240,21 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Enforce various channel modes and set options. The \037channel\037\n"
|
||||
"option indicates what channel to enforce the modes and options\n"
|
||||
"on. The \037what\037 option indicates what modes and options to\n"
|
||||
"enforce, and can be any of \002SECUREOPS\002, \002RESTRICTED\002, \002REGONLY\002, \002SSLONLY\002,\n"
|
||||
"\002BANS\002, or \002LIMIT\002.\n"
|
||||
" \n"
|
||||
"Use \002SECUREOPS\002 to enforce the SECUREOPS option, even if it is not\n"
|
||||
"enabled. Use \002RESTRICTED\002 to enforce the RESTRICTED option, also\n"
|
||||
"if it's not enabled. Use \002REGONLY\002 to kick all unregistered users\n"
|
||||
"from the channel. Use \002SSLONLY\002 to kick all users not using a secure\n"
|
||||
"connection from the channel. \002BANS\002 will enforce bans on the channel by\n"
|
||||
"kicking users affected by them, and \002LIMIT\002 will kick users until the\n"
|
||||
"user count drops below the channel limit, if one is set."));
|
||||
source.Reply(_(
|
||||
"Enforce various channel modes and set options. The \037channel\037 "
|
||||
"option indicates what channel to enforce the modes and options "
|
||||
"on. The \037what\037 option indicates what modes and options to "
|
||||
"enforce, and can be any of \002SECUREOPS\002, \002RESTRICTED\002, \002REGONLY\002, \002SSLONLY\002, "
|
||||
"\002BANS\002, or \002LIMIT\002."
|
||||
"\n\n"
|
||||
"Use \002SECUREOPS\002 to enforce the SECUREOPS option, even if it is not "
|
||||
"enabled. Use \002RESTRICTED\002 to enforce the RESTRICTED option, also "
|
||||
"if it's not enabled. Use \002REGONLY\002 to kick all unregistered users "
|
||||
"from the channel. Use \002SSLONLY\002 to kick all users not using a secure "
|
||||
"connection from the channel. \002BANS\002 will enforce bans on the channel by "
|
||||
"kicking users affected by them, and \002LIMIT\002 will kick users until the "
|
||||
"user count drops below the channel limit, if one is set."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_entrymsg.h"
|
||||
#include "modules/chanserv/entrymsg.h"
|
||||
|
||||
struct EntryMsgImpl final
|
||||
: EntryMsg
|
||||
@@ -29,16 +29,26 @@ struct EntryMsgImpl final
|
||||
}
|
||||
|
||||
~EntryMsgImpl() override;
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct EntryMsgTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
EntryMsgTypeImpl()
|
||||
: Serialize::Type("EntryMsg")
|
||||
{
|
||||
data.Store("ci", this->chan);
|
||||
data.Store("creator", this->creator);
|
||||
data.Store("message", this->message);
|
||||
data.Store("when", this->when);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *msg = static_cast<const EntryMsgImpl *>(obj);
|
||||
data.Store("ci", msg->chan);
|
||||
data.Store("creator", msg->creator);
|
||||
data.Store("message", msg->message);
|
||||
data.Store("when", msg->when);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
struct EntryMessageListImpl final
|
||||
@@ -68,7 +78,7 @@ EntryMsgImpl::~EntryMsgImpl()
|
||||
}
|
||||
|
||||
|
||||
Serializable *EntryMsgImpl::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
Serializable *EntryMsgTypeImpl::Unserialize(Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
Anope::string sci, screator, smessage;
|
||||
time_t swhen;
|
||||
@@ -142,7 +152,7 @@ private:
|
||||
{
|
||||
EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg");
|
||||
|
||||
if ((*messages)->size() >= Config->GetModule(this->owner)->Get<unsigned>("maxentries"))
|
||||
if ((*messages)->size() >= Config->GetModule(this->owner).Get<unsigned>("maxentries"))
|
||||
source.Reply(_("The entry message list for \002%s\002 is full."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
@@ -235,26 +245,32 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Controls what messages will be sent to users when they join the channel."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG ADD\002 command adds the given message to\n"
|
||||
"the list of messages shown to users when they join\n"
|
||||
"the channel."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG DEL\002 command removes the specified message from\n"
|
||||
"the list of messages shown to users when they join\n"
|
||||
"the channel. You can remove a message by specifying its number\n"
|
||||
"which you can get by listing the messages as explained below."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG LIST\002 command displays a listing of messages\n"
|
||||
"shown to users when they join the channel."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG CLEAR\002 command clears all entries from\n"
|
||||
"the list of messages shown to users when they join\n"
|
||||
"the channel, effectively disabling entry messages."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Adding, deleting, or clearing entry messages requires the\n"
|
||||
"SET permission."));
|
||||
source.Reply(_(
|
||||
"Controls what messages will be sent to users when they join the channel."
|
||||
"\n\n"
|
||||
"The \002%s\032ADD\002 command adds the given message to "
|
||||
"the list of messages shown to users when they join "
|
||||
"the channel."
|
||||
"\n\n"
|
||||
"The \002%s\032DEL\002 command removes the specified message from "
|
||||
"the list of messages shown to users when they join "
|
||||
"the channel. You can remove a message by specifying its number "
|
||||
"which you can get by listing the messages as explained below."
|
||||
"\n\n"
|
||||
"The \002%s\032LIST\002 command displays a listing of messages "
|
||||
"shown to users when they join the channel."
|
||||
"\n\n"
|
||||
"The \002%s\032CLEAR\002 command clears all entries from "
|
||||
"the list of messages shown to users when they join "
|
||||
"the channel, effectively disabling entry messages."
|
||||
"\n\n"
|
||||
"Adding, deleting, or clearing entry messages requires the "
|
||||
"SET permission."
|
||||
),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -264,12 +280,13 @@ class CSEntryMessage final
|
||||
{
|
||||
CommandEntryMessage commandentrymsg;
|
||||
ExtensibleItem<EntryMessageListImpl> eml;
|
||||
Serialize::Type entrymsg_type;
|
||||
EntryMsgTypeImpl entrymsg_type;
|
||||
|
||||
public:
|
||||
CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandentrymsg(this),
|
||||
eml(this, "entrymsg"), entrymsg_type("EntryMsg", EntryMsgImpl::Unserialize)
|
||||
CSEntryMessage(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandentrymsg(this)
|
||||
, eml(this, "entrymsg")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -77,10 +77,10 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
prefix = conf->GetModule("chanstats")->Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("chanstats")->Get<const Anope::string>("engine"));
|
||||
prefix = conf.GetModule("chanstats").Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf.GetModule("chanstats").Get<const Anope::string>("engine"));
|
||||
}
|
||||
|
||||
SQL::Result RunQuery(const SQL::Query &query)
|
||||
|
||||
@@ -104,10 +104,10 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
prefix = conf->GetModule("chanstats")->Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("chanstats")->Get<const Anope::string>("engine"));
|
||||
prefix = conf.GetModule("chanstats").Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf.GetModule("chanstats").Get<const Anope::string>("engine"));
|
||||
}
|
||||
|
||||
SQL::Result RunQuery(const SQL::Query &query)
|
||||
|
||||
@@ -93,7 +93,7 @@ class CommandCSFlags final
|
||||
|
||||
if (IRCD->IsChannelValid(mask))
|
||||
{
|
||||
if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access"))
|
||||
if (Config->GetModule("chanserv").Get<bool>("disallow_channel_access"))
|
||||
{
|
||||
source.Reply(_("Channels may not be on access lists."));
|
||||
return;
|
||||
@@ -116,7 +116,7 @@ class CommandCSFlags final
|
||||
else
|
||||
{
|
||||
na = NickAlias::Find(mask);
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
if (!na && Config->GetModule("chanserv").Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
return;
|
||||
@@ -179,7 +179,7 @@ class CommandCSFlags final
|
||||
}
|
||||
}
|
||||
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
|
||||
unsigned access_max = Config->GetModule("chanserv").Get<unsigned>("accessmax", "1000");
|
||||
if (access_max && ci->GetDeepAccessCount() >= access_max)
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
|
||||
@@ -444,24 +444,27 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("%s is another way to modify the channel access list, similar to\n"
|
||||
"the XOP and ACCESS methods."), source.command.c_str());
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002MODIFY\002 command allows you to modify the access list. If the mask is\n"
|
||||
"not already on the access list it is added, then the changes are applied.\n"
|
||||
"If the mask has no more flags, then the mask is removed from the access list.\n"
|
||||
"Additionally, you may use +* or -* to add or remove all flags, respectively. You are\n"
|
||||
"only able to modify the access list if you have the proper permission on the channel,\n"
|
||||
"and even then you can only give other people access to the equivalent of what your access is."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002LIST\002 command allows you to list existing entries on the channel access list.\n"
|
||||
"If a mask is given, the mask is wildcard matched against all existing entries on the\n"
|
||||
"access list, and only those entries are returned. If a set of flags is given, only those\n"
|
||||
"on the access list with the specified flags are returned."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002CLEAR\002 command clears the channel access list. This requires channel founder access."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The available flags are:"));
|
||||
source.Reply(_(
|
||||
"%s is another way to modify the channel access list, similar to "
|
||||
"the XOP and ACCESS methods."
|
||||
"\n\n"
|
||||
"The \002MODIFY\002 command allows you to modify the access list. If the mask is "
|
||||
"not already on the access list it is added, then the changes are applied. "
|
||||
"If the mask has no more flags, then the mask is removed from the access list. "
|
||||
"Additionally, you may use +* or -* to add or remove all flags, respectively. You are "
|
||||
"only able to modify the access list if you have the proper permission on the channel, "
|
||||
"and even then you can only give other people access to the equivalent of what your access is."
|
||||
"\n\n"
|
||||
"The \002LIST\002 command allows you to list existing entries on the channel access list. "
|
||||
"If a mask is given, the mask is wildcard matched against all existing entries on the "
|
||||
"access list, and only those entries are returned. If a set of flags is given, only those "
|
||||
"on the access list with the specified flags are returned."
|
||||
"\n\n"
|
||||
"The \002CLEAR\002 command clears the channel access list. This requires channel founder access."
|
||||
"\n\n"
|
||||
"The available flags are:"
|
||||
),
|
||||
source.command.nobreak().c_str());
|
||||
|
||||
typedef std::multimap<char, Anope::string, ci::less> reverse_map;
|
||||
reverse_map reverse;
|
||||
@@ -494,21 +497,21 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
defaultFlags.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("privilege"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
|
||||
{
|
||||
Configuration::Block *priv = conf->GetBlock("privilege", i);
|
||||
const auto &priv = conf.GetBlock("privilege", i);
|
||||
|
||||
const Anope::string &pname = priv->Get<const Anope::string>("name");
|
||||
const Anope::string &pname = priv.Get<const Anope::string>("name");
|
||||
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(pname);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
const Anope::string &value = priv->Get<const Anope::string>("flag");
|
||||
const Anope::string &value = priv.Get<const Anope::string>("flag");
|
||||
if (value.empty())
|
||||
continue;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
if (!ci->desc.empty())
|
||||
info[_("Description")] = ci->desc;
|
||||
|
||||
info[_("Registered")] = Anope::strftime(ci->time_registered, source.GetAccount());
|
||||
info[_("Registered")] = Anope::strftime(ci->registered, source.GetAccount());
|
||||
info[_("Last used")] = Anope::strftime(ci->last_used, source.GetAccount());
|
||||
|
||||
if (show_all)
|
||||
@@ -74,12 +74,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Lists information about the specified registered channel,\n"
|
||||
"including its founder, time of registration, last\n"
|
||||
"time used, and description. If the user issuing the\n"
|
||||
"command has the appropriate access for it, then the\n"
|
||||
"successor, last topic set, settings and expiration\n"
|
||||
"time will also be displayed when applicable."));
|
||||
source.Reply(_(
|
||||
"Lists information about the specified registered channel, "
|
||||
"including its founder, time of registration, last "
|
||||
"time used, and description. If the user issuing the "
|
||||
"command has the appropriate access for it, then the "
|
||||
"successor, last topic set, settings and expiration "
|
||||
"time will also be displayed when applicable."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -89,11 +89,14 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Tells %s to invite you or an optionally specified\n"
|
||||
"nick into the given channel.\n"
|
||||
" \n"
|
||||
"By default, limited to AOPs or those with level 5 access and above\n"
|
||||
"on the channel."), source.service->nick.c_str());
|
||||
source.Reply(_(
|
||||
"Tells %s to invite you or an optionally specified "
|
||||
"nick into the given channel."
|
||||
"\n\n"
|
||||
"By default, limited to AOPs or those with level 5 access and above "
|
||||
"on the channel."
|
||||
),
|
||||
source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,12 +44,11 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
|
||||
unsigned reasonmax = Config->GetModule("chanserv").Get<unsigned>("reasonmax", "200");
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
|
||||
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
|
||||
auto signkickformat = Config->GetModule("chanserv").Get<Anope::string>("signkickformat", "{message} ({nick})");
|
||||
|
||||
AccessGroup u_access = source.AccessFor(ci);
|
||||
|
||||
@@ -71,7 +70,10 @@ public:
|
||||
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
{
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
signkickformat = Anope::Template(signkickformat, {
|
||||
{ "message", reason },
|
||||
{ "nick", source.GetNick() },
|
||||
});
|
||||
c->Kick(ci->WhoSends(), u2, signkickformat);
|
||||
}
|
||||
else
|
||||
@@ -105,7 +107,10 @@ public:
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
{
|
||||
reason += " (Matches " + mask + ")";
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
signkickformat = Anope::Template(signkickformat, {
|
||||
{ "message", reason },
|
||||
{ "nick", source.GetNick() },
|
||||
});
|
||||
c->Kick(ci->WhoSends(), uc->user, signkickformat);
|
||||
}
|
||||
else
|
||||
@@ -126,10 +131,12 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Kicks a specified nick from a channel.\n"
|
||||
" \n"
|
||||
"By default, limited to AOPs or those with level 5 access\n"
|
||||
"and above on the channel. Channel founders can also specify masks."));
|
||||
source.Reply(_(
|
||||
"Kicks a specified nick from a channel."
|
||||
"\n\n"
|
||||
"By default, limited to AOPs or those with level 5 access "
|
||||
"and above on the channel. Channel founders can also specify masks."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
class CommandCSList final
|
||||
: public Command
|
||||
@@ -42,8 +42,10 @@ public:
|
||||
if (!num1.has_value() || !num2.has_value())
|
||||
{
|
||||
source.Reply(LIST_INCORRECT_RANGE);
|
||||
source.Reply(_("To search for channels starting with #, search for the channel\n"
|
||||
"name without the #-sign prepended (\002anope\002 instead of \002#anope\002)."));
|
||||
source.Reply(_(
|
||||
"To search for channels starting with #, search for the channel "
|
||||
"name without the #-sign prepended (\002anope\002 instead of \002#anope\002)."
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,7 +70,7 @@ public:
|
||||
}
|
||||
|
||||
Anope::string spattern = "#" + pattern;
|
||||
unsigned listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50");
|
||||
unsigned listmax = Config->GetModule(this->owner).Get<unsigned>("listmax", "50");
|
||||
|
||||
source.Reply(_("List of entries matching \002%s\002:"), pattern.c_str());
|
||||
|
||||
@@ -133,38 +135,43 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Lists all registered channels matching the given pattern.\n"
|
||||
"Channels with the \002PRIVATE\002 option set will only be\n"
|
||||
"displayed to Services Operators with the proper access.\n"
|
||||
"Channels with the \002NOEXPIRE\002 option set will have\n"
|
||||
"a \002!\002 prefixed to the channel for Services Operators to see.\n"
|
||||
" \n"
|
||||
"Note that a preceding '#' specifies a range, channel names\n"
|
||||
"are to be written without '#'.\n"
|
||||
" \n"
|
||||
"If the SUSPENDED or NOEXPIRE options are given, only channels\n"
|
||||
"which, respectively, are SUSPENDED or have the NOEXPIRE\n"
|
||||
"flag set will be displayed. If multiple options are given,\n"
|
||||
"all channels matching at least one option will be displayed.\n"
|
||||
"Note that these options are limited to \037Services Operators\037.\n"
|
||||
" \n"
|
||||
"Examples:\n"
|
||||
" \n"
|
||||
" \002LIST *anope*\002\n"
|
||||
" Lists all registered channels with \002anope\002 in their\n"
|
||||
" names (case insensitive).\n"
|
||||
" \n"
|
||||
" \002LIST * NOEXPIRE\002\n"
|
||||
" Lists all registered channels which have been set to not expire.\n"
|
||||
" \n"
|
||||
" \002LIST #51-100\002\n"
|
||||
" Lists all registered channels within the given range (51-100)."));
|
||||
source.Reply(_(
|
||||
"Lists all registered channels matching the given pattern. "
|
||||
"Channels with the \002PRIVATE\002 option set will only be "
|
||||
"displayed to Services Operators with the proper access. "
|
||||
"Channels with the \002NOEXPIRE\002 option set will have "
|
||||
"a \002!\002 prefixed to the channel for Services Operators to see."
|
||||
"\n\n"
|
||||
"Note that a preceding '#' specifies a range, channel names "
|
||||
"are to be written without '#'."
|
||||
"\n\n"
|
||||
"If the SUSPENDED or NOEXPIRE options are given, only channels "
|
||||
"which, respectively, are SUSPENDED or have the NOEXPIRE "
|
||||
"flag set will be displayed. If multiple options are given, "
|
||||
"all channels matching at least one option will be displayed. "
|
||||
"Note that these options are limited to \037Services Operators\037."
|
||||
"\n\n"
|
||||
"Examples:"
|
||||
"\n\n"
|
||||
" \002LIST\032*anope*\002\n"
|
||||
" Lists all registered channels with \002anope\002 in their\n"
|
||||
" names (case insensitive)."
|
||||
"\n\n"
|
||||
" \002LIST\032*\032NOEXPIRE\002\n"
|
||||
" Lists all registered channels which have been set to not expire."
|
||||
"\n\n"
|
||||
" \002LIST #51-100\002\n"
|
||||
" Lists all registered channels within the given range (51-100)."
|
||||
));
|
||||
|
||||
if (!Config->GetBlock("options")->Get<const Anope::string>("regexengine").empty())
|
||||
if (!Config->GetBlock("options").Get<const Anope::string>("regexengine").empty())
|
||||
{
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Regex matches are also supported using the %s engine.\n"
|
||||
"Enclose your pattern in // if this is desired."), Config->GetBlock("options")->Get<const Anope::string>("regexengine").c_str());
|
||||
source.Reply(_(
|
||||
"Regex matches are also supported using the %s engine. "
|
||||
"Enclose your pattern in // if this is desired."
|
||||
),
|
||||
Config->GetBlock("options").Get<const Anope::string>("regexengine").c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -234,8 +241,10 @@ public:
|
||||
BotInfo *bi;
|
||||
Anope::string cmd;
|
||||
if (Command::FindCommandFromService("chanserv/list", bi, cmd))
|
||||
source.Reply(_("When \002private\002 is set, the channel will not appear in\n"
|
||||
"%s's %s command."), bi->nick.c_str(), cmd.c_str());
|
||||
{
|
||||
source.Reply(_("When \002private\002 is set, the channel will not appear in %s's %s command."),
|
||||
bi->nick.c_str(), cmd.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
+57
-42
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_log.h"
|
||||
#include "modules/chanserv/log.h"
|
||||
|
||||
struct LogSettingImpl final
|
||||
: LogSetting
|
||||
@@ -34,20 +34,30 @@ struct LogSettingImpl final
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct LogSettingTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
LogSettingTypeImpl()
|
||||
: Serialize::Type("LogSetting")
|
||||
{
|
||||
data.Store("ci", chan);
|
||||
data.Store("service_name", service_name);
|
||||
data.Store("command_service", command_service);
|
||||
data.Store("command_name", command_name);
|
||||
data.Store("method", method);
|
||||
data.Store("extra", extra);
|
||||
data.Store("creator", creator);
|
||||
data.Store("created", created);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *ls = static_cast<const LogSettingImpl *>(obj);
|
||||
data.Store("ci", ls->chan);
|
||||
data.Store("service_name", ls->service_name);
|
||||
data.Store("command_service", ls->command_service);
|
||||
data.Store("command_name", ls->command_name);
|
||||
data.Store("method", ls->method);
|
||||
data.Store("extra", ls->extra);
|
||||
data.Store("creator", ls->creator);
|
||||
data.Store("created", ls->created);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
Anope::string sci;
|
||||
data["ci"] >> sci;
|
||||
@@ -261,26 +271,30 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The %s command allows users to configure logging settings\n"
|
||||
"for their channel. If no parameters are given this command\n"
|
||||
"lists the current logging methods in place for this channel.\n"
|
||||
" \n"
|
||||
"Otherwise, \037command\037 must be a command name, and \037method\037\n"
|
||||
"is one of the following logging methods:\n"
|
||||
" \n"
|
||||
" MESSAGE [status], NOTICE [status], MEMO\n"
|
||||
" \n"
|
||||
"Which are used to message, notice, and memo the channel respectively.\n"
|
||||
"With MESSAGE or NOTICE you must have a service bot assigned to and joined\n"
|
||||
"to your channel. Status may be a channel status such as @ or +.\n"
|
||||
" \n"
|
||||
"To remove a logging method use the same syntax as you would to add it.\n"
|
||||
" \n"
|
||||
source.Reply(_(
|
||||
"The %s command allows users to configure logging settings "
|
||||
"for their channel. If no parameters are given this command "
|
||||
"lists the current logging methods in place for this channel."
|
||||
"\n\n"
|
||||
"Otherwise, \037command\037 must be a command name, and \037method\037 "
|
||||
"is one of the following logging methods:"
|
||||
"\n\n"
|
||||
" MESSAGE\032[status], NOTICE\032[status], MEMO"
|
||||
"\n\n"
|
||||
"Which are used to message, notice, and memo the channel respectively. "
|
||||
"With MESSAGE or NOTICE you must have a service bot assigned to and joined "
|
||||
"to your channel. Status may be a channel status such as @ or +."
|
||||
"\n\n"
|
||||
"To remove a logging method use the same syntax as you would to add it."
|
||||
"\n\n"
|
||||
"Example:\n"
|
||||
" %s #anope chanserv/access MESSAGE @\n"
|
||||
" Would message any channel operators whenever someone used the\n"
|
||||
" ACCESS command on ChanServ on the channel."),
|
||||
source.command.upper().c_str(), source.command.upper().c_str());
|
||||
" %s\032#anope\032chanserv/access\032MESSAGE\032@\n"
|
||||
" Would message any channel operators whenever someone used the "
|
||||
"ACCESS command on ChanServ on the channel."
|
||||
),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -291,7 +305,7 @@ class CSLog final
|
||||
ServiceReference<MemoServService> MSService;
|
||||
CommandCSLog commandcslog;
|
||||
ExtensibleItem<LogSettingsImpl> logsettings;
|
||||
Serialize::Type logsetting_type;
|
||||
LogSettingTypeImpl logsetting_type;
|
||||
|
||||
struct LogDefault final
|
||||
{
|
||||
@@ -301,27 +315,28 @@ class CSLog final
|
||||
std::vector<LogDefault> defaults;
|
||||
|
||||
public:
|
||||
CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
MSService("MemoServService", "MemoServ"), commandcslog(this),
|
||||
logsettings(this, "logsettings"), logsetting_type("LogSetting", LogSettingImpl::Unserialize)
|
||||
CSLog(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, MSService("MemoServService", "MemoServ")
|
||||
, commandcslog(this)
|
||||
, logsettings(this, "logsettings")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
const auto &block = conf.GetModule(this);
|
||||
defaults.clear();
|
||||
|
||||
for (int i = 0; i < block->CountBlock("default"); ++i)
|
||||
for (int i = 0; i < block.CountBlock("default"); ++i)
|
||||
{
|
||||
Configuration::Block *def = block->GetBlock("default", i);
|
||||
const auto &def = block.GetBlock("default", i);
|
||||
|
||||
LogDefault ld;
|
||||
|
||||
ld.service = def->Get<const Anope::string>("service");
|
||||
ld.command = def->Get<const Anope::string>("command");
|
||||
ld.method = def->Get<const Anope::string>("method");
|
||||
ld.service = def.Get<const Anope::string>("service");
|
||||
ld.command = def.Get<const Anope::string>("command");
|
||||
ld.method = def.Get<const Anope::string>("method");
|
||||
|
||||
defaults.push_back(ld);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
struct ModeLockImpl final
|
||||
: ModeLock
|
||||
@@ -30,9 +30,17 @@ struct ModeLockImpl final
|
||||
ml->RemoveMLock(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
struct ModeLockTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
ModeLockTypeImpl()
|
||||
: Serialize::Type("ModeLock")
|
||||
{
|
||||
}
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
struct ModeLocksImpl final
|
||||
@@ -203,17 +211,18 @@ struct ModeLocksImpl final
|
||||
}
|
||||
};
|
||||
|
||||
void ModeLockImpl::Serialize(Serialize::Data &data) const
|
||||
void ModeLockTypeImpl::Serialize(const Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
data.Store("ci", this->ci);
|
||||
data.Store("set", this->set);
|
||||
data.Store("name", this->name);
|
||||
data.Store("param", this->param);
|
||||
data.Store("setter", this->setter);
|
||||
data.Store("created", this->created);
|
||||
const auto *ml = static_cast<const ModeLockImpl *>(obj);
|
||||
data.Store("ci", ml->ci);
|
||||
data.Store("set", ml->set);
|
||||
data.Store("name", ml->name);
|
||||
data.Store("param", ml->param);
|
||||
data.Store("setter", ml->setter);
|
||||
data.Store("created", ml->created);
|
||||
}
|
||||
|
||||
Serializable *ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
Serializable *ModeLockTypeImpl::Unserialize(Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
Anope::string sci;
|
||||
|
||||
@@ -336,7 +345,7 @@ class CommandCSMode final
|
||||
continue;
|
||||
}
|
||||
|
||||
if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "50"))
|
||||
if (modelocks->GetMLock().size() >= Config->GetModule(this->owner).Get<unsigned>("max", "50"))
|
||||
{
|
||||
source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str());
|
||||
continue;
|
||||
@@ -765,29 +774,39 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Mainly controls mode locks and mode access (which is different from channel access)\n"
|
||||
"on a channel.\n"
|
||||
" \n"
|
||||
"The \002%s LOCK\002 command allows you to add, delete, and view mode locks on a channel.\n"
|
||||
"If a mode is locked on or off, services will not allow that mode to be changed. The \002SET\002\n"
|
||||
"command will clear all existing mode locks and set the new one given, while \002ADD\002 and \002DEL\002\n"
|
||||
"modify the existing mode lock.\n"
|
||||
"Example:\n"
|
||||
" \002MODE #channel LOCK ADD +bmnt *!*@*aol*\002\n"
|
||||
" \n"
|
||||
"The \002%s SET\002 command allows you to set modes through services. Wildcards * and ? may\n"
|
||||
"be given as parameters for list and status modes.\n"
|
||||
"Example:\n"
|
||||
" \002MODE #channel SET +v *\002\n"
|
||||
" Sets voice status to all users in the channel.\n"
|
||||
" \n"
|
||||
" \002MODE #channel SET -b ~c:*\n"
|
||||
" Clears all extended bans that start with ~c:\n"
|
||||
" \n"
|
||||
"The \002%s CLEAR\002 command is an easy way to clear modes on a channel. \037what\037 may be\n"
|
||||
"any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If \037what\037\n"
|
||||
"is not given then all basic modes are removed."),
|
||||
source.command.upper().c_str(), source.command.upper().c_str(), source.command.upper().c_str());
|
||||
source.Reply(_(
|
||||
"Mainly controls mode locks and mode access (which is different from channel access) "
|
||||
"on a channel."
|
||||
"\n\n"
|
||||
"The \002%s\032LOCK\002 command allows you to add, delete, and view mode locks on a channel. "
|
||||
"If a mode is locked on or off, services will not allow that mode to be changed. The \002SET\002 "
|
||||
"command will clear all existing mode locks and set the new one given, while \002ADD\002 and \002DEL\002 "
|
||||
"modify the existing mode lock."
|
||||
"\n\n"
|
||||
"Example:\n"
|
||||
" \002%s\032#channel\032%s\032ADD\032+bmnt\032*!*@*aol*\002\n"
|
||||
"\n\n"
|
||||
"The \002%s\032SET\002 command allows you to set modes through services. Wildcards * and ? may "
|
||||
"be given as parameters for list and status modes."
|
||||
"\n\n"
|
||||
"Example:\n"
|
||||
" \002%s\032#channel\032SET\032+v\032*\002\n"
|
||||
" Sets voice status to all users in the channel."
|
||||
"\n\n"
|
||||
" \002%s\032#channel\032SET\032-b\032~c:*\n"
|
||||
" Clears all extended bans that start with ~c:"
|
||||
"\n\n"
|
||||
"The \002%s\032CLEAR\002 command is an easy way to clear modes on a channel. \037what\037 may be "
|
||||
"any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If \037what\037 "
|
||||
"is not given then all basic modes are removed."
|
||||
),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str(),
|
||||
source.command.nobreak().c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -915,13 +934,15 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
if (m.first)
|
||||
source.Reply(_("Gives %s status to the selected nicks on a channel. If \037nick\037 is\n"
|
||||
"not given, it will %s you."),
|
||||
m.second.upper().c_str(), m.second.lower().c_str());
|
||||
{
|
||||
source.Reply(_("Gives %s status to the selected nicks on a channel. If \037nick\037 is not given, it will %s you."),
|
||||
m.second.upper().c_str(), m.second.lower().c_str());
|
||||
}
|
||||
else
|
||||
source.Reply(_("Removes %s status from the selected nicks on a channel. If \037nick\037 is\n"
|
||||
"not given, it will de%s you."),
|
||||
m.second.upper().c_str(), m.second.lower().c_str());
|
||||
{
|
||||
source.Reply(_("Removes %s status from the selected nicks on a channel. If \037nick\037 is not given, it will de%s you."),
|
||||
m.second.upper().c_str(), m.second.lower().c_str());
|
||||
}
|
||||
source.Reply(" ");
|
||||
source.Reply(_("You must have the %s(ME) privilege on the channel to use this command."), m.second.upper().c_str());
|
||||
|
||||
@@ -935,33 +956,33 @@ class CSMode final
|
||||
CommandCSMode commandcsmode;
|
||||
CommandCSModes commandcsmodes;
|
||||
ExtensibleItem<ModeLocksImpl> modelocks;
|
||||
Serialize::Type modelocks_type;
|
||||
ModeLockTypeImpl modelocks_type;
|
||||
|
||||
public:
|
||||
CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandcsmode(this), commandcsmodes(this),
|
||||
modelocks(this, "modelocks"),
|
||||
modelocks_type("ModeLock", ModeLockImpl::Unserialize)
|
||||
CSMode(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandcsmode(this)
|
||||
, commandcsmodes(this)
|
||||
, modelocks(this, "modelocks")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
modes.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("command"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("command"); ++i)
|
||||
{
|
||||
Configuration::Block *block = conf->GetBlock("command", i);
|
||||
const auto &block = conf.GetBlock("command", i);
|
||||
|
||||
const Anope::string &cname = block->Get<const Anope::string>("name"),
|
||||
&cmd = block->Get<const Anope::string>("command");
|
||||
const Anope::string &cname = block.Get<const Anope::string>("name"),
|
||||
&cmd = block.Get<const Anope::string>("command");
|
||||
|
||||
if (cname.empty() || cmd != "chanserv/modes")
|
||||
continue;
|
||||
|
||||
const Anope::string &set = block->Get<const Anope::string>("set"),
|
||||
&unset = block->Get<const Anope::string>("unset");
|
||||
const Anope::string &set = block.Get<const Anope::string>("set"),
|
||||
&unset = block.Get<const Anope::string>("unset");
|
||||
|
||||
if (set.empty() && unset.empty())
|
||||
continue;
|
||||
@@ -1024,7 +1045,7 @@ public:
|
||||
{
|
||||
ModeLocks *ml = modelocks.Require(ci);
|
||||
Anope::string mlock;
|
||||
spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("mlock", "+nt"));
|
||||
spacesepstream sep(Config->GetModule(this).Get<const Anope::string>("mlock", "+nt"));
|
||||
if (sep.GetToken(mlock))
|
||||
{
|
||||
bool add = true;
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
{
|
||||
const Anope::string &chan = params[0];
|
||||
const Anope::string &chdesc = params.size() > 1 ? params[1] : "";
|
||||
unsigned maxregistered = Config->GetModule("chanserv")->Get<unsigned>("maxregistered");
|
||||
unsigned maxregistered = Config->GetModule("chanserv").Get<unsigned>("maxregistered");
|
||||
|
||||
User *u = source.GetUser();
|
||||
NickCore *nc = source.nc;
|
||||
@@ -84,28 +84,41 @@ public:
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Registers a channel in the %s database. In order\n"
|
||||
"to use this command, you must first be a channel operator\n"
|
||||
"on the channel you're trying to register.\n"
|
||||
"The description, which is optional, is a\n"
|
||||
"general description of the channel's purpose.\n"
|
||||
" \n"
|
||||
"When you register a channel, you are recorded as the\n"
|
||||
"\"founder\" of the channel. The channel founder is allowed\n"
|
||||
"to change all of the channel settings for the channel;\n"
|
||||
"%s will also automatically give the founder\n"
|
||||
"channel operator privileges when they enter the channel."),
|
||||
source.service->nick.c_str(), source.service->nick.c_str());
|
||||
source.Reply(_(
|
||||
"Registers a channel in the %s database. In order "
|
||||
"to use this command, you must first be a channel operator "
|
||||
"on the channel you're trying to register. "
|
||||
"The description, which is optional, is a "
|
||||
"general description of the channel's purpose. "
|
||||
"\n\n"
|
||||
"When you register a channel, you are recorded as the "
|
||||
"\"founder\" of the channel. The channel founder is allowed "
|
||||
"to change all of the channel settings for the channel; "
|
||||
"%s will also automatically give the founder "
|
||||
"channel operator privileges when they enter the channel."
|
||||
),
|
||||
source.service->nick.c_str(),
|
||||
source.service->nick.c_str());
|
||||
|
||||
BotInfo *bi;
|
||||
Anope::string cmd;
|
||||
if (Command::FindCommandFromService("chanserv/access", bi, cmd))
|
||||
source.Reply(_(" \n"
|
||||
"See the \002%s\002 command (\002%s HELP ACCESS\002) for\n"
|
||||
"information on giving a subset of these privileges to\n"
|
||||
"other channel users.\n"), cmd.c_str(), bi->GetQueryCommand().c_str());
|
||||
source.Reply(_(" \n"
|
||||
"NOTICE: In order to register a channel, you must have\n"
|
||||
{
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"See the \002%s\002 command (\002%s\032ACCESS\002) for "
|
||||
"information on giving a subset of these privileges to "
|
||||
"other channel users."
|
||||
),
|
||||
cmd.c_str(),
|
||||
bi->GetQueryCommand("generic/help").c_str());
|
||||
}
|
||||
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"NOTICE: In order to register a channel, you must have "
|
||||
"first registered your nickname."));
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user